在理解以下代码时我遇到了一些问题。 如果String的长度小于指定的大小(即' n' here),它是一个从键盘读取字符串的程序。
如果字符串的长度大于指定的大小,则该行上的剩余字符将被丢弃。
更具体地说,我想知道缓冲区内发生了什么以及getchar()
如何读取数据而不是将其存储在缓冲区中。
char * s_gets(char * st, int n)
{
char * ret_val;
int i = 0;
ret_val = fgets(st, n, stdin);
if (ret_val) // i.e., ret_val != NULL
{
while (st[i] != '\n' && st[i] != '\0')
i++;
if (st[i] == '\n')
st[i] = '\0';
else // must have words[i] == '\0'
while (getchar() != '\n')
continue;
}
return ret_val;
}
答案 0 :(得分:0)
代码略有缺陷,但或多或少地完成了概述的工作。它使用fgets()
来完成大量工作。从标准输入读取最多n - 1
个字符。当它返回时,有几种可能性:
fgets()
返回NULL
。st
中。缓冲区包含换行符。案例1最简单:代码返回NULL。通过扫描读取的字符串来处理案例2以查找换行符。如果找到换行符,则会用空字节覆盖它。案例3同时处理;如果找到的值不是换行符,则它必须是空字节。代码进入一个循环,读取更多字符,直到读取换行符。案例4与案例3的效果类似,但是循环中的代码错误地处理了这个问题 - 它没有检测到并处理EOF,因此代码将陷入无限循环。这是一个需要修复的错误。
getchar()
循环未向缓冲区st
分配任何内容 - 它不会对st
进行任何更改。它继续包含由fgets()
读取的空终止字符串。 getchar()
循环读取并丢弃读取的不适合缓冲区的行上剩余的任何字符。
代码应为:
char *s_gets(char *st, int n)
{
assert(n > 1 && st != NULL);
char *ret_val = fgets(st, n, stdin);
if (ret_val != NULL)
{
int i = 0;
while (st[i] != '\n' && st[i] != '\0')
i++;
if (st[i] == '\n')
st[i] = '\0';
else
{
int c;
while ((c = getchar()) != EOF && c != '\n')
continue;
}
}
return ret_val;
}
NULL或原始字符串的返回值与fgets()
使用的相同,但它不是最有用的返回值。如果代码返回它读取的字符串的长度,或者如果它遇到EOF(或读取错误)则返回EOF,这将更有用。信息随时可用 - 变量i
。