fgets实现(K&R)

11

我是编程新手,从Objective-C入手,但决定在进一步学习之前回归基础。我花时间学习C语言,并且正在努力理解指针。我的问题是关于K&R如何实现fgets(第二版p165)。下面的代码直接来自文本,并带有我的几点评论。

char* fgets(char* s, int n, FILE *iop)
{
    register int c;
    register char* cs;
    cs = s;

    while(--n > 0 && (c = getc(iop)) != EOF)
    {
    // put the input char into the current pointer position, then increment it
    // if a newline entered, break
    if((*cs++ = c) == '\n')
        break;          
    }

    *cs = '\0';
    return (c == EOF && cs == s) ? NULL : s;
}

1) 我们将一个 char* s 传递给 fgets 函数,将用户输入存储在其位置。为什么需要声明本地 char* cs - 然后将其初始化为 s?为什么不能在 if 语句内直接操作/添加到 s 中?既然 cs 初始化为指向 s,那么将字符添加到 cs 中不就是完全相同的事情吗?

2) 与上述内容有关...当函数返回时,会进行一个测试以查看 cs == s。为什么有必要这样做?

我认为我可能缺少非常基础的东西 - 我确实检查了 SO 和 Google,但无法完全弄清楚。谢谢!


2
从Objective-C开始,但决定在进一步学习之前回归基础,这很好,每个初学者都应该这样做。 - user529758
1
我刚开始感觉自己在 Obj-C 方面有所进步。回到 C 后,我又感觉自己像个新手一样笨拙了。但是,尽管我不断地遇到分段错误和奇怪的程序行为,但这绝对值得努力。 - cortexlock
这非常值得。掌握C语言对于理解Objective-C来说是必不可少的。 - user529758
1个回答

8
这是因为最后一行的检查,cs == s。这个比较检查修改后的指针cs与原始的s是否相同,以确定我们是否读取了任何字符。如果没有,则返回NULL。
通过使用cs,原始指针s得到保留。如果直接操作s(使用*s++而不是*cs++),那么我们就必须找到另一种方法来检查是否读取了任何字符。
有人也可以认为,将函数参数保持不变并将它们视为const是一个好习惯。一些程序员遵循这种做法来增强代码的清晰度。

非常感谢John。这使意图更加清晰,但如果可以的话,我还有几个问题...当'cs'被赋值为'cs = s'时,我认为指针现在指向完全相同的内存区域;因此执行'*cs++'将完全等同于'*s++'。这种假设是错误的吗? - cortexlock
抱歉我的评论超时了,而且我也在错误地进行评论标记... 这就是为什么我没有理解最后一行的原因。我认为既然两个指针都是“共享”的,那么当c==cs表达式评估时它们将是相同的。提前致谢。 - cortexlock
@JohnKugelman 为什么他们使用了 register int c; register char* cs;?而不是 int cchar* cs - noufal
1
如果 n 为1,则不会读取任何输入,fgets 将第一个字符设置为 '\0' 并立即返回。该字符串始终以空字符结尾。仅当有足够的空间时,换行符才会留在末尾;否则,换行符将保留未读取,以供下一个 I/O 调用使用。fgets 无法更改,因为它是标准 C 库的一部分。现在改变其行为为时已晚。数百万程序都期望它以这种方式运行。 - John Kugelman
1
@rootkea 是的,你说得对。我不知道为什么用那种措辞。我应该说 * 解引用 前一个地址 - John Kugelman
显示剩余5条评论

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