sscanf() 如何在 C 中拆分字符串
How sscanf() splits a string in C
所以基本上我有一个简单的字符串,我正在尝试使用 sscanf()
拆分这个字符串并将值存储在适当的变量中:
#include<stdio.h>
int main()
{
int i=10,j;
char ch = 'A',ch2;
float a=3.14,b;
char str[20]="10A3.140000";
sscanf(str,"%d%c%f",&j,&ch2,&b);
printf("%d %c %f\n",j,ch2,b);
return 0;
}
现在我的疑问是 sscanf
究竟是如何知道在哪里拆分字符串的。这里的值 10
进入变量 j
。字符 A
进入变量 ch2
,3.140000
进入变量 b
。 sscanf 究竟是如何解析这个字符串并将值存储在不同的变量中的。如果您能解释 sscanf
究竟如何与任何字符串一起工作,我们将不胜感激。我很难理解它。
scanf
根据您在格式字符串中定义的格式说明符使用 输入字符串。
让我们分析一下您的格式字符串:
sscanf(str,"%d%c%f",&j,&ch2,&b);
%d
解析搜索 十进制整数 的字符串。这意味着只接受 0-9
范围内的数字字符。此外,接受前导符号字符(如数字 -123
)。所有满足此条件的字符都被消耗
%c
扫描 any 字符,将其 ASCII 值保存在目标变量中。消耗单个字符
%f
解析搜索 floats 的字符串。与 %d
情况一样,所有十进制数字和符号字符都被接受,但它也接受 .
字符,将其解释为浮点数
所以,让我们再看看你输入的字符串:
char str[20]="10A3.140000";
scanf
从第一个字符开始解析。由于存在小数,因此它会消耗它们,直到找到第一个 non-numeric 字符 ('A'
)。整数 10
存储在 j
.
中
如果字符串在这里完成,scanf
将 returned 1.
scanf
从字母 'A'
开始继续解析。因为我们有 %c
格式说明符,这个字符被消耗并且值 65('A'
的 ASCII)存储在 ch2
.
如果字符串在这里完成,scanf
将 returned 2.
字母'A'
被消耗后scanf
从字符'3'
继续解析。 %f
格式说明符将接受所有剩余字符(因为它们都是有效的),值 3.14
存储在变量 b
.
中
scanf
现在 returns 3.
我试图理解 return 由 scanf
编辑的值,因为它正在检查您是否可以控制正在发生的事情。你的情况
if( sscanf(str,"%d%c%f",&j,&ch2,&b) == 3 )
{
printf("%d %c %f\n",j,ch2,b);
}
将防止格式错误的字符串导致未定义行为的情况。要理解这种情况,请考虑以下字符串:
char str[20]="10AB3.140000";
我们在第一个整数后有两个 非数字 字符。那么:
%d
仍然会消耗值 10
%c
仍然会消耗字母 'A'
- 但
%f
不会使用下面的字符串,因为子字符串 "B3.140000"
不能被解析为浮点数 :前导 'B'
强制 scanf
中断解析,值 2 将被 returned.
因此,如果不检查 return 值,未初始化 变量 b
将被访问。
这个解释很少 over-simplified,sscanf
中的内容不止于此,因为源代码本身就有 3,000 多行代码。
下面列出了您在示例中提到的格式说明符及其对应的匹配模式
%d
: [0-9]
,[-,+]
%f
: [0-9]
,[-,+,.]
%c
: [a-z]
,[A-Z]
, 其他 ASCII 字符
正在解析
- 首先,对于
%d
,它会先查找[+,-]
个符号,如果找不到则依次查找[0-9]
个个位数。一旦它在字符串中看到 non-single 数字 (A = 65),它将结束对 %d
的搜索并将 int
的值保存到传递给 sscanf
.
- 其次,对于
%c
,现在它将采用下一个传递的格式说明符,即 %c
,并从之前停止的位置重新开始。这次它只需要从字符串中读取一个字节并将其保存到传递给 sscanf
的相应地址
- 第三,对于
%f
,它会先搜索[+,-]
符号,如果没有找到再寻找.
和个位数[0-9]
。这一直持续到它得到一些不属于 %f
的东西,在这种情况下将是 [=34=]
。并保存到传给sscanf
的对应地址
最后,一旦一切都完成并且字符串被拆分,它 returns 解析的参数总数。因此,将传递的参数列表的数量与返回值进行比较是一个很好的编程习惯。
参考:
所以基本上我有一个简单的字符串,我正在尝试使用 sscanf()
拆分这个字符串并将值存储在适当的变量中:
#include<stdio.h>
int main()
{
int i=10,j;
char ch = 'A',ch2;
float a=3.14,b;
char str[20]="10A3.140000";
sscanf(str,"%d%c%f",&j,&ch2,&b);
printf("%d %c %f\n",j,ch2,b);
return 0;
}
现在我的疑问是 sscanf
究竟是如何知道在哪里拆分字符串的。这里的值 10
进入变量 j
。字符 A
进入变量 ch2
,3.140000
进入变量 b
。 sscanf 究竟是如何解析这个字符串并将值存储在不同的变量中的。如果您能解释 sscanf
究竟如何与任何字符串一起工作,我们将不胜感激。我很难理解它。
scanf
根据您在格式字符串中定义的格式说明符使用 输入字符串。
让我们分析一下您的格式字符串:
sscanf(str,"%d%c%f",&j,&ch2,&b);
%d
解析搜索 十进制整数 的字符串。这意味着只接受0-9
范围内的数字字符。此外,接受前导符号字符(如数字-123
)。所有满足此条件的字符都被消耗%c
扫描 any 字符,将其 ASCII 值保存在目标变量中。消耗单个字符%f
解析搜索 floats 的字符串。与%d
情况一样,所有十进制数字和符号字符都被接受,但它也接受.
字符,将其解释为浮点数
所以,让我们再看看你输入的字符串:
char str[20]="10A3.140000";
中scanf
从第一个字符开始解析。由于存在小数,因此它会消耗它们,直到找到第一个 non-numeric 字符 ('A'
)。整数10
存储在j
.如果字符串在这里完成,
scanf
将 returned 1.scanf
从字母'A'
开始继续解析。因为我们有%c
格式说明符,这个字符被消耗并且值 65('A'
的 ASCII)存储在ch2
.如果字符串在这里完成,
scanf
将 returned 2.字母
中'A'
被消耗后scanf
从字符'3'
继续解析。%f
格式说明符将接受所有剩余字符(因为它们都是有效的),值3.14
存储在变量b
.scanf
现在 returns 3.
我试图理解 return 由 scanf
编辑的值,因为它正在检查您是否可以控制正在发生的事情。你的情况
if( sscanf(str,"%d%c%f",&j,&ch2,&b) == 3 )
{
printf("%d %c %f\n",j,ch2,b);
}
将防止格式错误的字符串导致未定义行为的情况。要理解这种情况,请考虑以下字符串:
char str[20]="10AB3.140000";
我们在第一个整数后有两个 非数字 字符。那么:
%d
仍然会消耗值10
%c
仍然会消耗字母'A'
- 但
%f
不会使用下面的字符串,因为子字符串"B3.140000"
不能被解析为浮点数 :前导'B'
强制scanf
中断解析,值 2 将被 returned.
因此,如果不检查 return 值,未初始化 变量 b
将被访问。
这个解释很少 over-simplified,sscanf
中的内容不止于此,因为源代码本身就有 3,000 多行代码。
下面列出了您在示例中提到的格式说明符及其对应的匹配模式
%d
: [0-9]
,[-,+]
%f
: [0-9]
,[-,+,.]
%c
: [a-z]
,[A-Z]
, 其他 ASCII 字符
正在解析
- 首先,对于
%d
,它会先查找[+,-]
个符号,如果找不到则依次查找[0-9]
个个位数。一旦它在字符串中看到 non-single 数字 (A = 65),它将结束对%d
的搜索并将int
的值保存到传递给sscanf
. - 其次,对于
%c
,现在它将采用下一个传递的格式说明符,即%c
,并从之前停止的位置重新开始。这次它只需要从字符串中读取一个字节并将其保存到传递给sscanf
的相应地址
- 第三,对于
%f
,它会先搜索[+,-]
符号,如果没有找到再寻找.
和个位数[0-9]
。这一直持续到它得到一些不属于%f
的东西,在这种情况下将是[=34=]
。并保存到传给sscanf
的对应地址
最后,一旦一切都完成并且字符串被拆分,它 returns 解析的参数总数。因此,将传递的参数列表的数量与返回值进行比较是一个很好的编程习惯。
参考: