C语言 使用 sscanf 读取带空格的字符串
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2854488/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
reading a string with spaces with sscanf
提问by SDLFunTimes
For a project I'm trying to read an int and a string from a string. The only problem is sscanf appears to break reading an %s when it sees a space. Is there anyway to get around this limitation? Here's an example of what I'm trying to do:
对于一个项目,我试图从一个字符串中读取一个 int 和一个字符串。唯一的问题是 sscanf 在看到空格时似乎会中断读取 %s。有没有办法绕过这个限制?这是我正在尝试做的一个例子:
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char** argv) {
int age;
char* buffer;
buffer = malloc(200 * sizeof(char));
sscanf("19 cool kid", "%d %s", &age, buffer);
printf("%s is %d years old\n", buffer, age);
return 0;
}
What it prints is: "cool is 19 years old" where I need "cool kid is 19 years old". Does anyone know how to fix this?
它打印的是:“酷是 19 岁”,我需要“酷孩子是 19 岁”。有谁知道如何解决这一问题?
回答by BrunoLM
The following line will start reading a number (%d) followed by anything different from tabs or newlines (%[^\t\n]).
以下行将开始读取一个数字 ( %d),后跟与制表符或换行符 ( %[^\t\n])不同的任何内容。
sscanf("19 cool kid", "%d %[^\t\n]", &age, buffer);
回答by caf
You want the %cconversion specifier, which just reads a sequence of characters without special handling for whitespace.
您需要%c转换说明符,它只读取一个字符序列而无需对空格进行特殊处理。
Note that you need to fill the buffer with zeroes first, because the %cspecifier doesn't write a nul-terminator. You also need to specify the number of characters to read (otherwise it defaults to only 1):
请注意,您需要先用零填充缓冲区,因为说明%c符不写入空终止符。您还需要指定要读取的字符数(否则默认仅为 1):
memset(buffer, 0, 200);
sscanf("19 cool kid", "%d %199c", &age, buffer);
回答by paxdiablo
If you want to scan to the end of the string (stripping out a newline if there), just use:
如果你想扫描到字符串的末尾(如果有的话,去掉一个换行符),只需使用:
char *x = "19 cool kid";
sscanf (x, "%d %[^\n]", &age, buffer);
That's because %sonly matches non-whitespace characters and will stop on the first whitespace it finds. The %[^\n]format specifier will match every character that's not (because of ^) in the selection given (which is a newline). In other words, it will match any other character.
那是因为%s只匹配非空白字符并且会在它找到的第一个空白处停止。该%[^\n]格式说明会的每一个字符,这不是(因为匹配^中给出的选择)(这是一个换行符)。换句话说,它将匹配任何其他字符。
Keep in mind that you should have allocated enough space in your buffer to take the string since you cannot be sure how much will be read (a good reason to stay away from scanf/fscanfunless you use specific field widths).
请记住,您应该在缓冲区中分配足够的空间来获取字符串,因为您无法确定将读取多少(scanf/fscanf除非您使用特定的字段宽度,否则这是远离的一个很好的理由)。
You could do that with:
你可以这样做:
char *x = "19 cool kid";
char *buffer = malloc (strlen (x) + 1);
sscanf (x, "%d %[^\n]", &age, buffer);
(you don't need * sizeof(char)since that's always1 by definition).
(您不需要,* sizeof(char)因为根据定义它始终为1)。
回答by ?eurobur?
Since you want the trailing string from the input, you can use %n(number of characters consumed thus far) to get the position at which the trailing string starts. This avoids memory copies and buffer sizing issues, but comes at the cost that you may need to do them explicitly if you wanted a copy.
由于您想要来自输入的尾随字符串,您可以使用%n(到目前为止消耗的字符数)来获取尾随字符串开始的位置。这避免了内存副本和缓冲区大小问题,但代价是如果您想要副本,您可能需要明确地执行这些操作。
const char *input = "19 cool kid";
int age;
int nameStart = 0;
sscanf(input, "%d %n", &age, &nameStart);
printf("%s is %d years old\n", input + nameStart, age);
outputs:
输出:
cool kid is 19 years old
回答by Rob Heusdens
I guess this is what you want, it does exactly what you specified.
我想这就是您想要的,它完全符合您的要求。
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char** argv) {
int age;
char* buffer;
buffer = malloc(200 * sizeof(char));
sscanf("19 cool kid", "%d cool %s", &age, buffer);
printf("cool %s is %d years old\n", buffer, age);
return 0;
}
The format expects: first a number (and puts it at where &age points to), then whitespace (zero or more), then the literal string "cool", then whitespace (zero or more) again, and then finally a string (and put that at whatever buffer points to). You forgot the "cool" part in your format string, so the format then just assumes that is the string you were wanting to assign to buffer. But you don't want to assign that string, only skip it.
该格式要求:首先是一个数字(并将其放在 &age 指向的位置),然后是空格(零个或多个),然后是文字字符串“cool”,然后又是空格(零个或多个),最后是一个字符串(和把它放在任何缓冲区指向的地方)。您忘记了格式字符串中的“cool”部分,因此格式仅假定这是您想要分配给缓冲区的字符串。但是您不想分配该字符串,只需跳过它。
Alternative, you could also have a format string like: "%d %s %s", but then you must assign another buffer for it (with a different name), and print it as: "%s %s is %d years old\n".
或者,您也可以有一个格式字符串,如:“%d %s %s”,但是您必须为其分配另一个缓冲区(使用不同的名称),并将其打印为:“%s %s 是 %d 年旧\n”。

