fgetsを使った文字読み出し

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Yuuuu
記事: 1
登録日時: 4年前

fgetsを使った文字読み出し

#1

投稿記事 by Yuuuu » 4年前

質問させてください。現在テキストファイルをStdinで読み込んでいてそれをFgets関数を使って一行ずつ読み込み
配列に入れて全行読み込んでいます
条件としてはテキストの文字数は236文字以内行数は500行です。下の通りのプログラミングを書いたのですが一行しか読みこまれずこまっています。。
全行読めるように添削して頂けませんか?
もう一つ質問があります。
例えばFgetsを使ってある行の最初の文字が空欄の場合配列の最初の中身は空欄になりますか?
もしくは文字がでてきたらそれを一番最初にいれますか?
回答お願いいたします。

ファイルの


#include <stdio.h>
#include <stdlib.h>
#define N 236
int main(int argc, const char * argv[]) {
char array[N];
while(fgets(array,sizeof(char)*N,stdin) != NULL){
fprints("%s",array);
}
return 0;
}

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

Re: fgetsを使った文字読み出し

#2

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

Yuuuu さんが書きました:
4年前
条件としてはテキストの文字数は236文字以内行数は500行です。下の通りのプログラミングを書いたのですが一行しか読みこまれずこまっています。。
全行読めるように添削して頂けませんか?
あなたのコードの問題点は、以下のとおりです。

まず、arrayの要素数が足りません。
ここで扱う「文字」が1バイトで表せる文字のみであると仮定しても、
236要素しか無いので236文字の行を入れるには改行文字と終端文字分の2要素が足りません。
また、例えばUTF-8では1文字を最大4バイトで表すので、これを扱うのであれば要素が4倍必要です。
さらに、複数の文字を合成してできる絵文字などを1文字としてカウントするのであれば、さらに多くの要素が必要でしょう。

次に、非標準の識別子fprintsが定義なしで使われています。
文脈から、ここはかわりにprintfを使うべきでしょう。

fprintsをprintfにマクロ定義してコンパイルしたところ、入力の全ての行を読み込むことができました。
https://wandbox.org/permlink/J0QyJABh8RiXB98D
※1バイトの文字が235個や236個ある行も読み込めているように見えますが、
 一度に読み込むには配列の要素数が足りず、2回に分けて読み込まれています

fprintsが使われているため、普通はコンパイル(ここではリンクなども含めた実行ファイルを作る処理)ができず、
実行もできないため、1行も読み込めないはずです。
あなたがコンパイル・実行しているコードが意図したものであること、および最新のものであることを確認するべきでしょう。
もしくは、読み込んだ行を全てメモリ上に保持したい、ということでしょうか?

ちなみに、あなたが書いたものはプログラミングではなくプログラムです。
プログラムを書くことを、プログラミングといいます。
Yuuuu さんが書きました:
4年前
もう一つ質問があります。
例えばFgetsを使ってある行の最初の文字が空欄の場合配列の最初の中身は空欄になりますか?
もしくは文字がでてきたらそれを一番最初にいれますか?
「文字が空欄」というのは意味がよくわかりませんが、空行も空白文字もそのまま読み込まれます。
Yuuuu さんが書きました:
4年前
ファイルの
意味がわかりません。コピペミス、消し忘れ、もしくは途中で送信してしまったのでしょうか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: fgetsを使った文字読み出し

#3

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

読み込んだ行を全てメモリ上に保持するバージョンを作ってみました。
エラー時のメモリ開放は省略しています。

コード:

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

int main(int argc, const char * argv[]) {
    char** array = NULL;
    size_t current_line = 0;
    char* line = NULL;
    size_t line_length = 0;
    char buffer[256];
    while(fgets(buffer,sizeof(buffer),stdin) != NULL){
        /* 行の読み込みを進める */
        size_t len = strlen(buffer);
        line = realloc(line,line_length + len + 1);
        if(line == NULL) return 1;
        strcpy(line + line_length,buffer);
        line_length += len;
        /* 行の区切りを処理する */
        if(strchr(buffer,'\n') != NULL) {
            /* 読み込んだ行を登録して */
            array = realloc(array,sizeof(*array) * (current_line + 1));
            if(array == NULL) return 1;
            array[current_line++] = line;
            /* 次の行を読み込むために初期化する */
            line = NULL;
            line_length = 0;
        }
    }
    /* 最後に残った行を登録する */
    if(line != NULL) {
        array = realloc(array,sizeof(*array) * (current_line + 1));
        if(array == NULL) return 1;
        array[current_line++] = line;
    }

    /* 読み込んだ行を出力する */
    {
        size_t i;
        for(i = 0; i < current_line; i++) {
            printf("%3u: %s", (unsigned int)i, array[i]);
        }
    }

    /* 読み込んだデータを開放する */
    {
        size_t i;
        for(i = 0; i < current_line; i++) {
            free(array[i]);
        }
        free(array);
    }

    return 0;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

返信

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