[英]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.