用c语言澄清扫描

时间:2017-01-06 05:33:58

标签: c

是否可以在gets()中读取包含scanf()函数等空格的整个字符串?

我可以使用gets()函数来完成。

char s[30];
gets(s);

这将读取一行字符。可以在scanf()吗?

完成

2 个答案:

答案 0 :(得分:2)

您可以使用scanf()读取包含空格的行,但此功能很微妙,使用它非常容易出错。使用%[^\n]转换说明符,您可以告诉scanf()匹配字符以形成字符串,不包括'\n'个字符。如果这样做,则应指定最大字段宽度。此宽度指定要匹配的最大字符数,因此您必须为'\0'终结符留出空间。

输入流中的第一个字符可能是'\n'。在这种情况下,scanf()将返回0的值,因为在遇到换行符之前没有匹配项。但是,s中不会存储任何内容,因此您可能会有未定义的行为。为避免这种情况,您可以先使用scanf()转换说明符调用%*[\n],然后丢弃所有前导'\n'个字符。

读取字符串后,输入流中将有其他字符。至少存在'\n',如果用户输入的字符数超过最大字段宽度,则可能包含更多字符。然后,您可能希望丢弃这些额外的字符,以便它们不会干扰进一步的输入。下面的代码包含一个执行此操作的循环。

scanf()的第一次调用将消耗输入流中的所有换行符,直到遇到非换行符。虽然我认为对scanf()的第二次调用应始终是成功的,但最好始终检查scanf()的返回值(这是成功分配的数量)。我已将此值存储在result中,并在打印字符串之前检查它。如果scanf()返回意外结果,则会打印错误消息。

使用fgets()读取整行更好,更容易。您必须记住fgets()保留尾随换行符,因此您可能希望将其删除。用户还可能输入的字符数超过缓冲区将存储的字符数,而剩余的字符则保留在输入流中。在提示输入更多内容之前,您可能希望删除这些额外的字符。

同样,您应该检查fgets()的返回值;此函数返回指向存储缓冲区的第一个元素的指针,或者在发生错误时返回NULL指针。下面的代码替换字符串中的任何尾随换行符,从输入流中丢弃额外的字符,并仅在fgets()的调用成功时打印字符串。否则,将打印一条错误消息。

#include <stdio.h>

int main(void)
{
    char s[30];
    int result;

    printf("Please enter a line of input:\n");
    scanf("%*[\n]");                // throw away leading '\n' if present
    result = scanf("%29[^\n]", s);  // match up to 29 characters, excluding '\n'

    /* Clear extra characters from input stream */
    int c;
    while ((c = getchar()) != '\n' && c != EOF)
        continue;                   // discard extra characters

    if (result == 1) {
        puts(s);
    } else {
        fprintf(stderr, "EOF reached or error in scanf()\n");
    }

    printf("Please enter a line of input:\n");    
    char *ps = fgets(s, 30, stdin); // keeps '\n' character

    if (ps) {
        while (*ps && *ps != '\n') {
            ++ps;
        }
        if (*ps) {                  // replace '\n' with '\0'
            *ps = '\0';
        } else {
            while ((c = getchar()) != '\n' && c != EOF)
                continue;           // discard extra characters
        }

        puts(s);

    } else {
        fprintf(stderr, "EOF reached or error in fgets()\n");
    }

    return 0;
}

请注意,这两种获取输入的方法并不完全等效。这里写的scanf()方法不接受空行(即只包含'\n'字符的行),但接受由其他空白字符组成的行。 fscanf()方法将接受一个空行作为输入。

此外,如果忽略前导空白字符是可以接受的,那么遵循Jonathan Leffler在评论中给出的建议只使用scanf()的一次调用会更简单:

result = scanf(" %29[^\n]", s);

这将忽略前导空格字符,包括换行符。

答案 1 :(得分:1)

请勿使用scanf()gets()功能 - 请改用fgets()。但对于上述问题,请找到答案。

int main() {
    char a[30];
    scanf ("%29[^\n]%*c", name);
    printf("%s\n", a);
    return 0;
}

我也强烈推荐,就像我在开始时告诉他使用fgets()一样。我们显然不了解这种奇怪的要求。我会用fgets()来读取这个角色。

fgets(a, size(a), stdin);