C: сохранить значение из типа указателя на структуру в struct

#c #pointers #struct

#c #указатели #struct

Вопрос:

Я определил тип struct следующим образом:

 typedef struct _liste {
    int val;
    struct _liste *suiv;
} Liste;
  

Но когда я хочу сохранить оценщик в type, но это не работает
мой код:

 Liste A;
    for (int i = 0; i<3; i  ){
        scanf("%d",amp;A.val);
        *A = A.suiv
    }
  

но переменная A не сохраняется.
Как исправить? Спасибо

Комментарии:

1. Вы пытаетесь создать односвязный список?

2. Вы захотите присвоить следующему указателю значение NULL, а затем извлечь его оттуда. *A = A.suiv это бессмыслица, вы не можете программировать методом проб и ошибок — вы должны на самом деле понимать, что делает каждая отдельная строка кода, которую вы пишете.

Ответ №1:

В

 typedef struct _liste {
    int val;
    struct _liste *suiv;
} Liste;

Liste A;
    for (int i = 0; i<3; i  ){
        scanf("%d",amp;A.val);
        *A = A.suiv
    }
  

есть 2 проблемы

  • *A = A.suiv недопустимо, и вы хотели A = *(A.suiv) соблюдать типы (вне всякого поведения)
  • A.suiv не инициализируется, вы пропускаете выделение для каждой новой ячейки

Допустимый код может быть :

 Liste * head;
Liste ** p = amp;head;

for (int i = 0; i != 3; i  ) {
   *p = malloc(sizeof(Liste));
   scanf("%d",amp;(*p)->val);
   p = amp;(*p)->suiv;
}
*p = NULL;
  

Полный пример :

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

typedef struct _liste {
  int val;
  struct _liste *suiv;
} Liste;

int main()
{
  Liste * head;
  Liste ** p = amp;head;

  for (int i = 0; i != 3; i  ) {
    *p = malloc(sizeof(Liste));
    printf("valeur: ");
    scanf("%d",amp;(*p)->val); /* better to check scanf return 1 */
    p = amp;(*p)->suiv;
  }
  *p = NULL;

  /* show result and free ressources */
  printf("la liste est :");
  while (head != NULL) {
    printf(" %d", head->val);
    Liste * l = head;
    head = head->suiv;
    free(l);
  }
  putchar('n');
}
  

Компиляция и выполнение :

 /tmp % gcc -pedantic -Wall -Wextra l.c
/tmp % ./a.out
valeur: 1
valeur: 2
valeur: 3
la liste est : 1 2 3
  

выполнение под valgrind

 /tmp % valgrind ./a.out
==32505== Memcheck, a memory error detector
==32505== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==32505== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==32505== Command: ./a.out
==32505== 
valeur: 1
valeur: 2
valeur: 3
la liste est : 1 2 3
==32505== 
==32505== HEAP SUMMARY:
==32505==     in use at exit: 0 bytes in 0 blocks
==32505==   total heap usage: 3 allocs, 3 frees, 48 bytes allocated
==32505== 
==32505== All heap blocks were freed -- no leaks are possible
==32505== 
==32505== For counts of detected and suppressed errors, rerun with: -v
==32505== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6)
  

Если вы не хотите, чтобы список находился в куче :

 #include <stdio.h>

typedef struct _liste {
  int val;
  struct _liste *suiv;
} Liste;

#define N 3

int main()
{
  Liste liste[N];

  for (int i = 0; i != N; i  ) {
    printf("valeur: ");
    scanf("%d", amp;liste[i].val); /* better to check scanf return 1 */
    liste[i].suiv = amp;liste[i   1];
  }
  liste[N-1].suiv = NULL;

  /* show result (as a list, forget in an array) */
  Liste * p = liste;

  printf("la liste est :");
  while (p != NULL) {
    printf(" %d", p->val);
    p = p->suiv;
  }
  putchar('n');
}
  

но в этом случае лучше использовать не список, а просто массив int 😉

Комментарии:

1. ваш код не работает, программист завершает работу с кодом -1073741819

2. @TranQuocGiaCat Я добавил полную программу с исполнениями

3. большое вам спасибо, но я не понимаю, почему мы делаем двойной указатель в переменной p?

4. @TranQuocGiaCat двойной указатель позволяет записывать в поле suiv ранее созданного списка или в заголовок в первый раз. head — это Liste * ; , поэтому адрес head — это Liste ** ; и т.д. Вы понимаете?

5. да, и пока, если я хочу использовать 1 указатель * и 1 переменную normal, что мне делать?