【问题标题】:strtok - how avoid new line to and put to array of strings?strtok - 如何避免换行并放入字符串数组?
【发布时间】:2011-07-06 13:56:55
【问题描述】:

如果我欺骗了主题,我真的很抱歉,我在这里搜索它没有结果。 我有代码

void split(char* str, char* splitstr)
{
     char* p;
     char splitbuf[32];
     int i=0;
     p = strtok(str,",");
     while(p!= NULL)
     {
               printf("%s", p);    
               sprintf(&splitstr[i],"%s",p);
               i++;
               p = strtok (NULL, ",");

     }
}

如何使用正确的 sprintf 将 strtok 拆分的单词放入字符串数组? 我能以某种方式避免由 strtok 创建的断线吗? 我正在用 ANSI C 编程。我以相同的方式声明了数组 splitstr 和 str 。

char* splitstr;//in main char splitstr[32];

感谢您的帮助。


编辑:

我想做这样的事情: INPUT (它是一个字符串) > "aa,bbb,ccc,ddd" 我声明:char tab[33]; 输出(如果可能,将所有项目保存到字符串数组)> 选项卡 [0] 是“aa” 选项卡 [1] 是“bbb” ... tab[3] 是 "ddd" 但不是 "ddd(newline)"

edit2 [18:16]

我忘记添加数据字符串来自文件的读取行。这就是我写“ddd(newline)”的原因。之后我发现新行也由 strtok 显示,但作为另一个项目。顺便说一句,所有答案都很好地考虑了这个问题。几秒钟前我的笔记本电脑坏了(我不知道为什么屏幕变黑了) 一旦我控制了我的电脑,我就会检查代码。 :-)

【问题讨论】:

  • 不太确定您要达到的目标。如果你用字符串“a,b,c”调用split,你期望splitstr返回什么?你想创建一个 C 字符串数组 {"a", "b", "c"}?
  • 注意数组和指针的区别。 它们不是一回事。
  • strtok 是一个有点“难”的函数。例如,如果您想用空格分割字符串 "one two three"strtok 更改该字符串(它不能是指向文字字符串的指针)到 "one#two#three",其中 @987654327 @ 实际上是 NUL 字符 ('\0')。
  • 正如下面的 Kevin 所说,如果你想得到一个字符串数组,那么你需要将 splitstr 声明为 char[something][32]。同样正如@pmg 所说,您需要非常小心地理解数组和指针之间的区别。
  • 最后一个值后换行的问题是最容易处理的问题。它存在是因为您使用的输入法已将其留在那里(无论该输入法是什么)。如果您不想要它,最好在使用拆分方法之前将其剥离。你得到“ddd(newline)”的原因是因为你从“aa,bbb,ccc,ddd(newline)”开始。strtok 和 sprintf 都没有把它放在那里。顺便说一句,你最好使用 strcpy 而不是 sprintf .

标签: c arrays string split strtok


【解决方案1】:

如果我理解正确,你想保存 strtok 获得的字符串。在这种情况下,您需要将 splitstr 声明为 char[MAX_LINES][32] 并使用 strcpy,如下所示:

strcpy(splitstr[i], p);

其中 i 是使用 strtok 读取的第 i 个字符串。

【讨论】:

    【解决方案2】:

    请注意,我不是 ansi C 专家,更多的是 C++ 专家,但这里是工作代码。它使用固定大小的数组,这可能是也可能不是问题。做其他事情需要更复杂的内存管理:

    /* Not sure about the declaration of splitstr here, and whether there's a better way.
       char** isn't sufficient. */
    int split(char* str, char splitstr[256][32])
    {
       char* p;
       int i=0;
       p = strtok(str,",");
       while(p) {
       strcpy(splitstr[i++], p);
           p = strtok (NULL, ",");
       }
       return i;
    }
    
    int main(int argc, char* argv[])
    {
     char input[256];
      char result[256][32];
      strcpy(input, "aa,bbb,ccc,ddd");
      int count = split(input, result);
    
      for (int i=0; i<count; i++) {
        printf("%s\n", result[i]);
      }
          printf("the end\n");
    }
    

    请注意,我输入 "aa,bbb,ccc,ddd" 并输出 {"aa", "bbb", "ccc", "ddd" }。结果中没有换行符。

    【讨论】:

    • 是的,这是真的,我看得很清楚,但是如果我读到这样的内容会发生什么: line1:aa,bb,cc(newline) line2:dd,ee,(newline) ?Result: aa bb cc(双空格)dd ee。对吗?
    • 嗯。不明白你的意思。如果你将 "aa,bb,cc(newline)" 传递给 split 你会得到 {"aa","bb","cc(newline)" }。如果你传入 "dd,ee,(newline)" 你会得到 {"dd","ee","(newline)"}。不确定您在这里期待什么或“(双空格)”期待什么。如果您不希望在输出字符串的末尾出现换行符,则必须在读入字符串后并在传递给 split 之前从字符串末尾删除换行符。
    【解决方案3】:

    试一试:

    #include <stdlib.h>
    #include <string.h>
    ...
    void split(char *str, char **splitstr) 
    {      
      char *p;      
      int i=0;      
    
      p = strtok(str,",");      
      while(p!= NULL)      
      {                
        printf("%s", p);
        splitsr[i] = malloc(strlen(p) + 1);
        if (splitstr[i])
          strcpy(splitstr[i], p);
        i++;
        p = strtok (NULL, ",");       
      } 
    }
    

    然后,在main

    #define MAX_LEN  ... // max allowed length of input string, including 0 terminator
    #define MAX_STR  ... // max allowed number of substrings in input string
    
    int main(void)
    {
      char input[MAX_LEN]; 
      char *strs[MAX_STR] = {NULL}; 
      ...
      split(input, strs);
      ...
    }
    

    一些解释。

    strsmain 中定义为指向char 的指针数组。每个数组元素将指向从输入字符串中提取的字符串。在 main 中,所有分配的都是指针数组,每个元素最初为 NULL;每个元素的内存将根据子字符串的长度在split 函数中使用malloc 分配。 某处 完成strs 后,您需要使用free 释放这些指针:

    for (i = 0; i < MAX_STR; i++)
      free(strs[i]);
    

    现在,为什么 splitstr 声明为 char ** 而不是 char *[MAX_STR]?除非它是sizeof&amp; 运算符的操作数,或者是用于在声明中初始化另一个数组的字符串文字,否则数组表达式的类型将隐式从N-element array of T 转换为pointer to T,并且表达式的值将是数组中第一个元素的位置。

    当我们拨打split时:

    split(input, strs);
    

    数组表达式inputchar [MAX_LENGTH]类型隐式转换为char *(T == char),数组表达式strschar *[MAX_STRS]类型隐式转换为char **( T == char *)。所以splitstr 接收两个参数的指针值,而不是数组值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-06-30
      • 2021-04-02
      • 2015-12-16
      • 1970-01-01
      • 1970-01-01
      • 2010-12-01
      • 2020-02-24
      相关资源
      最近更新 更多