C语言 使用 fgets 从 C 文件中读取字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2531629/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 04:58:46  来源:igfitidea点击:

Using fgets to read strings from file in C

cstringfile-io

提问by Ivan

I am trying to read strings from a file that has each string on a new line but I think it reads a newline character once instead of a string and I don't know why. If I'm going about reading strings the wrong way please correct me.

我试图从一个文件中读取字符串,每个字符串都在一个新行上,但我认为它读取一个换行符而不是一个字符串,我不知道为什么。如果我打算以错误的方式阅读字符串,请纠正我。

    i=0;
F1 = fopen("alg.txt", "r"); 
F2 = fopen("tul.txt", "w"); 
     if(!feof(F1)) {
     do{ //start scanning file
     fgets(inimene[i].Enimi, 20, F1);
     fgets(inimene[i].Pnimi, 20, F1);
     fgets(inimene[i].Kood, 12, F1);
     printf("i=%d\nEnimi=%s\nPnimi=%s\nKaad=%s",i,inimene[i].Enimi,inimene[i].Pnimi,inimene[i].Kood);
     i++;}
     while(!feof(F1));};
/*finish getting structs*/

The printf is there to let me see what was read into what and here is the result

printf 在那里让我看看读到了什么,这是结果

i=0
Enimi=peter

Pnimi=pupkin

Kood=223456iatb i=1
Enimi=

Pnimi=masha

Kaad=gubkina
i=2
Enimi=234567iasb

Pnimi=sasha

Kood=dudkina

As you can see after the first struct is read there is a blank(a newline?) onct and then everything is shifted. I suppose I could read a dummy string to absorb that extra blank and then nothing would be shifted, but that doesn't help me understand the problem and avoid in the future.

正如您在读取第一个结构后所看到的那样,有一个空白(换行符?) onct 然后一切都被转移了。我想我可以读取一个虚拟字符串来吸收额外的空白,然后什么都不会移动,但这并不能帮助我理解问题并在未来避免。

Edit 1: I know that it stops at a newline character but still reads it. I'm wondering why it doesn't read it during the third string and transfers to the fourth string instead of giving the fourth string the fourth line of the source but it happens just once. The file is formatted like this by the way

编辑 1:我知道它停在换行符处,但仍会读取它。我想知道为什么它不在第三个字符串中读取它并转移到第四个字符串而不是将源的第四行提供给第四个字符串,但它只发生一次。文件格式是这样的

peter 
pupkin 
223456iatb 
masha 
gubkina 
234567iasb 
sasha 
dudkina 
123456iasb 

回答by James McNellis

fgetsstops reading when it reads a newline, but the newline is considered a valid character and is included in the returned string.

fgets在读取换行符时停止读取,但换行符被视为有效字符并包含在返回的字符串中。

If you want to remove it, you'll need to trim it yourself:

如果你想删除它,你需要自己修剪它:

length = strlen(str);
if (str[length - 1] == '\n') 
    str[length - 1] = '
Kood=223456iatb i=1
               ^
';

Where stris the string into which you read the data from the file, and lengthis of type size_t.

str从文件中读取数据的字符串在哪里length,类型为size_t.

To answer the edit to the question: the reason the newline is not read during the third read is because you are not reading enough characters. You give fgetsa limit of 12 characters, which means it can actually read a maximum of 11 characters since it has to add the null terminator to the end.

回答对问题的编辑:在第三次阅读期间未读取换行符的原因是因为您没有阅读足够的字符。您给出fgets了 12 个字符的限制,这意味着它实际上最多可以读取 11 个字符,因为它必须在末尾添加空终止符。

The line you read is 11 characters in length before the newline. Note that there is a space at the end of that line when you output it:

您阅读的行在换行符之前的长度为 11 个字符。请注意,输出时该行末尾有一个空格:

while (fgets(inimene[i].Enimi, 20, F1) != 0 &&
       fgets(inimene[i].Pnimi, 20, F1) != 0 &&
       fgets(inimene[i].Kood,  12, F1) != 0)
{
    printf("i=%d\nEnimi=%s\nPnimi=%s\nKaad=%s", i, inimene[i].Enimi, inimene[i].Pnimi, inimene[i].Kood);
    i++;
}

回答by Jonathan Leffler

As already stated, if there's enough room in the buffer, then fgets()reads the data including the newline into the buffer and null terminates the line. If there isn't enough room in the buffer before coming across the newline, fgets()copies what it can (the length of the buffer minus one byte) and null terminates the string. The library resumes reading from where fgets()left off on the next iteration.

如前所述,如果缓冲区中有足够的空间,则将fgets()包括换行符在内的数据读入缓冲区,而 null 将终止该行。如果在遇到换行符之前缓冲区中没有足够的空间,则fgets()复制它可以复制的内容(缓冲区的长度减去一个字节)并且 null 终止字符串。库fgets()在下一次迭代中从停止的地方继续读取。

Don't mess with buffers smaller than 2 bytes long.

不要弄乱长度小于 2 字节的缓冲区。

Note that gets()removes the newline (but does not protect you from buffer overflows, so do not use it). If things go as currently planned, gets()will be removed from the next version of the C standard; it will be a long time before it is removed from C libraries (it will just become a non-standard - or ex-standard - additional function available for abuse).

请注意,gets()删除换行符(但不能保护您免受缓冲区溢出的影响,因此请勿使用它)。如果事情按目前的计划进行,gets()将从下一个版本的 C 标准中删除;它需要很长时间才能从 C 库中删除(它将只是成为一个非标准 - 或前标准 - 可供滥用的附加功能)。

Your code should check each of the fgets()function calls:

您的代码应该检查每个fgets()函数调用:

while( fgets(inimene[i].Enimi,sizeof inimene[i].Enimi,F1) &&
       fgets(inimene[i].Pnimi,sizeof inimene[i].Pnimi,F1) &&
       fgets(inimene[i].Kood,sizeof inimene[i].Kood,F1) )
{
if( strchr(inimene[i].Enimi,'\n') ) *strchr(inimene[i].Enimi,'\n')=0;
if( strchr(inimene[i].Pnimi,'\n') ) *strchr(inimene[i].Pnimi,'\n')=0;
if( strchr(inimene[i].Kood,'\n') ) *strchr(inimene[i].Kood,'\n')=0;
printf("i=%d\nEnimi=%s\nPnimi=%s\nKaad=%s", i, inimene[i].Enimi, inimene[i].Pnimi,inimene[i].Kood);
    i++;
}

There are places for do/while loops; they are not used very often, though.

有用于 do/while 循环的地方;不过,它们并不经常使用。

回答by codaddict

the fgets function reads newline char as a part of the string read.

fgets 函数读取换行符作为读取的字符串的一部分。

From the description of fgets:

fgets描述

The fgets() function shall read bytes from stream into the array pointed to by s, until n-1 bytes are read, or a newline is read and transferred to s, or an end-of-file condition is encountered. The string is then terminated with a null byte.

fgets() 函数应从流中读取字节到 s 指向的数组中,直到读取 n-1 个字节,或者读取换行符并将其传输到 s,或者遇到文件结束条件。然后该字符串以空字节终止。

回答by user411313

if Enimi/Pnimi/Kood are arrays not pointers:

如果 Enimi/Pnimi/Kood 是数组而不是指针:

##代码##