繁体   English   中英

我有一个字符串str,其中有两个数组(可以更多),我想将其转换为C中的整数数组

[英]I have a string str which has two array (can be more) that I would like to convert to integer arrays in C

例如,输入:

c[] = "[1,2,3][5,7,8]"

输出:

a = [1,2,3] //of type int a[]
b = [5,7,8] //of type int b[]

我尝试使用strtok删除“]”。 但是,当我下次使用strtok时,我将无法使用它。 如果我尝试打印输出,我得到

[1,2,3
[1
2
3

代替

[1,2,3
[1
2
3
[5,7,8
[5
7
8

到目前为止我拥有的代码

char c[] = "[1,2,3][5,7,8]"; 

char *token = strtok(c, "]");
for (token; token != NULL ; token = strtok(NULL, "]")){
    puts(token);
    char *comma = strtok(c, ",");
    for (comma; comma != NULL; comma = strtok(NULL, ",")){
        puts(comma);
    }
}

您的问题是,strtok有内存。 第一次传递字符串时,只要您将NULL作为第一个参数传递,它就会被记住并反复使用。

但是,在循环中,您可以使用参数再次调用strtok。 因此,这个新的字符串(仅是第一个标记)被放置在strtok的内存中,并且在内部循环中对其进行了完全处理之后,在外部循环中没有剩下要标记化的内容。

看一下该线程 ,它更详细地说明了strtok的工作方式。

但是,您很幸运:strtok正在处理您首先在原处传递的字符串(这就是为什么您必须传递要标记为char*的字符串,但分隔符可以是const char* )。 因此,您可以执行以下操作:

char c[] = "[1,2,3][5,7,8]";

char* next = c;
char* token;
while((token = strtok(next, "]")))
{
    puts(token);
    next += strlen(token) + 1; // move next behind the token
    token = strtok(token, ",");
    do
    {
        puts(token);
    }
    while((token = strtok(NULL, ",")));
}

如果您想知道多余的括号,可以防止在编译器中出现警告(“可能的分配而不是比较”)。

该解决方案具有两个strtok_s嵌套循环,因为strtok不可重入。 这是MSVC,某些系统实现了类似的strtok_r

我已经按照您的问题的顶部创建了输出,可以将其修改为适合其他输出,这不是很清楚。 在这种情况下,并不需要两个嵌套循环,但是您后面的示例通过分解逗号输入而使问题变得困惑。

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

int main(void) {
    char c[] = "[1,2,3][5,7,8]"; 
    char *tok1 = NULL;
    char *tok2 = NULL;
    char *end1 = NULL;
    char *end2 = NULL;
    int comma = 0;
    char identifier = 'a';

    tok1 = strtok_s(c, "[]", &end1);
    while(tok1 != NULL) {                       // outer loop splitting [bracket] parts
        printf("%c = [", identifier);
        comma = 0;                              // control comma output
        tok2 = strtok_s(tok1, ",", &end2);
        while(tok2 != NULL) {                   // inner loop splitting ,comma, parts
            if(comma) {                         // check if comma required
                printf(",");
            }
            printf("%s", tok2);
            comma = 1;                          // a comma will be needed
            tok2 = strtok_s(NULL, ",", &end2);
        }
        printf("] //of type int %c[]\n", identifier);
        identifier++;
        tok1 = strtok_s(NULL, "[]", &end1);
    }
    return 0;
}

您无需在[方括号]中进行检查的简单程序是

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

int main(void) {
    char c[] = "[1,2,3][5,7,8]"; 
    char *tok = NULL;
    char identifier = 'a';

    tok = strtok(c, "[]");
    while(tok != NULL) {
        printf("%c = [%s] //of type int %c[]\n", identifier, tok, identifier);
        identifier++;
        tok = strtok(NULL, "[]");
    }
    return 0;
}

在这两种情况下,输出均为:

a = [1,2,3] //of type int a[]
b = [5,7,8] //of type int b[]

EDIT修改了第二个示例,以根据上面OP最近的评论提供输出。

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

int main(void) {
    char c[] = "[1,2,3][5,7,8]"; 
    char *tok = NULL;
    char identifier = 'a';

    tok = strtok(c, "[]");
    while(tok != NULL) {
        printf("int %c[] = { %s };\n", identifier, tok, identifier);
        identifier++;
        tok = strtok(NULL, "[]");
    }
    return 0;
}

程序输出:

int a[] = { 1,2,3 };
int b[] = { 5,7,8 };

如果要将字符串数字字符串转换为整数值数组(每个值一个字符)(或在任何字符数字前允许-表示数组的负值 ),则最好编写一个简单的步骤通过字符串并手动执行转换。

下面是使用字符串的数组索引的示例。 您可以轻松地将数组索引符号更改为指针符号,这对于某些人来说更直观。

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

size_t str2arr (char *d, size_t max, char *s, size_t *ofs);

int main (int argc, char **argv) {

    char c[] = "[1,2,3][5,7,8]";
    char *p = argc > 1 ? argv[1] : c;
    size_t i, offset = 0, na = 0, nb = 0, nchr = strlen (p);
    char a[nchr], b[nchr];

    memset (a, 0, nchr * sizeof *a);  /* zero each VLA */
    memset (b, 0, nchr * sizeof *b);

    na = str2arr (a, nchr, p, &offset);          /* convert first segment */
    nb = str2arr (b, nchr, p + offset, &offset); /* convert second segment */

    for (i = 0; i < na; i++)                     /* output results */
        printf (" a[%2zu] : % d\n", i, a[i]);
    putchar ('\n');

    for (i = 0; i < nb; i++)
        printf (" b[%2zu] : % d\n", i, b[i]);
    putchar ('\n');

    return 0;
}

/** convert a string of characters to an array of values
 *  including accounting for negative values. the destination
 *  index `di` returns the number of characters conversions, the
 *  offset of the next segment within 's' is updated in pointer 'ofs'
 */
size_t str2arr (char *d, size_t max, char *s, size_t *ofs)
{
    if (!d || !s || !*s) return 0;  /* validate input */
    size_t di = 0, neg = 0;
    register size_t si = 0;

    for (; di < max && s[si]; si++, di++) {       /* for each character */
        if (s[si] == ']') break;
        while (s[si] && (s[si] < '0' || ('9' < s[si]))) { /* if not digit */
            if (s[si] == '-') neg = 1;          /* if '-' sign, set flag */
            else neg = 0;              /* clear if not last before digit */
            si++;
        }
        if (!s[si]) break;                 /* validate not end of string */
        d[di] = neg ? -(s[si] - '0') : s[si] - '0';  /* convert to digit */
        neg = 0;                                     /* reset flag */
    }

    *ofs = si + 1;  /* update offset before return  */

    return di;      /* return number of conversions */
}

使用/输出示例

$ ./bin/str2arr
 a[ 0] :  1
 a[ 1] :  2
 a[ 2] :  3

 b[ 0] :  5
 b[ 1] :  7
 b[ 2] :  8

$ ./bin/str2arr "[1,2,3,4][5,6,-5,7,-1,8,9,2]"
 a[ 0] :  1
 a[ 1] :  2
 a[ 2] :  3
 a[ 3] :  4

 b[ 0] :  5
 b[ 1] :  6
 b[ 2] : -5
 b[ 3] :  7
 b[ 4] : -1
 b[ 5] :  8
 b[ 6] :  9
 b[ 7] :  2

仔细研究一下,将此方法与其他答案进行比较。 在C语言中,您可以根据自己的需要对数据的解析方式进行精细控制。 如果您不需要处理负值 ,那么实现会更加简单。 如果您有任何疑问,请告诉我。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM