如何遍历 str 并将每个标记分配给作为全局变量的数组

问题描述

在这代码中,我调用了输入函数并将输入分配给了一个全局变量。然后我在我的 parseFunction 中使用 strtok() 解析全局字符串,用空格将其分开。我将每个令牌分配给一个全局数组。

#define BUFFERSIZE 80
char input[BUFFERSIZE];
char parsed[BUFFERSIZE][50];

void getinput() {
      printf("input command ");
      fgets(input,BUFFERSIZE,stdin);
}

void parseFunction() {
      int i = 0;
      char* tok;
      char* delim = " \n";
      while(tok != NULL) {
            parsed[i] = tok;
            i++;
            tok = strktok(NULL,delim);
      }
      parsed[i] = NULL;
}

int main() {

      getinput();
      parseFunction();

}

我收到以下错误,我不明白出了什么问题。

error: incompatible types when assigning to type ‘char[50]’ from type ‘char *’
         parsed[i] = tok;
                   ^
shell.c:51:15: error: incompatible types when assigning to type ‘char[50]’ from type ‘void *’
     parsed[i] = NULL;

解决方法

评论有助于您完成编译,但还有一些问题等着您。我猜 BUFFERSIZE 是字符串的最大长度,并且您想要一个由 50 个大小为 BUFFERSIZE 的字符串组成的数组。您指定的是大小为 50 的 BUFFERSIZE 字符串。我想您想要 -

#define BUFFERSIZE 80
char input[BUFFERSIZE];
char parsed[50][BUFFERSIZE]; /* size of each of 50 strings is the same as input now,which I think is what you wanted */

如果您同意 Kaylem 关于存储指针的评论(这将起作用),那么它实际上应该是。

#define BUFFERSIZE 80
char input[BUFFERSIZE];
char *parsed[50]; /* an array of 50 pointers to char */

但是您可能想也可能不想重新考虑这一点。下一个问题是如何使用 strtok 迭代输入字符串。当您第一次测试其进入 while 循环的值时,tok 未初始化。结果是不确定的。从内存访问崩溃到简单地为 NULL 并且永远不会进入您的循环,任何疯狂的事情都可能发生。我想你想要的是。

#define BUFFERSIZE 80
char input[BUFFERSIZE];
char *parsed[50];

void parseFunction() {
      int i = 0;
      char* tok;
      char* delim = " \n";
      for (tok = strtok(input,delim); tok != NULL; tok = strtok(NULL,delim) { /* you have to use input the first time you call strtok */
            parsed[i++] = tok; /* short-cut */
            /* maybe a check on i to make sure it doesn't go beyond 49 or you'll crash */
      }
      parsed[i] = NULL;
}

如果您真的想存储指向 input 字符串内位置的指针。但是,假设您将字符串 input 重用于另一轮输入,并将标记添加到 parsed 的末尾。如果您将上述内容放入循环中并从控制台获取更多数据,再次使用 input,并打算将其添加到“已解析”中,就像它是一大组令牌一样。有人输入 10 个标记,然后您存储指向标记的指针 - 指向 input 内部的指针,strtok 正在通过将分隔符替换为空终止符进行修改。然后你得到另外 5 个,然后将这 5 个指针添加到“解析”数组的末尾。前 10 个现在将指向垃圾,因为 fgets 会覆盖输入的内容,strtok 已将其设置为作为子字符串的集合读取。该行为将再次未定义,但几乎肯定会产生垃圾。更安全的方法是实际复制字符串。您使用上面两个声明中的第一个并执行类似 -

#define BUFFERSIZE 80
char input[BUFFERSIZE];
char parsed[50][BUFFERSIZE];

void parseFunction() {
      int i = 0;
      char* tok;
      char* delim = " \n";
      for (tok = strtok(input,delim) {
            strcpy(parsed[i++],tok); /* actually move the chars into one of the strings in "input" */
      }
      parsed[i][0] = '\0'; /* use an empty string in stead of a NULL pointer */
}

现在,无论 input 发生什么,parsed 的内容都是安全的。一些挑剔的 C99 或 C++ 编译器会要求您将 parsed[i] 转换为 char*strcpy,如 (char*)parsed[i]。从技术上讲,parsed[i] 属于 char (*)[BUFFERSIZE] 类型,但较旧的 C 不在乎。

,

在你的代码编译器抱怨,

#define BUFFERSIZE 80
char input[BUFFERSIZE];
char parsed[BUFFERSIZE][50];

void getInput() {
      printf("input command ");
      fgets(input,BUFFERSIZE,stdin);
}

void parseFunction() {
      int i = 0;
      char* tok;
      char* delim = " \n";
      while(tok != NULL) {
            parsed[i] = tok;   // here is error...
            i++;
            tok = strktok(NULL,delim); // this is strtok(original),if you didn't made a wrapper or your own...
      }
      parsed[i] = NULL; //here is error..
}

int main() {

      getInput();
      parseFunction();

}

一个可能的解决方案可能是...

#define BUFFERSIZE 80
char input[BUFFERSIZE];
char parsed[BUFFERSIZE][50];

void getInput() {
      printf("input command ");
      fgets(input,stdin);
}

void parseFunction() {
      int i = 0,j =0; //edit
      char* tok =NULL; //edit
      char* delim = " \n";
      tok = strktok(NULL,delim);  //edit...
      while(tok != NULL) {
            parsed[i][j] = tok;   //edit
            i++;
            tok = strtok(NULL,delim);
      }
      parsed[i][j] = NULL;  //edit
}

int main() {

      getInput();
      parseFunction();

}