在以下代码中:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
char** tab;
int n;
}slist;
void print(slist* p);
void add(slist* p, const char* s);
void add(slist* p, const char* s)
{
if(p->n==0)
{
p->tab=(char**)malloc(sizeof(char**));
}
strcpy(p->tab[p->n],s);
p->n=p->n+1;
}
void print(slist* p)
{
int i;
printf("[");
for(i=0;i<p->n;i++)
printf(" %s",p->tab[i]);
printf(" ]");
}
int main()
{
char s1[25] = "Picsou";
char s2[25] = "Flairsou";
slist* p = (slist*)malloc(sizeof(slist));
p->n=0;
p->tab=NULL;
add(p,s1);
add(p,s2);
print(p);
return 0;
}
函数add()
不起作用,但如果我将其更改为:
void add(slist* p, const char* s)
{
if(p->n==0)
{
p->tab=(char**)malloc(sizeof(char**));
}
p->tab[p->n]=s;
p->n=p->n+1;
}
它看起来效果很好。在第一种情况下,输出仅为" ["
;
在第二种情况下,它应该是:" [ Picsou Flairsou ] "
。
我不明白为什么。
我也试过这个:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
char** tab;
int n;
}slist;
void print(slist* p);
void add(slist* p, const char* s);
void print(slist* p)
{
int i;
printf("[");
for(i=0;i<p->n;i++)
printf(" %s",p->tab[i]);
printf(" ]");
}
void add(slist* p, const char* s)
{
slist* tmp = (slist*)malloc(sizeof(slist));
tmp->tab=(char**)malloc(sizeof(char*)*(p->n+1));
int i;
for(i=0;i<p->n;i++)
tmp->tab[i]=(char*)malloc(sizeof(char));
strcpy(tmp->tab[p->n],s);
tmp->n=p->n+1;
p = tmp;
}
int main()
{
char* s1 = "Picsou";
char* s2 = "Flairsou";
slist* p = (slist*)malloc(sizeof(slist));
p->n=0;
p->tab=NULL;
add(p,s1);
add(p,s2);
print(p);
return 0;
}
答案 0 :(得分:2)
这里有很多错误,这对于处理指针的人来说很常见。从哪里开始...我只是按照代码中出现的顺序排列。
这不是&#34;列表&#34;。
它是一个阵列......有点像。如果你说&#34; list&#34;对于C程序员,他们会认为你的意思是一个链表。
数组分配不正确。
if(p->n==0) { p->tab=(char**)malloc(sizeof(char**)); }
这里你已经分配了足够的存储单个指针。第二次拨打add
时,您将在最后访问内存。您也错误地投射了结果(在C中,您不会从malloc
投射返回值)。此外,您向读者提供了令人困惑的信息,因为您打算分配一个数组,该数组将包含char*
类型的元素, NOT char**
。
您必须允许阵列在需要时动态扩展(目前不适合您的能力 - 可能会在几天内尝试)或设置最大大小。让我们这样做。
const int MAX_SIZE = 100;
if( p->n==0 )
{
p->tab = malloc( MAX_SIZE * sizeof(char*) );
}
else if( p->n == MAX_SIZE )
{
printf( "Maximum size exceeded!\n" );
return;
}
如果您愿意,可以使用calloc
代替malloc
。它将在分配后对块进行零初始化:calloc( MAX_SIZE, sizeof(char*) )
复制到未初始化的指针。
strcpy(p->tab[p->n],s);
您为tab
分配了内存,但是您没有分配其元素指向的内存,这里您有未定义的行为(最有可能导致分段错误,但可以执行任何操作)。
确保您有一个有效的指针,它指向的位置为您复制到其中的数据保留了足够的存储空间:
p->tab[p->n] = malloc( strlen(s) + 1 );
strcpy( p->tab[p->n], s );
存储可能无效的指针。
您的选择&#34;效果非常好&#34;用途:
p->tab[p->n]=s;
但是,这个工作的唯一原因是因为这些指针在你使用&#34; list&#34;的整个时间内仍然有效。 (但实际上程序没有&#34;工作&#34;因为我在第2号中突出显示的原因。
有时我们希望在程序中使用这种行为,并设计我们的数据结构来索引它们不拥有的指针。但更常见的是,特别是初学者,你最好复制数据(而不是简单地复制指针)。因此,您将使用我在上面第3条中建议的方法。
没有评论!!
以下代码有很多问题,我不会将它拆开或解释它们。
void add(slist* p, const char* s) { slist* tmp = (slist*)malloc(sizeof(slist)); tmp->tab=(char**)malloc(sizeof(char*)*(p->n+1)); int i; for(i=0;i<p->n;i++) tmp->tab[i]=(char*)malloc(sizeof(char)); strcpy(tmp->tab[p->n],s); tmp->n=p->n+1; p = tmp; }
但是,您似乎尝试执行与realloc
类似的操作。这是我在第2号中提到的选项,我说你可能还没准备好。但无论如何要阅读它:realloc