我的执行名称是test4。
输入:
$ ./test4 cccc zz abcdef0123456789 aaabbbcccddd
我希望创建一个char *类型的链表,如下所示:
---> 12:aaabbbcccddd ---> 12:abcdef0123456789 ---> 2:zz ---> 4:cccc
每个节点的形式为“n:a”(n是字符串a的长度,n <= 12,如果a的长度大于12,则n = 12)
以下是我的代码:
struct Node *prepend(struct Node *list, char *s)
{
struct Node *node = (struct Node *)malloc(sizeof(struct Node));
if (node == NULL)
return NULL;
int length_s = strlen(s);
if (length_s > 12)
length_s = 12;
char* temp = NULL;
sprintf(temp,"%d:%s", length_s, s);
strcpy(node->data, temp);
node->next = list;
return node;
}
prepend函数链接一个新节点列表
struct Node {
struct Node *next;
char *data;
};
int main(int argc, char **argv)
{
struct Node *list = NULL;
argv++;
while (*argv)
{
list = prepend(list,*argv);
argv++;
}
return 0;
}
假设包含所有必需的库和结构,运行代码时我不断收到分段错误。我如何解决它?我相信问题出在sprintf中,但无法弄清楚原因。
答案 0 :(得分:2)
您不在此处为temp
分配内存:
char* temp = NULL;
sprintf(temp,"%d:%s", length_s, s);
您可以使用静态的字符数组或为其动态分配内存。
为了复制你想要的东西,你应该这样:
如果data
Node
为char*
,
node->data = malloc((length_s + 1) + 1 + digits_of_length);
sprintf(node->data,"%d:%s", length_s, s);
如果data
的{{1}}是一个字符数组,您应该这样做:
Node
如你所见,这有点令人讨厌,因为你必须找到长度的数字,以便分配内存。
为什么不使用名为str_length的额外字段来扩充sprintf(node->data,"%d:%s", ((length_s + 1) + 1 + digits_of_length), s);
,这将跟踪当前节点所持有的字符串的长度。这样,你可以修改你的功能:
Node
当你去做这个时,不要忘记写一个struct Node *prepend(struct Node *list, char *s)
{
struct Node *node = (struct Node *)malloc(sizeof(struct Node));
if (node == NULL)
return NULL;
int length_s = strlen(s);
node->data = malloc(length_s + 1);
strcpy(node->data, temp);
node->str_length = length_s + 1;
node->next = list;
return node;
}
,它将取消分配整个列表。
另外,不要施放malloc返回的内容。 Why?
答案 1 :(得分:1)
问题在于这些陈述
char* temp = NULL;
sprintf(temp,"%d:%s", length_s, s);
您没有分配poointer temp指向的内存。 Sp该程序已定义为begaviour。
如果不使用结构中的指针而使用大小为12 + 1
的数组,则可以简化生活,因为复制字符串的长度限制为12个字符。
例如
enum { size = 13 };
struct Node
{
char data[size];
Node *next;
};
//...
struct Node *prepend( struct Node *list, const char *s )
{
struct Node *node = ( struct Node * )malloc( sizeof( struct Node ) );
if ( node == NULL ) return list;
strnspy( node->data, s, size );
node->data[size - 1] = '\0';
node->next = list;
return node;
}
如果你需要使用指针而不是字符数组和sprintft而不是strncpy hen你可以写
struct Node *prepend( struct Node *list, const char *s )
{
const size_t N = 12;
struct Node *node = ( struct Node * )malloc( sizeof( struct Node ) );
if ( node == NULL ) return list;
node->data = malloc( ( N + 1 ) * sizeof( char ) );
sprintf( node->data, "%*.*s", N, N, s );
node->next = list;
return node;
}
当不再需要列表时,您必须删除它。例如
void delete( struct Node *list )
{
while ( list )
{
Node *tmp = list;
list = list->next;
free( tmp->data );
free( tmp );
}
}