使用scanf读取以"/"分隔的字符串和整数

14

输入包含一个字符串和一个整数,它们之间用'/'分隔,就像这样:

hello/17

我想要把输入读取到一个字符串和一个 int 中,就像这样:

char str[20];
int num;
scanf("%s/%d", str, &num);  // this how I tried to do it.

我似乎做不到,有什么建议吗?


有趣的问题。scanf 可能有一些模拟匹配不仅仅是 %s 的东西。 - Eregrith
使用%s%[转换时,请不要忘记提供字段宽度!我们不喜欢缓冲区溢出... - Toby Speight
3个回答

17

scanf 在读取 %s 时,等待一个以空格结尾的字符串。

尝试直接指定不允许的字符集:

  scanf("%19[^/]/%d", str, &num);

您可以在这里了解更多有关格式化代码的信息。


9

您只需要运行以下程序:

#include <stdio.h>

int main (void) {
    char str[20] = {'\0'};
    int count, num = 42;

    count = sscanf ("hello/17", "%s/%d", str, &num);

    printf ("String was '%s'\n", str);
    printf ("Number was %d\n", num);
    printf ("Count  was %d\n", count);

    return 0;
}

为了看出为什么会发生这种情况。输出结果如下:
String was 'hello/17'
Number was 42
Count  was 1

原因与%s格式说明符有关。根据C99 7.19.6.2 fscanf函数(在C11中基本不变,下划线是我的注释):

s:匹配一个非空白字符序列。

由于/不是空白字符,所以它被包含在字符串中,与此同理,17也是。这也通过sscanf仅返回1(表示只扫描了一个项)来表明。
那么你接下来要找的就是能够扫描任何字符除了/并将其转换为字符串的方法(包括空格)。标准的同一部分也提供了帮助:

[:从预期字符集(扫描集)中匹配一个非空字符序列。转换说明符包括格式字符串中的所有后续字符,直到匹配的右方括号(])。方括号之间的字符(扫描列表)组成扫描集,除非左方括号后面是脱字符(^),此时扫描集包含不出现在脱字符和右方括号之间的扫描列表中的所有字符。

换句话说,可以使用类似如下的代码:
#include <stdio.h>
int main (void) {
    char str[20] = {'\0'};
    int count, num = 42;

    count = sscanf ("hello/17", "%[^/]/%d", str, &num);

    printf ("String was '%s'\n", str);
    printf ("Number was %d\n", num);
    printf ("Count  was %d\n", count);

    return 0;
}

这将为您提供以下内容:

String was 'hello'
Number was 17
Count  was 2

还有一个建议:永远不要使用未限制长度的%s%[scanf一起使用;这将导致缓冲区溢出攻击。如果您想要一个强大的用户输入函数,请参阅此答案

一旦您将其作为字符串输入,您可以随心所欲地使用sscanf而不必担心缓冲区溢出(因为您已经限制了输入大小)。


0

可能是这样的:

char str[20];
int num;

scanf("%19[^/]%*c%d", str, &num);

%*c 读取一个字符并将其丢弃


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接