【问题标题】:fgets implementation (K&R)fgets 实施 (K&R)
【发布时间】:2013-05-06 11:30:08
【问题描述】:

我是编程新手,从 Objective-C 开始,但我决定在进一步学习之前回到基础。我在 C 语言上花了一些时间,并且在指针混乱中苦苦挣扎。我的问题是关于 K&R 说 fgets 是如何实现的(p165,第 2 版。)下面的代码直接来自我的几个 cmets 的文本。

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,但无法完全弄清楚。谢谢!

【问题讨论】:

  • “从 Objective-C 开始,但决定在进一步发展之前回到基础” - 太好了,每个初学者都应该这样做。
  • 我刚刚开始觉得我在 Obj-C 中取得了某种进展。自从回到 C 语言后,我又觉得自己像个彻头彻尾的笨蛋,但尽管我一再反对分段错误和奇怪的程序行为,但绝对值得付出努力。
  • 绝对值得。掌握 C 对于理解 Objective-C 是不可避免的。

标签: c pointers


【解决方案1】:

这是因为最后一行的检查,cs == s。此比较检查修改后的指针 cs 与原始 s 是否已读取任何字符。如果没有,则返回 NULL。

通过在整个原始指针s 中使用cs 被保留。如果s 被直接操作(*s++ 而不是*cs++),那么我们必须找到另一种方法来检查是否读取了任何字符。

人们也可以争辩说,不理会函数参数并将它们视为const 是一种好习惯。一些程序员遵循这种做法来提高代码的清晰度。

【讨论】:

  • 非常感谢约翰。这使得意图更清晰,但如果我可以的话还有几个问题......当'cs'被分配给'cs = s'时,我认为指针现在指向完全相同的内存区域;因此,执行 '*cs++' 将完全等同于 '*s++'。这个假设是错误的吗?
  • 对不起,我的评论超时了,而且我的评论标记也错误......这就是为什么我不明白最后一行的原因。我认为看到两个指针都是“共享的”,那么当 c==cs 表达式评估时它们将是相同的。提前致谢。
  • @GasMan14 他们在分配后指向同一个地址,这是正确的。不过,*cs++ 不会修改 s。确保您了解优先级:*cs++ 等于 *(cs++) 而不是 (*cs)++cs++ 递增 cs,使其指向下一个地址,然后 * 取消引用该地址。 s 不会更改,因为 scs 是两个单独的变量。如果语句是(*cs)++,那么 更改*s 的值。 (请注意,不是s,而是*s。)
  • 感谢约翰的所有帮助。
  • 如果n 为1,则不读取任何输入,fgets 将第一个字符设置为'\0' 并立即返回。字符串始终以空值结尾。换行符只有在有空间的情况下才会留在末尾;否则,换行符将未被读取,以供下一次 I/O 调用使用。 fgets 无法更改,因为它是标准 C 库的一部分。改变它的行为为时已晚。数以百万计的程序期望它以这种方式运行。
猜你喜欢
  • 1970-01-01
  • 2012-11-06
  • 1970-01-01
  • 1970-01-01
  • 2013-08-05
  • 1970-01-01
  • 2012-07-02
  • 1970-01-01
  • 2016-10-10
相关资源
最近更新 更多