gn6*_*n66 1 c arrays string multidimensional-array
当我想在动态数组中保存字符串时,我遇到了分段错误.
我有一个程序执行此操作:
用户插入char"s"
程序进入循环并将数组中的字符串保存(名称:cod).
当用户插入char"t"时,它会停止
之后我将该数组保存在新动态数组的第一个位置(名称:vec).
然后,如果用户再次插入char"s"
程序进入循环并将字符串保存在数组中.
当用户插入char"t"时,它会停止
之后我将该数组保存在新动态数组的第二个位置.
等等.
这是我的代码:
int main(){
char Cod[30][11];
char tmp[11];
char ***vec;
int i = 0;
strcpy (tmp, "p");
vec = (char *** ) malloc (sizeof ( char *) );
vec[0] = (char ** ) malloc (sizeof ( char *) * 30);
do {
scanf("%s", tmp);
while( (strcmp (tmp, "p")) != 0){
strcpy ( Cod[i] , tmp );
scanf("%s", tmp);
i++;
}
vec = (char ***) realloc (vec, sizeof ( char *) * (i + 1));
vec[i + 1] = (char ** ) realloc (vec[i + 1], sizeof ( char *) * (30));
vec[i-1] = (char **) Cod;
scanf("%s", tmp);
}
while((strcmp (tmp, "s")) == 0);
printf("%s", vec[0][0]);
Run Code Online (Sandbox Code Playgroud)
返回0;
}
这是代码的一部分:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char Cod[30][11];
char tmp[11];
int i = 0;
strcpy (tmp, "p");
do {
scanf("%s", tmp);
while( (strcmp (tmp, "p")) != 0){
strcpy ( Cod[i] , tmp );
scanf("%s", tmp);
i++;
}
scanf("%s", tmp);
}
while((strcmp (tmp, "s")) == 0);
printf("%s", Cod[0]);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我开始修复这段代码,但很快意识到它有很多错误,我不知道从哪里开始.所以相反,这反过来是一个代码审查答案,如果它是详细和挑剔我道歉.
C中有一条经验法则,如果你需要两个以上的指针间接层,你的代码就会被混淆,应该重写(参考MISRA-C:2004 17.5).
在这种情况下使用动态内存分配没有任何意义,因为在程序启动时你已经知道没有字符串将超过11个字符,并且不会有超过30个字符串.如果这种情况不成立,你需要编写一个更安全的输入方法,最好用fgets()来防止缓冲区溢出.确保输入不超出数组"Cod"的范围.您可以静态分配30*11 = 330个字节而不会有良心.它会使代码更快.
对于字符串数组有3级间接是没有意义的.你甚至没有使用动态内存来保存字符串的副本,你只需要分配指针.这根本没有任何意义.如果需要指向的指针查找表Cod然后静态分配它,它只需要sizeof(char*)*30个字节.
如前所述,您只能在以前使用malloc/calloc:ed的指针上使用realloc.
如前所述,永远不要在C中使用malloc/realloc的结果进行类型转换.这是C++实践.在C中,它破坏了类型安全性并隐藏了类型兼容性错误.如果您想了解详细信息,可以在此处进行无数详细的讨论.
如果在用户字符串中找不到"p"怎么办?该计划将受到严重破坏.
不要将影响基本程序功能的变量命名为抽象的东西,如tmp,vec等.tmp可以重命名为input_buf或其他东西等.
避免使用代码中的幻数,使用const或#define作为数组长度常量.
您可以在C中初始化字符串,不需要strcpy来执行此操作. char input_buf[INP_BUF_N] = "p";
要在字符串中搜索char,请使用strchr().
您不应该让用户在外部do-while循环中使用scanf()两次输入相同的东西,这可能是一个错字错误.
您不能在静态数组数组与指向指针之间进行疯狂的类型转换.这取决于指向指针的指针的结构.因为一个典型的哑学校书动态2D数组(malloc(X sizeof(char)... malloc(Y*sizeof(char))不会相邻地分配内存.在这里有关于此的大量讨论.
(您可以使用数组指针或"mangling"在相邻内存中分配动态2D数组,但这些是相当高级的主题)
正如您希望的那样,这里明智的选择是从头开始重写此代码.