**关闭。**此题需要debugging details。目前不接受答复。
编辑问题以包含desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem。这将帮助其他人回答这个问题。
昨天关门了。
Improve this question
我在试着恢复。txt文件的文本,把它变成一个记录,以创建一个基本的“全球定位系统”。我确实设法把文本变成了一个记录,然而,代码运行的时间越长,出现的错误就越频繁(比如它写的是“hungry”而不是“hungry”)。
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
typedef int bool;
#define TRUE 1
#define FALSE 0
// definir string
typedef char string[1024];
//Define event
typedef struct{
string action[49],preconds[24],add[24],delete[24];
int NbPreconds,NbAdd,NbDelete;
}Event;
int parseLine(char source[], string cible[]){
int i=0, n=0; // i: source[], n: cible[]
while(source[i]!=':') i++; // go until ':'
i++; // avancer au debut de la premiere chaine
int j=i; // point beginning of first chain with j
while(source[i]!='\n'){
if(source[i]==','){
memcpy(&cible[n], &source[j], i-j); // extract characters from j to i
n++;
j=i+1; // j beginning of chain
}
i++;
}
return n;
}
int main(){
Event event[49];
string start[49],finish[49];
int NbStart,NbFinish,i,k,x,Z;
char source[100];
FILE* txtfile = fopen("school.txt","r"); // insérer "monkeys.txt" / "blocs.txt" / "school.txt" pour choisir le fichier
if(txtfile == NULL){ // tester le fichier s'il existe
printf("Fichier inexistant.\n");
exit(0);
}
else{
printf("Fichier ouvert.\n");
}
//Lire les Conditions de départ & de Fin
fgets(source,100,txtfile);
NbStart=parseLine(source,start);
printf("Condition Départ:\n");
for(i=0; i<NbStart;i++){
printf(" - %s\n",start[i]);
}
fgets(source,100,txtfile);
string tempo[]={""};
NbFinish=parseLine(source,finish);
printf("Condition Fin:\n");
for(i=0;i<NbFinish;i++){
printf(" - %s\n",finish[i]);
}
//read action
int NbE=0;
while(fgets(source,100,txtfile)!=NULL){
fgets(source,100,txtfile);
parseLine(source, event[NbE].action);
//read preconds
fgets(source,100,txtfile);
event[NbE].NbPreconds=parseLine(source, event[NbE].preconds);
for(i=0;i<event[NbE].NbPreconds;i++){
printf("Precond: %s\n",event[NbE].preconds[i]);
}
//read add
fgets(source,100,txtfile);
event[NbE].NbAdd=parseLine(source, event[NbE].add);
for(i=0;i<event[NbE].NbAdd;i++){
printf("Add: %s\n",event[NbE].add[i]);
}
//read delete
fgets(source,100,txtfile);
event[NbE].NbDelete=parseLine(source, event[NbE].delete);
for(i=0;i<event[NbE].NbDelete;i++){
printf("Delete: %s\n",event[NbE].delete[i]);
}
}
bool Test=0; //Not complete
while(Test==0){
Test=1;
for(i=0;i<NbStart;i++){
for(k=0;k<NbStart;k++){
if(start[k]==finish[i]){
Z++;
if(Z==NbFinish){
Test=1;
}
}
}
}
Z=0;
}
if(Test==1){
printf("Le résultat a était trouvé en %d étapes.\n",x);
}
fclose(txtfile);
}
输入:
start:at door,on floor,has ball,hungry,chair at door,
finish:not hungry,
****
action:climb on chair,
preconds:chair at middle room,at middle room,on floor,
add:at bananas,on chair,
delete:at middle room,on floor,
****
action:push chair from door to middle room,
preconds:chair at door,at door,
add:chair at middle room,at middle room,
delete:chair at door,at door,
****
action:walk from door to middle room,
preconds:at door,on floor,
add:at middle room,
delete:at door,
****
action:grasp bananas,
preconds:at bananas,empty handed,
add:has bananas,
delete:empty handed,
****
action:drop ball,
preconds:has ball,
add:empty handed,
delete:has ball,
****
action:eat bananas,
preconds:has bananas,
add:empty handed,not hungry,
delete:has bananas,hungry,
输出:
Fichier ouvert.
Condition Départ:
- at door
- on floor
- has ball
- hungry
- chair at door
Condition Fin:
- not hungry
Precond: chair at middle room
Precond: at middle room
Precond: on floor
Add: at bananas
Add: on chair
Delete: at middle room
Delete: on floor
Precond: chair at doorle room
Precond: at doorle room
Add: chair at middle room
Add: at middle room
Delete: chair at doorm
Delete: at doorr
Precond: at doort doorle room
Precond: on floore room
Add: at middle roome room
Delete: at doort doorm
Precond: at bananasoorle room
Precond: empty handedom
Add: has bananasoome room
Delete: empty handedrm
Precond: has ballasoorle room
Add: empty handedome room
Delete: has ballndedrm
Precond: has bananasorle room
Add: empty handedome room
Add: not hungryroom
Delete: has bananasdrm
Delete: hungryrr
Le résultat a était trouvé en 0 étapes.
1条答案
按热度按时间axzmvihb1#
如何使用GNU调试器查找bug
下面是一个如何使用GNU debugger(GDB)查找bug的示例。如果您使用的是带有另一个调试器的IDE,也可以使用该调试器。所有调试器都应该具有下面描述的功能,尽管语法可能不同。此外,一些调试器允许您通过鼠标单击按钮来发出命令,而不是键入命令。
在您发布的输出中,第一行不正确的是以下行:
它应该是:
这一行输出由代码行打印
和
event[NbE].preconds[i]
应该由行设置也就是程序中的两行。是69号线。
因此,我们将您的程序加载到GDB中,并使用以下GDB命令在第69行设置断点:
然后,我们开始使用
命令
程序现在将运行到第一次到达第69行上的断点。
我们现在使用以下命令设置GDB,使其在程序停止时显示
event[NbE].preconds
的值:GDB现在告诉我这个变量有以下值:
这意味着2D数组中所有数组的所有元素都具有值
0
。它可能会告诉你同样的情况,尽管这并不能保证,因为你没有以任何方式初始化这些值。现在我们通过使用以下命令跳过函数调用,转到下一行:
GDB现在告诉我们关于
event[NbE].preconds
的以下内容:这些由
parseLine
创建的字符串看起来很好,所以我们继续运行程序,直到再次到达断点,使用以下命令:GDB告诉我们,
event[NbE].preconds
自上次程序停止以来没有被更改,所以我们使用以下命令再次跳过函数调用parseLine
:GDB现在告诉我们,
event[NbE].preconds
已更改为以下值:此值不正确。所以我们现在知道第二时间线69被执行,函数
parseLine
将给予我们无效的结果。因此,我们使用命令重新启动程序我们告诉GDB,我们不再希望每次程序停止时都被告知
event[NbE].preconds
的值,通过使用以下命令:现在我们重复上面的步骤,除了
display
命令之外,但是在第二次遇到第69行的断点时,我们没有使用n
命令跳过对parseLine
的函数调用,而是使用命令进入函数调用,这样我们就可以确切地看到函数是如何生成错误的输出的。
进入函数后,我们发出命令
来监视该字符串的内容。
发出命令后
跳到下一行几次(您可以简单地按Enter重复上一个命令),我们看到在该函数中对
memcpy
的调用将更改cible[0]
的内容致:
我们看到
memcpy
覆盖了cible[0]
的前13个字符,但没有写入空终止字符。因此,字符le room
是middle room
的残余,middle room
是字符串先前内容的一部分。函数
parseLine
的其余部分也从不向字符串写入终止null字符,因此错误的字符串最终会被传回并打印出来。因此,我们现在知道,最明显的修复方法是函数
parseLine
在调用memcpy
之后向字符串添加一个终止空字符。