如何仅使用sscanf从字符串中提取所有数字?

如何仅使用sscanf从字符串中提取所有数字?,c,string,scanf,C,String,Scanf,如何仅在C中使用sscanf从以下格式的字符串中提取所有数字: (3、2、4、5、10) 空白可以无处不在,当然不能在数字之间。 每个位置可以有0个或更多空白 字符串必须具有正确的格式,否则将导致错误。 例如,“3,2”是一个错误。 每一个不是空白或部分格式的字符都是错误的 仅使用sscanf(非可选) 当然,我的想法是使用sscanf进行while循环,但格式是我的问题 编辑:括号内的数字可以不同。因此,括号内可以有0个数字或n个数字。n是任意数字。(a,a+1,…,a+n) 编辑2:当然可以

如何仅在C中使用sscanf从以下格式的字符串中提取所有数字:

(3、2、4、5、10)

空白可以无处不在,当然不能在数字之间。 每个位置可以有0个或更多空白

字符串必须具有正确的格式,否则将导致错误。 例如,“3,2”是一个错误。 每一个不是空白或部分格式的字符都是错误的

仅使用sscanf(非可选)

当然,我的想法是使用sscanf进行while循环,但格式是我的问题

编辑:括号内的数字可以不同。因此,括号内可以有0个数字或n个数字。n是任意数字。(a,a+1,…,a+n)

编辑2:当然可以使用stdio.h中包含的所有内容,但不能使用扩展库 似乎数据的格式可以概括为:任意位置的空白;开括号后是一个或多个纯整数序列(无符号,无小数点),由逗号分隔,并以右括号终止。或者,在
之间可以有零整数

必须使用
sscanf()
处理数据;没有关于单个调用
sscanf()
的规定。与文件I/O备选方案(
scanf()
fscanf()
等)相比,使用
sscanf()
的优点之一是,如果需要,可以重试扫描

请注意,
scanf()
系列不能很好地处理“可选项”。空白通常很小-除了
%c
%[…]
(扫描集)之外的所有转换说明符和
%n
跳过前导空格,格式字符串中的空格字符与输入中的零个或多个空格字符匹配

