如果我们必须使用由空格组成的多个字符串作为输入,我们可以使用scanf(“%[^ \ n] s,str)吗?

时间:2017-06-26 15:23:42

标签: c string

scanf("%[^\n]s",str1);
scanf("%[^\n]s",str2);

当我将它用于多个数组时,它无法正常工作。 我身边有什么错误,或者我们不能将它用于多个阵列吗?

2 个答案:

答案 0 :(得分:0)

可能:

scanf(" %[^\n]",str1);
scanf(" %[^\n]",str2);

请注意前面的空格,强制scanf()跳过前导空格(并且第一次调用未读取的换行计为空白字符)。

但是:此代码可能存在未定义的行为,如果输入的行长于str1str2,则会导致缓冲区溢出可以存储。 你永远不应该写这样的代码

使用scanf(),您可以使用字段宽度来限制读取的字符数量:

str1[256];
scanf(" %255[^\n]", str1); // one less because a 0 character must be appended

更好的方法是使用专用于阅读行的功能fgets()

#include <stdio.h>      // for fgets()
#include <string.h>     // for strcspn()
#define BUFFERSIZE 256

// [...]
str1[BUFFERSIZE];

int main(void)
{
    // [...]
    // no need to subtract 1 here, `fgets()` accounts for the trailing `0`:
    if (!fgets(str1, BUFFERSIZE, stdin))
    {
        // read error, e.g. print error message
        exit(1);
    }

    // fgets includes the newline if there was one, so strip it:
    str1[strcspn(str1, "\n")] = 0;

    // [...]
}

答案 1 :(得分:0)

在您描述时调用scanf() ...

scanf("%[^\n]s",str1);

将标准输入中的字符读入由str1指定的字符数组,跳过前导空格,但不包括第一个换行符。 换行符(如果有)仍然未读。如果导致零个字符传输到数组,则会发生匹配失败(因此您不能依赖正在写入的字符串终结符)。否则,scanf()会尝试读取(并忽略)'s'个字符,但这必须始终产生匹配的失败;不会消耗任何角色。

如果在尝试匹配%[指令时发生不可避免的匹配失败,则该函数将返回0;如果尝试匹配&#39; s,则该函数将返回1。如果在从标准输入读取零个字符时,或者如果发生I / O错误,它将返回EOF

如果您尝试使用相同的格式再次阅读,则第二次读取必须始终在%[指令中输入失败或匹配失败,因为如果有更多字符可用,则下一个必须是换行符。

通常,通过fgets()更好地逐行阅读。如果你必须通过scanf()来做,那么你应该按照这些方式做点什么:

char str1[100];
char c;
int result;

// Note use of a field width to protect from buffer overrun:
result = scanf("%99[^\n]%c", str1, &c);
switch (result) {
    case EOF: /* no characters available or I/O error */
        /* ... handle error ... */
        break;
    case 0:
        /* the first character was a newline */
        result = getchar();  // consume the newline
        assert(result == '\n');
        str1[0] = '\0';      // ensure the (empty) string is terminated
        break;
    case 1:
        /* should happen only at end of file or on I/O error */
        assert(feof(stdin) || ferror(stdin));
        /* ... any special handling for this being the last line of the file ... */
        break;
    case 2:
        if (c != `\n`) {
            /* the line was longer than 99 characters (excluding the newline) */
            /* ... recover from overlength line ... */
        }
        break;
    default:
        /* should never happen */
        /* ... handle unexpected result ... */
}

即使没有填写一些细节,这也非常冗长,所以我建议你把它分解成自己的功能。另请注意,fgets()使其简化 er ,但它仍然有其复杂性。特别是,您仍需要注意超长行,fgets()包括字符串中的尾部换行符(如果有的话)。