1. Aperçu

Le langage C permet aux utilisateurs de spécifier une structure de données composée de différents types de données réunis en un tout pour être référencés. Les données réunies dans ce tout sont interdépendantes. Une telle structure de données est appelée structure, ce qui équivaut à un enregistrement dans d'autres langages de haut niveau.

La forme générale de déclaration d'un type de structure est la suivante :

struct 结构体名
{成员列表};

Le nom de la structure sert de marqueur du type de structure, également appelé étiquette de structure. À l'intérieur des accolades se trouvent les membres de la structure, qui forment ensemble la structure. Chaque membre doit avoir une déclaration de type, par exemple :

Type name member name;

La liste des membres peut aussi être appelée liste des champs, et le premier membre est aussi appelé champ dans la structure. Les règles de nommage des membres sont les mêmes que les règles de nommage des variables.

struct student
{
    int num;
    char name[20];
    char sex;
    int age;
    float score;
    char addr[30];
};

2. Méthodes de définition de variables de type structure

Ce qui a été spécifié précédemment n'est qu'un type de structure, qui est comme un modèle mais ne contient aucune donnée spécifique, et le système ne lui alloue pas d'unités de mémoire réelles. Afin d'utiliser des données de type structure dans un programme, des variables du type de structure doivent être définies et des données spécifiques y être stockées. Les trois méthodes suivantes peuvent être utilisées pour définir des variables de type structure.

(1) Déclarer d'abord le type de structure, puis définir les noms des variables

Comme ci-dessus, un type de structure struct student a été défini, et il peut être utilisé pour définir des variables. Par exemple :

struct student{  //结构体类型名
    ...
    ...
    ...
}student1, student2 //结构体变量名

student1 et student2 sont définis comme des variables de type struct student.

Après la définition des variables de structure, le système leur alloue des unités de mémoire. Par exemple, student1 et student2 occupent chacun 59 octets en mémoire.

Notez que la différence entre définir une variable comme un type standard (type de données de base) et comme un type structure est que ce dernier exige non seulement de spécifier la variable comme un type structure, mais aussi de préciser un type structure particulier (par exemple, le type struct student), car de nombreux types structure spécifiques peuvent être définis. Lorsque vous définissez une variable comme un entier, il vous suffit de la spécifier comme int.

(2) Définir des variables tout en déclarant le type

Par exemple :

struct student
{
    int num;
    char name[20];
    char sex;
    int age;
    float score;
    char addr[30];
}student1, student2;

Son effet est le même que celui de la première méthode, c'est-à-dire définir deux variables de type struct student, student1 et student2. La forme générale de cette définition est :

struct 结构体名
{
    成员表列
}变量名表列;

(3) Définir directement des variables de type structure

Sa forme générale est :

struct
{
    成员表列
}变量名表列;

C'est-à-dire que le nom de la structure n'apparaît pas.

