用分隔符将字符串分割成标记并保存为变量

时间:2022-02-06 02:42:51

I want to split a string into tokens and save data into variables. I have the following string:

我想将字符串分割成记号并将数据保存到变量中。我有以下字符串:

John|Doe|Melbourne|6270|AU

约翰墨尔本| | Doe | 6270 |盟

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

5 个解决方案

#1


9  

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

#2


5  

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.

这使用%[]字符集格式说明符来获取“除了垂直条之外的所有内容”。宽度包含在其中,以防止缓冲区溢出。

#3


3  

just keep on calling strtok

继续打电话给斯特托克

char* name = strtok(str, "|");
char* surname = strtok(NULL, "|");
...

#4


3  

strtok returns 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:

要解决高华斯的评论,使用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;
  • 它修改输入字符串,将每次出现的分隔符替换为0,这意味着它不能用于字符串文字。如果要保留原始字符串,则必须复制到strtok;
  • It uses a single, static buffer to store the string it's modifying, making it non-reentrant - if multiple threads make calls to strtok to 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);
  • 它使用一个单一的静态缓冲区存储字符串修改,使其不可重入,如果多个线程调用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_rfunction。

#5


2  

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

}

#1


9  

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

#2


5  

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.

这使用%[]字符集格式说明符来获取“除了垂直条之外的所有内容”。宽度包含在其中,以防止缓冲区溢出。

#3


3  

just keep on calling strtok

继续打电话给斯特托克

char* name = strtok(str, "|");
char* surname = strtok(NULL, "|");
...

#4


3  

strtok returns 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:

要解决高华斯的评论,使用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;
  • 它修改输入字符串,将每次出现的分隔符替换为0,这意味着它不能用于字符串文字。如果要保留原始字符串,则必须复制到strtok;
  • It uses a single, static buffer to store the string it's modifying, making it non-reentrant - if multiple threads make calls to strtok to 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);
  • 它使用一个单一的静态缓冲区存储字符串修改,使其不可重入,如果多个线程调用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_rfunction。

#5


2  

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

}