1

我试图将以下字符串分成三个单独的变量,即a、b和c:

"   mov/1/1/1,0 STR{7}, r7" 

每个都需要保存字符串的不同段,例如:

a = "mov/1/1/1,0"
b = "STR{7}"
c = "r7"

每个命令之间可能有空格或制表符;这就是使这段代码部分更棘手的原因。

我尝试使用strtok, 进行字符串操作,但没有成功。

char command[50] = "    mov/1/1/1,0 STR{7}, r7";
char a[10], b[10], c[10];
char * ptr = strtok(command, "\t");
strcpy(a, ptr);
ptr = strtok(NULL, "\t");
strcpy(b, ptr);
ptr = strtok(NULL, ", ");
strcpy(c, ptr);

但这会使变量变得非常混乱,a, b并且c会保存比应有的值更多的值,从而导致程序崩溃。

输入可能会有所不同:

"   mov/1/1/1,0 STR{7}, r7"
"jsr /0,0            PRTSTR"
"mov/1/1/0,0         STRADD{5}, LASTCHAR {r3} "

其中 a、b 和 c 的值更改为给定字符串的不同部分。

我被告知使用 sscanf 比 strtok 更安全,但我不确定它为什么以及如何帮助我。

我很高兴听到你的意见!

4

3 回答 3

2

这应该可以解决问题:

sscanf(command, "%s,%s,%s", &a, &b, &c)

从 scanf 手册页中,%s吃空格,无论是空格还是制表符:

s :匹配一系列非空白字符;下一个指针必须是一个指向字符数组的指针,它的长度足以容纳输入序列和自动添加的终止空字节 ('\0')。输入字符串在空白处或最大字段宽度处停止,以先发生者为准。

于 2013-08-17T20:45:50.607 回答
0

我对 using 有所保留strtok(),但是使用它的这段代码似乎可以满足您的需求。正如我在评论中指出的那样,示例字符串"jsr /0,0 PRTSTR"在工作中抛出了一个扳手;它在第二个字段中有一个重要的逗号,而在其他两个示例字符串中,第二个字段中的逗号不重要。如果您需要删除尾随逗号,您可以在基于空格的拆分之后执行此操作 - 如此代码所示。第二个循环测试该zap_trailing_commas()函数以确保它在退化情况下的行为,切换尾随逗号但不会下溢缓冲区的开头或任何可怕的东西。

#include <stdio.h>
#include <string.h>

static void zap_trailing_commas(char *str)
{
    size_t len = strlen(str);
    while (len-- > 0 && str[len] == ',')
        str[len] = '\0';
}

static void splitter(char *command)
{
    char a[20], b[20], c[20];
    char *ptr = strtok(command, " \t");
    strcpy(a, ptr);
    zap_trailing_commas(a);
    ptr = strtok(NULL, " \t");
    strcpy(b, ptr);
    zap_trailing_commas(b);
    ptr = strtok(NULL, " \t");
    strcpy(c, ptr);
    zap_trailing_commas(c);
    printf("<<%s>> <<%s>> <<%s>>\n", a, b, c);
}

int main(void)
{
    char data[][50] =
    {
        "   mov/1/1/1,0 STR{7}, r7",
        "jsr /0,0            PRTSTR",
        "mov/1/1/0,0         STRADD{5}, LASTCHAR {r3} ",
    };

    for (size_t i = 0; i < sizeof(data)/sizeof(data[0]); i++)
        splitter(data[i]);

    char commas[][10] = { "X,,,", "X,,", "X,", "X" };
    for (size_t i = 0; i < sizeof(commas)/sizeof(commas[0]); i++)
    {
        printf("<<%s>> ", commas[i]);
        zap_trailing_commas(&commas[i][1]);
        printf("<<%s>>\n", commas[i]);
    }

    return 0;
}

样本输出:

<<mov/1/1/1,0>> <<STR{7}>> <<r7>>
<<jsr>> <</0,0>> <<PRTSTR>>
<<mov/1/1/0,0>> <<STRADD{5}>> <<LASTCHAR>>
<<X,,,>> <<X>>
<<X,,>> <<X>>
<<X,>> <<X>>
<<X>> <<X>>

我还测试了一个用逗号代替 X 的变体,并且只留下了单个逗号。

于 2013-08-18T04:01:19.813 回答
0

您可能知道可以使用sscanf()与 相同的方式scanf(),不同之处在于 sscanf 从字符串扫描,而 scanf 从标准输入扫描。
在这个问题中,您可以指定 scanf,使用一组“总是跳过”的字符,就像在这个链接中所做的那样。
由于您对扫描所有三个字符串有不同的约束集,因此您可以在 sscanf() 中的%*[^...]每个字符串之前使用 指定这些约束。%s

于 2013-08-17T21:27:59.440 回答