fgets()
改行まで読み取り、改行を文字列に保持し、出力するためにputs()
指定された文字列に常に改行を追加します。したがって、コードで使用すると、ダブルスペースの出力が得られます。
fputs(str, stdout)
の代わりに使用しputs()
ます。改行を追加しません。
廃止された関数gets()
— C 標準の 2011 バージョンから削除されました — は改行まで読み取りますが、それを削除しました。gets()
とのputs()
ペアは、 と のようにうまく連携しましfgets()
たfputs()
。ただし、絶対に使用しないでくださいgets()
。それは起こるのを待っている大惨事です。(1988 年gets()
に移行した最初のインターネット ワーム — Google で「morris インターネット ワーム」を検索)。
コメントで、審問官は次のように尋ねました。
行を特定のサイズの char 配列に読み込む必要があるのはなぜですか?
利用可能なスペースをオーバーランしないようにする必要があるためです。C は、文字列のスペースの自動割り当てを行いません。これは、いくつかの観点から見ると、その弱点の 1 つです。それは強みでもありますが、言語の初心者を日常的に混乱させます。入力コードで 1 行に十分なスペースを割り当てたい場合は、POSIX 関数を使用しますgetline()
。
'\0'
特定の行の文字数が常にわかるとは限らないので、ヒットするまで読み取りと出力を行う方がよいでしょうか?
いいえ、一般的にはヒットしません'\0'
。ほとんどのテキスト ファイルには、これらのいずれも含まれていません。行に十分なスペースを割り当てたくない場合は、次を使用します。
int c;
while ((c = getchar()) != EOF)
putchar(c);
これはユーザー コードで一度に 1 文字を読み取りますが、基礎となる標準 I/O パッケージが入力をバッファリングするため、それほどコストがかからず、プログラムをそのように実装することは完全に実現可能です。行で作業する必要がある場合は、行に十分なスペースを割り当てるか (私はchar buffer[4096];
日常的に使用しています) getline()
、.
そして、チャーリー・バーンズはコメントで尋ねました:
getline() がもっと頻繁に提案されないのはなぜですか?
getline()
比較的新しく、まだどこでも利用できるとは限らないため、あまり言及されていないと思います。POSIX 2008 に追加されました。Linux および BSD で使用できます。他の主要な Unix バリアント (AIX、HP-UX、Solaris) についてはよくわかりません。自分で書くのは難しくありませんが (私はそれをやったことがあります)、移植可能なコードを書く必要がある場合 (特に「移植可能」に「Microsoft」が含まれる場合) は厄介です。そのメリットの 1 つは、読み取った行が実際にどれくらいの長さだったかがわかることです。
使用例getline()
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
char *line = 0;
size_t length = 0;
char const name[] = "/myFile/path/test.txt";
FILE *file = fopen(name, "r");
if (file == NULL)
{
fprintf(stderr, "%s: failed to open file %s\n", argv[0], name);
return -1;
}
while (getline(&line, &length, file) > 0)
fputs(str, stdout);
free(line);
fclose(file);
return 0;
}