将字符串解析为整数并将它们存储在 C 中的数组(范围值)中

Parse the string into integers and store them in array (range values) in C

{s20-s23,s25-s28,s30,s31}

以上是输入的字符串,需要解析并存储到数组中。数组应该如下-

20, 22, 23, 25, 26, 27, 28, 30, 31 

即范围内的值也应该被存储(s20-s23,s25-s28)。我试图做同样的事情,但找不到办法。请参考以下程序并建议更改以获得相同的输出。提前致谢。

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int main(void) {
    char *str = "{s20-s23,s30,s31}", *p = str;
    int arr[100];
    int i = 0;
    int flag = 0;
    while (*p) {
        if (isdigit(*p)) {
            int val = strtol(p, &p, 10);
            arr[i] = val;
            i++;
            printf("%ld\n", val);
        } else {
            p++;
        }
    }
    printf("\n"); 

    for(int j=0; j<i;j++){ 
        printf("%d\n",arr[j]);
    }
    return 0;
}

以上程序的输出是(缺失范围内的值)

20, 23, 25, 28, 30, 31

您的输入 "{s20-s23,s25-s28,s30,s31}" 是以 { 开头的字符串,后跟零个或多个范围,然后是终止词 }。每个 range 都是一个 cell,带有一个可选的 -,后跟另一个 cell 和一个分隔符 ,,除非它是最后一个范围。单元格是 s 后跟一个无符号数。这个讨论将是一个非正式的指定语法。然后你只是实现了一个函数来处理每个术语:

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

const char *parse_chr(const char *s, char c) {
    if(*s != c) return NULL;;
    return s + 1;
}

const char *parse_cell(const char *s, unsigned *v) {
    s = parse_chr(s, 's');
    if(!s) return s;
    // assumes values is between 0 and UINT_MAX
    *v = strtol(s, (char **) &s, 10);
    return s;
}

const char *parse_range(const char *s, unsigned *start, unsigned *end) {
    s = parse_cell(s, start);
    if(!s) return s;
    if(*s != '-') {
        *end = *start;
        goto out;
    }
    s = parse_cell(s + 1, end);
    if(!s) return s;
out:
    return *s == ',' ? s + 1 : s;
}

// assumes v is sufficently large
const char *parse(const char *s, unsigned *n, unsigned *v) {
    s = parse_chr(s, '{');
    if(!s) return s;
    *n = 0;
    for(;;) {
        if(*s != 's') break;
        unsigned start, end;
        s = parse_range(s, &start, &end);
        if(!s || (start > end)) return s;
        for(; start <= end; (*n)++, v++, start++) *v = start;
    }
    s = parse_chr(s, '}');
    return parse_chr(s, '[=10=]');
}

int main() {
    unsigned values[100];
    unsigned len;
    if(!parse("{s20-s23,s25-s28,s30,s31}", &len, values)) {
        printf("parse failed\n");
        return 1;
    }
    for(int i = 0; i < len; i++) {
        printf("%u%s", values[i], i + 1 < len ? ", " : "\n");
    }
    return 0;
}

这会产生预期的结果(假设示例输出中缺少的 21 是规范错误):

20, 21, 22, 23, 25, 26, 27, 28, 30, 31

我更喜欢 parser() returns struct ranges 的数组,然后让另一个函数扩展该列表。 parser() 可能应该采用 max length 所以我们不会向 v 写入太多元素,也许像 snprintf() 允许 v 为 NULL 这样你就可以得到一个计数。另一个不错的选择是让它分配一个数组,如果需要,可以使用 realloc() 来增加数组。改进错误报告也是一个好主意,这样解析就会告诉您失败的位置和原因。