2

我必须在函数中使用双指针来将元素填充到结构中(函数必须为 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;
}
4

3 回答 3

2

此代码片段

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
于 2020-04-24T21:29:53.610 回答
1

问题是您的函数在创建新列表时(即第一次调用它)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:为避免在严格的、符合标准的编译器上出现警告(和可能的错误),您应该在函数void的括号内添加createRecord,以指定它不接受参数:

sNums* createRecord(void);

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

消息:此声明不是原型;添加 '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;
}
于 2020-04-24T21:37:09.697 回答
1

您希望做最小的更改:

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 $ 
于 2020-04-24T21:27:28.007 回答