【问题标题】:C split a char array into different variablesC将一个char数组拆分为不同的变量
【发布时间】:2012-05-08 02:54:45
【问题描述】:

在 C 中,如何通过分隔符分隔 char 数组?还是操作字符串更好?有哪些好的 C 字符操作函数?

【问题讨论】:

标签: c arrays string char


【解决方案1】:
#include<string.h>
#include<stdio.h>
int main()
{
    char input[16] = "abc,d";
    char *p;
    p = strtok(input, ",");

    if(p)
    {
    printf("%s\n", p);
    }
    p = strtok(NULL, ",");

    if(p)
           printf("%s\n", p);
    return 0;
}

你可以看看这个程序。首先你应该使用 strtok(input, ",").input 是你想要拆分的字符串。然后你使用 strtok(NULL, ",")。如果返回值为真,则可以打印另一组。

【讨论】:

  • 谢谢你的代码,对不起愚蠢的问题,你为什么要第二次使用 strtok?另外,“如果返回值为真,则可以打印另一组”是什么意思。什么意思?
【解决方案2】:

strtok() strtok() 不是可重入函数。

strtok_r() 是 strtok() 的可重入版本。这是手册中的示例程序:

   #include <stdio.h>
   #include <stdlib.h>
   #include <string.h>

   int main(int argc, char *argv[])
   {
       char *str1, *str2, *token, *subtoken;
       char *saveptr1, *saveptr2;
       int j;

       if (argc != 4) {
           fprintf(stderr, "Usage: %s string delim subdelim\n",argv[0]);
           exit(EXIT_FAILURE);
       }

       for (j = 1, str1 = argv[1]; ; j++, str1 = NULL) {
           token = strtok_r(str1, argv[2], &saveptr1);
           if (token == NULL)
               break;
           printf("%d: %s\n", j, token);

           for (str2 = token; ; str2 = NULL) {
               subtoken = strtok_r(str2, argv[3], &saveptr2);
               if (subtoken == NULL)
                   break;
               printf(" --> %s\n", subtoken);
           }
       }

       exit(EXIT_SUCCESS);
   }

对子令牌进行操作的示例运行,该子令牌是从基于不同分隔符的前一个令牌获得的:

$ ./a.out hello:word:bye=abc:def:ghi = :

1: hello:word:bye
 --> hello
 --> word
 --> bye
2: abc:def:ghi
 --> abc
 --> def
 --> ghi

【讨论】:

  • 请不要推荐strtok,它是不可重入的。它的“大哥”strtok_r好多了。
  • @Thiruvalluvar:这不仅仅是线程安全——如果你想同时标记两个不同的字符串怎么办,例如在同一个循环中?
  • 举个例子就好了。
  • @SSHThis 接受的答案中已经有一个例子。我不想重复同样的事情。
  • 点已接受,但strtok_r 哪个更好/更安全呢?
【解决方案3】:

一个选项是 strtok

示例:

char name[20];
//pretend name is set to the value "My name"

您想在两个单词之间的空格处拆分它

split=strtok(name," ");

while(split != NULL)
{
    word=split;
    split=strtok(NULL," ");
}

【讨论】:

    【解决方案4】:

    您可以简单地将分隔符替换为 NULL 字符,并将新创建的 NULL 字符之后的地址存储在新的 char* 指针中:

    char* input = "asdf|qwer"
    char* parts[10];
    int partcount = 0;
    
    parts[partcount++] = input;
    
    char* ptr = input;
    while(*ptr) { //check if the string is over
        if(*ptr == '|') {
            *ptr = 0;
            parts[partcount++] = ptr + 1;
        }
        ptr++;
    }
    

    请注意,如果输入字符串包含超过 9 个分隔符,则此代码当然不起作用。

    【讨论】:

      【解决方案5】:

      我想出了这个。这似乎对我来说效果最好。它转换一串数字并将其拆分为整数数组:

      void splitInput(int arr[], int sizeArr, char num[])
      {
          for(int i = 0; i < sizeArr; i++)
              // We are subtracting 48 because the numbers in ASCII starts at 48.
              arr[i] = (int)num[i] - 48;
      }
      

      【讨论】:

        【解决方案6】:

        我就是这样做的。

        void SplitBufferToArray(char *buffer, char * delim, char ** Output) {
        
            int partcount = 0;
            Output[partcount++] = buffer;
        
            char* ptr = buffer;
            while (ptr != 0) { //check if the string is over
                ptr = strstr(ptr, delim);
                if (ptr != NULL) {
                    *ptr = 0;
                    Output[partcount++] = ptr + strlen(delim);
                    ptr = ptr + strlen(delim);
                }
        
            }
            Output[partcount++] = NULL;
        }
        

        【讨论】:

          【解决方案7】:

          此外,您可以将sscanf 用于一些非常简单 的场景,例如当您确切知道字符串有多少部分 以及它由什么组成时。您还可以即时解析参数。 不要将其用于用户输入,因为该函数不会报告转换错误。

          例子:

          char text[] = "1:22:300:4444:-5";
          int i1, i2, i3, i4, i5;
          sscanf(text, "%d:%d:%d:%d:%d", &i1, &i2, &i3, &i4, &i5);
          printf("%d, %d, %d, %d, %d", i1, i2, i3, i4, i5);
          

          输出:

          1、22、300、4444、-5

          如其他答案所述,对于更高级的内容,strtok()strtok_r() 是您的最佳选择。

          【讨论】:

            猜你喜欢
            • 2012-02-25
            • 2017-10-27
            • 2013-02-23
            • 2021-12-06
            • 1970-01-01
            • 2011-10-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多