繁体   English   中英

c语言中的scanf说明

[英]Scanf clarification in c language

是否可以读取包含空格的整个字符串,例如scanf() gets()函数?

我可以使用gets()函数来做到这一点。

char s[30];
gets(s);

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

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

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

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

第一次调用scanf()将消耗输入流中的所有换行符,直到遇到非换行符。 虽然我认为对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);

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

不要使用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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM