gpt4 book ai didi

c - 为什么 for 循环终止但其中的 memcpy 复制相同的子字符串?

转载 作者:行者123 更新时间:2023-11-30 19:05:04 25 4
gpt4 key购买 nike

我的作业要求我们缩短用户输入句子的单词。然后将缩短的单词放入链表中。当代码的齿轮卡住时:句子中的最后一个单词被保存到每个节点中。应该实现什么修复,以便代码每次都将 diff 字放入节点中。

注意:我查看了涉及 memcpy 的问题并使用 0 和\0 预先填充数组。我还使用 & 和不使用 & 更改了 memcpy 的参数。我还使用了 memmove 和 strncpy。尚未询问“for 循环中的 memcpy 将数组的子字符串复制到节点”的这种变体。

这是我的代码。希望在您的答案的评论中推荐有关 c 或 java 的学习资源链接。以及改进代码的建议。当然,如果您有我的问题的更简洁/准确的版本,我会很乐意更新它。谢谢!

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

typedef struct node
{
char *four_letters;
struct node *next_node;
}node;

struct node* head= NULL;

char sentence[120][40]={0}, four_letters[40]={0}; // Tried \0,"0".

int word, num_words=-1;

void scan(); void print(); void sentence_into_list();

void add(struct node **head, char *four_letters);

void display(struct node *head);



int main()
{
scan();
printf("\n");
print();
printf("\n");

sentence_into_list();
display(head);
return 0;
}



void scan()
{
for(word=0;;word++)
{
scanf("%s",sentence[word]);
num_words++;
if(getchar()=='\n')
break;
}

}

void print()
{
for(word=0;word<=num_words;word++)
{
printf("%s ", sentence[word]);
}
}

void sentence_into_list()
{
for (word=0;word<=num_words;word++)
{
memcpy(four_letters, sentence[word], 4); //tried & //tried strncpy, memmove.
add(&head, four_letters);
}
}

void add(struct node **head, char *four_letters)

{
struct node *new_node = malloc(sizeof(struct node));

new_node->four_letters = four_letters;
new_node->next_node = *head;
*head=new_node;

}

void display(struct node* head)
{
struct node *current;
current = head;
if(current!=NULL)
{
printf("List:");
do
{
printf("%s ",current->four_letters);
current = current->next_node;
}

while(current!=NULL);
printf("\n");
}
else
{
printf("empty\n");
}
}

最佳答案

the last word in the sentence gets saved into every node. ....

发生这种情况是因为列表中所有节点的 four_letters 指针都指向全局声明的相同内存位置 four_letters [char 缓冲区- four_letters[40]={0};]。因此,无论 four_letters 的最后一个值是什么,都将反射(reflect)在所有节点中。

解决此问题的一种方法是 -
为节点 four_letters 指针分配一 block 足以容纳数据的内存,并将 four_letters 的内容复制到其中。或者,您可以使用strdup它会为您执行此操作。

因此,在 add() 函数中,替换此

new_node->four_letters = four_letters;

有了这个

new_node->four_letters = strdup(four_letters);

strdup 创建传递给它的字符串的副本。它返回一个指向新分配的内存的指针,因此,一旦使用完毕,您应该释放它,如下所示:

free (node_ptr->four_letters); //node_ptr is pointer to current node

在释放列表节点动态分配的内存时,请确保首先释放节点结构中动态分配的成员,然后再释放节点本身。

解决这个问题的另一种方法是 -
char 数组作为 node 结构的成员,而不是在 node 结构中使用指向 char 的指针,像这样:

typedef struct node
{
char four_letters[5]; // 5 because it is suppose to keep the four letters only and +1 is for null-terminating character
struct node *next_node;
}node;

并将传递给add()four_letters的内容复制到结构体节点成员four_letters。这样,您就不需要释放内存了。

您的代码还有一个问题 -
在函数 sentence_into_list() 中,您正在执行以下操作:

    memcpy(four_letters, sentence[word], 4);
add(&head, four_letters);

此处,您将 sentence[word] 的前 4 个字符复制到 four_letters,但您还应该添加空终止字符在将缓冲区传递给 add() 之前,在缓冲区的第 four_letters 位置处,如下所示:

four_letters[4] = '\0';

C语言没有原生的字符串类型。在 C 中,字符串实际上是一个以空字符 \0 结尾的一维字符数组。

您在代码中没有看到任何问题,因为您正在用零初始化缓冲区:

four_letters[40]={0};

并且每次您只将 4 字符复制到其中。因此,在第 5 位置,您始终会看到 \0。但假设您将缓冲区用于不同大小的字符串。在这种情况下,您必须将终止空字符放在字符串的末尾。

<小时/>

附加:

我可以看到您无法释放为列表节点动态分配的内存。遵循良好的编程习惯,养成在使用完动态分配的内存后释放它的习惯。

关于c - 为什么 for 循环终止但其中的 memcpy 复制相同的子字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50671988/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com