c - 链表中的顺序有时有效,有时无效。很奇怪
问题描述
此代码只是尝试创建字符的链接列表。奇怪的是,有时它有效,有时则无效。我真的不知道为什么。
#include <stdio.h>
#include <stdlib.h>
struct mychar {
char value;
struct mychar *nextPtr;
};
typedef struct mychar Mychar;
void insert(Mychar **, char );
void printlist(Mychar *);
int main(){
Mychar *startPtr = NULL;
while (1) {
char letter;
printf("\nScrivi il carattere da aggiungere: ");
scanf("\n%c", &letter);
insert(&startPtr, letter);
printlist(startPtr);
}
}
void insert(Mychar **sPtr, char newvalue){
Mychar *newnodePtr = calloc(1, sizeof(Mychar));
if (!newnodePtr){
printf("\n\nError in memory allocation.\n\n");
return;
}
newnodePtr->value = newvalue;
Mychar *previousPtr = NULL;
Mychar *currentPtr = *sPtr;
while ( currentPtr!=NULL && newvalue > (currentPtr->value) ){
previousPtr = currentPtr;
currentPtr = currentPtr->nextPtr;
}
if (previousPtr==NULL){
newnodePtr->nextPtr = NULL;
*sPtr = newnodePtr;
} else {
previousPtr->nextPtr = newnodePtr;
newnodePtr->nextPtr = currentPtr;
}
}
void printlist(Mychar *sPtr){
Mychar *currentPtr = sPtr;
while (currentPtr!=NULL){
printf("%c", currentPtr->value);
currentPtr = currentPtr->nextPtr;
}
}
Output1(似乎不起作用,当添加一个小写字母时,所有节点都消失了):
Write the char to add: a
a
Write the char to add: b
ab
Write the char to add: c
abc
Write the char to add: z
abcz
Write the char to add: a
a
Write the char to add: b
ab
Write the char to add: z
abz
Write the char to add: a
a
Write the char to add: ^C
输出 2(似乎有效):
Write the char to add: A
A
Write the char to add: B
AB
Write the char to add: C
ABC
Write the char to add: a
ABCa
Write the char to add: z
ABCaz
Write the char to add: a
ABCaaz
Write the char to add: b
ABCaabz
Write the char to add: Z
ABCZaabz
Write the char to add: ^C
另外,我想释放退出程序时创建的所有节点(例如使用 Ctrl+c)..
如何释放所有动态分配的节点?
解决方案
nextPtr
在节点将成为新列表头的情况下,您的代码无法正确连接新节点的成员。您可以通过执行以下操作来解决此问题,并显着简化插入:
void insert(Mychar **sPtr, char newvalue)
{
while (*sPtr && (*sPtr)->value < newvalue)
sPtr = &(*sPtr)->nextPtr;
Mychar *newPtr = malloc(sizeof *newPtr);
if (!newPtr)
{
perror("Failed to allocate new node");
return;
}
newPtr->value = newvalue;
newPtr->nextPtr = *sPtr;
*sPtr = newPtr;
}
这种技术具有隐式处理所有插入情况的额外好处,包括头部、中间和尾部位置。
既然你问过如何释放列表,上面的代码应该会给你一些见解,但它可能看起来像这样:
void freelist(Mychar **sPtr)
{
while (*sPtr)
{
Mychar *tmp = *sPtr;
*sPtr = tmp->nextPtr;
free(tmp);
}
}
推荐阅读
- regex - 检查单元格是否包含来自另一个单元格的关键字 - Google 表格
- c# - 奇怪的缩放问题
- c# - 数据已发送后服务器不发送数据
- sql-server - 如果是上半月或下半月,则返回函数
- ruby-on-rails - Rails ActionMailer
- amazon-web-services - 有什么方法可以使用 AWS Lambda 将本地存储照片/视频上传到 s3 存储桶中
- javascript - 当使用 rxjs 6 在 angular 6 中有新请求时如何取消正在进行的 HTTP 请求
- php - Laravel 首先或创建重复项
- node.js - Node.js 上的多个服务器
- android - 如何在线性布局中指定元素所在的一侧?