【问题标题】:Problem entering values to a struct with double pointers使用双指针向结构输入值时出现问题
【发布时间】:2020-08-08 13:40:15
【问题描述】:

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

#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;
}

【问题讨论】:

  • 当您想打印地址时,请使用%p 格式。 addRecords 必须分配*head

标签: c struct append singly-linked-list function-definition


【解决方案1】:

这段代码sn-p

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

【讨论】:

    【解决方案2】:

    你希望做最小的改变:

    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 $ 
    

    【讨论】:

      【解决方案3】:

      问题是您的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 : 这个声明不是原型;添加 'void' 使其成为 零参数函数原型

      最后:

      但它不打印任何东西。

      那是因为你从不打电话给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;
      }
      

      【讨论】:

        猜你喜欢
        • 2013-04-13
        • 1970-01-01
        • 1970-01-01
        • 2020-11-15
        • 1970-01-01
        • 2021-12-25
        • 2011-11-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多