プログラミング言語C 第2版(K&R)の内容について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
cookierinon

プログラミング言語C 第2版(K&R)の内容について

#1

投稿記事 by cookierinon » 9年前

C言語初心者です。プログラミング言語C 第2版(K&R)の内容について質問させていただきます。
P36にある”一番長い行をプリントするプログラム”について、
15行目のmax = 0;を3行上に移す(int max;とchar line[MAXLINE];の間に挿入する)と以下のエラーが発生してしまいます。
↑の行為の何が駄目なのかさっぱりわかりません、どなたか教えていただけないでしょうか?
環境はvisual studio 2010です。

\sample1-9.c(12): error C2143: 構文エラー : ';' が '型' の前にありません。
\sample1-9.c(13): error C2143: 構文エラー : ';' が '型' の前にありません。
\sample1-9.c(15): error C2065: 'line' : 定義されていない識別子です。
\sample1-9.c(15): warning C4047: '関数' : 間接参照のレベルが 'char *' と 'int' で異なっています。
\sample1-9.c(15): warning C4024: 'getline' : の型が 1 の仮引数および実引数と異なります。
\sample1-9.c(18): error C2065: 'longest' : 定義されていない識別子です。
\sample1-9.c(18): warning C4047: '関数' : 間接参照のレベルが 'char *' と 'int' で異なっています。
\sample1-9.c(18): warning C4024: 'copy' : の型が 1 の仮引数および実引数と異なります。
\sample1-9.c(18): error C2065: 'line' : 定義されていない識別子です。
\sample1-9.c(18): warning C4047: '関数' : 間接参照のレベルが 'char *' と 'int' で異なっています。
\sample1-9.c(18): warning C4024: 'copy' : の型が 2 の仮引数および実引数と異なります。
\sample1-9.c(21): error C2065: 'longest' : 定義されていない識別子です。
1>
1>ビルドに失敗しました。

コード:

#include <stdio.h>
#define MAXLINE 1000

/* getline関数の宣言 */
int getline(char line[], int maxline);
/* copy関数の宣言 */
void copy(char to[], char from[]);

main(){	/* copy関数で格納した最大文字数の配列の中身を印字 */
	int len;	/* 現在行の長さ(文字数) */
	int max;	/* 文字数の最大値 */
	char line[MAXLINE];	/* 現在入力中の文字列を格納する配列 */
	char longest[MAXLINE];	/* 最大文字数の配列 */

	max = 0;
	while((len = getline(line, MAXLINE)) > 0){
		if(len > max){
			max = len;
			copy(longest, line);
		}
	}
	if(max > 0)
		printf("%s", longest);
	return 0;
}

/* getline関数の定義 */
int getline(char s[], int lim){	/* 配列(引数)内の文字数(戻り値)を調べて返す */
	int i,c;

	for(i=0; i < lim-1 && (c= getchar()) != EOF && c != '\n'; ++i)
		s[i] = c;
	if(c == '\n'){
		s[i] = c;
		++i;
	}
	s[i] = '\0';
	return i;
}

/* copy関数の定義 */
void copy(char to[], char from[]){	/* 文字数最大値を更新した文字列from[]をto[]にcopy */
	int i;	/* iはfor用 */

	i = 0;
	while((to[i] = from[i]) != '\0'){
		++i;
	}
}

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: プログラミング言語C 第2版(K&R)の内容について

#2

投稿記事 by h2so5 » 9年前

エラーが出るコードを貼ってください。

初級者
記事: 200
登録日時: 13年前

Re: プログラミング言語C 第2版(K&R)の内容について

#3

投稿記事 by 初級者 » 9年前

max = 0;

のような実行文の後ろに
変数定義が来るのは、
文法上認められていません。

cookierinon

Re: プログラミング言語C 第2版(K&R)の内容について

#4

投稿記事 by cookierinon » 9年前

