scanf错误处理C

scanf错误处理C,c,error-handling,C,Error Handling,如果我想输入 [Name] [Name] 我怎样才能发现 [Name] [Name] [Name] 和返回错误 这是我到目前为止得到的 char in[20]; char out[20]; scanf(" %s %s", out, in); scanf返回有效转换的参数数。在第一种情况下,返回值是2,在后一种情况下是3 要检查正确数量的参数,这可能有助于: char in[20]; char out[20]; char error[20]; int check; check = sca

如果我想输入

[Name] [Name]
我怎样才能发现

[Name] [Name] [Name] 
和返回错误

这是我到目前为止得到的

char in[20];
char out[20];
scanf(" %s %s", out, in);

scanf
返回有效转换的参数数。在第一种情况下,返回值是2,在后一种情况下是3

要检查正确数量的参数,这可能有助于:

char in[20];
char out[20];
char error[20];
int check;

check = scanf(" %s %s %s", out, in, error);
if(check != 2)
{
    // TODO: error handling
}
编辑:现在它应该可以工作了,请参见下面的评论


当然,正如其他海报所述:scanf被认为不是一个非常安全的功能,因为可能会发生缓冲区溢出,您应该避免使用它。最好使用
fgets()
将输入读取到缓冲区,然后尝试解析所需的参数。

这是家庭作业,因此可能需要在某些(任意)限制下工作。然而,短语“
scanf
错误处理”在C编程语言中有点矛盾

最好的方法是读入一行/其他合适的块并用C字符串函数解析它。您可以在一行
scanf
中完成此操作,但有许多缺点:

  • 您可以防止缓冲区溢出,但如果缓冲区不够大,则无法恢复
  • 您可以为字符串指定特定的字符范围,但它看起来有点不规则,标准中没有强制要求使用
    scanf
    格式的
    “%[”
    行为
  • 您可以检查第三个名称,但代码看起来不直观-看起来您不希望只有两个名称,而是希望有三个名称。
    scanf
    也让您无法控制如何处理空白
  • 编辑:从你的问题开始,我最初认为这些名称包含在括号中(a la
    “[Bruce][Wayne]”
    ),但现在看来,这只是你表示占位符的惯例

    不管怎么说,尽管我非常不喜欢scanf,它还是有它的用途的。对我来说,最大的杀手是无法区分行尾和简单的空格分隔。要解决这个问题,你可以调用将数据读入缓冲区,然后在缓冲区上调用
    sscanf
    。这给了你们两个)更安全的读取(
    scanf
    与其他更直接的函数从缓冲区读取的能力相混淆)和b)scanf格式的好处

    如果您必须使用
    scanf
    ,您的格式基本上如下:

    " %s %s %s"
    
    第三个是不可取的。正如的答案所示,您需要将数据读入三个缓冲区,并检查第三个缓冲区是否通过。但是,如果您正在读取此数据的多个连续行,则下一行的第一个条目将满足第三个槽位,错误地给出错误。我强烈建议使用
    fgets
    sscanf
    或将
    sscanf
    丢弃,以便在这种情况下进行更精确的手动解析


    这里有一个链接,如果你错过了我之前偷偷进来的那一个。如果你决定放弃
    sscanf
    ,这里有一些其他函数需要研究:(或者,或者)查找名称的长度,或者(但请不要
    strncpy
    ,它不是你认为的那样)将数据复制到缓冲区。

    是“不要使用
    scanf
    ”一个可接受的答案(当然,如果我们详细说明的话)?另外,
    Name
    s是否保证不包含空格/括号/疯狂字符,这些字符会弄脏
    %s
    格式字符串?是
    “[Bruce Wayne]”
    有效?是的,不保证有空格,空格将代表下一个元素wold是Name然后是next line Name然后是next line Name Name等等这将不起作用,因为如果有第三个参数,
    scanf
    将愉快地让它在流中等待,只扫描前两个名称,然后返回2。这对检查是否可能存在第三个名称。我必须承认你是对的:/似乎我对这个名称考虑得不够透彻。一个愚蠢的问题,fgets()会给我相同的函数吗?不,不幸的是不会。fgets()让你从缓冲区读取,就像用于输入的stdin缓冲区。“fgets(buf,100,stdin);”从stdin中读取100个字符到缓冲区buf中。在wads之后,缓冲区可以使用安全函数(如sscanf)读取。例如:sscanf(buf,“%20s%20s%20s”,out,in,error);因为在我的情况下,可能会有一行新的。error可能会被读取为下一行,不是吗?抱歉,它的[Name]\n…可能更多[Name]\名称是否由括号分隔?输入是
    “[Clark][Kent]\n”
    还是仅
    “Clark Kent\n”
    ?Clark Kent\n…可能更多。那么我最好先读一整行,然后按空格分开吗?我是用java做的,但我不知道如何在CAll good advice中做到这一点,但我会更进一步。放弃
    fscanf
    ,转而选择
    getline
    (不是c标准,而是POSIX的一部分)或者可以读取任意长度的行而不冒缓冲区溢出风险的许多等效库之一。@dmckee-或者使用GNU readline(或BSD editline)获得更多功能。即使没有这些库,也可以编写
    getline
    (或精简
    readline
    )函数并不是很难,一旦写了它肯定会节省很多时间。然而,这只是家庭作业,所以我愿意接受教授可能不希望人们试图理解
    malloc