私はCISクラスの小さな演習に取り組んできましたが、Cがファイルから読み取るために使用する方法に非常に混乱しています。本当に必要なのは、ファイルを1行ずつ読み取り、各行から収集した情報を使用していくつかの操作を行うことです。私はgetlineメソッドなどを運が悪かったので試してみました。私のコードは現在次のとおりです。
int main(char *argc, char* argv[]){
const char *filename = argv[0];
FILE *file = fopen(filename, "r");
char *line = NULL;
while(!feof(file)){
sscanf(line, filename, "%s");
printf("%s\n", line);
}
return 1;
}
現在、sscanfメソッドでsegフォールトが発生していますが、その理由はわかりません。私は完全なC初心者であり、私が見逃していた大きな画像があるかどうか疑問に思っています。ありがとう
非常に少数の行で非常に多くの問題。私はおそらくいくつかを忘れます:
そう
#include <stdio.h>
int main(int argc, char* argv[])
{
char const* const fileName = argv[1]; /* should check that argc > 1 */
FILE* file = fopen(fileName, "r"); /* should check the result */
char line[256];
while (fgets(line, sizeof(line), file)) {
/* note that fgets don't strip the terminating \n, checking its
presence would allow to handle lines longer that sizeof(line) */
printf("%s", line);
}
/* may check feof here to make a difference between eof and io failure -- network
timeout for instance */
fclose(file);
return 0;
}
ファイルから行を読み取るには、fgets
関数を使用する必要があります。指定されたファイルから、改行文字またはEOF
までの文字列を読み取ります。
sscanf
を定数文字列リテラル%s
に読み込むためのフォーマット文字列としてfilename
を使用するため、コードでline
を使用してもまったく機能しません。
SEGVの理由は、line
が指す未割り当てメモリに書き込むためです。
\t
改行ではなく、\n
タブなどの他の区切り文字を扱っているとします。
区切り文字へのより一般的なアプローチは、 getc()
の使用です。これは、一度に1文字を取得します。
getc()
はint
を返すため、EOF
との等価性をテストできます。
次に、最大line[BUFFER_MAX_LENGTH]
文字をスタックに格納するために、タイプchar
の配列BUFFER_MAX_LENGTH-1
を定義します(最後の文字を\0
ターミネータ文字として保存する必要があります)。
配列を使用すると、malloc
およびfree
を使用してヒープ上に適切な長さの文字ポインターを作成する必要がなくなります。
#define BUFFER_MAX_LENGTH 1024
int main(int argc, char* argv[])
{
FILE *file = NULL;
char line[BUFFER_MAX_LENGTH];
int tempChar;
unsigned int tempCharIdx = 0U;
if (argc == 2)
file = fopen(argv[1], "r");
else {
fprintf(stderr, "error: wrong number of arguments\n"
"usage: %s textfile\n", argv[0]);
return EXIT_FAILURE;
}
if (!file) {
fprintf(stderr, "error: could not open textfile: %s\n", argv[1]);
return EXIT_FAILURE;
}
/* get a character from the file pointer */
while(tempChar = fgetc(file))
{
/* avoid buffer overflow error */
if (tempCharIdx == BUFFER_MAX_LENGTH) {
fprintf(stderr, "error: line is too long. increase BUFFER_MAX_LENGTH.\n");
return EXIT_FAILURE;
}
/* test character value */
if (tempChar == EOF) {
line[tempCharIdx] = '\0';
fprintf(stdout, "%s\n", line);
break;
}
else if (tempChar == '\n') {
line[tempCharIdx] = '\0';
tempCharIdx = 0U;
fprintf(stdout, "%s\n", line);
continue;
}
else
line[tempCharIdx++] = (char)tempChar;
}
return EXIT_SUCCESS;
}
char *
を使用する必要がある場合でも、このコードを使用できますが、行の入力に満たされると、line[]
配列をstrdup()
使用できます。 free
この重複した文字列を使い終わったら、メモリリークが発生します。
#define BUFFER_MAX_LENGTH 1024
int main(int argc, char* argv[])
{
FILE *file = NULL;
char line[BUFFER_MAX_LENGTH];
int tempChar;
unsigned int tempCharIdx = 0U;
char *dynamicLine = NULL;
if (argc == 2)
file = fopen(argv[1], "r");
else {
fprintf(stderr, "error: wrong number of arguments\n"
"usage: %s textfile\n", argv[0]);
return EXIT_FAILURE;
}
if (!file) {
fprintf(stderr, "error: could not open textfile: %s\n", argv[1]);
return EXIT_FAILURE;
}
while(tempChar = fgetc(file))
{
/* avoid buffer overflow error */
if (tempCharIdx == BUFFER_MAX_LENGTH) {
fprintf(stderr, "error: line is too long. increase BUFFER_MAX_LENGTH.\n");
return EXIT_FAILURE;
}
/* test character value */
if (tempChar == EOF) {
line[tempCharIdx] = '\0';
dynamicLine = strdup(line);
fprintf(stdout, "%s\n", dynamicLine);
free(dynamicLine);
dynamicLine = NULL;
break;
}
else if (tempChar == '\n') {
line[tempCharIdx] = '\0';
tempCharIdx = 0U;
dynamicLine = strdup(line);
fprintf(stdout, "%s\n", dynamicLine);
free(dynamicLine);
dynamicLine = NULL;
continue;
}
else
line[tempCharIdx++] = (char)tempChar;
}
return EXIT_SUCCESS;
}