循环中 printf 的 Getline 行为

Getline behavior with printf in loop

为什么我需要敲两次回车才能改变当前目录?我注意到,如果我更改循环中 printf 语句的位置,行为就会发生变化。我不明白这是为什么。

下面的工作代码。它在 Ubuntu 系统上编译。它的工作量很小。其中大部分是手册页中的用法。

#define _GNU_SOURCE // http://man7.org/linux/man-pages/man3/getline.3.html
#include <stdio.h>
#include <unistd.h> // http://man7.org/linux/man-pages/man3/getcwd.3.html
int main() {
    char *line = NULL;
    size_t linecap = 0;
    ssize_t linelen;
    while ((linelen = getline(&line, &linecap, stdin)) > 0) {
        char * buf = NULL;
        size_t size = 1000;
        char * s = getcwd(buf, size);
        printf("%s# ", s);
        *(line+linelen-1) = '[=10=]';
        chdir(&line[3]);
    }
    return 0;
}

我没有得到程序的输出,我在下面显示了这一点(首先,我需要按一次回车键来获得提示——这没关系,并且是为这个例子准备的)。

/path/to/dir# cd ..
/path/to/dir# 
/path/to#

您的循环执行以下逻辑:

  • 等待用户输入
  • 打印当前目录
  • 更改当前目录

因此每次输入用户输入时,它都会显示旧目录、更改目录(没有可见输出)然后等待新输入。这确实是您的示例输出显示的内容。

要获得您想要的行为,请移动 getcwd 并向下显示到 chdir 调用下方。

请注意,如果此人随后输入了一个短于 3 的字符串(例如,他们再次按下 Enter,我在测试时做了,你也是),你仍然会继续调用 chdir(&line[3]);,导致意外结果(可能UB) 因为这已经过了字符串的末尾。在我的系统上它重复了 chdir("..")。要解决此问题,您可能应该检查 linelen >= 3(并且它确实以 cd 开头),如果不是,则不要调用 chdir