用strtok()拆分字符串。

问题描述 投票:0回答:1

我有一个字符串想分成两个不同的字符串,定界符是 $$$.例如,在左边是产品名称,右边是其数量。milk $$$ 45左边是产品名称,右边是数量。我曾用过 strtok 来拆分字符串,但很遗憾,我无法提取数字。

int num;
char *token = strtok(str, DELIMITER);
printf("%s\n", token);
strcpy(component->name, token);
char *number = strtok(NULL, "       ");
num = atoi(number);
printf("%s\n", number);

printf 调用是为了调试。

c
1个回答
1
投票

我没有调试你的代码,但用 strtok_r() 其更好、更直观。C语言提供了两个函数 strtok()strtok_r() 用于用定界符分割一个字符串。

strtok_r()

就像 strtok() C中的函数。strtok_r() 做同样的工作,将一个字符串解析成一个标记序列。strtok_r() 是一个 reentrant strtok()的版本

功能签名

char *strtok_r(char *str, const char *delim, char **saveptr);

第三个论点 saveptr 是一个指向 char * 变量,在内部被 strtok_r() 以便在解析同一字符串的连续调用之间保持上下文。

#include <stdio.h>
#include <string.h> /*for the strtok function*/
#include <ctype.h> /*for the isalpha function*/
int main()
{
    /*assume your string is a raw string just like the one bellow. and if its not.
    please modify the code.
    */
    char str[80] = "milk $$$ 45 meat $$$ 89 water $$$ 12";
    const char* delim = " $$$ ";
    char* token = NULL;
    char* rest = str;
    int num;

    while ((token = strtok_r(rest, " $$$ ", &rest)))
    {
        /*if its a number we will convert it to integer number*/
        if (!isalpha(token[0]))
        {
            num = atoi(token);
            printf("The price is: %d\n",num);
        }
        /*else it is a string*/
        printf("The prodact name is: %s\n", token);

    }


    return 0;
}

0
投票

问题是,你从这样的字符串开始(字符串中的空白对参数没有实质性影响)。

 milk$$$45

假设 DELIMITER"$" (重复美元符号) "$$$" 不会让它看起来有多个 $ 迹象),那么在这之后,你有。

milk\0$$45

在第二个搜索 strtok() 剩余的第一个人继续 $. 它隔离了令牌 $$45 没有空格。 如果在数字前有一个空格,那么它就会将令牌隔离起来 $$ 而不是。) 当你通过 $$45atoi(),它的评价是 0. 你可以通过 printf("[[%s]]\n", number);.

你也许应该用以下方法来解决这个问题。

char *number = strtok(NULL, " \t$");

这将跳过前导空格,标签。$ 字符,然后停止在下一个字符(或字符串末尾的空字节)。 请注意,这段代码并没有确保有3个 $ 符号来分隔名称和数字。


0
投票

你想把输入的字符串拆分在一个定界符串上 $$$: strtok() 不是一个精确的解决方案,因为它不搜索定界符字符串,而是将定界符字符串中的任何字符序列视为定界符。传递 "$$$" 相当于只通过 "$".由于第二次调用使用了不同的定界符集(空格),所以 strtok() 将返回 $$ 作为第二个代币,所以你得到 0 改装后 atoi().

有不同的方法来解决这个问题。

  • 使用 "$""$ \t" 作为第二次调用的定界符。strtok(). 这是很草率的,但在你的情况下会有效,因为第二个字段不包含嵌入的空格和 atoi 忽略前导空格。

    int num;
    char *token = strtok(str, "$");
    if (token) {
        printf("%s\n", token);
        strcpy(component->name, token);
        char *number = strtok(NULL, "$");
        if (number) {
            num = atoi(number);
            printf("%s\n", number);
        }
    }
    
  • 使用 strstr 来定位定界符字符串,并跳过它来获取第二部分。

    int num;
    char *token = str;
    char *p = strstr(str, "$$$");
    if (p) {
        p = '\0';
        p += 3;
    }
    printf("%s\n", token);
    strcpy(component->name, token);
    char *number = p;
    if (number) {
        num = atoi(number);
        printf("%s\n", number);
    }
    
  • 写一个自定义的函数来分割定界符上的字符串, 并且为了一致性而修剪白色空间:

    #include <string.h>
    #include <ctype.h>
    
    char *trim_token(char *str) {
        if (str) {
            size_t len = strlen(str);
            while (len > 0 && isspace((unsigned char)str[-1])
                str[--len] = '\0';
            while (isspace((unsigned char)str[0])
                str++;
        }
        return str;
    }
    
    char *get_token(char *str, const char *delim, char **context) {
        if (!str)
            str = context;
        if (!str)
            return NULL;   // no more tokens
        char *p = strstr(str, delim);
        if (p) {
            *p = '\0';
            p += strlen(delim);
        }
        *context = p;
        // trimming starting and trailing white space from the token is
        //   a good idea, just return str to preserve these spaces.
        return trim_token(str);
    }
    

    并这样使用。

    int num;
    char *context;
    char *token = get_token(str, "$$$", &context);
    if (token) {
        printf("%s\n", token);
        strcpy(component->name, token);
    }
    char *number = get_token(NULL, "$$$", &context);
    if (number) {
        num = atoi(number);
        printf("%s\n", number);
    }
    
© www.soinside.com 2019 - 2024. All rights reserved.