スポンサーリンク

| キーワード:

C/C++ fgetsで一行読み込む

fgetsで一行取得するサンプルは多数あるのだけれど一行がバッファサイズ超えたらどうするのというサンプルがあまりなかった。というか意味をなさないのだろうけれど。

呼び出し元

int main()
{
  char* txt = new char[1024];

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

  bool readable = true;
  while(readable){

    read_1_line(txt, fp);//一行読み込み

    printf("%s\n", txt);

    readable = feof(fp) == 0;

  }
  getchar();

  delete[] txt;
    return 0;
}

一行読み込み関数

関数本体

バッファサイズが小さいので大抵は一行に収まりきらず複数回fgetsが走る。そしてfgetsがnullptrを返すか、読み込んだ文字列の最後が"\n\0"という並びの時だけループを抜ける。

#include <cstring>

void read_1_line(char* txt, FILE* fp) {
  txt[0] = '\0';

  const int BUF_SIZE = 10;//バッファサイズが小さい
  char buffer[BUF_SIZE];

  while(fgets(buffer, BUF_SIZE, fp) ){

    strcat(txt, buffer);
    char* p = strchr(txt, '\n');//改行の削除
    if (p) {
      *p = '\0';
      break;
    }

  }
}

fgetsの挙動と改行の削除

fgetsは改行までを一行と見なして読み込む。大抵は改行が最後に入るのだが入らないこともあるのでこの方法をとる。

(参考)FIO36-C. fgets() が改行文字を読み取ると仮定しない

バッファサイズが10,読み込み文字がそれぞれ以下の時のfgetsで読み込まれる内容。

ファイル内の一行の文字一回目二回目コメント
01234567--一回で読み込める。
最後に改行
末尾は'\0'
012345678二回にわたって読み込む。
一回目に改行は入らない。
二回目は、一回目で読めなかった'\n'だけが読み込まれる
末尾は [1] 0 '\0' となりnull終端
0123456789 二回にわたって読み込む。
一回目に改行は入らない。
二回目は、一回目で読めなかった'9' '\n'
末尾は [2] 0 '\0' となりnull終端

C++のstring型に結合するように変更

このままでは結局引数txtの要素数に依存してしまうので、結果をどんどんstring型変数へ結合していく。

std::string read_1_line(FILE* fp) {

  std::string str;

  const int BUF_SIZE = 10;
  char buffer[BUF_SIZE];

  while (fgets(buffer, BUF_SIZE, fp)) {

    char* p = strchr(buffer, '\n');
    if (p) {
      *p = '\0';
    }
    str += buffer;

    if (p)break;
  }

  return str;//コピーコスト?知らん。
}

もっともこれをやりだすとそもそもfgetsを使う必要云々という議論に発展する気がする。でもfstreamは嫌いだ。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: