C 打印链表时,最后一个元素值显示在第一个和最后一个位置

C 打印链表时,最后一个元素值显示在第一个和最后一个位置,c,linked-list,C,Linked List,新年快乐 这个问题源于一个项目,该项目在C语言中编写了一个名为Laby chiffres的游戏。要查看该游戏在第三批游戏中的外观,请点击此链接: 上下文: 我使用一个链表来存储玩家通过数字网格所走的路径。玩家的目标是找到一条从出发点到到达点的路径,路径的长度和总数都给定。菜单上有一个switch语句,然后是一个接受玩家想要进入的方向的语句。这是因为我有代码显示播放器到每个数字的“通道”被正确记录 问题: 当我试图打印路径时(这是分配的要求,对玩家来说很有用),我会以正确的顺序打印路径,但最后一个

新年快乐

这个问题源于一个项目,该项目在C语言中编写了一个名为Laby chiffres的游戏。要查看该游戏在第三批游戏中的外观,请点击此链接:

上下文: 我使用一个链表来存储玩家通过数字网格所走的路径。玩家的目标是找到一条从出发点到到达点的路径,路径的长度和总数都给定。菜单上有一个switch语句,然后是一个接受玩家想要进入的方向的语句。这是因为我有代码显示播放器到每个数字的“通道”被正确记录

问题: 当我试图打印路径时(这是分配的要求,对玩家来说很有用),我会以正确的顺序打印路径,但最后一个元素(即玩家最近移动到的位置)显示在列表的开始和结束处

示例:玩家使用如下值在位置上移动。从出发点值5->8->4->1开始。每个阶段打印的内容是:

5->
8->8->
4->8->4->
1->8->4->1->
我尝试过的 我看过其他几个链表问题,但没有一个问题与我看到的问题相同。 我尝试过改变很多事情,但老实说,现在我做的实验比任何事情都多。例如,将
empiler
函数更改为在错误的一端添加元素时,会按错误的顺序(如预期)打印路径,但仍会打印两次最近到达的数字,仅在路径的开头,而不是在开始和结尾各打印一个

相关功能 讲师明确表示,打印需要颠倒顺序,因此以下是打印功能:

void affiche_chemin (PLATEAU jeu, PILE pile){ 
    afficher_pile_inverse(&jeu , jeu.chemin.P_sommet);
    printf("\n");
}

void afficher_pile_inverse(PLATEAU *P_jeu, ELEMENT *P_cur){    
    if(P_cur != NULL){
        afficher_pile_inverse(P_jeu,P_cur->P_suivant);
        printf("%d->",lire_valeur_a(P_jeu,&P_cur->valeur));
    }       
}
lire\u valeur\u a
读取网格中的值,该值是下面给出的
平台
结构的一部分,并从文本文件中读取。这似乎是可行的,所以我不打算将其包括在内,以尽量缩短问题的长度

添加元素的功能是:

ELEMENT* empiler(PILE *P_liste, ELEMENT *P_elt_ajoute){
   P_elt_ajoute ->P_suivant = P_liste->P_sommet; 
   P_liste->P_sommet = P_elt_ajoute;             
   return P_elt_ajoute;
}
鉴于讲师关于需要颠倒顺序才能正确打印的评论,我认为我在列表的右端添加了元素

这些函数初始化路径,并分配一个新的
元素
,仅供下一个摘录中参考

void initialiser_pile(PILE *P_pile){
    P_pile->P_sommet = NULL;
}

ELEMENT *nouvel_element (POSITION nouvelle_valeur){
    ELEMENT *P_elt;
    P_elt =(ELEMENT*) malloc(sizeof(ELEMENT));
    if(P_elt ) {    /* NULL equivalent to false like 0 */
        P_elt->valeur = nouvelle_valeur;
        P_elt->P_suivant = NULL;
    }
    return P_elt;
}
此代码首次在读取游戏文本文件时设置路径,因此这是第一次使用
empiler
向路径添加元素。(此摘录来自一个长函数,该函数多次使用
fscanf
读取游戏文本文件,似乎工作正常。)

以下功能用于在游戏期间添加元素

int choix_indep_jeu_update(PLATEAU *jeu, POSITION *new_pos, int pas, int dir){  
    ELEMENT *new = nouvel_element(*new_pos);//1 Make new element

    if (new == NULL) return 0;
        empiler( &jeu->chemin, new );//should add new element

    jeu->longcur++;
    jeu->sumcur = jeu->sumcur + lire_valeur_a(jeu, new_pos);

    affiche_grille(*jeu);
    affiche_chemin(*jeu,jeu->chemin);
    return 1;
}
数据结构 类型定义结构位置{ int indl;//木质的标记 int indc;//科隆符号 }位置

typedef struct element_st{
    POSITION valeur;
    struct element_st *P_suivant;
    }ELEMENT;

typedef struct pile_st{
    ELEMENT * P_sommet;
    }PILE;

typedef struct plat_st{
//########## GAME FILE INFORMATION
    int nl;        //number of lines in grid
    int nc;        //number of columns in grid
    POSITION dep;  //position du depart: dep.indl and dep.indc
    POSITION arr;  //position d'arrive: arr.indl and arr.indc
    int longdem;   //length demanded
    int sumdem;    //total demanded
    int ** grille; //Playing grid 
//#######INFO re GAME IN PROGRESS ########
    int longcur;  //longueur courant
    int sumcur;   //totale courant
    PILE chemin;  //The path
    }PLATEAU;

我简化了您的代码,假设您希望empiler()将元素插入列表的前面,那么它们的顺序就相反了,那么代码似乎可以正常工作。我添加了afficher\u pile\u inverse1(),以便最后一个值后面没有“->”。因此,创建列表时出错,或者网格函数存在问题,您没有显示该问题

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

typedef int POSITION;

typedef struct element_st{
    POSITION valeur;
    struct element_st *P_suivant;
}ELEMENT;

typedef struct pile_st{
    ELEMENT * P_sommet;
}PILE;

void empiler(PILE *P_liste, ELEMENT *P_elt_ajoute){
   P_elt_ajoute ->P_suivant = P_liste->P_sommet; 
   P_liste->P_sommet = P_elt_ajoute;             
}

void afficher_pile_inverse1(ELEMENT *P_cur){    
    if(P_cur != NULL){
        afficher_pile_inverse1(P_cur->P_suivant);
        printf("%d->",P_cur->valeur);
    }       
}

void afficher_pile_inverse(ELEMENT *P_cur){    
    if(P_cur != NULL){
        afficher_pile_inverse1(P_cur->P_suivant);
        printf("%d",P_cur->valeur);
    }       
}

void affiche_chemin (PILE pile){
    afficher_pile_inverse(pile.P_sommet);
    printf("\n");
}

int main(void){
ELEMENT ae[4] = {{0,NULL},{1,NULL},{2,NULL},{3,NULL}};
PILE P_liste = {NULL};
size_t i;
    for(i = 0; i < 4; i++)
        empiler(&P_liste, &ae[i]);
    affiche_chemin(P_liste); 
    return 0;
}
#包括
#包括
typedef int位置;
类型定义结构元素{
瓦勒尔位置;
结构元素stp;
}元素;
类型定义结构桩{
元素*P_sommet;
}桩;
空堆(堆*P_列表,元素*P_elt_ajute){
P_elt_ajute->P_suivant=P_liste->P_sommet;
P_liste->P_sommet=P_elt_ajute;
}
无效附加桩逆1(元素*P\u cur){
if(P_cur!=NULL){
固定桩1(桩号->桩号);
printf(“%d->”,P\u cur->valeur);
}       
}
无效附加桩逆(元素*P\u cur){
if(P_cur!=NULL){
固定桩1(桩号->桩号);
printf(“%d”,P\u cur->valeur);
}       
}
空桩(桩){
粘贴桩逆(pile.P\u sommet);
printf(“\n”);
}
内部主(空){
元素ae[4]={{0,NULL},{1,NULL},{2,NULL},{3,NULL};
PILE P_liste={NULL};
尺寸i;
对于(i=0;i<4;i++)
empiler(&P_liste,&ae[i]);
阿菲切切明(P_liste);
返回0;
}

这是培养调试技能的绝佳机会。逐步检查代码以了解其行为方式的原因。无论如何,您都会获得一次投票,因为您的问题比大多数“调试我的代码”问题要好得多(除了带有单字母变量名称的代码等,这些问题的详细信息为0)。然而,@OliverCharlesworth说的话。这是大量的代码,您比我们更适合调试它。拿出调试器并开始断点/步进/检查。好的,谢谢Oliver和Martin。我将试一试。由于需要反向打印移动列表,也许值得一提的是,简单创建的链表(在根节点添加新节点)无论如何都将以反向顺序解析。如果你想“撤销”最近的移动,这很简单,因为这样的列表可以像后进先出堆栈一样工作。另外:为什么需要
结构桩
?您不能只使用指向链接列表根的
struct元素的指针吗?作为一种廉价的调试,除了
valeur
之外,您还可以使用
%p
打印列表节点的指针值。如果所有指针都不同(但您的值不同),那么您的
lire\u valeur\u a
就有问题。我认为问题不在于打印顺序,而在于打印时最后和第一个元素的值相同。返回的节点指针只是一种方便;该函数可以安全地在void上下文中使用。@MOehm-我更改了示例代码,因此它是原始帖子中代码的简化版本,并且可以正常工作
#include <stdio.h>
#include <stdlib.h>

typedef int POSITION;

typedef struct element_st{
    POSITION valeur;
    struct element_st *P_suivant;
}ELEMENT;

typedef struct pile_st{
    ELEMENT * P_sommet;
}PILE;

void empiler(PILE *P_liste, ELEMENT *P_elt_ajoute){
   P_elt_ajoute ->P_suivant = P_liste->P_sommet; 
   P_liste->P_sommet = P_elt_ajoute;             
}

void afficher_pile_inverse1(ELEMENT *P_cur){    
    if(P_cur != NULL){
        afficher_pile_inverse1(P_cur->P_suivant);
        printf("%d->",P_cur->valeur);
    }       
}

void afficher_pile_inverse(ELEMENT *P_cur){    
    if(P_cur != NULL){
        afficher_pile_inverse1(P_cur->P_suivant);
        printf("%d",P_cur->valeur);
    }       
}

void affiche_chemin (PILE pile){
    afficher_pile_inverse(pile.P_sommet);
    printf("\n");
}

int main(void){
ELEMENT ae[4] = {{0,NULL},{1,NULL},{2,NULL},{3,NULL}};
PILE P_liste = {NULL};
size_t i;
    for(i = 0; i < 4; i++)
        empiler(&P_liste, &ae[i]);
    affiche_chemin(P_liste); 
    return 0;
}