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