fgets最大可读取大小

3

使用 fgets 输入一个字符串,我对读取的字符串长度有疑问。

例如,考虑以下程序。

char str[50];
int i;
int len;
printf("Enter name:\n");
fgets(str,11,stdin);
len = strlen(str);
printf("len :  %d\n",len);
  1. 如果我输入123456789strlen会返回10。

  2. 如果我输入1234567890strlen仍然返回10?

我认为strlen也将换行符考虑在内了。我是正确的吗? (我知道fgets将换行符作为字符串的一部分)

当我输入恰好10个字符时,第二个例子有什么问题?这里字符串长度应该是11对吧?10 + 1(换行符)= 11


printf("len : %d",len); printf("str : %s",str); printf("hi");return 0; } 添加一些打印语句有助于澄清下面给出的答案。请注意 "hi" 的输出。 - kumar
3个回答

4

fgets函数最多读取比给定长度参数小1个字符,并且保留换行符作为输入的一部分,只要换行符是前(length - 1)个字符之一。

因此,在您的第一种情况下,假设123456789后面跟着一个换行符,fgets已经读取了包括换行符在内的9个字符,产生长度为10的字符串;在您的第二种情况下,fgets将在读取10个字符1234567890后停止,产生长度为10的字符串。


1
小修正:如果 #/字符 >= 最大长度,它将不会保留换行符。如下面的示例所示。 - paulsm4
1
@paulsm4 我相信从我的第一行已经很清楚了:_最多读取比给定长度参数少1个字符_。 - pb2q

3

这里有一个例子:

#include <stdio.h>
#include <string.h>

#define MAX_DIGITS 5

int
main ()
{
  char buf[80];
  char *s = NULL;
  printf ("\n>>Enter string, %d digits or less: ", MAX_DIGITS);
  s = fgets (buf, MAX_DIGITS+1, stdin);
  printf ("strlen(buf)=%d, buf=%s, strlen(s)=%d, s=%s\n",
    strlen(buf), buf, strlen(s), s);
  return 0;
}

以下是示例输出,包括“MAX_DIGITS”和“MAX_DIGITS + 1”:

>>Enter string, 5 digits or less: 1
strlen(buf)=2, buf=1
, strlen(s)=2, s=1
.

>>Enter string, 5 digits or less: 12
strlen(buf)=3, buf=12
, strlen(s)=3, s=12
.

>>Enter string, 5 digits or less: 123
strlen(buf)=4, buf=123
, strlen(s)=4, s=123
.

>>Enter string, 5 digits or less: 1234
strlen(buf)=5, buf=1234
, strlen(s)=5, s=1234
.

>>Enter string, 5 digits or less: 12345
strlen(buf)=5, buf=12345, strlen(s)=5, s=12345.

>>Enter string, 5 digits or less: 123456
strlen(buf)=5, buf=12345, strlen(s)=5, s=12345.

你会注意到:
  1. 当 #/digits < MAX_DIGITS 时,返回缓冲区会保留 "\n"。

  2. 当 #/digits >= MAX_DIGITS 时,"\n" 将被移除。

  3. 你的缓冲区必须能够容纳 MAX_DIGITS+1。


你的缓冲区必须能够容纳MAX_DIGITS+1个字符。因此,缓冲区应该有足够的空间来存储换行符,即+1。感谢您的帮助。 - kumar
@kumar 为了存储换行符,应该将其设置为 +2,因为 fgets 已经减去了一个用于存储空终止符值 -> '\0';也就是说,如果你传递的是 6,它最多会读取 5 个字符(4 个数字 + CR 或 5 个数字)。如果你传递的是 7,它将读取 5 个数字加上一个回车符。 - Scooter

-1
实际上,fgets需要一个size参数(在您的情况下为11),以便考虑字符串末尾的\0。从fgets手册页中可以看到:

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

因此,我们知道当您输入123456789\n时,读取会在\n处停止。然而,当您输入1234567890\n时,fgets()会处理输入,但它只取前10个字符并忽略后面的所有内容。
如果您的字符串有额外的输入,那么您的字符串将在fget()size-1处,并且最后一个字符为\0,因此输出保持不变。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接