C语言 C 通过分隔符将字符串拆分为标记并另存为变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17085189/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C split string into token by delimiter and save as variables
提问by bsteo
I want to split a string into tokens and save data into variables. I have the following string:
我想将字符串拆分为标记并将数据保存到变量中。我有以下字符串:
John|Doe|Melbourne|6270|AU
John|Doe|Melbourne|6270|AU
I need to split it by |and every token keep as variable so I can use them in my program, like:
我需要将它拆分,|并且每个令牌都保留为变量,以便我可以在我的程序中使用它们,例如:
fname = "John"
lname = "Doe"
city = "Melbourne"
zip = "6270"
country = "AU"
tried this so far, I can access first token the rest I don't know how (besides a while loop that doesn't help me):
到目前为止,我可以访问第一个令牌,其余的我不知道如何(除了对我没有帮助的 while 循环):
#include <stdio.h>
#include <string.h>
int main (void) {
char str[] = "John|Doe|Melbourne|6270|AU";
strtok(str, "|");
printf("%s\n", str);
return 0;
}
回答by BLUEPIXY
char fname[32], lname[32], city[32], zip[32], country[32];
strcpy(fname, strtok(str , "|"));
strcpy(lname, strtok(NULL, "|"));
strcpy(city , strtok(NULL, "|"));
strcpy(zip , strtok(NULL, "|"));
strcpy(country, strtok(NULL, "|"));
printf("%s\n", fname);
printf("%s\n", lname);
printf("%s\n", city);
printf("%s\n", zip);
printf("%s\n", country);
回答by unwind
If the format is constant, you can use sscanf():
如果格式不变,您可以使用sscanf():
char fname[32], lname[32], city[32], zip[16], country[8];
if(sscanf(str, "%31[^|]|%31[^|]|%31[^|]|%15[^|]%7s",
fname, lname, city, zip, country) == 5)
{
}
This uses the %[]character set format specifier to grab "everything except a vertical bar". The width is included to prevent buffer overruns.
这使用%[]字符集格式说明符来抓取“除垂直条之外的所有内容”。包括宽度以防止缓冲区溢出。
回答by AndersK
just keep on calling strtok
继续调用 strtok
char* name = strtok(str, "|");
char* surname = strtok(NULL, "|");
...
回答by John Bode
strtokreturns a pointer to the token; pass NULL as the first argument to retrieve successive tokens:
strtok返回一个指向令牌的指针;传递 NULL 作为检索连续令牌的第一个参数:
#define FIELD_LENGTH 20
#define NUM_FIELDS 5
...
char target[NUM_FIELDS][FIELD_LENGTH];
int field = 0;
...
while ( get_next_string( str )) // where get_next_string retrieves your next
{ // delimited string
char *token = strtok( str, "|" );
while ( token )
{
strcpy( target[i++], token );
token = strtok( NULL, "|" );
}
}
Edit
编辑
To address Golgauth's comment, there are some important things to remember about using strtok:
为了解决 Golgauth 的评论,使用 时需要记住一些重要的事情strtok:
- It modifies the input string by replacing each occurrence of the delimiter with a 0, meaning it cannot be used on a string literal. If you want to preserve the original string, you will have to make a copy to pass to
strtok; - It uses a single, static buffer to store the string it's modifying, making it non-reentrant- if multiple threads make calls to
strtokto tokenize different strings, they'll wind up stepping on each other (this is known as a race condition, where the behavior of the program depends on which thread gets access to something first). Also, you can't nest calls to strtok (that is, get a token, then split it into subtokens, then get the next token);
- 它通过用 0 替换每个出现的分隔符来修改输入字符串,这意味着它不能用于字符串文字。如果要保留原始字符串,则必须制作副本以传递给
strtok; - 它使用单个静态缓冲区来存储它正在修改的字符串,使其不可重入- 如果多个线程调用
strtok以标记不同的字符串,它们最终会相互踩踏(这称为竞争条件,其中程序的行为取决于哪个线程首先访问某些东西)。此外,您不能嵌套对 strtok 的调用(即获取令牌,然后将其拆分为子令牌,然后获取下一个令牌);
The online 2011 standard mentions a safer (and IINM re-entrant) alternative, strtok_s, as part of Annex K (Bounds-checking interfaces); some implementations also provide a strtok_rfunction which is re-entrant.
2011 年在线标准提到了一个更安全(和 IINM 可重入)的替代方案strtok_s,作为附件 K(边界检查接口)的一部分;一些实现还提供了strtok_r可重入的功能。
回答by collaborator
You can use sscanf with that (it can scan strings up to a given delimiter)
您可以使用 sscanf (它可以扫描字符串到给定的分隔符)
int n;
char fname[128]= "", lname[128]= "", city[128]= "", zipcode[128]= "", country[128]= "";
n= sscanf str("%127[^|]|%127[^|]|%127[^|]|%127[^|]|%127s", fname, lname, city, zipcode, country);
if (n==5) { // five fields scanned
}

