仅当字符串与以下字符串结构匹配时,才如何将字符串拆分为两个字符串(数组名称,索引号):“ ArrayName [index]”。 数组名称最多可以包含31个字符,索引最多可以包含3个字符。
我找到了以下示例,该示例假定可与“ Matrix [index1] [index2]”一起使用。我真的不明白它是怎么做的,以便分解我需要得到琴弦的那部分。
sscanf(inputString, "%32[^[]%*[[]%3[^]]%*[^[]%*[[]%3[^]]", matrixName, index1,index2) == 3
这次尝试失败了,我想念什么?
sscanf(inputString, "%32[^[]%*[[]%3[^]]", arrayName, index) == 2
答案 0 :(得分:1)
仅当字符串与以下字符串结构匹配时,才如何将字符串拆分为两个字符串(数组名称,索引号):
使用sscanf
,您不需要。如果您的意思是说您输入的内容与模式不匹配,那么您就可以依靠任何东西而无需修改。这是因为sscanf
与scanf
系列的其余部分一样,是线性处理其输入和格式的,没有回溯,并且根据设计,它会在成功匹配输入字段时填充它们。因此,如果您使用分配多个字段或带有尾随文字字符的格式进行扫描,那么即使发生匹配失败,也可能会为某些字段存储结果。
但是如果您认为可以,那么@gsamaras's answer提供了一种几乎正确的方法,可以使用sscanf
根据您指定的格式来解析和验证字符串。该答案还很好地解释了格式字符串的含义。这样做的问题在于,它无法区分完全匹配格式的输入和输入的最后]
匹配失败或后面没有其他字符的输入。
以下是该代码的一种变体,它也解决了这些后端问题:
char array_name[32] = {0}, idx[4] = {0}, c = 0;
int n;
if (sscanf(str, "%31[^[][%3[^]]%c%n", array_name, idx, &c, &n) >= 3
&& c == ']' && str[n] == '\0')
printf("arrayName = %s\nindex = %s\n", array_name, idx);
else
printf("Not in the expected format \"ArrayName[idx]\"\n");
格式上的差异是用]
伪指令替换文字终止符%c
,该伪指令匹配任何一个字符,并添加%n伪指令,导致字符数到目前为止已存储的读取输入中,没有消耗任何输入。
这样,如果返回值至少为3,那么我们就知道整个格式都已匹配(%n
不会产生匹配失败,但是文档尚不清楚,并且行为是否不一致是否会导致匹配失败)返回的字段计数)。在那种情况下,我们检查变量c
以确定是否有一个期望的]
结束符,并且我们使用记录在n
中的字符数来验证字符串被解析(因此str[n]
指向字符串终止符)。
在这一点上,您可能想知道这一切到底有多复杂和神秘。您这样做是正确的。解析结构化输入是一个复杂而棘手的命题,一方面,scanf
系列函数也很难使用。对于像您这样的情况,最好使用regex匹配器,或者最好使用机器生成的词法分析器(请参见lex),并可能通过机器生成的解析器进行扩展(请参见yacc) )。甚至手写解析器通过字符串功能和字符比较来处理输入字符串,也可能会有所改进。无论如何,它仍然很复杂,但是那些工具至少可以使它变得不那么神秘。
注意 :以上假设索引可以是最多三个字符的任何字符串。如果您要表示它必须是数字,也许是一个十进制数,或者也许是非负数,那么可以调整格式以达到此目的。
答案 1 :(得分:0)
一个让您入门的天真例子:
#include <stdio.h>
#include <string.h>
int main(void)
{
char str[] = "myArray[123]";
char array_name[32] = {0}, idx[4] = {0};
if(sscanf(str, "%31[^[][%3[^]]]", array_name, idx) == 2)
printf("arrayName = %s\nindex = %s\n", array_name, idx);
else
printf("Not in the expected format \"ArrayName[idx]\"\n");
return 0;
}
输出:
arrayName = myArray
index = 123
可以找到容易的,非预期的格式,例如“ ArrayNameidx”和“ abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP [idx]”,但找不到“ ArrayName [idx””。
sscanf()
的本质是告诉它在哪里停止,否则%s
会读到下一个空格。
此否定的扫描集%[^[]
表示已读,直到找到一个开括号。
此否定的扫描集%[^]]
表示已读,直到找到右括号为止。
注意:我分别使用31和3作为宽度说明符,因为我们要为NULL终止符保留最后一个插槽,因为假定数组的名称最多为31个字符,而索引3为最多。令牌的数组大小为允许的最大长度加一。
答案 2 :(得分:0)
如何使用sscanf分析字符串数据?
使用"%n"
检测完成的扫描。
数组名称最多可以包含31个字符,索引最多可以包含3个字符。
为便于说明,我们假设索引需要限制为数值[0-999]。
使用字符串文字串联来更清楚地显示格式。
char name[32]; // array name can be 31 characters
#define NAME_FMT "%31[^[]"
char idx[4]; //
#define IDX_FMT "%3[0-9]"
int n = 0; // be sure to initialize
sscanf(str, NAME_FMT "[" IDX_FMT "]" "%n", array_name, idx, &n);
// Did scan complete (is `n` non-zero) with no extra text?
if (n && str[n] == '\0') {
printf("arrayName = %s\nindex = %d\n", array_name, atoi(idx));
} else {
printf("Not in the expected format \"ArrayName[idx]\"\n");
}