Concernant les types structure, quelques points doivent être expliqués :

  • a. Type et variable sont des concepts différents et ne doivent pas être confondus. Vous pouvez uniquement affecter des valeurs à des variables, y accéder ou effectuer des opérations sur celles-ci, et non sur un type. Au moment de la compilation, aucun espace n'est alloué pour les types ; l'espace n'est alloué que pour les variables.
  • b. Les membres (c'est-à-dire les champs) d'une structure peuvent être utilisés indépendamment, et leur rôle et leur statut sont équivalents à ceux de variables ordinaires.
  • c. Un membre peut aussi être une variable de structure. Par exemple :

    struct date // 声明一个结构体类型
    {
        int month;
        int day;
        int year;
    }
    
    struct student
    {
        int num;
        char name[20];
        char sex;
        int age;
        struct date birthday;
        char addr[30];
    }student1, student2;

    Déclarez d'abord un type struct date, qui représente « date » et comprend trois membres : month, day, year. Ensuite, lors de la déclaration du type struct student, spécifiez le membre birthday comme étant de type struct date.

  • d. Les noms de membres peuvent être identiques aux noms de variables du programme, mais ils ne représentent pas le même objet.

3. Référencer les variables de structure

(1) Une variable de structure ne peut pas être entrée ou sortie dans son ensemble.

Chaque membre d'une variable de structure peut uniquement être entré ou sorti séparément. La façon de référencer un membre d'une variable de structure est :

Struct variable name.member name

Par exemple, student1.num représente le membre num de la variable student1, c'est-à-dire l'élément num de student1. Vous pouvez affecter une valeur à un membre d'une variable. Par exemple : student1.num = 10010;

.Le point est l'opérateur de membre (composant). Il a la priorité la plus élevée parmi tous les opérateurs, donc student1.num peut être traité comme un tout. L'effet de l'instruction d'affectation ci-dessus est d'affecter l'entier 10010 au membre num de la variable student1.

(2) Si un membre est lui-même d'un type structure, plusieurs opérateurs de membre sont nécessaires pour trouver le membre de niveau le plus bas, niveau par niveau. Seul le membre de niveau le plus bas peut être affecté, accédé ou manipulé.

Par exemple : on peut accéder aux membres de la variable de structure student1 comme ceci :

student1.num
student1.birthday.month

Notez que student1.birthday ne peut pas être utilisé pour accéder au membre birthday de la variable student1, car birthday est lui-même une variable de structure.

((3) Les membres d'une variable de structure peuvent effectuer diverses opérations comme des variables ordinaires (les opérations autorisées sont déterminées par leur type).

student2.score = student1.score;
sum = student1.score + student2.score;
student1.age ++;
++ student1.age;

Comme.L'opérateur . a la priorité la plus élevée, student1.age++ effectue une opération d'auto-incrémentation sur student1.age, plutôt que d'effectuer d'abord une auto-incrémentation sur age.

(4) Vous pouvez référencer l'adresse d'un membre d'une variable de structure. Vous pouvez également référencer l'adresse d'une variable de structure. Par exemple :

scanf("%d", &student1.num);// 输入 student1.num 的值
printf("%o", &student1);// 输出 student1 的首地址

Mais vous ne pouvez pas utiliser l'instruction suivante pour lire une variable de structure entière, par exemple :

scanf("%d,%s,%c,%d,%f,%s", &student1);

L'adresse d'une variable de structure est principalement utilisée comme paramètre de fonction pour transmettre l'adresse de la structure.


4. Initialisation des variables de structure

Comme les variables d'autres types, les variables de structure peuvent recevoir des valeurs initiales au moment de la définition.

Exemple

#include <stdio.h> struct student { long int num; char name[20]; char sex; char addr[30]; }a = {89031, "Li Lin", 'M', "123 Beijing Road"}; void main() { printf("NO. : %ld\nname: %s\nsex: %c\naddress: %s\n", a.num, a.name, a.sex, a.addr); }

5. Tableaux de structures

Une variable de structure peut stocker un ensemble de données (comme le numéro d'étudiant, le nom, les notes, etc. d'un étudiant). S'il y a les données de 10 étudiants à traiter dans des calculs, il faut évidemment utiliser un tableau, c'est-à-dire un tableau de structures. La différence entre un tableau de structures et les tableaux numériques présentés précédemment est que chaque élément du tableau est une donnée de type structure, et ils comprennent chacun divers membres (composants).

5.1 Définition des tableaux de structures

Comme pour la définition des variables de structure, il suffit de le spécifier comme un tableau.

struct student
{
    int num;
    char name[20];
    char sex;
    int age;
    float score;
    char addr[30];
};
struct student stu[3];

Ce qui précède définit un tableau stu dont les éléments sont de type struct student, et le tableau possède 3 éléments. Vous pouvez également définir directement un tableau de structures. Par exemple :

struct student
{
    int num;
    ....

}stu[3];

ou 

struct

{
    int num;
     ...
}stu[3];

5.2 Initialisation des tableaux de structures

Comme les autres types de tableaux, les tableaux de structures peuvent être initialisés, par exemple :

struct student
{
    int mum;
    char name[20];
    char sex;
    int age;
    float score;
    char addr[30];
}stu[3] = {{10101,"Li Lin", 'M', 18, 87.5, "103 Beijing Road"},
            {10101,"Li Lin", 'M', 18, 87.5, "103 Beijing Road"},
            {10101,"Li Lin", 'M', 18, 87.5, "103 Beijing Road"}};

Lors de la définition du tableau stu, le nombre d'éléments peut être omis, c'est-à-dire écrit sous la forme suivante :

stu[] = {{...},{...},{...}};

Au moment de la compilation, le système détermine le nombre d'éléments du tableau en fonction du nombre de constantes de structure données comme valeurs initiales.

Bien sûr, l'initialisation du tableau peut également utiliser la forme suivante :

struct student
{
    int num;
    ...
};
struct student stu[] = {{...},{...},{...}};

C'est-à-dire, déclarez d'abord le type de structure, puis définissez le tableau comme ce type de structure, et initialisez-le lors de la définition du tableau.

D'après ce qui précède, on peut voir que la forme générale de l'initialisation d'un tableau de structures consiste à ajouter après la définition du tableau :

5.3 Exemple d'application des tableaux de structures

L'exemple suivant illustre la définition et le référencement des tableaux de structures.

Exemple

#include <stdio.h> #include <string.h> #include <stdlib.h> struct person { char name[20]; int count; }leader[3] = {{"Li", 0},  {"Zhang", 0},  {"Fun", 0}}; void main() { int i, j; char leader_name[20]; for(i = 1; i<= 10;i++) { scanf("%s", leader_name); for(j=0;j<3;j++) if(strcmp(leader_name, leader[j].name) == 0) leader[j].count ++; } printf("\n"); for(i=0;i<3;i++) printf("%5s: %d\n", leader[i].name, leader[i].count); system("pause"); }

Le résultat d'exécution est le suivant :

LI
Li
Fun
Zhang
Zhang
Fun
Li
Fun
Zhang
Li

   Li: 3
Zhang: 3
  Fun: 3

6. Pointeurs vers des données de type structure

Un pointeur vers une variable de structure est l'adresse de début du segment mémoire occupé par cette variable. Une variable pointeur peut être définie pour pointer vers une variable de structure, auquel cas la valeur de la variable pointeur est l'adresse de début de la variable de structure. Une variable pointeur peut également être utilisée pour pointer vers un élément d'un tableau de structures.

6.1 Pointeur vers une variable de structure

Application d'un pointeur vers une variable de structure :

Exemple

#include <string.h> #include <stdio.h> #include <stdlib.b> struct student { long num; char name[20]; char sex; float score; }; void main() { struct student stu_1; struct student *p; p = &stu_1; stu_1.num = 89101; strcpy(stu_1.name, "Li Lin"); stu_1.sex = 'M'; stu_1.score = 89.5; printf("N° :%ld\nnom: %s\nsexe:%c\nnote:%f\n", stu_1.num, stu_1.name, stu_1.sex, stu_1.score); printf("N° :%ld\nnom: %s\nsexe:%c\nnote:%f\n", (*p).num, (*p).name, (*p).sex, (*p).score); system("pause"); }

.num ou stu

.name comme argument réel d'une fonction pour transmettre la valeur de l'argument réel au paramètre formel. L'utilisation est la même que celle d'une variable ordinaire comme argument réel, et cela relève du passage par valeur. Il convient de noter que les types de l'argument réel et du paramètre formel doivent être cohérents.

NO. :89101
name: Li Lin
sex:M
score:89.500000
NO. :89101
name: Li Lin
sex:M
score:89.500000

On peut voir que la sortie des deux instructions printf est identique.

En langage C, pour des raisons de commodité et d'intuitivité, (*p).num peut être remplacé par p->num. Il représente le membre num dans la variable de structure *p (c'est-à-dire la variable de structure pointée par p). De même, (*p).name est équivalent à p->name.

C'est-à-dire que les trois formes suivantes sont équivalentes :

  • a. variable de structure.nom du membre
  • b. (*p).nom du membre
  • c. p-> nom du membre

Les éléments de sortie de la dernière fonction printf ci-dessus peuvent être réécrits comme suit :

printf("NO. :%ld\nname: %s\nsex:%c\nscore:%f\n",p->num, p->name, p->sex, p->score);

où->est appelé l'opérateur flèche.

Analysez les opérateurs suivants :

  • p -> n obtient la valeur du membre n dans la variable de structure pointée par p.
  • p -> n ++ obtient la valeur du membre n dans la variable de structure pointée par p, et après avoir utilisé la valeur, l'incrémente de 1.
  • ++p -> n obtient la valeur du membre n dans la variable de structure pointée par p et l'incrémente de 1 (incrémenter d'abord).

6.2 Pointeur vers un tableau de structures

Comme introduit précédemment, les pointeurs et les variables de pointeur peuvent être utilisés pour pointer vers des tableaux ou des éléments de tableau. De même, les variables de pointeur peuvent également être utilisées pour pointer vers des tableaux de structures et leurs éléments.

Application d'un pointeur à un tableau de structures.

Exemple

#include <stdio.h> #inlcude <stdlib.h> struct student { int num; char name[20]; char sex; int age; }; struct student stu[3] = {{10101, "Li Lin", 'M', 18},  {10102, "Zhang Fun", 'M', 19},  {10103, "Wang Min", 'F', 20}}; int main() { struct student *p; printf("N° nom sexe âge\n"); for(p=stu; p<stu+3;p++) printf("%5d %-20s %2c %4d\n", p->num, p->name, p->sex, p->age); system("pause"); }

Le résultat d'exécution est le suivant :

No.    name        sex        age
10101 Li Lin                M       18
10102 Zhang Fun        M       19
10103 Wang Min          F        20

Notez les deux points suivants :

(

1) Si la valeur initiale de p est stu, c'est-à-dire qu'il pointe vers le premier élément, alors après p + 1, il pointe vers l'adresse de début de l'élément suivant. Par exemple :

(++p) -> num incrémente d'abord p de 1, puis obtient la valeur du membre num dans l'élément vers lequel il pointe (c'est-à-dire 10102).

(p++) ->num obtient d'abord la valeur de p->num (c'est-à-dire 10101), puis incrémente p de 1, en pointant vers stu

Notez la différence entre les deux cas ci-dessus.

(2) Le programme a défini le pointeur p comme une variable pointant vers des données de type struct student. Il ne peut pointer que vers des données de type struct student (la valeur de p est l'adresse de début d'un élément du tableau stu), et ne peut pas pointer vers un membre à l'intérieur d'un élément du tableau stu (c'est-à-dire que l'adresse de p ne peut pas être une adresse de membre). Par exemple, ce qui suit est incorrect :

p = &stu[1].name

Une erreur se produira à la compilation. Ne pensez jamais que, puisque p stocke une adresse, n'importe quelle adresse peut lui être assignée. Si les types d'adresse sont différents, une conversion de type forcée peut être utilisée. Par exemple :

p = (struct student *)&stu[1].name;

À ce stade, l'adresse de début du membre name de stu

6.3 Utilisation de variables de structure et de pointeurs vers des structures comme paramètres de fonction

Il existe trois méthodes pour transmettre la valeur d'une variable de structure à une autre fonction :

  • (1) Utiliser un membre d'une variable de structure comme argument. Par exemple, utilisez stu
  • (2) Utiliser une variable de structure comme paramètre. Les anciennes versions du système C ne permettaient pas d'utiliser une variable de structure comme argument effectif ; ANSI C a supprimé cette restriction. Toutefois, lorsqu'une variable de structure est utilisée comme argument effectif, la méthode de passage par valeur est adoptée, et toutes les unités mémoire occupées par la variable de structure sont transmises au paramètre formel dans l'ordre. Le paramètre formel doit également être une variable de structure du même type. Lors de l'appel de la fonction, le paramètre formel occupe également des unités mémoire. Cette méthode de passage a un coût important en espace et en temps. Si la structure est très grande, le coût est considérable. De plus, comme la méthode de passage par valeur est utilisée, si la valeur du paramètre formel (également une variable de structure) est modifiée pendant l'exécution de la fonction appelée, cette valeur ne peut pas être renvoyée à la fonction appelante, ce qui cause souvent des inconvénients. Par conséquent, cette méthode est généralement moins utilisée.
  • (3) Utiliser un pointeur vers une variable de structure (ou un tableau) comme argument effectif, et transmettre l'adresse de la variable de structure (ou du tableau) au paramètre formel.

Utilisation d'une variable de structure comme paramètre de fonction.

Exemple

#include <stdio.h> #define FORMAT "%d\n%s\n%f\n%f\n%f\n" struct student { int num; char name[20]; float score[3]; }; void print(struct student stu) { printf(FORMAT, stu.num, stu.score[0], stu.score[1], stu.score[2]); printf("\n"); } void main() { struct student stu; stu.num = 12345; strcpy(stu.name, "Li Li"); stu.score[0] = 67.5; stu.score[1] = 89; stu.score[2] = 78.6; printf(stu); }

Modifiez ce qui précède pour utiliser un pointeur vers une variable de structure comme argument réel.

Exemple

#include <stdio.h> #define FORMAT "%d\n%s\n%f\n%f\n%f\n" struct student { int num; char name[20]; float score[3]; }stu = {12345, "Li Li", 67.5, 89, 78.6}; void print(struct student *p) { printf(FORMAT, p->num, p->name, p->score[0], p->score[1], p->score[2]); printf("\n"); } void main() { print(&stu); }

7. Manipulation des listes chaînées avec des pointeurs

7.1 Aperçu des listes chaînées

Une liste chaînée est une structure de données courante et importante. C'est une structure qui effectue une allocation dynamique de mémoire.

Une liste chaînée possède une variable pointeur de tête, qui stocke une adresse pointant vers un élément. Chaque élément de la liste chaînée est appelé un nœud. Chaque nœud doit comprendre deux parties : l'une correspond aux données réelles dont l'utilisateur a besoin, et l'autre à l'adresse du nœud suivant. On peut voir que le pointeur de tête head pointe vers le premier élément, et le premier élément pointe vers le deuxième élément, ... jusqu'au dernier élément. Cet élément ne pointe plus vers d'autres éléments ; il est appelé la queue de la liste, et sa partie adresse contient un NULL (ce qui signifie une adresse vide), et la liste chaînée se termine ici.

On peut voir que les éléments d'une liste chaînée n'ont pas besoin d'être stockés de manière contiguë en mémoire. Pour trouver un certain élément, vous devez d'abord trouver l'élément précédent, et ce n'est qu'ensuite que vous pouvez trouver l'élément suivant en fonction de l'adresse de l'élément suivant qu'il fournit. Sans le pointeur de tête head, il est impossible d'accéder à toute la liste chaînée.

On peut voir que ce type de structure de données de liste chaînée doit être implémenté à l'aide de variables de pointeur. C'est-à-dire qu'un nœud doit contenir une variable de pointeur pour stocker l'adresse du nœud suivant.

Précédemment, nous avons présenté les variables de structure. Les utiliser comme nœuds dans une liste chaînée est tout à fait approprié. Une variable de structure contient plusieurs membres ; ces membres peuvent être de type numérique, de type caractère, de type tableau ou de type pointeur. Nous utilisons ce membre de type pointeur pour stocker l'adresse du nœud suivant. Par exemple, nous pouvons concevoir un tel type de structure :

struct student
{
    int num;
    float score;
    struct student *next;
};

Parmi eux, les membres num et score servent à stocker des données utiles dans le nœud (les données nécessaires à l'utilisateur). next est un membre de type pointeur, qui pointe vers des données de type struct student (c'est le type de structure qui contient next). Un membre de type pointeur peut pointer vers des données de structure d'autres types, et peut aussi pointer vers des données du type de structure dans lequel il réside. Maintenant next est un membre du type struct student, et il pointe vers des données du type struct student. De cette façon, une liste chaînée peut être établie.

Veuillez noter : le simple fait de définir un type struct student n'alloue pas réellement d'espace de stockage ; des unités de mémoire ne sont allouées que lorsque des variables sont définies.

7.2 Liste chaînée simple

L'exemple suivant illustre comment créer et afficher une liste chaînée simple :

Exemple

#include <stdio.h> #include <stdlib.h> #define NULL 0 struct student { long num; float score; struct student *next; }; void main() { struct student a, b, c, *head, *p; a.num = 99101; a.score = 89.5; b.num = 99103; b.score = 90; c.num = 99107; c.score = 85;// attribuer des valeurs aux membres num et score du nœud head = &a;// affecter l'adresse de début du nœud a au pointeur de tête head a.next = &b;// affecter l'adresse de début du nœud b au membre next du nœud a b.next = &c; c.next = NULL;// le membre next du nœud c ne stocke l'adresse d'aucun autre nœud p = head;// faire pointer le pointeur p vers le nœud a do { printf("%ld %5.1f\n", p->num, p->score);// afficher les données du nœud pointé par p p = p->next;// faire pointer p vers le nœud suivant }while(p != NULL);// après avoir affiché le nœud c, la valeur de p est NULL system("pause"); }

Résultat de l'exécution:

99101  89.5
99103  90.0
99107  85.0

7.3 Fonctions nécessaires au traitement des listes chaînées dynamiques

(1) fonction malloc

void *malloc(unsigned int size);

Sa fonction est d'allouer un espace contigu de longueur size dans la zone de stockage dynamique de la mémoire. La valeur de cette fonction (c'est-à-dire la valeur de retour) est un pointeur vers l'adresse de début de l'espace alloué (type de base void). Si cette fonction ne s'exécute pas correctement (par exemple, espace mémoire insuffisant), elle renvoie le pointeur nul NULL.

(2) fonction calloc

void *calloc(unsigned n, unsigned size);

Sa fonction est d'allouer n espaces contigus de longueur size dans la zone de stockage dynamique de la mémoire. La fonction renvoie un pointeur vers l'adresse de début de l'espace alloué ; si l'allocation échoue, elle renvoie NULL. La fonction calloc peut être utilisée pour allouer un espace de stockage dynamique pour un tableau à une dimension, où n est le nombre d'éléments du tableau et chaque élément a une longueur size.

(3) fonction free

void free(void *p);

Sa fonction est de libérer la zone mémoire pointée par p, afin que cette partie de la zone mémoire puisse être utilisée par d'autres variables. p est la valeur renvoyée par le dernier appel à la fonction calloc ou malloc. La fonction free n'a pas de valeur de retour. Veuillez noter : les fonctions malloc et calloc fournies par les versions antérieures de C renvoyaient des pointeurs vers des données de type caractère. Les fonctions malloc et calloc fournies par ANSI C sont spécifiées comme étant de type void *.

7.4 Création d'une liste chaînée dynamique

Ce que l'on appelle créer une liste chaînée dynamique consiste à construire une liste chaînée à partir de zéro pendant l'exécution du programme, c'est-à-dire à ouvrir des nœuds un par un, à saisir des données pour chaque nœud et à établir la relation de liaison de l'avant vers l'arrière.

Exemple

#include <stdio.h> #include <stdlib.h> #define NULL 0 #define LEN sizeof(struct student) struct student { long num; float score; struct student *next; }; struct student *create() { struct student *p1, *p2, *head; int num; float score; int n = 0; head = NULL; p1 = p2 = (struct student *)malloc(LEN); printf("Veuillez saisir num et score.\n"); scanf("%d,%f", &p1->num, &p1->score); while(p1->num != 0) { n ++; if(n == 1) head = p1; else p2->next = p1; p2 = p1; p1 = (struct student *)malloc(sizeof(struct student)); printf("veuillez saisir num et score.\n"); scanf("%d,%f", &p1->num, &p1->score); } p2->next = NULL; return head; } void printlist(struct student *head) { struct student *p; p = head; if(head != NULL) { do { printf("num=%d score=%f\n", p->num, p->score); p = p->next; }while(p != NULL); } } void main() { struct student *head; head = create(); printlist(head); system("pause"); }

Voici diverses opérations sur la liste chaînée

Afficher la liste chaînée :

void printlist(struct student *head)
{
    struct student *p;
    p = head;

    if(head != NULL)
    {
        do 
        {
            printf("num=%d score=%5.2f\n", p->num, p->score);
            p = p->next;
        } while (p != NULL);
    }
    /* while(p -> next != NULL)
    {
        printf("num=%d score=%f\n", p->num, p->score);
        p = p->next;
    }*/
}
Supprimer un nœud :
struct student *delNode(struct student *head, int num)
{
    printf("delNode.\n");
    struct student *p1, *p2;
    if(head == NULL)
    {
        printf("The List is NULL.\n");
    }
    else
    {
        p1 = head;
        while(p1->next != NULL && p1->num != num)
        {
            p2 = p1;
            p1 = p1->next;
        }
        if(p1->num == num)
        {
            if(p1 == head)
                head = p1->next;
            else
                p2->next = p1->next;
        }
        else
            printf("Can not find list num.\n");
    }
    return head;
}

Mettre à jour un nœud :

struct student *update(struct student *head, int index, int num, float score)
{
    printf("update.\n");
    struct student *p;
    if(head == NULL)
    {
        printf("The List is NULL.\n");
    }
    else
    {
        p = head;
        while(p->next != NULL && p->num != index)
        {
            p = p->next;
        }
        if(p->num == index)
        {
            p->num = num;
            p->score = score;
        }
        else
            printf("Can not find list index.\n");
    }
    return head;
}

Ajouter un nœud :

struct student *add(struct student *head, int index, int num, float score)
{
    printf("add.\n");
    struct student *p1, *p2, *p3;
    if(head == NULL)
    {
        printf("The List is NULL.\n");
    }
    else
    {
        p1 = p2 = head;
        while(p1->next != NULL && p1->num != index)
        {
            p1 = p1->next;
            p2 = p1;
        }
        if(p1->num == index)
        {
            p3 = (struct student *)malloc(LEN);
            p3->num = num;
            p3->score = score;

            if(p2->next == NULL)
            {
                p2->next = p3;
                p3->next = NULL;
            }
            else
            {
                p3->next = p2->next;
                p2->next = p3;   
            }
        }
        else
            printf("Can not find list index.\n");
    }
    return head;
}

Lien original : http://www.cnblogs.com/qkhhxkj/archive/2011/06/28/2091818.html

Ouvrage de référence : Le chapitre sur les types de structures dans le livre de M. Tan Haoqiang *C Programming*.