1

我从C Primer Plus中阅读了一段代码,并努力理解*find = '\0';

#include <stdio.h>
#include <string.h>

char *s_gets(char *st, int n);

struct book {
    char title[40];
    char author[40];
    float value;
}

int main(void) {
    ...
}

char *s_gets(char *st, int n) {
    char *ret_val;
    char *find;

    ret_val = fgets(st, n, stdin);
    if (ret_val) {
        find = strchr(st, '\n'); //look for newline
        if (find)                // if address is not null
            *find = '\0';        //place a null character there
        else
            while (getchar() != '\n')
                continue;  //dispose rest of line
    }
    return ret_val;
}

为了什么目的应该find = strchr(st, '\n');遵循*find = '\0';

我搜索strchr但发现它是一个奇怪的名字,虽然可以了解它的功能。名字strchr是从哪里来的stringcharacter

4

1 回答 1

4

如果字符串中确实有换行符,则使用的代码find = strchr(s, '\n')和后面的代码会删除fgets()结果字符串中读取并包含在其中的换行符。通常,您可以使用另一种更紧凑的表示法:

s[strcspn(s, "\n")] = '\0';

这是在没有任何可见的条件代码的情况下编写的。(如果没有换行符,则空字节会覆盖现有的空字节。)

总体目标似乎是使s_gets()行为更像一个古董,危险且不再是标准函数,gets()它读取并包含换行符,但结果中不包含换行符。该gets()功能还有其他设计缺陷,使其成为一个被遗忘的功能——永远不要使用它!

显示的代码还检测何时没有读取换行符,然后进入危险循环以读取该行的其余部分。循环应该是:

else
{
    int c;
    while ((c = getchar()) != EOF && c != '\n')
        ;
}

检测EOF很重要;并非所有文件都以换行符结尾。可靠地检测 EOF 也很重要,这意味着必须使用此代码int c(而原始有缺陷的循环可以避免使用类似 的变量c)。如果不小心使用了此代码char c而不是类型)。int ccharchar

请注意,strcspn()在此代码中不能直接使用所示的选项,因为这样您就无法检测数据中是否有换行符;您只知道通话后数据中没有换行符。正如Antti Haapala 指出的那样,您可以捕获结果,strcspn()然后决定是否找到换行符,因此是否读取到行尾(如果 EOF 之前没有 EOL,则读取到文件末尾)。

于 2018-10-18T03:32:36.933 回答