У меня есть простая программа для вставки элементов в конец связанного списка с помощью вызова функции.
Мой код:
struct Date{
int data;
struct Date *next;
};
void print(struct Date *date_head);
void add(int date, struct Date *date_head);
int main(){
struct Date *date_head=NULL;
add(12,date_head);
add(15,date_head);
}
void print(struct Date *date_head){
struct Date *ptr=date_head;
printf("Dates: ");
while(ptr!=NULL){
printf("%d ",ptr->data);
ptr=ptr->next;
}
printf("\n");
}
void add(int date, struct Date *date_head){
//newDate
struct Date *newDate;
newDate = (struct Date *)malloc(sizeof(struct Date));
newDate->data=date;
newDate->next=NULL;
//inserting newDate at end
struct Date *date_ptr;
date_ptr=date_head;
if (date_ptr==NULL) {date_head=newDate;}
else{
while(date_ptr->next!=NULL){
date_ptr=date_ptr->next;
}
date_ptr->next=newDate;
}
print(date_head);
}
Что я хочу:
Даты: 12
Даты: 12 15
Что я получаю:
Даты: 12
Даты: 15
Структура становится NULL вне функции добавления. Даже когда я использую указатели. Почему?
Не знаю, совершаю ли я ошибку новичка.
2 ответа
Лучше хотя бы поменять местами параметры функции типа
void add(int date, struct Date *date_head, int date );
Функция принимает указатель на головной узел, объявленный в main по значению. То есть функция имеет дело с копией значения указателя. Изменение копии внутри функции отражается на исходном указателе.
Также может произойти сбой выделения памяти внутри функции. Вы должны сообщить о такой ситуации вызывающей функции.
Таким образом, функция должна возвращать целое число, указывающее, было ли выделение нового узла успешным, и она должна принимать указатель на головной узел по ссылке, то есть через указатель на него.
С учетом всего этого объявление и определение функции будут выглядеть следующим образом.
int add( struct Date **date_head, int date )
{
struct Date *newDate = malloc( sizeof( struct Date ) );
int success = newDate != NULL;
if ( success )
{
newDate->data = date;
newDate->next = NULL;
while ( *date_head != NULL ) date_head = &( *date_head )->next;
*date_head = newDate;
}
return success;
}
В main вы должны написать
struct Date *date_head=NULL;
add( &date_head, 12 );
add( &date_head, 15 );
Также параметр функции должен иметь квалификатор const
, потому что список внутри функции не изменяется.
void print( const struct Date *date_head );
И если вы хотите добавить новый узел в конец списка, то лучше объявить двусторонний односвязный список.
Вы передаете значение указателя date_head в функцию добавления, поэтому функция добавления будет иметь другую копию этого указателя, и даже если вы измените значение этого указателя в функции добавления и установите его на какой-то номер адреса, он не будет влияет на date_head, который вы создали в main, поэтому он всегда будет нулевым, вместо этого вы можете передать его по адресу:
int main(){
struct Date *date_head=NULL;
add(12,&date_head);
add(15,&date_head);
}
И отредактируйте функцию добавления следующим образом:
void add(int date, struct Date **date_head){
//newDate
struct Date *newDate;
newDate = (struct Date *)malloc(sizeof(struct Date));
newDate->data=date;
newDate->next=NULL;
//inserting newDate at end
struct Date *date_ptr;
date_ptr=*date_head;
if (date_ptr==NULL) {*date_head= newDate;}
else{
while(date_ptr->next!=NULL){
date_ptr=date_ptr->next;
}
date_ptr->next=newDate;
}
print(*date_head);
}
Похожие вопросы
Связанные вопросы
Новые вопросы
c
C - это язык программирования общего назначения, используемый для системного программирования (ОС и встраиваемых), библиотек, игр и кроссплатформенности. Этот тег следует использовать с общими вопросами, касающимися языка C, как это определено в стандарте ISO 9899 (последняя версия 9899: 2018, если не указано иное, а также для запросов, специфичных для версии, с c89, c99, c11 и т. Д.). C отличается от C ++ и не должен сочетаться с тэгом C ++ без разумной причины.
date_head=newDate
вы присваиваете только локальную переменную аргумента, переменная или выражение, которые вы использовали в вызове, не изменят значение. Пожалуйста, изучите тему эмуляции передачи по ссылке в C. Подсказка: здесь используются указатели, оператор указателя на&
и оператор разыменования*
.add
очень неэффективна. Представьте, что ваш список содержит 100 000 элементов, тогда для добавления еще одного элемента вам нужно просмотреть все 100 000 существующих элементов. Обычно для связанного списка вы также должны поддерживать хвостовой указатель (указатель на последний элемент). Тогда добавление элемента происходит мгновенно.