随后调用fgets函数c得不到预期的结果

时间:2017-09-28 07:08:05

标签: c arrays string fgets

我只是在尝试一个随机代码,发现了一个奇怪的问题。这是我的代码

#include<stdio.h>
int main(void) {
char name[6],name2[6];
fgets(name,100,stdin);
fgets(name2,100,stdin);
printf("%s\n",name);
printf("%s\n",name2);
return 0;
}

此代码仅打印我在name2数组中提供的输入,并且它不打印名称数组

例如:输入

abcdef
zyxwvu

代码只打印下面的字符串

zyxwvu

另一个问题:如果我给第二个大于大小的字符串。例如:

abcdef
zyxwvug      // name2 is defined to be 6 characters and I have given 7 here

然后打印:

g
zyxwvug 

请帮助我了解最新情况。我在代码上使用Gcc编译器:块IDE:)

1 个答案:

答案 0 :(得分:0)

正如评论中所指出的,您的问题来自fgets的使用。

<强>与fgets

如果我们阅读fgets manual

  

fgets()从流中读取最多一个一个大小字符,并将它们存储到s指向的缓冲区中。读数在EOF或换行符后停止。如果读取换行符,则将其存储到缓冲区中。终止空字节(\0)存储在缓冲区中的最后一个字符之后。

这是什么意思?

当你写fgets(name, 100, stdin);时,假设:

  • 数据将从stdin
  • 中读取
  • 数据将存储在name
  • 最多99个字符将从stdin读取并存储到name
  • \0字符将被添加到name

字符串

这是什么意思,我们试着读100个字符,我们只得到99?

这是由于C中的字符串存储:字符串是字符的续集,以\0结尾。

使用这个事实,函数和人们都知道字符串有多长。

考虑strlenstrcpy函数。

例如:

/* this string is valid: we explictily terminate it */
char valid_string[5] = {'g', 'o', 'o', 'd', '\n'};

/* this string is not: we do not know what is after the 'd' in memory
   the next '\0' can be far away... */
char valid_string[3] = {'b', 'a', 'd'};

您的问题

所以你的问题如下:

  • 你保留两个数字为\0的6个字符的数组,你只能在这些字符串中存储5个字符
  • 你告诉fgets你可以在你的字符串中使用100个字符。

运行程序时,如果你给:

  • 4个字符或更少字符串(例如:&#34; abcd&#34;):这将有效,fgetsabcd\n\0写入name
  • 5个字符串或更多字符串:您将有一个未定义的行为:额外的字符将存储在字符串之后,正如您所注意到的:当您为第二个字符串提供zyxwvug时,第一个字符串已经过了写...

如何修复

#include<stdio.h>

#define STRING_SIZE 6
#define STRING_SIZE_INCLUDING_FINAL_0 (STRING_SIZE+1)

int main(void) {
    /* defines array to store what we want (6 char string here) */
    char name[STRING_SIZE_INCLUDING_FINAL_0];
    char name2[STRING_SIZE_INCLUDING_FINAL_0];

    /* use fgets we right way:
       fgets is told what is the size of my arrays.
       Warning, this sizeof operation won't work with pointers... */
    fgets(name, sizeof name, stdin);
    fgets(name2, sizeof name2, stdin);

    /* display the result */
    printf("'%s'\n",name);
    printf("'%s'\n",name2);
    return 0;
}