简体   繁体   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

As an Example, Input: 例如,输入:

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

Output: 输出:

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

I have tried using strtok to remove "]". 我尝试使用strtok删除“]”。 But, when I use strtok next time, I am not able to use it. 但是,当我下次使用strtok时,我将无法使用它。 If I try to print the output, I get 如果我尝试打印输出,我得到

[1,2,3
[1
2
3

instead of 代替

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

Code that I have so far 到目前为止我拥有的代码

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);
    }
}

Your problem is, that strtok has a memory. 您的问题是,strtok有内存。 First time that you pass in a string, it is remembered and then used again and again as long as you pass in NULL as first parameter. 第一次传递字符串时,只要您将NULL作为第一个参数传递,它就会被记住并反复使用。

However, within your loop, you call strtok again with a parameter. 但是,在循环中,您可以使用参数再次调用strtok。 So this new string (which is the first token only) is placed in strtok's memory, and after it is processed completely in the inner loop, there is nothing left to tokenize in the outer loop. 因此,这个新的字符串(仅是第一个标记)被放置在strtok的内存中,并且在内部循环中对其进行了完全处理之后,在外部循环中没有剩下要标记化的内容。

Have a look at this thread , it explains more detailed how strtok works. 看一下该线程 ,它更详细地说明了strtok的工作方式。

However, you are lucky: strtok is manipulating the string you first passed in place (this is why you have to pass the string to be tokenized as char* , but the delimiters can be a const char* ). 但是,您很幸运:strtok正在处理您首先在原处传递的字符串(这就是为什么您必须传递要标记为char*的字符串,但分隔符可以是const char* )。 So you can do this: 因此,您可以执行以下操作:

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, ",")));
}

If you are wondering about the extra parentheses, these are to prevent a warning in the compiler ("possible assignment instead of comparison"). 如果您想知道多余的括号,可以防止在编译器中出现警告(“可能的分配而不是比较”)。

This solution has two nested loops of strtok_s , because strtok is not re-entrant. 该解决方案具有两个strtok_s嵌套循环,因为strtok不可重入。 This is MSVC, some systems implement the similar strtok_r . 这是MSVC,某些系统实现了类似的strtok_r

I have created output in accordance with the top of your question, this can be modified to suit other output, it was not very clear. 我已经按照您的问题的顶部创建了输出,可以将其修改为适合其他输出,这不是很清楚。 In this case, it was not really necessary to have two nested loops, but your subsequent examples confuse the issue by breaking up the comma'ed input. 在这种情况下,并不需要两个嵌套循环,但是您后面的示例通过分解逗号输入而使问题变得困惑。

#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;
}

The simpler program where you don't need to examine within the [brackets] is 您无需在[方括号]中进行检查的简单程序是

#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;
}

In both cases the output is: 在这两种情况下,输出均为:

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

EDIT altered the second example to give output as per OP's recent comment above. 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;
}

Program output: 程序输出:

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

If you are converting a string of character digits to an array of integer values, one character per value (or allowing a - before any character digit to indicate a negative value for your array), you may be better off writing a simple function to step though the string and perform your conversions manually. 如果要将字符串数字字符串转换为整数值数组(每个值一个字符)(或在任何字符数字前允许-表示数组的负值 ),则最好编写一个简单的步骤通过字符串并手动执行转换。

An example using array indexing of the string could be written a follows. 下面是使用字符串的数组索引的示例。 You could easily change the array index notations to pointer notation which is more intuitive to some. 您可以轻松地将数组索引符号更改为指针符号,这对于某些人来说更直观。

#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 */
}

Example Use/Output 使用/输出示例

$ ./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

Look it over, compare this approach to the other answers. 仔细研究一下,将此方法与其他答案进行比较。 In C, you have as much fine-grain-control over how you parse data as you want to exercise. 在C语言中,您可以根据自己的需要对数据的解析方式进行精细控制。 If you have no need to handle negative values, then the implementation is much simpler. 如果您不需要处理负值 ,那么实现会更加简单。 Let me know if you have any questions. 如果您有任何疑问,请告诉我。

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

相关问题 如何将具有 2 位或更多位数字的 integer 显示为字符串? - How can I display integer that has 2 or more digits as a string? 如何在C中按索引对齐两个整数数组? - How can I align two integer arrays by index in C? 如何将 C 中的两个整数数组与 for 循环合并 - How can I merge two integer arrays in C with for loops 我如何合并这两个数组? C - How would I merge these two arrays? C 如何在C中将整数转换为Unicode字符串? - How can I convert an integer into a Unicode string in C? 如何在C中将整数转换为十六进制字符串? - How can I convert an integer to a hexadecimal string in C? 如何在不使用其他 arrays 的情况下交换 C 中指针字符串数组中的两个字符串? - how can I swap two strings in a string-array of pointers in C without using other arrays? 我可以像使用字符串数组一样使用指针打印出int数组吗? - Can I use pointer to print out arrays of int array just like arrays of string? 我可以像处理字符串数组那样同时定义和分配一个 integer 数组吗? - Can I define and assign an integer array at the same time like we do with the string array? 在找到两个输入 arrays 的并集和交集的 C 程序中,我在交集部分有问题 - In C program which find union and intersection of two input arrays, I have a problem in intersection part
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM