为啥要使用 strtok(line, "\n") **not** 来去除 fgets() 留下的换行符
Posted
技术标签:
【中文标题】为啥要使用 strtok(line, "\\n") **not** 来去除 fgets() 留下的换行符【英文标题】:Why should strtok(line, "\n") **not** be used to strip the newline left by fgets()为什么要使用 strtok(line, "\n") **not** 来去除 fgets() 留下的换行符 【发布时间】:2021-01-25 22:12:52 【问题描述】:fgets()
是读取输入行的安全函数,但它将从文件中读取的 新行 字节 '\n'
存储在数组中(如果合适)。
在许多情况下,如果不是大多数情况下,此新行必须在进一步处理行内容之前被删除。
可以使用几种简单的方法,但我看到了一个紧凑而棘手的建议:
strtok(line, "\n"); // strip the newline
为什么这种方法不正确,为什么它并不总是有效?
【问题讨论】:
密切相关:Removing trailing newline character from fgets() input. @FredLarson:有趣的参考。我专门针对我最近多次看到的strtok()
的滥用。
是的,这是我链接的问题的已接受答案的一部分。
【参考方案1】:
该方法很棘手,因为strtok()
函数对全局隐藏状态变量有副作用。这可能会影响周围的代码并证明难以调试。
此外,还有一个简单的情况,strtok(line, "\n")
不会用空字节覆盖'\n'
:如果fgets()
读取的行是一个空行,只包含一个新行 字节。对于此内容,strtok()
将跳过最初的换行,搜索不存在的不同字符,并返回NULL
不 修改数组。因此它不会剥离 新行。
这是不使用strtok(line, "\n")
去除换行字节的令人信服的理由。
当然可以通过以下方式解决这个问题:
if (*line == '\n')
*line = '\0';
else
strtok(line, "\n");
或繁琐的单行:
(void)(*line == '\n' ? (*line = '\0') : (strtok(line, "\n"), 0);
if (!strtok(line, "\n")) *line = '\0';
(void)(strtok(line, "\n") || (*line = '\0'));
但代码不再紧凑,还有其他副作用。
其他方法可用:
使用明确的for
语句:
for (char *p = line; *p; p++)
if (*p == '\n')
*p = '\0';
使用strlen()
:
size_t len = strlen(line);
if (len > 1 && line[len - 1] == '\n')
line[--len] = '\0';
// len is the length if the stripped line
使用strchr()
:
char *p = strchr(line, '\n');
if (p)
*p = '\0';
在单行中使用strcspn()
:
line[strcspn(line, "\n")] = '\0'; // strip the newline if any.
【讨论】:
+ 就像用两天时间为机械臂编程一个螺丝。 @0___________: 或使用steam hammer 钉钉子:)以上是关于为啥要使用 strtok(line, "\n") **not** 来去除 fgets() 留下的换行符的主要内容,如果未能解决你的问题,请参考以下文章