0

When writing a program for a class that utilizes pointers to array of struct, ive run into an issue regarding using the data stored in the srtuct. The file read function populates the array of struct just fine and later displays the correct information. However the write function when displaying items to be changed it appears to scrabble or outright miss data for racer positions 2 and 4. im at my wits end trying to figure out as to why this is happening. the file it is reading from and to is "Car.txt" with this data in it;

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

I have a test print while loop right befor modification selection that shows that there is a smile face ascii icon just after Leia's name that was generated. But upon selecting an aspect to modify and displaying what the current aspect is (name, make, number, color) the data being called appears to be jumbled or outright missing despite being displayed nearly perfect moments before. Something of note I am very much an amature and my knowledge of the tools in codeblocks (what i am using for writing and compiling) is sparse.

#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-Lewis\n\n");

    //Asking user to choose game mode
    printf("Hello, please choose a game mode:\nManual(0) Two players*INCOMPLETE,NOT WORKING*\nAutomatic(1) One player + bots\n");
    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-4\n\n");
    fReadFile(carptr,iBracket);
    scanf("%d", &iDriver1);
    printf("would you like to modify these racer's stats?1=Y ANY #=N\n");
    scanf(" %d", &iSelect);
        if(iSelect==1)
        {
            fWriteFile(carptr,iDriver1,iBracket);
        }
    printf("Let the racing begin\n");//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 file\n");
    }
    while (fscanf(fpi,"%15s %15s %d %15s",&ptr[iCount].cName,&ptr[iCount].cMake,&ptr[iCount].iNum,&ptr[iCount].cColor)!=EOF)
    {
        printf("Racer %d:\nName:%s\nMake:%s\nCar Number:%d\nCar Color:%s\n\n",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 file\n");
    }
    printf("What would you like to modify?\nRacer:1\nCar make:2\nCar Number:3\nCar Color:4\n");//asking what the player would like to modify about the racer data until they are satisfied
    while(iCount!=iBracket)
    {
        printf("%s %s %d %s\n",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:%d\n",iDriver);
            printf("The current racer is %s\n",ptr[iDriver].cName);
            scanf("%15s",&ptr[iDriver].cName);
            printf("The new racer is %s\n\n",ptr[iDriver].cName);
            goto label;
            break;
        case 2:
            printf("What make of car would you like to have?\n");
            printf("The current make is %s\n",ptr[iDriver].cMake);
            scanf("%15s",&ptr[iDriver].cMake);
            printf("The new car make is %s\n\n",ptr[iDriver].cMake);
            goto label;
            break;
        case 3:
            printf("What number would you like you car to have?\n");
            printf("The current Number is %d\n",ptr[iDriver].iNum);
            scanf("%d",&ptr[iDriver].iNum);
            printf("The new car number is %d\n\n",ptr[iDriver].iNum);
            goto label;
            break;
        case 4:
            printf("What color car would you like to have?\n");
            printf("The current color is %s\n",ptr[iDriver].cColor);
            scanf("%15s",&ptr[iDriver].cColor);
            printf("The new car color is %s\n\n",ptr[iDriver].cColor);
            goto label;
            break;
        default:
        printf("Default ");
        label:
        printf("If you wish to continue editing please select another category to edit.\n\nRacer:1\nCar make:2\nCar Number:3\nCar Color:4\nIf you wish to exit modification please press 5\n");
        scanf("%d", &iSelect);
    }
    }
    //should write changes made to the file
    fclose(fpi);
}

1 Answers1

1

This is not the complete list of issues, however:

  1. Always check the return values of scanf() & fscanf(). disadvantages-of-scanf

  2. Passing the address of &racer to functions fReadFile() & fWriteFile() is not required. Array decays to base address of first element.

  3. Passing address of array members in struct for scanf() & fscanf() is not required, for the same reason as 2 above.

  4. You've line ptr++; in fReadFile(), it moves the base address of struct-array forward, hence you can only read two records. For the third you invoke undefined behaviour. Remove that line.

  5. Specify spaces between fields in format string of fscanf(), like so fscanf(fpi,"%s %s %d %s",

  6. Specify size of string to limit reading over array bounds, like so fscanf(fpi,"%15s %15s %d %15s",. Same goes for scanf() format string.

  7. Ideally, it's better to use fgets() or getline() and parse the input yourself; gives you more control over handling errors.

With these changes, code compiles and reads four records from the input file.

जलजनक
  • 3,072
  • 2
  • 24
  • 30
  • The issue isnt reading from the file but using the data in the array of struct in another function. think ive followed you outline as close as possible. 1# The printf in the while loop in fReadfile proves that the scanf has read the data into the array of character. 2#/3# Issue is rectified 4# used a for loop to decrement ptr back to start 5#added spaces 6#%15s format added 7# i cannot find a method to reliably collect the data. One of the requirements of this code is to be modular and accept changes. In addition the file must be read until EOF. – Phirebird 27 Apr 25 '22 at 19:27