h2so5 さんが書きました:エラーが出るコードを貼ってください。
max = 0; を3行上の位置に変えています

コード:

#include <stdio.h>
#define MAXLINE 1000

/* getline関数の宣言 */
int getline(char hairetu[], int maxline);
/* copy関数の宣言 */
void copy(char to[], char from[]);

main(){	/* copy関数で格納した最大文字数の配列の中身を印字 */
	int max;
	int len;
	max = 0;
	char line[MAXLINE];	/* 現在入力中の文字列を格納する配列 */
	char longest[MAXLINE];	/* 最大文字数の配列 */

	while((len = getline(line, MAXLINE)) > 0){
		if(len > max){
			max = len;
			copy(longest, line);
		}
	}
	if(max > 0)
		printf("%s", longest);
	return 0;
}

/* getline関数の定義 */
int getline(char s[], int lim){	/* 配列(引数)内の文字数(戻り値)を調べて返す */
	int i,c;

	for(i=0; i < lim-1 && (c= getchar()) != EOF && c != '\n'; ++i)
		s[i] = c;
	if(c == '\n'){
		s[i] = c;
		++i;
	}
	s[i] = '\0';
	return i;
}

/* copy関数の定義 */
void copy(char to[], char from[]){	/* 文字数最大値を更新した文字列from[]をto[]にcopy */
	int i;	/* iはfor用 */

	i = 0;
	while((to[i] = from[i]) != '\0'){
		++i;
	}
}

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: プログラミング言語C 第2版(K&R)の内容について

#5

投稿記事 by h2so5 » 9年前

C89では変数の宣言はブロックの先頭でまとめて行う必要があります。
C99以降では宣言を途中で行ってもエラーになりませんがVisual Studio 2010は対応していません。

cookierinon

Re: プログラミング言語C 第2版(K&R)の内容について

#6

投稿記事 by cookierinon » 9年前

皆様迅速な回答ありがとうございます。
h2so5 さんが書きました:C89では変数の宣言はブロックの先頭でまとめて行う必要があります。
C99以降では宣言を途中で行ってもエラーになりませんがVisual Studio 2010は対応していません。
返信を受けて少し調べたのですが要するにC99という規格を実装したVS2013だとエラーにはならない、
それ以前の環境の場合、またコードの理論としても、
関数の頭で変数(配列含め)の宣言を”全て”行わなければならない、後に初期化等の記述

という理解でよろしいでしょうか?

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: プログラミング言語C 第2版(K&R)の内容について

#7

投稿記事 by h2so5 » 9年前

初期化については、C89でも

コード:

    int max = 0;
    int len;
    char line[MAXLINE]; /* 現在入力中の文字列を格納する配列 */
    char longest[MAXLINE];  /* 最大文字数の配列 */
というように宣言と初期化を同時に行うことはできます。
cookierinon さんが書きました: それ以前の環境の場合、またコードの理論としても、
関数の頭で変数(配列含め)の宣言を”全て”行わなければならない、後に初期化等の記述
コードの理論の問題ではなく、C89では規格上の制限として先頭でしか宣言できないというだけです。

関数の頭ではなく、ブロックの頭です。
関数の中にif文やfor文のブロックが存在する場合その先頭で変数を宣言することができます。

VS2013では(試していませんが)エラーにはならないはずです。

cookierinon

Re: プログラミング言語C 第2版(K&R)の内容について

#8

投稿記事 by cookierinon » 9年前

h2so5 さんが書きました:
コードの理論の問題ではなく、C89では規格上の制限として先頭でしか宣言できないというだけです。

関数の頭ではなく、ブロックの頭です。
関数の中にif文やfor文のブロックが存在する場合その先頭で変数を宣言することができます。

VS2013では(試していませんが)エラーにはならないはずです。[/quote]



ブロックの頭で宣言をまとめて行うor宣言と同時に初期化を行うとエラーにならない、ですか。
丁寧なご指摘、ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る