ついに夏本番!さぁ、家族でキャンプに行くぞ! >>

C言語を今日から始めたじいさんです。
宜しくお願い致します。

メモ帳を使って3行ほどの文字列を入力して、text.txtファイルに保存します。
この文字列を読み込んで、1行ずつ印刷しようとしていますが fgetsでtxtファイルの終了条件がわかりません。

while(fgets(row , sizeof( row ) , fp) != NULL){
printf("%s\n , row);
}
fclose( fp );
return 0;

のようにしているのですが、3行印字処理をして異常終了してしまいます。
本に出ている例をそのまま実行しているのですが、うまくいきません。

txtファイルをダンプしてみると各行の後ろに0d 0aたぶんCR,LFが入っていてNULL=00(?)はありません。テキストファイルの作り方に問題があるのでしょうか?
それともfgetsの使い方に誤りがあるのでしょうか?

このQ&Aに関連する最新のQ&A

A 回答 (7件)

txtファイルの3行目の次が空行(改行だけの行)になっていないですか?



3行目の終わりのCRLFの次にもうひとつのCRLFがないか、ダンプで確認してみて下さい。
    • good
    • 0
この回答へのお礼

0d 0aがCR,LFならば、3行目の終わりの0d 0aのみで
もうひとつの0d 0aはありませんでした。
ダンプからすると変なコード等は一切はいっていないのですが、
もう一度、作成しなおしてみたら動いてしまいました。
正常に動いたファイルのダンプと全く同じなのですが???

これ以上は初心者なのでギブアップです。
色々とアドバイス頂き有難う御座いました。

お礼日時:2009/05/24 00:38

>実際のファイルはカンマであることを確認しました。



ということは、データファイルの内容は正しいが、
#3さんの回答への補足で提示されたソースコードだと
実行時に落ちてしまうということですか?

この回答への補足

データが画面に出力され
[NULL]
が最後に出力されて
「問題が発生しました・・・・」
になってしまいます。

補足日時:2009/05/23 23:22
    • good
    • 0

今回の件の原因は、#4さんの回答のとおり、データファイルの形式に問題があったためです。



それはさておき、

>実際はこのようなソースコードになっています。

何だか小出しにされると、困ってしまうのです。
じゃあ、最初に提示されたソースコードは何だったの?それに対する回答はムダだったの?という話です。

この回答への補足

申し訳ございませんでした。
初めてのC言語で、変なコメント等をたくさん入れていたので、
わかりやすくしようとしてかえっておかしくしてしまいました。

補足日時:2009/05/23 23:31
    • good
    • 0

>001,aiueo.05


>003,sasisuseso.55
名前と年齢の区切りがカンマ","ではないですが。

この回答への補足

コピペすれば良かったですね。
新たに入力したので間違えてしまいました。
実際のファイルはカンマであることを確認しました。
どうもすいませんでした。

補足日時:2009/05/23 23:06
    • good
    • 0

fgets()は「読み込むものが無い」、つまりファイル終端に辿り着いたらNULLを返します。


ぱっと見では(#2で修正されてる部分はともかくとして)コード自体に問題はないと思いますが、どのようなtext.txtを読んだらどのように異常が発生しましたか?

この回答への補足

テキストファイルはメモ帳を使って以下のような文字列を入力しています。
001,aiueo.05
002,kakikukeko,99
003,sasisuseso.55
実際のソースコードは
#include <stdio.h>
#include <string.h>
typedef struct list{
char id[3+1];
char name[10+1];
char age[2+1];
}list;
int main(void)
{
list lists[100];
FILE *fp;
char row[20];
char *p;
int i=0;

fp = fopen("./test.txt","r");

if(fp == NULL){
printf("ファイルをオープンできませんでした。\n");
return 1;
}
else{
printf("ファイルをオープンしました。\n");
}


while(fgets(row, sizeof(row), fp) != NULL){
p = strtok(row, ",");
printf("%s\n",p);
strcpy(lists[i].id, p);
p = strtok(NULL, ",");
printf("%s\n",p);
strcpy(lists[i].name, p);
p = strtok(NULL, ",");
printf("%s\n",p);
strcpy(lists[i].age, p);
i++;
}

fclose(fp);
return 0;
エラーメッセージは
「問題が発生したため、xxx.exeを終了します。ご不便をおかけして申し訳ありません」

補足日時:2009/05/23 22:21
    • good
    • 0

ご提示くださったソースコードには、



>while(fgets(row , sizeof( row ) , fp) != NULL){
全角の{ を使っている

>printf("%s\n , row);
" の対応が取れていない

というエラーがありました。これらを修正した下記のコードを使って、
aaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbbbbb
cccccccccccccccccccc

という内容のtest.textを読込むと、当方の環境では想定どおりの結果を得ました。
お使いの入力ファイルの1行の長さが配列の定義範囲を超えている、というようなことはありませんか?


#include <stdio.h>

int main(void)
{
FILE *fp;
char row[24];

fp = fopen("./test.text", "r");
if (fp == NULL) {
printf("ファイルオープンエラー\n");
return -1;
}
while (fgets(row, sizeof(row), fp) != NULL) {
printf("%s\n", row);
}
fclose(fp);
return 0;
}

この回答への補足

申し訳ございません。
実際はこのようなソースコードになっています。

test.txt
001,aiueo.05
002,kakikukeko,99
003,sasisuseso.55

#include <stdio.h>
#include <string.h>
typedef struct list{
char id[3+1];
char name[10+1];
char age[2+1];
}list;
int main(void)
{
list lists[100];
FILE *fp;
char row[20];
char *p;
int i=0;

fp = fopen("./test.txt","r");

if(fp == NULL){
printf("ファイルをオープンできませんでした。\n");
return 1;
}
else{
printf("ファイルをオープンしました。\n");
}


while(fgets(row, sizeof(row), fp) != NULL){
p = strtok(row, ",");
printf("%s\n",p);
strcpy(lists[i].id, p);
p = strtok(NULL, ",");
printf("%s\n",p);
strcpy(lists[i].name, p);
p = strtok(NULL, ",");
printf("%s\n",p);
strcpy(lists[i].age, p);
i++;
}

fclose(fp);
return 0;

補足日時:2009/05/23 22:09
    • good
    • 0

ソースコードを、全部見せていただけますか?


断片だけを見ても、原因や対策がわからないことがあります。

この回答への補足

以下のようなプログラムです。

#include <stdio.h>
#include <string.h>

int main(void)
{
FILE *fp;
char row[24];

fp=fopen("./test.text","r");
if(fp==NULL){
printf("ファイルオープンエラー\n");
return -1;
}
while(fgets(row , sizeof( row ) , fp) != NULL){
printf("%s\n , row);
}
fclose( fp );
return 0;

補足日時:2009/05/23 20:39
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qfgetsなどのときのstdinのバッファを消すには?

こんにちは,今C(C++でない)を使用しています。
たとえば,
char str[20]
fgets(str,sizeof(str),stdin)
としたときに20字以上を打つと,stdinのバッファに20字以上の分が残ったままになります。

C++などでは
fflush(stdin)で,うまくいきますが,普通のCでは対応がされていないみたいでうまくいきません。

よろしくお願いします。

Aベストアンサー

あ,テキスト入力だからこんな大掛かりなことしなくてもいいんだ.
末尾に'\n'が出るまで掃出せばいいんですよね.

fgets(str, sizeof(str), stdin);
if ( str[strlen(str)-1] != '\n' ){
while( getchar() != '\n' );
}

でいいんだ.失礼しました.

QEnterキーを押されたら次の処理に移るという事をしたい。

コンソールアプリケーション上で文字列を表示させた後、ユーザーがエンターキーを押したら次の文字列を表示するという仕様にしたいのですが、エンターキーだけ入力待ちにするっていうのはどのように書けばいいんでしょうか?

Aベストアンサー

#include <stdio.h>

int main(void)
{
char *str[] = {"abc", "def", "ghi", "jkl"};
int i;

for(i = 0; i < 4; i ++){
while(getchar() != '\n') ;
puts(str[i]);
}
return 0;
}

Q数字以外が入力されたらエラー文を出したい。

scanfで数字を取り込みたいのですが、ここでaなどのアルファベットや記号を入力すると、無限ループが発生してしまいます。
エラーが出ないように、数字以外が入力されたら、エラーメッセージを出すようなプログラムを作りたいのですが、どうすれば出来るでしょうか。

Aベストアンサー

★アドバイス
>scanfで数字を取り込みたいのですが、ここでaなどのアルファベットや記号を入力すると、
>無限ループが発生してしまいます。
 ↑
 ソースとかを見せて欲しいです。
 見ないとなぜ無限ループするのか判断できません。
>エラーが出ないように、数字以外が入力されたら、エラーメッセージを出すようなプログラムを
>作りたいのですが、どうすれば出来るでしょうか。
 ↑
 多分、scanf で整数の入力を行っていると思うので文字列で入力するようにします。
 そしてそのその文字列を strtod() 関数で整数に変換します。
・このときグローバル変数の errno を調べて ERANGE なら整数値のオーバーフローが起きたとか、
 第2引数で私のポインタに変換できなくなった位置をセットしますので、このポインタが \0 文字
 以外なら数字以外(アルファベットや記号)が混ざっていることになります。
・下にそのサンプルを載せます。

サンプル:
char buff[ 256 ];
char *argp;
int value;

// 文字列で入力
scanf( "%s", buff );
value = strtol( buff, &argp, 10 ); ←10進数で変換

// ここでチェック
if ( (errno != ERANGE) && (*argp != '\0') ){
 printf( "変換不可能な文字が入力されています。\n" );
 exit( 1 );
}

その他:
・上記のサンプルを使うには errno.h をインクルードして下さい。
 このヘッダに ERANGE 定数が定義されています。
 あと stdlib.h もインクルードしないと strtol() 関数が利用できません。
・以上。下の『参考URL』もどうぞ。

参考URL:http://www9.plala.or.jp/sgwr-t/lib/strtol.html

★アドバイス
>scanfで数字を取り込みたいのですが、ここでaなどのアルファベットや記号を入力すると、
>無限ループが発生してしまいます。
 ↑
 ソースとかを見せて欲しいです。
 見ないとなぜ無限ループするのか判断できません。
>エラーが出ないように、数字以外が入力されたら、エラーメッセージを出すようなプログラムを
>作りたいのですが、どうすれば出来るでしょうか。
 ↑
 多分、scanf で整数の入力を行っていると思うので文字列で入力するようにします。
 そしてそのその文字列を str...続きを読む

Qfgetsで拾われる改行文字を削除したい

お世話になります

 C言語初心者のものです。今課題でC言語を用いたプログラミングを
Fedora上でやっています。問題は、fgetsでテキストファイルから、取得
した文字列の中から改行文字を削除できないことです。文字変数のアド
レスはわかっているのですが、終端文字に置換しようとすると、セグメ
ントエラーになってしまいます。これは如何にして解決すべきでしょう
か。よろしくお願いします。

Aベストアンサー

ポインタとかアドレスとか、C言語の用語としてあるものを別の意味に使うとまぎらわしいです。

「ポインタ」「アドレス」と言われたら、 この例なら str, str+i が思い浮びます。
「文字変数のアドレス」だと
char c ;
に対しての
&c
が思い浮びます。

配列なら「添字」、意味的には「x文字目」ですね。

> for(i=0;;i++){
> if(*(str+i)=='/n') {
> *(str+i)='\0';
> break;
> }
> }
/nが\nの間違いなら、この方法で半分正解です。もう少し広い範囲(可能なら全体)で見ないことにはなんとも言えません。
fgetsが最大文字数に達したり、ファイルの最後になったりで、strに改行文字が含まれない場合には、このループは止まりません(Segmentension Falutになって止まる)

・そのような状態になってないか、予めチェックする
・ループを終了させる仕組みを用意しておく
: forの終了条件を記述する、for中で if(*(str+i)=='\0') { break;} 等としておく、等
といった対策が必要です。


あと細かいところを言えば
・strを配列で用意したなら *(s+i)じゃなくてs[i]でいいんじゃないかな
・あるいは char *pみたいにしておいて、 iのループでなく pでループを組む( for(p=str;*p!='\0';p++) )とか。

ポインタとかアドレスとか、C言語の用語としてあるものを別の意味に使うとまぎらわしいです。

「ポインタ」「アドレス」と言われたら、 この例なら str, str+i が思い浮びます。
「文字変数のアドレス」だと
char c ;
に対しての
&c
が思い浮びます。

配列なら「添字」、意味的には「x文字目」ですね。

> for(i=0;;i++){
> if(*(str+i)=='/n') {
> *(str+i)='\0';
> break;
> }
> }
/nが\nの間違いなら、この方法で半分正解です。もう少し広い範囲(可能なら全体)で見ないことにはなんとも言えません。
fgetsが...続きを読む

Qバッファとは何ですか

C言語を使用してるとバッファという言葉がよく出てきますがバッファとは何ですか
メモリとは違うものですか
訳をみても緩衝材とか一時的に蓄える場所という意味でよく分かりません
一時的でない使い方も多い気がしますが実際はどういうものですか

Aベストアンサー

#1です

寝ぼけて適当に書いたので修正。

すぐ見つけることができたもので正確なものは英語版ですがこちらくらいかも。
Data buffer - Wikipedia (en.)
http://en.wikipedia.org/wiki/Data_buffer

一応簡単なものはこちらです。
バッファとは - e-Wrods
http://e-words.jp/w/E38390E38383E38395E382A1.html

「複数の機器やソフトウェアの間でデータをやり取りするときに、処理速度や転送速度の差を補うためにデータを一時的に保存しておく記憶装置や記憶領域のこと。」
が現在の基本定義です。処理速度・転送速度の差のための緩衝材的な意味です。

昔はソフトウェアとハードウェア間に使うデータでソフトウェア側がデータを受け取るか、整形して送信するときに使うメモリ領域が基本的にバッファでした。
マルチプロセッサ・マルチタスクの時代になってくると、ソフトウェア間の処理速度の違いを吸収するために使うメモリ領域にもバッファという言葉が使われるようになりました。ソフトウェア間で逐次(FIFO)処理されるデータのためのメモリ領域がこちらの使われ方の主戦場といったところでしょうか。

ソフトウェア間でただ一括転送されるデータならバッファという言葉は誤用ということになるのですが、よく誤用されます。

#1です

寝ぼけて適当に書いたので修正。

すぐ見つけることができたもので正確なものは英語版ですがこちらくらいかも。
Data buffer - Wikipedia (en.)
http://en.wikipedia.org/wiki/Data_buffer

一応簡単なものはこちらです。
バッファとは - e-Wrods
http://e-words.jp/w/E38390E38383E38395E382A1.html

「複数の機器やソフトウェアの間でデータをやり取りするときに、処理速度や転送速度の差を補うためにデータを一時的に保存しておく記憶装置や記憶領域のこと。」
が現在の基本定義です。処理速度・転送速...続きを読む

Qファイルから読み取った改行文字を消す方法

C言語のプログラムから、テキストファイルを読み込むと、改行文字が・になってしまい、なんだか汚くみえてしまいます。
なので、ファイルから読み取った改行文字を消す方法が知りたいです。教えて下さい。

Aベストアンサー

★アドバイス
・普通に『\n』を検索して『\0』に書き換えれば改行消去できます。

サンプル:
char buff[ 256 ];
char *find;
FILE *fp;

ファイルのオープン
 :
while ( fgets(buff,sizeof(buff),fp) != NULL ){
 if ( (find = strchr(buff,'\n')) != NULL ){
  *find = '\0';
 }
 :
 処理
 :
}
 :
ファイルのクローズ

Q配列のNULL初期化について

C言語についての課題の一部です。
int型の配列 iArrayをNULL初期化したいのですが、
課題では下のように書かれています。
&iArray[] = NULL;
このような書き方でNULL初期化することは可能なのでしょうか?

Aベストアンサー

>NULL初期化することは可能なのでしょうか?
できません。文法上間違っています。

また、NULLはint型の値ではないので、「NULLで初期化する」とは言いません。
ちなみにiArrayを0で初期化する場合は下記のようになります。
int iArray[5];
int i;
for (i=0; i<sizeof(iArray)/sizeof(i); i++) {
iArray[i] = 0;
}
他にも色々な方法があります。参考まで。

QC言語 変換指定%sについてです。

現場での経験もあるPGなのですが、C言語の基礎を復習していたら疑問に思うことが出てきてしまったので、質問させて下さい。

printf関数などに使われる変換指定%sについてですが、
char word[] = "test";
char *pointer;
pointer = word;
とした場合、pointerの値は文字列wordの先頭アドレスになるので、
printf ("%x", pointer);
とすれば、そのアドレス値が表示されるのはとてもよくわかるのですが、
printf ("%s", pointer);
とした場合に、"test"と表示されるのがイマイチ納得できないんです。
printf ("%s", *pointer);
なら、まだわかるんですけど・・・

変換指定の%sというものは、
「アドレスを受け取って、受け取ったアドレスにある文字列を\0がくるまで表示する」
というものなのでしょうか?

int型のポインタで同じように
printf ("%d", pointer);
とすると、pointerの値であるアドレスが10進数表示されて、pointerが指している変数の値を表示するには、
printf ("%d", *pointer);
としなければならないわけで、そういうことをいろいろ考えていたら、収拾がつかなくなってしまって(^_^;)

「とにかく%sはそういうものなの!!」と丸暗記すれば困るようなことはないのですが、どうにもモヤモヤしっぱなしなので、%sの動きについて詳しくお分かりの方がいらっしゃいましたら、ご教授下さい。

よろしくお願いしますm(__)m

現場での経験もあるPGなのですが、C言語の基礎を復習していたら疑問に思うことが出てきてしまったので、質問させて下さい。

printf関数などに使われる変換指定%sについてですが、
char word[] = "test";
char *pointer;
pointer = word;
とした場合、pointerの値は文字列wordの先頭アドレスになるので、
printf ("%x", pointer);
とすれば、そのアドレス値が表示されるのはとてもよくわかるのですが、
printf ("%s", pointer);
とした場合に、"test"と表示されるのがイマイチ納得できないんです。
pri...続きを読む

Aベストアンサー

C言語の規格上では。
%につづく変換指定子sは空白類でない文字の並びに相当し、
長さ修飾が存在しない場合、対応する実引数は文字型配列の
先頭要素へのポインタで無ければならない
配列内の終端ナル文字の直前まで書き込み精度が指定された場合、
精度を超える書き込みは行わない。精度が指定されない場合、
または精度が配列より大きい場合その配列はナル文字を含まなければ
ならないとされています。

つまり配列より小さい精度が指定されなければ受け取ったポインタを
文字配列の先頭要素とし\0が出てくるまで表示します。

QC言語 配列の長さの上限

C言語で配列Array[N]の長さNの上限っていくらなんでしょうか?
もし可能なのであれば上限を2147483647にしたいのですが、方法を教えてください。

Aベストアンサー

そもそもWindowsの32bit版はアプリが仮想メモリ空間を2GBしか使えません。2GBを超えるには64bit版が必要です。
たとえ64bit版OSだとしても添え字が2147483647って、単純なintの配列だとしても4x2147483647=8GB必要ですね。実メモリ16GBとかのPCを用意しますか?
そもそも配列で2147483647個必要なアルゴリズムに問題ありだと思います。

Q入力する数字のサイズ制限について

よろしくお願いします。

C言語において、以下のようなコードで数字の入力を
行う場合、入力される数字がintのサイズを超えると問題があります。

int a;

printf("数字を入力してください。");
scanf("%d",&a);

一般的に入力される数字のサイズが不明の場合、どのようなコードを書けばよいのでしょうか?

ご存知の方お願いします。

Aベストアンサー

>一般的に入力される数字のサイズが不明の場合、どのようなコードを書けばよいのでしょうか?

int型変数に格納できない値が入力された場合にエラーとしたいのでしょうか? それでしたら、fgetsで入力データをバッファに格納してからチェックを行うことで可能となります。(もしくはチェックを行う関数を利用する。) longの場合でサンプルを作ってみました。

--------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <limits.h>

#define ERR_MSG(msg) {printf("%s\n", (#msg)); exit(1);}

int main() {

   char buf[256];
   long a;

   /*入力*/
   printf("%s", "数字を入力してください:");
   fgets(buf, sizeof(buf), stdin);
   buf[strlen(buf) - 1] = '\0'; /*改行削除*/
   
   /*変換*/
   if (strncmp(buf, "0", 2) != 0) { /*入力値 != 0*/
      errno = 0;
      a = strtol(buf, NULL, 10);
      
      if (a == 0) {
         ERR_MSG(変換失敗)
      }
      
      if ((errno == ERANGE) && (a == LONG_MAX)) {
         ERR_MSG(レンジエラー : 入力値 > LONG_MAX)
      }
      else if ((errno == ERANGE) && (a == LONG_MIN)) {
         ERR_MSG(レンジエラー : 入力値 < LONG_MIN)
      }
   }
   else { /*入力値 == 0*/
      a = 0;
   }
   
   /*出力*/
   printf("入力値:%d\n", a);

   return 0;
}

>一般的に入力される数字のサイズが不明の場合、どのようなコードを書けばよいのでしょうか?

int型変数に格納できない値が入力された場合にエラーとしたいのでしょうか? それでしたら、fgetsで入力データをバッファに格納してからチェックを行うことで可能となります。(もしくはチェックを行う関数を利用する。) longの場合でサンプルを作ってみました。

--------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#inc...続きを読む


人気Q&Aランキング