Reputation: 17
I'm trying to create a program which will take information from 10 racers. The program will get and store the first name, last name, age, gender (m/f), and time for their race (hh:mm:ss). To do this I planned to have an array of structures containing each of the above elements for each racer. I then came across the problem of asking "Please enter the name of the first racer" because the word "first" needs to be changed to "second", "third" and so on... A loop wouldn't be able to do that. So I decided to then make an array of strings, where the first element of the array would be the word "first" and so on. So then I could use a loop to print the right word for each racer by accessing each element of the places array.
I'm not very experienced with strings, and arrays of strings, I searched online for some help and came up with the following program, it uses an array of characters with a pointer, which I dont quite understand, must be something to do with the strings. Anyways, when I run the program I get serious problems and have to re-open Visual Studio. Hoping someone can give me a hand and help clear up some mysteries about these arrays of strings and the significance of the pointer. Thanks!
#include <stdio.h>
#include <math.h>
typedef struct DATASET
{
char firstname[12], lastname[12], gender;
int age, hours, minutes, seconds;
};
#define MaxRacers 10
int main()
{
int i;
DATASET data[MaxRacers];
char *places[MaxRacers];
char place1[6] = "First";
char place2[7] = "Second";
char place3[6] = "Third";
char place4[7] = "Fourth";
char place5[6] = "Fifth";
char place6[6] = "Sixth";
char place7[8] = "Seventh";
char place8[7] = "Eighth";
char place9[6] = "Ninth";
char place10[6] = "Tenth";
places[0] = place1;
places[1] = place2;
places[2] = place3;
places[3] = place4;
places[4] - place5;
places[5] = place6;
places[6] = place7;
places[7] = place8;
places[8] = place9;
places[9] = place10;
printf("%s", places[1]); // TEST which works fine
for(i = 0, i < MaxRacers; i = i + 1;)
{
printf("Enter the name of the %s finisher\n", places[i]); // Problem
}
getchar();
return(0);
}
Now Ive got things going a bit further, Im running into a problem now as soon as I have finished entering the last name of the first finisher the program exits out of the command window and a new window comes up saying:
"Exception thrown at 0x0FF6D0F1 (ucrtbased.dll) in ConsoleApplication30.exe: 0xC0000005: Access violation writing location 0xFFFFFFCC.
If there is a handler for this exception, the program may be safely continued."
#include <stdio.h>
#include <math.h>
struct DATASET
{
char firstname[12], lastname[12], gender;
int age, hours, minutes, seconds;
};
#define MaxRacers 10
int main()
{
int i;
DATASET data[MaxRacers];
char *places[] = { "First", "Second", "Third", "Fourth", "Fifth", "Sixth", "Seventh", "Eighth", "Ninth", "Tenth" };
for (i = 0; i < MaxRacers; i++)
{
printf("Enter the first name of the %s finisher:\n", places[i]);
scanf("%s", data[i].firstname);
printf("Enter the last name of the %s finisher:\n", places[i]);
scanf("%s", data[i].lastname);
printf("Enter the gender of the %s finisher: [m/f]: \n", places[i]);
scanf("%c", data[i].gender);
printf("Enter the age of the %s finisher:\n", places[i]);
scanf("%d", data[i].age);
printf("Enter the time of the %s finisher: [hh:mm:ss]\n", places[i]);
scanf("%d:%d:%d", data[i].hours, data[i].minutes, data[i].seconds);
printf("\n\n");
}
getchar();
return(0);
}
Upvotes: 0
Views: 80
Reputation: 21323
In your second iteration of this question, you report that:
Im running into a problem now as soon as I have finished entering the last name of the first finisher
I believe that this problem is due to the fact that you have incorrectly declared data[]
. DATASET
is a struct
, not a typedef
, so you need:
struct DATASET data[MaxRacers];
But this reveals a new problem. You have several issues around your calls to scanf()
. First, you are failing to provide addresses to store the results of scanf()
in several instances. To fix this, you need to change to:
printf("Enter the gender of the %s finisher: [m/f]: \n", places[i]);
scanf("%c", &data[i].gender);
printf("Enter the age of the %s finisher:\n", places[i]);
scanf("%d", &data[i].age);
printf("Enter the time of the %s finisher: [hh:mm:ss]\n", places[i]);
scanf("%d:%d:%d", &data[i].hours, &data[i].minutes, &data[i].seconds);
But yet another problem is now apparent. The (evil) function scanf()
often leaves newlines and other characters behind, polluting the input stream for the next input function. I personally usually write a function to handle user input in the form of strings, and then use strtol()
to convert the results if numeric input is desired.
The simplest thing for you to do, though, would be to simply write a function to clear the input stream before using scanf()
with the %c
specifier:
void clear_stream(void)
{
int ch;
while ((ch = getchar()) != '\n' && ch != EOF)
continue; // remove unwanted characters
}
Then modify your input code like this:
printf("Enter the first name of the %s finisher:\n", places[i]);
scanf("%s", data[i].firstname);
printf("Enter the last name of the %s finisher:\n", places[i]);
scanf("%s", data[i].lastname);
printf("Enter the gender of the %s finisher: [m/f]: \n", places[i]);
clear_stream();
scanf("%c", &data[i].gender);
printf("Enter the age of the %s finisher:\n", places[i]);
scanf("%d", &data[i].age);
printf("Enter the time of the %s finisher: [hh:mm:ss]\n", places[i]);
scanf("%d:%d:%d", &data[i].hours, &data[i].minutes, &data[i].seconds);
printf("\n\n");
With many format specifiers, scanf()
skips over leading whitespace, including newlines. But this is not true for the %c
specifier, and this means that if you enter, say a string, the newline that is left behind in the input stream will be picked up instead of the character that you want.
These changes will get your code running. But your input scheme is fragile. It doesn't check to be sure that there was input (scanf()
returns the number of values that were read) and it doesn't validate values. Do you want the user to input a negative age? I would urge you to at least rethink your input code to be sure that you get the input that you want. And because scanf()
is error-prone, you should really consider using fgets()
or write your own input function, such as the one that I linked to earlier.
Upvotes: 1
Reputation: 119877
for(i = 0, i < MaxRacers; i = i + 1;)
The for
loop doesn't work like that. Try this:
for(i = 0; i < MaxRacers; i++)
// ^ ^
// | |
// semicolon here more idiomatic
In addition, you should use the idiomatic character array initialization:
char *places[MaxRacers] = { "First", "Second", ... };
not only because it is way easier to type than your 20 lines of places
, but also because there are far less chances to miss a typo like
places[3] = place4;
places[4] - place5; // <---- whoops
places[5] = place6;
While we're at it,
typedef struct DATASET
{ // whatever
};
makes little sense. It doesn't create any typedef name, so the word typedef
is useless. It is equivalent to
struct DATASET
{ // whatever
};
Because of that, this declaration
DATASET data[MaxRacers];
is invalid in C. It is valid in C++, which probably means you are using a C++ compiler. If you are learning C, make sure your source file extension is .c
.
Upvotes: 1