アプリ版:「スタンプのみでお礼する」機能のリリースについて

一週間で身につくC言語というサイトでC言語の勉強をしています。
http://c-lang.sevendays-study.com/problemex4.html
上記URLのprobex7-6. 
以下の、nums.txtには、,(コンマ)で区切られた英単語が入っている。この単語のなかから、"a"で始まる文字列のみを表示し、その数も出力しなさい。
「nums.txt」の内容
apple,orange,angel,lucky
「実行結果」
aから始まる単語
apple
angel
----------
個数:2
この問題がわかりません。。。
今、私が考えているのは、nums.txtにある文字列をそれぞれ配列に格納して
aから始まる単語を読み取るやり方です。
mallocで配列を確保して代入したいのですが、どうもうまく動きません。

#include <stdio.h>
#include <stdlib.h>

#define SIZE 256

void main()
{
FILE* file;
errno_t err;
char line[SIZE];
char* pt = NULL;
int c, i;

err = fopen_s(&file, "C:\\test\\write.txt", "r");
if (err != 0)
{
printf("ファイルが開けません\n");
exit(1);
}

while ((c = fgetc(file)) != EOF)
{
if (c == ',')
{
printf("\n");
}
else
{
pt = (char*)malloc(sizeof(char)*SIZE);
for (i = 0; i < SIZE; i++) {
pt[i] = (char)c;
}
for(i=0;i<SIZE;i++){
printf("%c", pt[i]);
}

}
free(pt);
printf("\n");
}
}

「実行結果」
aaaaaa......a (256個)
ppppp.....p(256個)
ppppp.....p(256個)
llllllll.....l(256個)
eeeee....e(256個)

↑このようにappleの文字がそれぞれ256個表示されるようになってしまいました。
ご教授ください。

A 回答 (4件)

いつfgetc(file)を実行しているのでしょうか。


while()のループ前の判定時に実行していますね。
cの値を呼び出すたびにfgetc()を実行しているわけではないのでwhile(){}の中にあるforループを動かしている間はcの値は変化しません。

せっかくline[]なる配列を作ったのですから、いったんwhileループの先頭で","までの文字列をline[]に格納してから(","が出たらヌル文字\0で終端しておくとprintf("%s",line)で文字列を出力できます)、後の処理に回しましょう。
    • good
    • 0

1もじずつ読み込み、lineにためて行きます。


読み込んだ1文字が改行かカンマなら、その文字を\0に変えて、lineの
内容を印字します。lineの先頭の1文字が'a'ならaのカウンターに1加算します。
#include <stdio.h>
#include <stdlib.h>

#define SIZE 256

void main()
{
FILE *file;
errno_t err;
char line[SIZE];
char *pt = NULL;
int c, i;
int a_ctr;
err = fopen_s(&file, "C:\\test\\write.txt", "r");
if (err != 0) {
printf("ファイルが開けません\n");
exit(1);
}
i = 0;
a_ctr = 0;
while ((c = fgetc(file)) != EOF) {
line[i] = c;
i++;
if (c == ',' || c=='\n') {
line[i-1] = '\0';
printf("%s\n",line);
if (line[0] == 'a'){
a_ctr++;
}
i = 0;
}
}
printf("aで始まる単語の数は%d個\n",a_ctr);
}
    • good
    • 0
この回答へのお礼

皆様、ご回答いただきありがとうございました。
おかげで、なんとか結果表示することが出来ました。

プログラム…面白い…~!!

お礼日時:2020/11/20 08:36

このような場合は状態遷移を整理することをお勧めします。


https://ja.wikipedia.org/wiki/%E7%8A%B6%E6%85%8B …

本件の状態遷移ならば、以下が考えられます。

〇 内部状態
状態1 : 単語の読取前 (初期状態)
状態2 : A単語の読取中
状態3 : 他単語の読捨中
状態4 : 入力終了
〇 状態遷移
状態1 → 状態2 // 'a' が入力された
状態1 → 状態3 // 'a' 以外が入力された
状態2 → 状態1 // カンマが入力された
状態2 → 状態2 // その他が入力された
状態3 → 状態1 // カンマが入力された
状態3 → 状態3 // その他が入力された
全状態 → 状態4 // EOF が入力された
〇 遷移に伴う動作
状態1 → 状態2 // 入力文字をそのまま出力, 個数の変数を加算
状態2 → 状態2 // 入力文字をそのまま出力
状態2 → 状態2以外 // 単語区切りのために改行を出力
全状態 → 状態4 // 個数の報告行を出力

状態遷移が整理できたら、以下のように実装しましょう。

int mode = 1; // 状態の初期値
int aword = 0;
while (true) {
_ c = fgetc(file);
_ if (c == EOF) {
_ _ if (mode == 2) putchar('\n'); // 状態2→4 の遷移に伴う動作
_ _ break; // 状態4 をループ終了で表現
_ }
_ switch (mode) {
_ case 1:
_ _ if (c == 'a') { // 状態1でaが入力された
_ _ _ mode = 2; // 遷移先の状態
_ _ _ aword++; putchar(c); // 遷移に伴う動作
_ _ } else ...
_ _ break;
_ case 2: ...
_ case 3: ...
_ }
}
printf("%d\n", aword);
    • good
    • 0

cが','以外の時は、else以下free(pt);printf("\n");までのところがまとめて実行されるので、実行結果がそうなるのは当然かと。



どのタイミングでmallocを実行して、どのようにpt[i]に代入して、どの条件で内容をprintfし、どのタイミングでfreeを実行するか、をきちんと考えることからですね。
    • good
    • 0

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