代码 函数
string\u analyzer()
完成了这项工作;它有一个相当复杂的接口,因为它本身没有I/O—它分析字符串并将数字添加到传递给函数的数组结构中。它还设置了一条消息,告诉调用方出错的地方。其他函数是支持函数(用于
struct int_数组
类型)和测试线束(
main()
plus
test_string_analyzer()


我投票结束这个问题,因为。哦,我忘了写这个。当然,它可以超过五个。任何数字都是负数吗?用加号标记为正数吗?另请参见。它们总是无符号的,从来没有negative@JonathanLeffler我理解这个解决方案,但我的问题是格式化。就像它不是字符串一样对于数字,它更像是一个有x个空格的集合。我的问题是从一个数字到另一个数字,中间有所有的东西。我能在一个循环中完成这些吗?再次,非常感谢!我总是被ppl愿意在这里做的事弄得头晕目眩!谢谢
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct int_array
{
    char   *base;
    size_t  maxlen;
    size_t  curlen;
};

static void dump_int_array(const char *tag, const struct int_array *array);
static void add_to_int_array(struct int_array *array, int data);
static void free_int_array(struct int_array *array);
static void test_string_analyzer(const char *str);

static int string_analyzer(const char *str, struct int_array *array, char **msg)
{
    int offset;
    int length = strlen(str);
    int data;
    char trailer;

    if (sscanf(str, " ( %[)] %n", &trailer, &offset) == 1)
    {
        /* Empty list */
        assert(trailer == ')');
        if (offset == length)
        {
            *msg = "it is an empty list";
            return 0;
        }
        else
        {
            *msg = "it has extra characters after an empty list";
            return -1;
        }
    }

    if (sscanf(str, " ( %d %c%n", &data, &trailer, &offset) != 2 ||
        (trailer != ',' && trailer != ')'))
    {
        *msg = "it does not start correctly";
        return -1;
    }
    add_to_int_array(array, data);
    if (trailer == ')' && offset == length)
    {
        *msg = "it is valid";
        return 0;
    }
    const char *source = str + offset;
    while (sscanf(source, "%d %[,)] %n", &data, &trailer, &offset) == 2)
    {
        add_to_int_array(array, data);
        length = strlen(source);
        if (trailer == ')' && offset == length)
        {
            *msg = "it is valid";
            return 0;
        }
        else if (trailer == ')')
        {
            *msg = "it does not end correctly";
            return -1;
        }
        source += offset;
    }
    *msg = "it is incorrectly formatted";
    return -1;
}

int main(void)
{
    const char *samples[] =
    {
        /* Valid */
        " (3, 2, 4,5, 10 )",
        " ( 4 , 6 ) ",
        "(4)",
        "()",
        /* random -n 15 10 99 | commalist -t -B 8 -b '"( ' -T ' )",' */
        "( 65, 83, 81, 60, 61, 23, 48, 89, 67, 27, 73, 25, 92, 13, 67 )",
        /* Invalid */
        " (3,2, ",
        "3,2",
        " (3,2,1) apathy",
        " () apathy",
        " (3,X,1)",
        " (3X,1)",
    };
    enum { NUM_SAMPLES = sizeof(samples) / sizeof(samples[0]) };

    for (int i = 0; i < NUM_SAMPLES; i++)
        test_string_analyzer(samples[i]);

    return 0;
}

static void test_string_analyzer(const char *str)
{
    struct int_array array = { 0, 0, 0 };
    char *msg = 0;

    printf("Analyzing [%s]\n", str);
    int rc = string_analyzer(str, &array, &msg);
    if (rc == 0)
        printf("String '%s' OK: %s\n", str, msg);
    else
        printf("String '%s' is misformatted: %s\n", str, msg);
    dump_int_array("List contents", &array);

    free_int_array(&array);
}

static void dump_int_array(const char *tag, const struct int_array *array)
{
    int length = printf("%s (%zu): ", tag, array->curlen);
    const char *pad = "";
    for (size_t i = 0; i < array->curlen; i++)
    {
        length += printf("%s%d", pad, array->base[i]);
        pad = ", ";
        if (length >= 64)
        {
            pad = "    ";
            length = 0;
            putchar('\n');
        }
    }
    if (length > 0)
        putchar('\n');
}

static void add_to_int_array(struct int_array *array, int data)
{
    if (array->curlen >= array->maxlen)
    {
        assert(array->curlen == array->maxlen);
        size_t newlen = array->maxlen * 2 + 2;
        void  *newarr = realloc(array->base, newlen * sizeof(array->base[0]));
        if (newarr == NULL)
        {
        }
        array->base = newarr;
        array->maxlen = newlen;
    }
    array->base[array->curlen++] = data;
}

static void free_int_array(struct int_array *array)
{
    free(array->base);
    array->base = 0;
    array->maxlen = 0;
    array->curlen = 0;
}
Analyzing [ (3, 2, 4,5, 10 )]
String ' (3, 2, 4,5, 10 )' OK: it is valid
List contents (5): 3, 2, 4, 5, 10
Analyzing [ ( 4 , 6 ) ]
String ' ( 4 , 6 ) ' OK: it is valid
List contents (2): 4, 6
Analyzing [(4)]
String '(4)' OK: it is valid
List contents (1): 4
Analyzing [()]
String '()' OK: it is an empty list
List contents (0): 
Analyzing [( 65, 83, 81, 60, 61, 23, 48, 89, 67, 27, 73, 25, 92, 13, 67 )]
String '( 65, 83, 81, 60, 61, 23, 48, 89, 67, 27, 73, 25, 92, 13, 67 )' OK: it is valid
List contents (15): 65, 83, 81, 60, 61, 23, 48, 89, 67, 27, 73, 25
    92, 13, 67
Analyzing [ (3,2, ]
String ' (3,2, ' is misformatted: it is incorrectly formatted
List contents (2): 3, 2
Analyzing [3,2]
String '3,2' is misformatted: it does not start correctly
List contents (0): 
Analyzing [ (3,2,1) apathy]
String ' (3,2,1) apathy' is misformatted: it does not end correctly
List contents (3): 3, 2, 1
Analyzing [ () apathy]
String ' () apathy' is misformatted: it has extra characters after an empty list
List contents (0): 
Analyzing [ (3,X,1)]
String ' (3,X,1)' is misformatted: it is incorrectly formatted
List contents (1): 3
Analyzing [ (3X,1)]
String ' (3X,1)' is misformatted: it does not start correctly
List contents (0):