在这段代码中,我调用输入函数并将输入分配给一个全局变量。然后我在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迭代输入字符串。当您第一次测试tok
的值进入while循环时,它是未初始化的。结果未定义。任何疯狂的事情都可能发生,从内存访问崩溃到意外变成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
正在通过用空终止符替换delimeter来修改该指针。然后你得到另一个5,并将这5个指针添加到你的"0"的末尾;解析的";大堆前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); tok != NULL; tok = strtok(NULL, delim) {
strcpy(parsed[i++], tok); /* actually move the chars into one of the strings in "input" */
}
parsed[i][0] = ' '; /* use an empty string in stead of a NULL pointer */
}
现在,不管input
发生了什么,parsed
的内容都是安全的。一些挑剔的C99或C++编译器将要求将parsed[i]
强制转换为strcpy
的char*
,如(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, BUFFERSIZE, 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();
}