问题描述
在这段代码中,我调用了输入函数并将输入分配给了一个全局变量。然后我在我的 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();
}