Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c语言中的Scanf澄清_C - Fatal编程技术网

c语言中的Scanf澄清

c语言中的Scanf澄清,c,C,是否可以读取包含空格的整个字符串,如scanf中的gets函数 我可以使用gets函数来完成它 char s[30]; gets(s); 这将读取一行字符。这可以在scanf中完成吗?不要使用scanf或gets函数-而是使用fgets。但对于上述问题,请找到答案 int main() { char a[30]; scanf ("%29[^\n]%*c", name); printf("%s\n", a); return 0; } 正如我在开始时所说的那样,强

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

我可以使用gets函数来完成它

char s[30];
gets(s);
这将读取一行字符。这可以在scanf中完成吗?

不要使用scanf或gets函数-而是使用fgets。但对于上述问题,请找到答案

int main() {
    char a[30];
    scanf ("%29[^\n]%*c", name);
    printf("%s\n", a);
    return 0;
}
正如我在开始时所说的那样,强烈推荐使用fgets。我们显然不理解这个奇怪的要求。我会用FGET来读这个角色

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

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

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

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

第一次调用scanf将使用输入流中的所有换行符,直到遇到非换行符为止。虽然我相信第二次调用scanf应该总是成功的,但最好的做法是始终检查scanf的返回值,即成功分配的数量。我已将此值存储在结果中,并在打印字符串之前检查它。如果scanf返回意外结果,将打印错误消息

#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;
}
使用FGET来读取整行文字会更好、更容易。必须记住,fgets保留了尾随的换行符,因此可能需要删除它。还有一种可能性是,用户输入的字符数可能超过缓冲区存储的字符数,剩余的字符留在输入流中。在提示更多输入之前,您可能需要删除这些额外字符

再次检查fgets的返回值;此函数返回指向存储缓冲区第一个元素的指针,或在发生错误时返回空指针。下面的代码替换字符串中的任何尾随换行符,丢弃输入流中的额外字符,并且仅当对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;
}

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

我想这是你的一种工作方式?你可以用它来读一行,但它不是最好的工具。相反,我建议你使用。不要使用gets。这是一个危险而糟糕的功能。它在C99标准中也被弃用,并被完全从C11标准中删除。@请参阅Kaddo Your使用了错误的宽度限制,并且存在与此相同的问题。您可以使用scanf,很可能是错误的,或者听从好的建议。@SeekAddo getline不是标准C库的一部分。使用stdin时,它也容易受到黑客攻击,占用大量内存,因为它甚至不强制执行合理的内存使用限制。使用scanf%[^\n],a;,如果尝试读取的第一个字符是“\n”,这将导致生成带有printf%s,a;的UB;。最好检查scanf.scanf%[^\n]]*c,name的返回值;有相同的。我已经用我的编译器检查过了,我无法重新创建这个问题,而且我讨厌用scanf。我刚刚为用户提供了一种方法。我将编辑我的文章,介绍如何在fgetsIf中实现这一点。如果您的程序是a.out,那么在类Unix系统上运行a.out会给您带来未定义的行为;未使用任何确定值初始化数组a。若要重新创建问题,请执行以下操作:scanf%29[^\n]%*c,a;对于int i=0;如果前导空格或制表符不重要,使用scanf%29[^\n,s比两次调用scanf更简单。您应该检查第二次scanf是否成功读取任何内容。我想我应该创建静态内联void gobblevoid{int c;而c=getchar!=EOF&&c!='\n';}使用两次,而不是两次写出循环。@JonathanLeffler-我不清楚字符串中是否需要前导空格,因此我使用了两次调用的笨重的scanf解决方案。通常我会删除函数的流清除代码,但我决定不在这里,因为有两种不同的方法在使用没有理由不检查sca的退货
核因子;那还在对我唠叨。我认为它总是必须是1;我想函数中可能有错误。我会编辑。你的答案更好。注意:1建议在scanf->End of file中输入错误,或在scanf 2中输入错误导致scanf%*[\n];不允许输入空行。@chux-我改进了错误消息。您是对的,scanf和fgets方法对于空行的行为是不同的;我在回答的最后补充了一些评论,指出了这一点。谢谢好建议。