解析字符串以获取以逗号分隔的整数字符对

时间:2016-11-13 06:49:13

标签: c++ c string data-structures split

我正在开展一个项目,我在这个项目中给出了一个以这种格式的标题开头的文件:a1,b3,t11, 2,,5,\3,*4,344,00,。它始终是一个ASCII字符的序列,后跟一个用逗号分隔的整数,其序列始终以00,结尾。

基本上我要做的就是通过这个并将每个字符/整数对放入我拥有的数据类型中,将这两个作为参数并生成这些参数。例如,我上面给出的标题是一个以('a',1), ('b',3),('t',11),(',',5)(' ',2),('\',3),('*',4),('3',44)为元素的向量。

我在解析它时遇到了麻烦。到目前为止我还是:

  • 从第一个字符中提取我的文本文件中的标题,直到' 00,'标题结束的地方。我可以获得字符串格式的头字符串或字符向量(更容易解析)
  • 尝试使用sscanf解析下一个字符和下一个int,然后将这些字符添加到我的向量中,然后使用子字符串删除我已经分析过的字符串部分(这很混乱,没有得到我正确的结果)
  • 尝试通过字符串作为向量并检查每个元素以查看它是一个整数,一个字符还是一个逗号并相应地执行,但这不适用于多位整数或当角色本身是一个int

    我知道我可以很容易地根据逗号分割我的字符串,但我不知道如何做到这一点,仍然将字符中的整数分开,同时保留两者并计算我需要视为字符的整数。

    非常感谢任何建议或有用的标准库或字符串函数。

  • 2 个答案:

    答案 0 :(得分:0)

    由于您已经发现可以忽略最后3个字符,因此使用sscanf就足够了。 您可以使用sscanf读取一个字符(或getch函数),使用sscanf读取整数,最后甚至忽略一个字符。

    如果您在理解如何操作时遇到问题,请注释。

    答案 1 :(得分:0)

    许多人的一种可能性是将数据存储在结构中。这使用了一组结构,但可以根据需要使用mallocrealloc分配结构 解析字符串可以使用指针和strtol完成,它将解析整数并给出指向整数后面的字符的指针。可以将该指针前进以在下一次迭代中使用以获取ASCII字符和整数。

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    #define SIZE 100
    
    struct pair {
        char ascii;
        int  integer;
    };
    
    int main( void) {
        char input[] = "a1,b3,!0,t11, 2,,5,\\3,*4,34400,";
        char *pt = input;//start with pt pointing to first character of input
        char *end = input;
        int each = 0;
        int loop = 0;
        int length = 0;
        struct pair pairs[SIZE] = { { '\0', 0}};
    
        //assuming input will always end in 00, ( or ,00,)
        //remove those three ( or 4 ??) characters
        length = strlen ( input);
        if ( length > 3) {
            input[length - 3] = '\0';
        }
        for ( each = 0; each < SIZE; each++) {
            //get the ASCII character and advance one character
            pairs[each].ascii = *pt;
            pt++;
            //get the integer
            pairs[each].integer = strtol ( pt, &end, 10);
            //end==pt indicates the expected integer is missing
            if ( end == pt) {
                printf ( "expected an integer\n");
                break;
            }
            //at the end of the string?
            if ( *end == '\0') {
                //if there are elements remaining, add one to each as one more was used
                if ( each < SIZE - 1) {
                    each++;
                }
                break;
            }
            //the character following the integer should be a comma
            if ( *end != ',') {
                //if there are elements remaining, add one to each as one more was used
                if ( each < SIZE - 1) {
                    each++;
                }
                printf ( "format problem\n");
                break;
            }
            //for the next iteration, advance pt by one character past end
            pt = end + 1;
        }
        //loop through and print the used structures
        for ( loop = 0; loop < each; loop++) {
            printf ( "ascii[%d] = %c   ", loop, pairs[loop].ascii);
            printf ( "integer[%d] = %d\n", loop, pairs[loop].integer);
        }
    
        return 0;
    }
    

    另一种选择是使用动态分配 这也使用sscanf来解析输入。 %n将捕获扫描处理的字符数。然后可以使用offsetadd变量来迭代输入。最后一次扫描只捕获ascii字符和整数,sscanf的返回值为2。

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    struct pair {
        char ascii;
        int  integer;
    };
    
    int main( void) {
        char input[] = "a1,b3,!0,t11, 2,,5,\\3,*4,34400,";
        char comma = '\0';
        char ascii = '\0';
        int integer = 0;
        int result = 0;
        int loop = 0;
        int length = 0;
        int used = 0;
        int add = 0;
        int offset = 0;
        struct pair *pairs = NULL;//so realloc will work on first call
        struct pair *temp = NULL;
    
        //assuming input will always end in 00, ( or ,00,)
        //remove those three ( or 4 ??) characters
        length = strlen ( input);
        if ( length > 3) {
            input[length - 3] = '\0';
        }
        while ( ( result = sscanf ( &input[offset], "%c%d%c%n"
        , &ascii, &integer, &comma, &add)) >= 2) {//the last scan will only get two items
            if ( ( temp = realloc ( pairs, ( used + 1) * sizeof ( *pairs))) == NULL) {
                fprintf ( stderr, "problem allocating\n");
                break;
            }
            pairs = temp;
    
            pairs[used].ascii = ascii;
            pairs[used].integer = integer;
            //one more element was used
            used++;
            //the character following the integer should be a comma
            if ( result == 3 && comma != ',') {
                printf ( "format problem\n");
                break;
            }
            //for the next iteration, add to offset
            offset += add;
        }
        for ( loop = 0; loop < used; loop++) {
            printf ( "ascii[%d] = %c   ", loop, pairs[loop].ascii);
            printf ( "value[%d] = %d\n", loop, pairs[loop].integer);
        }
    
        free ( pairs);
    
        return 0;
    }