下記にある「言語ファイル入出力について」のsuzukiです

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

下記にある「言語ファイル入出力について」のsuzukiです

#1

投稿記事 by suzuki » 10年前

返信ボタンが適用されなくなってしまったのでこちらから、返信失礼致します。

みけCAT様
早速の返信ありがとうございます。
記入漏れで申し訳ないのですが、初心者です。

fprintf(fp,"%s,%d,%d,%d,%d,",name,year,month,day,y);
の記入のとき、
なぜscanfは%s改行入力できないのでしょうか?

また
・nameに含まれるコンマをエスケープしてから出力する、もしくはnameの行を最後に出力する
こちらの後者の文章は順番をかえるだけで宜しいのでしょうか?

・読み込むときには、fgetsでデータを読み込んだ後にパースを使って各データを復元する、もしくはgetcで読みながらパースする
パースとはどのようなことでしょうか?
調べましたがよくわからず、具体例など出してくれると助かります。

せっかく回答頂いたのですが、くだらない質問ばかりで、申し訳ございません。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 下記にある「言語ファイル入出力について」のsuzukiです

#2

投稿記事 by みけCAT » 10年前

suzuki さんが書きました:返信ボタンが適用されなくなってしまったのでこちらから、返信失礼致します。
前のトピックへのリンクを貼っておくといいと思います。
http://dixq.net/forum/viewtopic.php?f=3&t=15759
suzuki さんが書きました:fprintf(fp,"%s,%d,%d,%d,%d,",name,year,month,day,y);
の記入のとき、
なぜscanfは%s改行入力できないのでしょうか?
scanfは%sで改行を読み込むことができないからです。
なぜならば、scanfは改行、半角空白、タブを区切り文字として認識するからです。
suzuki さんが書きました:・nameに含まれるコンマをエスケープしてから出力する、もしくはnameの行を最後に出力する
こちらの後者の文章は順番をかえるだけで宜しいのでしょうか?
はい。
ただし、「nameの行を最後に出力する」ではなく、「nameを行の最後に出力する」です。
コピペが使えない環境からの返信ですか?
suzuki さんが書きました:・読み込むときには、fgetsでデータを読み込んだ後にパースを使って各データを復元する、もしくはgetcで読みながらパースする
パースとはどのようなことでしょうか?
調べましたがよくわからず、具体例など出してくれると助かります。
パースとは構文解析のことです。
これは

コード:

gochiusa,42,39
kinmoza,12345,9876
yuyushiki,12345678,87654321
のように(文字列),(数値),(数値)の形の行が並んだデータをパースするサンプルです。
エスケープのデコードや、エラーチェックはしていません。
また、コピペを用いたあまり良くない実装だと思います。

コード:

#include <stdio.h>
#include <ctype.h>

int parse_input(char *str, int *num1, int *num2, FILE* fp) {
	int input;
	/* 文字列を読み込む(バッファオーバーラン対策なし) */
	for (;;) {
		input = getc(fp);
		if (input == EOF || input == '\n') return 0; /* 予期せぬデータの終わり */
		if (input == ',') { /* データの区切り */
			*str = '\0';
			break;
		}
		*(str++) = input;
	}
	/* 整数型データ1を読み込む */
	*num1 = 0;
	for (;;) {
		input = getc(fp);
		if (input == EOF || input == '\n') return 0; /* 予期せぬデータの終わり */
		if (input == ',') { /* データの区切り */
			break;
		}
		if (!isdigit(input)) return 0; /* 不正なデータ */
		*num1 = *num1 * 10 + (input - '0'); /* 数値を更新する(オーバーフロー対策なし) */
	}
	/* 整数型データ2を読み込む */
	*num2 = 0;
	for (;;) {
		input = getc(fp);
		if (input == EOF || input == '\n') break; /* データの終わり */
		if (input == ',') { /* 予期せぬデータの区切り */
			return 0;
		}
		if (!isdigit(input)) return 0; /* 不正なデータ */
		*num2 = *num2 * 10 + (input - '0'); /* 数値を更新する(オーバーフロー対策なし) */
	}
	/* 読み取り成功 */
	return 1;
}

int main(void) {
	char str[1024];
	int num1, num2;
	while(parse_input(str, &num1, &num2, stdin)) {
		puts("-----");
		printf("str  = %s\n", str);
		printf("num1 = %d\n", num1);
		printf("num2 = %d\n", num2);
	}
	return 0;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

suzuki

Re: 下記にある「言語ファイル入出力について」のsuzukiです

#3

投稿記事 by suzuki » 10年前

みけCAT様
回答ありがとうございます。
fgetsで読み込んでから、記憶するために、パースの形式で記憶するのでしょうか?
このプログラムからどうつなげていいか、悩んでおります。

度々申し訳ございません。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 下記にある「言語ファイル入出力について」のsuzukiです

#4

投稿記事 by みけCAT » 10年前

suzuki さんが書きました:fgetsで読み込んでから、記憶するために、パースの形式で記憶するのでしょうか?
fgetsで読み込んでからパースしてもいいし、サンプルのようにgetcで読み込みながら記憶してもかまいません。
ただし、「パースの形式で記憶する」というのは間違いだと思います。
suzuki さんが書きました:このプログラムからどうつなげていいか、悩んでおります。
整数を読み込む処理を2セット増やし、
fgetsの代わりに提示したサンプルのparse_inputでcBuf/name, year, month, date, yを読み込むといいと思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

suzuki

Re: 下記にある「言語ファイル入出力について」のsuzukiです

#5

投稿記事 by suzuki » 10年前

パースが完全にはわかってないので、試しに理解しながらそのサンプルをファイルオープンのfgetsの下にいれて、プログラムにあう値を入れてみたところエラーがでてしまいました。

パースからちゃんと勉強したいと思います。

全体がどのようなコードになるのか、早く知って理解したいです。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 下記にある「言語ファイル入出力について」のsuzukiです

#6

投稿記事 by みけCAT » 10年前

suzuki さんが書きました:パースが完全にはわかってないので、試しに理解しながらそのサンプルをファイルオープンのfgetsの下にいれて、プログラムにあう値を入れてみたところエラーがでてしまいました。
そのコードを貼っていただけると、修正するべき点を教えられるかもしれません。
suzuki さんが書きました:パースからちゃんと勉強したいと思います。

全体がどのようなコードになるのか、早く知って理解したいです。
ヒントをもらわずに自力で勉強したいなら、それでどうぞ。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

かずま

Re: 下記にある「言語ファイル入出力について」のsuzukiです

#7

投稿記事 by かずま » 10年前

fprintf(fp, "%s,%d,%d,%d\n", name, year, month, day)
で書いたものなら、
fscanf(fp, " %[^,],%d,%d,%d", name, &year, &month, &day)
で読めるはずです。fscanf が parse してくれるわけです。
%[ の前のスペースに注意。改行文字の読み飛ばしに必要です。

コード:

#include <stdio.h>
 
struct Data {
    char *name;
    int year, month, day;
};

struct Data data[3] = {
    { "かつお", 2003, 7, 7 },
    { "わかめ", 2005, 3, 3 },
    { "たらお", 2011, 5, 5 },
};

int main(void)
{
    FILE *fp;
    char name[256];
    int year, month, day, i;

    fp = fopen("data.txt", "w");
    if (!fp) return 1;
    for (i = 0; i < 3; i++) {
        struct Data *p = &data[i];
        fprintf(fp, "%s,%d,%d,%d\n", p->name, p->year, p->month, p->day);
    }
    fclose(fp);

    fp = fopen("data.txt", "r");
    if (!fp) return 1;
    while (fscanf(fp, " %[^,],%d,%d,%d", name, &year, &month, &day) == 4)
        printf("%s %d年 %d月 %d日\n", name, year, month, day);
    fclose(fp);
    return 0;
}

閉鎖

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