使用双指针向结构输入值时出现问题

Problem entering values to a struct with double pointers

我必须在函数中使用双指针来将元素填充到结构中(函数必须为空)。但它不打印任何东西。我认为问题出在传递正确的地址但找不到它。

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

typedef struct nums{
    int num;
    struct nums *ptr;
}sNums;

void addRecords(sNums** head);
sNums* createRecord();
void prinrecords(sNums* head);

int main(int argc, char const *argv[])
{
    sNums* head=NULL;
    printf("%d\n", &head);
    for (int i = 0; i < 3; ++i)
    {
        addRecords(&head);
    }
    system ("pause");
}

这是打印存储元素的函数:

void prinrecords(sNums* head){
    while(head!=NULL){
        printf("{%d} ", head->num);
        head=head->ptr;
    }
}

这里是使用双指针添加元素的函数:

void addRecords(sNums** head){
    sNums* temp_new=createRecord();
    sNums* fst_position;
    fst_position=*head;
    printf("%d\n", fst_position);
    if (fst_position == NULL)
    {
        fst_position=temp_new;
        return ;
    }
    while(fst_position->ptr!=NULL){
    fst_position=fst_position->ptr;
    }
    fst_position->ptr=temp_new; 
}

sNums* createRecord(){
    sNums *new=(sNums*)malloc(sizeof(sNums));
    printf("Enter Number: ");
    scanf("%d", &new->num);
    new->ptr=NULL;
    return new;
}

您希望进行最小的更改:

void addRecords(sNums** head){
  sNums* temp_new=createRecord();

  if (*head == NULL)
    *head = temp_new;
  else {
    sNums* fst_position = *head;

    while(fst_position->ptr!=NULL){
      fst_position=fst_position->ptr;
    }
    fst_position->ptr=temp_new; 
  }
}

否则你永远不会保存第一个单元格或下一个单元格,因为你总是从一个空列表开始而不修改它

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

typedef struct nums{
    int num;
    struct nums *ptr;
}sNums;

void addRecords(sNums** head);
sNums* createRecord();
void prinrecords(sNums* head);

int main(int argc, char const *argv[])
{
    sNums* head=NULL;

    for (int i = 0; i < 3; ++i)
    {
        addRecords(&head);
    }
    prinrecords(head);
    putchar('\n');
}

void prinrecords(sNums* head){
    while(head!=NULL){
        printf("{%d} ", head->num);
        head=head->ptr;
    }
}

void addRecords(sNums** head){
  sNums* temp_new=createRecord();

  if (*head == NULL)
    *head = temp_new;
  else {
    sNums* fst_position = *head;

    while(fst_position->ptr!=NULL){
      fst_position=fst_position->ptr;
    }
    fst_position->ptr=temp_new; 
  }
}

sNums* createRecord(){
    sNums *new=(sNums*)malloc(sizeof(sNums));
    printf("Enter Number: ");
    scanf("%d", &new->num);
    new->ptr=NULL;
    return new;
}

编译与执行:

pi@raspberrypi:/tmp $ gcc -Wall a.c
pi@raspberrypi:/tmp $ ./a.out
Enter Number: 1
Enter Number: 2
Enter Number: 3
{1} {2} {3} 
pi@raspberrypi:/tmp $ 

这段代码

fst_position=*head;
//...
if (fst_position == NULL)
{
    fst_position=temp_new;
    return ;
}

不更改通过引用传递的头指针。它改变局部变量 fst_position.

函数可以这样定义

void addRecords(sNums** head)
{
    while ( *head != NULL ) head = &( *head )->ptr;

    *head = createRecord();
}

就是这样。只有两种说法。 :)

虽然总体来说功能设计的不好。例如,输入将添加到列表中的数字应该在函数 createRecord.

之外

此外,内存分配可能会失败。在这种情况下,您的程序将具有未定义的行为。

下面有一个演示程序,展示了如何重新设计您的函数。

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

typedef struct nums
{
    int num;
    struct nums *ptr;
} sNums;

int addRecords(sNums** head, int num );
sNums* createRecord();
void prinrecords( const sNums* head );

sNums * createRecord( int num ) 
{
    sNums *node = malloc( sizeof( sNums ) );

    if ( node != NULL )
    {
        node->num = num;
        node->ptr = NULL;
    }

    return node;
}

int addRecords( sNums** head, int num )
{
    sNums *node = createRecord( num );
    int success = node != NULL;

    if ( success )
    {
        while ( *head != NULL ) head = &( *head )->ptr;

        *head = node;
    }

    return success;
}

void prinrecords( const sNums *head )
{
    for ( ; head != NULL; head = head->ptr )
    {
        printf( "%d -> ", head->num );
    }
    puts( "null" );
}

int main(void) 
{
    sNums* head = NULL;
    const size_t N = 10;

    for ( size_t i = 0; i < N; ++i )
    {
        int num;

        printf( "Enter a number: " );
        scanf( "%d", &num );

        addRecords( &head, num );
    }

    prinrecords( head );

    return 0;
}

程序输出可能看起来像

Enter a number: 0
Enter a number: 1
Enter a number: 2
Enter a number: 3
Enter a number: 4
Enter a number: 5
Enter a number: 6
Enter a number: 7
Enter a number: 8
Enter a number: 9
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null

问题是您的 addRecords 函数在创建新列表时(即第一次调用它时)没有更改给定的 head 指针!你应该这样做,而不是:

void addRecords(sNums** head)
{
    sNums* temp_new = createRecord();
    sNums* fst_position;
    fst_position = *head;
//  printf("%d\n", fst_position);
    printf("%p\n", (void*)(fst_position));/// Let's keep the format/argument arrangement cool!
    if (fst_position == NULL) {
    //  fst_position = temp_new; // This WON'T change the 'head' pointer...
        *head = temp_new;        // ... but this will!
        return;
    }
    while (fst_position->ptr != NULL) {
        fst_position = fst_position->ptr;
    }
    fst_position->ptr = temp_new;
    // Here, we don't change the 'head' pointer, so its OK!
}

注意:请参阅我对您的指针报告行所做的更改:对指针参数使用 %d 格式说明符是未定义的行为,并且会在指针不是与 int.

大小相同

注意 2:为了避免在严格的、符合标准的编译器上出现警告(和可能的错误),您应该在 createRecord 函数的括号内添加 void,以指定它不需要参数:

sNums* createRecord(void);

没有这个,clang-cl 编译器(例如)会给你这个建议:

message : this declaration is not a prototype; add 'void' to make it a prototype for a zero-parameter function

最后:

But it doesn't print anything.

那是因为你从来没有打电话给 prinrecords!将调用添加到您的 main 函数:

int main(int argc, char const* argv[])
{
    sNums* head = NULL;
    printf("%p\n", (void*)(&head));// Keep format/agument cool!
    for (int i = 0; i < 3; ++i) {
        addRecords(&head);
    }
    prinrecords(head); // You forgot this!
    system("pause");
    return 0;
}