2

我想从键盘中读取要插入到列表中的数据。比如我输入ins "name_to_insert" 19930412,字符串name应该是name_to_insert,不带引号date应该是19930412。我不知道如何正确指定第二个sscanf。

char op[4], name[30], s[50];
int date;
while (scanf("%[^\n]%*c", s)==1)
{
    sscanf(s, "%s", op);
    if (strcmp(op, "ins")==0)
    {
        sscanf(s, "%*s %[^0-9]%d", name, &date);
        printf("Name is %s and date is %d\n", name, date);
    }
}
4

3 回答 3

1

我通过简单地从名称中删除第一个和最后一个字符来解决引号问题:

char op[4], nameTemp[30], *name, s[50];
int date;
while (scanf("%[^\n]%*c", s)==1)
{
    sscanf(s, "%s", op);
    if (strcmp(op, "ins")==0)
    {
        sscanf(s, "%*s %[^0-9]%d", nameTemp, &date);
        name=nameTemp+1;
        name[strlen(name)-2]='\0';
        printf("Name is %s and date is %d\n", name, date);
    }
}
于 2013-03-16T08:33:58.757 回答
1

你几乎是对的。假设引号是强制性的,您只需将扫描集转换说明符包含在引号中:

if (sscanf(s, "%*s \"%29[^\"]\" %d", name, &date) != 2)
    ...oops...

注意%29[^0-9]; 这将字符串限制为 29 个字节加上'\0'适合您的 30 字节数组的终端 null。你可能也应该对你的外衣进行类似的检查scanf(),或者只是使用fgets()而不是scanf()那里。

如果引号是可选的,您必须更加努力,将名称扫描为非数字并在扫描后删除引号:

if (sscanf(s, "%*s %29[^0-9] %d", name, &date) != 2)
    ...oops...

下面是一些测试代码:

#include <stdio.h>

static void scanner(const char *fmt, const char *s)
{
    char name[30];
    int  date;

    if (sscanf(s, fmt, name, &date) != 2)
        printf("Scan failed {%s} and {%s}\n", fmt, s);
    else
        printf("{%s} and {%s} => {%s} %d\n", fmt, s, name, date);
}

int main(void)
{
    char source[][30] =
    {
        "ins \"name in quotes\" 12345",
        "ins name without quotes 12345",
    };
    enum { NUM_SOURCE = sizeof(source) / sizeof(source[0]) };
    char format[][20] =
    {
        "%*s \"%29[^\"]\" %d",
        "%*s %29[^0-9] %d",
    };
    enum { NUM_FORMAT = sizeof(format) / sizeof(format[0]) };

    for (int i = 0; i < NUM_FORMAT; i++)
    {
        for (int j = 0; j < NUM_SOURCE; j++)
            scanner(format[i], source[j]);
    }
    return 0;
}

样本输出:

{%*s "%29[^"]" %d} and {ins "name in quotes" 12345} => {name in quotes} 12345
Scan failed {%*s "%29[^"]" %d} and {ins name without quotes 12345}
{%*s %29[^0-9] %d} and {ins "name in quotes" 12345} => {"name in quotes" } 12345
{%*s %29[^0-9] %d} and {ins name without quotes 12345} => {name without quotes } 12345

失败的转换是意料之中的;该格式查找引号,但没有任何引号。

我还使用了稍微不同的线束和格式字符串:

"%*s %1[\"]%29[^\"]%1[\"] %d"

(传递两个 2 字符的字符串q1q2, 来保存引号),但是当引号丢失时,扫描失败;引号不是可选的。

请注意,名称有尾随空格和第二种格式的引号;这些将不得不单独删除。

于 2013-03-16T07:57:18.730 回答
0
sscanf(s, "%*s \"%[^\"]\" %d", name, &date);
于 2013-03-16T13:26:42.243 回答