看了其他答案,对于 C 语言的初学者来说,由于代码紧凑,可能会难以理解。我认为应该为初学者提供一个更简单的方法,即直接解析字符串,而不是使用 strtok
...就像这样:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
char **parseInput(const char *str, int *nLen);
void resizeptr(char ***, int nLen);
int main(int argc, char **argv){
int maxLen = 0;
int i = 0;
char **ptr = NULL;
char *str = "valgrind --leak-check=yes --track-origins=yes ./a.out";
ptr = parseInput(str, &maxLen);
if (!ptr) printf("Error!\n");
else{
for (i = 0; i < maxLen; i++) printf("%s\n", ptr[i]);
}
for (i = 0; i < maxLen; i++) free(ptr[i]);
free(ptr);
return 0;
}
char **parseInput(const char *str, int *Index){
char **pStr = NULL;
char *ptr = (char *)str;
int charPos = 0, indx = 0;
while (ptr++ && *ptr){
if (!isspace(*ptr) && *ptr) charPos++;
else{
resizeptr(&ptr, ++indx);
pStr[indx-1] = (char *)malloc(((charPos+1) * sizeof(char))+1);
if (!pStr[indx-1]) return NULL;
strncpy(pStr[indx-1], ptr - (charPos+1), charPos+1);
pStr[indx-1][charPos+1]='\0';
charPos = 0;
}
}
if (charPos > 0){
resizeptr(&pStr, ++indx);
pStr[indx-1] = (char *)malloc(((charPos+1) * sizeof(char))+1);
if (!pStr[indx-1]) return NULL;
strncpy(pStr[indx-1], ptr - (charPos+1), charPos+1);
pStr[indx-1][charPos+1]='\0';
}
*Index = indx;
return (char **)pStr;
}
void resizeptr(char ***ptr, int nLen){
if (*(ptr) == (char **)NULL){
*(ptr) = (char **)malloc(nLen * sizeof(char*));
if (!*(ptr)) perror("error!");
}else{
char **tmp = (char **)realloc(*(ptr),nLen);
if (!tmp) perror("error!");
*(ptr) = tmp;
}
}
我稍微修改了代码,使它更容易理解。我只使用了一个字符串函数
strncpy
。虽然这个函数有点冗长,但它可以动态地重新分配字符串数组的大小,而不是使用硬编码的MAX_ARGS。这意味着当只需要3或4个指针时,双指针已经占用了内存,使用
realloc
可以使内存使用更加高效和小巧。简单的解析可以通过使用
isspace
来完成,它会迭代使用指针。当遇到空格时,它会
realloc
双指针,并
malloc
偏移量以保存字符串。
请注意,在
resizeptr
函数中如何使用三级指针。实际上,我认为这是一个简单的C程序、指针、realloc、malloc、按引用传递、解析字符串的基本元素的绝佳示例...
希望这能帮到你,
最好的祝愿,
汤姆。