chq*_*lie 3 c newline fgets strtok
fgets()是一个读取一行输入的安全函数,但它会将从文件中读取的新行字节存储'\n'在数组中(如果合适的话)。
在许多情况下(如果不是大多数情况),必须在进一步处理行内容之前删除此新行。
可以使用几种简单的方法,但我看到了一个紧凑而棘手的建议:
strtok(line, "\n"); // strip the newline
Run Code Online (Sandbox Code Playgroud)
为什么这种方法不正确,为什么它并不总是有效?
该方法很棘手,因为该strtok()函数对全局隐藏状态变量有副作用。这可能会影响周围的代码并证明难以调试。
此外,有一种简单的情况strtok(line, "\n")不会'\n'用空字节覆盖:如果读取的行fgets()是仅包含单个新行字节的空行。对于此内容,strtok()将跳过初始的新行,搜索不存在的不同字符,并返回NULL 不修改数组。因此它不会剥离新行。
这是不用于strtok(line, "\n")剥离新行字节的一个令人信服的理由。
当然,可以通过编写以下内容来解决此问题:
if (*line == '\n')
*line = '\0';
else
strtok(line, "\n");
Run Code Online (Sandbox Code Playgroud)
或繁琐的单线:
(void)(*line == '\n' ? (*line = '\0') : (strtok(line, "\n"), 0);
Run Code Online (Sandbox Code Playgroud)
if (!strtok(line, "\n")) *line = '\0';
Run Code Online (Sandbox Code Playgroud)
(void)(strtok(line, "\n") || (*line = '\0'));
Run Code Online (Sandbox Code Playgroud)
但是代码不再紧凑,仍然有其他副作用。
其他方法可用:
使用显式for语句:
for (char *p = line; *p; p++) {
if (*p == '\n')
*p = '\0';
}
Run Code Online (Sandbox Code Playgroud)
使用strlen():
size_t len = strlen(line);
if (len > 1 && line[len - 1] == '\n') {
line[--len] = '\0';
}
// len is the length if the stripped line
Run Code Online (Sandbox Code Playgroud)
使用strchr():
char *p = strchr(line, '\n');
if (p) {
*p = '\0';
}
Run Code Online (Sandbox Code Playgroud)
使用strcspn()在一衬垫:
line[strcspn(line, "\n")] = '\0'; // strip the newline if any.
Run Code Online (Sandbox Code Playgroud)