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