简体   繁体   English

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

[英]using scanf to read a string and an int separated by /

The input consists a string and an integer, which are separated by a '/' , like this:输入由一个字符串和一个整数组成,用'/'分隔,如下所示:

hello/17

And I want to read the input into a string and an int , like this:我想将输入读入一个字符串和一个int ,如下所示:

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

I can't seem to make it, any advice?我似乎无法做到,有什么建议吗?

scanf awaits a whitespace terminated string when it tries to read %s . scanf尝试读取%s时,它会等待一个以空格结尾的字符串。

Try to specify the forbidden character set directly:尝试直接指定禁用字符集:

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

You can read more about the formating codes here您可以 在此处阅读有关格式化代码的更多信息

You only need to run the following program:您只需要运行以下程序:

#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;
}

to see why this is happening.看看为什么会这样。 The output is:输出是:

String was 'hello/17'
Number was 42
Count  was 1

The reason has to do with the %s format specifier.原因与%s格式说明符有关。 From C99 7.19.6.2 The fscanf function (largely unchanged in C11, and the italics are mine):从 C99 7.19.6.2 The fscanf function (在 C11 中基本没有变化,斜体是我的):

s : matches a sequence of non-white-space characters. s :匹配一系列非空白字符。

Since / is not white space, it gets included in the string bit, as does the 17 for the same reason.由于/不是空格,它被包含在字符串位中,出于同样的原因, 17也是如此。 That's also indicated by the fact that sscanf returns 1 , meaning that only one item was scanned. sscanf返回1的事实也表明了这一点,这意味着只扫描了一项

What you'll then be looking for is something that scans any characters other than / into the string (including white space).什么,你会再寻找的东西,它可以扫描比其他任何字符/成字符串(包括空格)。 The same section of the standard helps out there as well:标准的同一部分也有帮助:

[ : matches a nonempty sequence of characters from a set of expected characters (the scanset). [ : 匹配一组预期字符(扫描集)中的非空字符序列。 The conversion specifier includes all subsequent characters in the format string, up to and including the matching right bracket (]).转换说明符包括格式字符串中的所有后续字符,直到并包括匹配的右括号 (])。 The characters between the brackets (the scanlist) compose the scanset, unless the character after the left bracket is a circumflex (^), in which case the scanset contains all characters that do not appear in the scanlist between the circumflex and the right bracket.括号之间的字符(扫描列表)组成扫描集,除非左括号后面的字符是一个抑扬符 (^),在这种情况下,扫描集包含所有未出现在抑扬符和右括号之间的扫描列表中的字符。

In other words, something like:换句话说,类似于:

#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;
}

which gives you:这给了你:

String was 'hello'
Number was 17
Count  was 2

One other piece of advice: never ever use scanf with an unbounded %s or %[ ;另外一个忠告:永远用不完scanf采用无界%s%[ ; you're asking for a buffer overflow attack.您要求进行缓冲区溢出攻击。 If you want a robust user input function, see this answer .如果您想要一个强大的用户输入功能,请参阅此答案

Once you have it in as a string, you can sscanf it to your heart's content without worrying about buffer overflow (since you've limited the size on input).一旦将它作为字符串输入,您就可以将它sscanf到您想要的内容,而不必担心缓冲区溢出(因为您限制了输入的大小)。

Could be like that:可能是这样的:

char str[20];
int num;

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

%*c reads one character and discards it %*c读取一个字符并丢弃它

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

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