使用双指针向结构输入值时出现问题
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;
}
我必须在函数中使用双指针来将元素填充到结构中(函数必须为空)。但它不打印任何东西。我认为问题出在传递正确的地址但找不到它。
#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;
}