我正在尝试用 c 编写一个程序来获取用户的输入(字符)。用户应该能够根据需要键入输入("无限")。
这是我最终编写的程序,完全没有错误:
法典:
/*
main:
we will try to get an input from the user.
if we succeed, call insert function.
if we don't succeed, call freeList function.
if we encounter 'n' or EOF, we quit the program.
print the list, the free it.
insert (type void. does not return a value):
if allocation is successful, then we can put a new item in the linked list.
the item is a type node.
we don't care the number of nodes in the list.
if allocation is not successful, call free function.
free:
free the memory.
*/
#include <stdio.h>
#include <stdlib.h>
typedef struct list *ptr;
typedef struct list{
char data;
ptr next;
}node; /*describes a linked list.*/
void insert(ptr *H, char c);
void freeList(ptr *H);
void printList(ptr *H);
int main(){
char c;
printf("enter a stringn");
ptr H=(ptr)malloc(sizeof(node));/*create an empty list. this is its head.*/
while ((c=getchar())!=EOF && c!='n'){
insert(&H,c);
}
printList(&H); /*print the list*/
freeList(&H); /*free the list*/
printf("n");
return 0;
}
void insert(ptr *H, char c){
ptr p1;
p1=*H;
ptr T=(ptr)malloc(sizeof(node)); /*try to allocate a new memory cell*/
if (!T)
{
printList(H);
freeList(H); /*we should not free H because we will
lose the list we've created.*/
}
else
{
T->data=c;
while(p1->next)
{
p1=p1->next;
}
p1->next=T; /*add T to the end of the linked list*/
}
}
void freeList(ptr *H){
ptr p1; /*helper pointer*/
while(*H){ /*while H points to a certain node*/
p1=*H;
(*H)=p1->next;
free(p1);
}
}
void printList(ptr *H){ /*a copy of H is sent so no problem working with it.*/
ptr p1=*H; printf("string is: n");
while (p1) /*while H is not null */
{
printf("%c", p1->data);
p1=p1->next;
}
}
这段代码确实有效,但任何反馈都很好。
尝试获取NULL
指针的地址可能会导致分段错误 - 您应该使列表的HEAD
成为分配的节点而不是NULL
指针。
通过调试器(如 gdb
)运行代码也很有用,它将告诉您导致分段错误的行(并显示调用堆栈)。
解决警告应该相当简单。
-
flag
未使用,因此可以将其删除。 - 您应该传递
*H
而不是H
传递给printList
- 您应该传递
H
而不是&H
传递给freeList
或者,您可以将函数更改为采用 ptr
s 而不是 ptr *
s,因为我认为没有理由传递 node **
s(这就是ptr *
会变成的样子)。在这种情况下,它应该是将H
传递给函数而不用担心它们的指针类型的简单情况(尽管正如 WhozCraig 所说,这可能不是一个好主意)。
这可能是您要查找的内容,并在代码中提供注释来解释正在发生的事情。使用指针,更重要的是,指针到指针逻辑是...异常。。。你第一次接触到它。希望这有所帮助。
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
typedef struct list *ptr;
typedef struct list
{
char data;
ptr next;
} node;
void insert(ptr *H, char c);
void freeList(ptr *H);
void printList(ptr H);
int main()
{
ptr H = NULL;
int c;
printf("enter a stringn");
while (((c=getchar())!=EOF) && c!='n')
insert(&H,(char)c);
printList(H); /*print the list*/
freeList(&H); /*free the list*/
printf("n");
return 0;
}
void insert(ptr *H, char c)
{
// NOTE: while the pointer held in the pointer-to-pointer H
// is not NULL, move to the next pointer. Notice how we store
// the *address* of the 'next' member in our H variable as we
// walk. When we reach the end-of-list the value of the address
// held in the pointer whos address we're storing in H will be
// null. As a bonus, H will hold the address of the pointer we
// need to update, which we do.
while (*H)
H = &(*H)->next;
// allocate new node, assigning to the pointer
// dereferenced by the address held in *H
*H = malloc(sizeof(**H));
(*H)->data = c;
(*H)->next = NULL;
}
void freeList(ptr *H)
{
// NOTE: same logic as before. using H as a pointer-to-pointer
// to walk through the chain of pointers. each time we save the
// value to a temp, advance to the next pointer, and delete the
// saved value.
while (*H)
{
ptr tmp = *H;
*H = (*H)->next;
free(tmp);
}
}
void printList(ptr H)
{
// NOTE: No need for a pointer-to-pointer here.
while (H)
{
printf("%c", H->data);
H=H->next;
}
}
综上所述,我强烈建议完全消除ptr
意识形态,而简单地使用正确声明的带有星号的指针。C 程序员希望看到这些。他们喊道:"看!我是一个指针" =O
归 freeList 函数可能是
void freeList(ptr *H)
{
if(*H!=NULL)
{
freeList(&(*H)->next);
free(*H);
}
}
类似地打印列表和插入可以重写