C语言 数组结构和函数的数据调用问题



在为使用指向结构体数组的指针的类编写程序时,我遇到了一个关于使用结构体中存储的数据的问题。文件读取函数会很好地填充struct数组,然后显示正确的信息。然而,当显示要更改的项目时,write函数似乎会擦除或完全遗漏赛车位置2和4的数据。我绞尽脑汁想弄明白为什么会发生这种事。它读取的文件是"Car.txt">

Kirk Porsche 6 Silver
Spock Ferrari 7 Red
Leia Lamborghini 8 Yellow
Jaba Ford 9 Black 

在修改选择之前,我有一个测试打印while循环,显示在Leia的名字生成之后有一个笑脸ascii图标。但是,在选择要修改的方面并显示当前方面是什么(名称、制造、数字、颜色)时,被调用的数据似乎是混乱的或完全丢失的,尽管之前显示的几乎是完美的。值得注意的是,我是一个非常成熟的人,我对代码块工具(我用来编写和编译的工具)的了解很少。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <conio.h>
#include <time.h>
#include <string.h>
#define MAX 10
#define MIN 1
struct car;
//Initalizing needed functions
void fReadFile(struct car *ptr,int iBracket);
void fWriteFile(struct car *ptr,int iDriver,int iBracket);
void fRace4man(struct car *ptr,int iBracket);
void fResultsWrite(struct car *ptr,int a[],int iBracket);
int fRandgen(int min, int max);
struct car
{
char cName[16];
char cMake[16];
int iNum;
char cColor[16];
int iPosition;
int iPole;
};

int main (void)
{
//initializing variables
srand (time(NULL));
int iSelect,iDriver1=0,iDriver2=0,iBracket;
struct car *carptr, racer;
carptr= &racer;

//Code Author
printf("Phoenix Sampair-Lewisnn");
//Asking user to choose game mode
printf("Hello, please choose a game mode:nManual(0) Two players*INCOMPLETE,NOT WORKING*nAutomatic(1) One player + botsn");
scanf("%d", &iSelect);
if(iSelect==0)//manual mode
{
iBracket=2;
//could not be completed in time
}
else if(iSelect==1)//automatic mode
{
iBracket=4;
system("cls");
//Asking player to choose a racer from the text file
printf("Please select your racer. 1-4nn");
fReadFile(carptr,iBracket);
scanf("%d", &iDriver1);
printf("would you like to modify these racer's stats?1=Y ANY #=Nn");
scanf(" %d", &iSelect);
if(iSelect==1)
{
fWriteFile(carptr,iDriver1,iBracket);
}
printf("Let the racing beginn");//begins random racer decision and distance rolls for the race until on reached the finish line
fRace4man(carptr,iBracket);
}
getch();
return 0;
}
int fRandgen(int min, int max)
{
int range=max-min+1;
return rand()%range + min;
}
void fReadFile(struct car *ptr, int iBracket)
{
int iCount=0;
FILE *fpi =fopen("Car.txt","r");
if (fpi==NULL)
{
printf("Error, can not open filen");
}
while (fscanf(fpi,"%15s %15s %d %15s",&ptr[iCount].cName,&ptr[iCount].cMake,&ptr[iCount].iNum,&ptr[iCount].cColor)!=EOF)
{
printf("Racer %d:nName:%snMake:%snCar Number:%dnCar Color:%snn",iCount+1,ptr[iCount].cName,ptr[iCount].cMake,ptr[iCount].iNum,ptr[iCount].cColor);//printing racer data for player to view
ptr++;
iCount++;
}
fclose(fpi);
}
void fWriteFile(struct car *ptr, int iDriver,int iBracket)
{
int iSelect=0;
int iCount=0;
int i;
iDriver--;
FILE *fpi =fopen("Car.txt","r+");
if (fpi==NULL)
{
printf("Error, can not open filen");
}
printf("What would you like to modify?nRacer:1nCar make:2nCar Number:3nCar Color:4n");//asking what the player would like to modify about the racer data until they are satisfied
while(iCount!=iBracket)
{
printf("%s %s %d %sn",ptr[iCount].cName,ptr[iCount].cMake,ptr[iCount].iNum,ptr[iCount].cColor);
ptr++;
iCount++;
}
for(i=0;i<4;i++)
{
ptr--;
}
scanf( "%d", &iSelect);
while(iSelect!=5)
{
switch (iSelect)
{
case 1:
printf("Who would you like to be your new racer?n");
printf("driver:%dn",iDriver);
printf("The current racer is %sn",ptr[iDriver].cName);
scanf("%15s",&ptr[iDriver].cName);
printf("The new racer is %snn",ptr[iDriver].cName);
goto label;
break;
case 2:
printf("What make of car would you like to have?n");
printf("The current make is %sn",ptr[iDriver].cMake);
scanf("%15s",&ptr[iDriver].cMake);
printf("The new car make is %snn",ptr[iDriver].cMake);
goto label;
break;
case 3:
printf("What number would you like you car to have?n");
printf("The current Number is %dn",ptr[iDriver].iNum);
scanf("%d",&ptr[iDriver].iNum);
printf("The new car number is %dnn",ptr[iDriver].iNum);
goto label;
break;
case 4:
printf("What color car would you like to have?n");
printf("The current color is %sn",ptr[iDriver].cColor);
scanf("%15s",&ptr[iDriver].cColor);
printf("The new car color is %snn",ptr[iDriver].cColor);
goto label;
break;
default:
printf("Default ");
label:
printf("If you wish to continue editing please select another category to edit.nnRacer:1nCar make:2nCar Number:3nCar Color:4nIf you wish to exit modification please press 5n");
scanf("%d", &iSelect);
}
}
//should write changes made to the file
fclose(fpi);
}

这不是问题的完整列表,但是:

  1. 始终检查scanf()&fscanf()。disadvantages-of-scanf

  2. &racer的地址传递给函数fReadFile()&fWriteFile()不是必需的。数组衰减到第一个元素的基址。

  3. scanf()传递struct数组成员的地址&fscanf()不需要,原因与上面的2相同。

  4. 您在fReadFile()中行ptr++;,它将struct-array的基址向前移动,因此您只能读取两条记录。对于第三种,调用未定义的行为。删除那一行

  5. fscanf()格式字符串中指定字段之间的空格,如fscanf(fpi,"%s %s %d %s",

  6. 指定字符串的大小以限制读取超出数组边界,如fscanf(fpi,"%15s %15s %d %15s",scanf()格式字符串也是如此。

  7. 理想情况下,最好使用fgets()getline()并自己解析输入;

通过这些更改,代码编译并从输入文件读取四条记录。

相关内容

最新更新