Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 从用户处获取输入并打印的链接列表_C_Linked List_Malloc - Fatal编程技术网

C 从用户处获取输入并打印的链接列表

C 从用户处获取输入并打印的链接列表,c,linked-list,malloc,C,Linked List,Malloc,我正在尝试用c编写一个程序,从用户那里获取输入(chars)。用户应该能够输入他想要的任何内容(“无限”) 这是我最终编写的程序,没有任何错误: 代码: /* 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

我正在尝试用c编写一个程序,从用户那里获取输入(chars)。用户应该能够输入他想要的任何内容(“无限”)

这是我最终编写的程序,没有任何错误:

代码:

/*
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 string\n");
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;
    }

}
/*
主要内容:
我们将尝试从用户那里获取输入。
如果我们成功,调用insert函数。
如果我们没有成功,调用freeList函数。
如果遇到“\n”或EOF,我们将退出该程序。
打印列表,然后释放它。
插入(键入void。不返回值):
如果分配成功,那么我们可以在链表中放置一个新项目。
该项是一个类型节点。
我们不关心列表中的节点数。
如果分配不成功,则调用自由函数。
免费:
释放内存。
*/
#包括
#包括
类型定义结构列表*ptr;
类型定义结构列表{
字符数据;
ptr-next;
}节点/*描述一个链接列表*/
无效插入(ptr*H,字符c);
无效自由列表(ptr*H);
无效打印列表(ptr*H);
int main(){
字符c;
printf(“输入字符串”);
ptr H=(ptr)malloc(sizeof(node));/*创建一个空列表。这是它的头*/
而((c=getchar())!=EOF&&c!='\n'){
插入(&H,c);
}
打印列表(&H);/*打印列表*/
释放列表(&H);/*释放列表*/
printf(“\n”);
返回0;
}
无效插入(ptr*H,字符c){
ptr-p1;
p1=*H;
ptr T=(ptr)malloc(sizeof(node));/*尝试分配一个新的内存单元*/
如果(!T)
{
打印列表(H);
自由列表(H);/*我们不应该释放H,因为我们会
丢失我们创建的列表*/
}
其他的
{
T->data=c;
同时(p1->next)
{
p1=p1->next;
}
p1->next=T;/*将T添加到链表的末尾*/
}
}
无效自由列表(ptr*H){
ptr p1;/*辅助指针*/
while(*H){/*而H指向某个节点*/
p1=*H;
(*H)=p1->next;
自由(p1);
}   
}
void printList(ptr*H){/*发送了H的副本,因此使用它没有问题*/
ptr p1=*H;printf(“字符串为:\n”);
while(p1)/*而H不为空*/
{
printf(“%c”,p1->data);
p1=p1->next;
}
}

此代码实际上有效,但任何反馈都是好的。

试图获取
NULL
指针的地址可能会导致分段错误-您应该将列表的
设置为已分配的节点,而不是
NULL
指针

通过调试器(如
gdb
)运行代码也很有用,它将告诉您导致分段错误的行(并显示调用堆栈)

解决警告应该相当简单

  • 标志
    未使用,因此可以将其删除
  • 您应该将
    *H
    而不是
    H
    传递到
    printList
  • 您应该将
    H
    而不是
    &H
    传递到
    freeList

或者,您可以将函数更改为采用
ptr
s而不是
ptr*
s,因为我认为没有理由通过
node**
s(这就是
ptr*
将变成的)。在这种情况下,只需将
H
s传递给函数,而不必担心它们的指针类型(尽管,正如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 string\n");

    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;
类型定义结构列表
{
字符数据;
ptr-next;
}节点;
无效插入(ptr*H,字符c);
无效自由列表(ptr*H);
无效打印列表(ptr H);
int main()
{
ptr H=NULL;
INTC;
printf(“输入字符串”);
而(((c=getchar())!=EOF)和&c!='\n')
插入(&H,(字符)c);
打印列表(H);/*打印列表*/
释放列表(&H);/*释放列表*/
printf(“\n”);
返回0;
}
无效插入(ptr*H,字符c)
{
//注意:当指针保持在指向指针H的指针中时
//不为NULL,移动到下一个指针。注意我们如何存储
//当我们
//走。当我们到达列表的末尾时,地址的值
//保存在指针中,我们在H中存储的地址将是
//null。作为奖励,H将保留我们所使用的指针的地址
//我们需要更新。
while(*H)
H=&(*H)->下一步;
//分配新节点,分配给指针
//由*H中的地址解除引用
*H=malloc(sizeof(**H));
(*H)->数据=c;
(*H)->next=NULL;
}
无效自由列表(ptr*H)
{
//注:逻辑与前面相同。使用H作为指向指针的指针
//遍历指针链。每次我们保存
//值,前进到下一个指针,然后删除
//保存的价值。
while(*H)
{
ptr-tmp=*H;
*H=(*H)->下一步;
免费(tmp);
}
}
无效打印列表(ptr H)
{
//注意:这里不需要指向指针的指针。
while(H)
{
printf(“%c”,H->data);
H=H->next;
}
}

综上所述,我强烈建议完全消除
ptr
思想,只使用正确声明的带星号的指针。C程序员希望看到这些。他们大声说:“看!我是一个指针”=O

void freeList(ptr *H)
{  
   if(*H!=NULL)
   {
    freeList(&(*H)->next);
    free(*H);
   }
}

同样,printList和insert也可以重写

不要重新定义标准函数的名称
free
。谢谢!这是一个开始:)Mau FATtou应该考虑通过一个调试器运行代码,如<代码> GDB < /Cord>,这将告诉您哪一行导致了分割错误。试图获得<代码> null > />代码指针的地址肯定会导致分割错误-应该使列表的<代码>头<代码>被分配。
节点
而不是
NULL
指针