I want to get student name mid-term and final points and write them in a txt file but when I use a loop, It never get student name. It always gives it a miss. How can I use feof with a loop? I want to get student names mid-term and final point and calculate the average from the got points and It must get always name and points till user press the end of file.
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<conio.h>
void main()
{
FILE *Points;
char namesOfStudents[10];
int pointsOfStudents[1][2];
double AverageOfStudents[1];
int i=0,j=1;
int numberOfStudents;
Points = fopen("C:\\Users\\Toshiba\\Desktop\\PointsOfStudent.txt", "a+");
fprintf(Points, "Name\t\t 1.Grade\t2.Grade\t\tAverage\n");
/* printf("How many students will you enter: ");
scanf("%d",&numberOfStudents);*/
//while (!feof(Points))
printf("Please enter new students name: ");
gets(namesOfStudents);
printf("\nPlease enter new students first point: ");
scanf("%d",&pointsOfStudents[0][0]);
printf("\nPlease enter new students second point: ");
scanf("%d",&pointsOfStudents[0][1]);
for (; i < strlen(namesOfStudents); i++)
{
fprintf(Points, "%c", namesOfStudents[i]); //To write
student name to file
}
fprintf(Points,"\t\t ");
fprintf(Points,"%d\t\t",pointsOfStudents[0][0]); //to write
student's first point
fprintf(Points,"%d\t\t",pointsOfStudents[0][1]); //to write
student's second point
fprintf(Points,"%d\n",(pointsOfStudents[0][0]+pointsOfStudents[0]
[1])/2); //to calculate and write average
system("cls");
fclose(Points);
system("Pause");
}
Several things:
First, NEVER NEVER NEVER NEVER NEVER use gets - it is dangerous, it will introduce a point of failure and/or massive security hole in your code, and it has been removed from the standard library as of the 2011 version of the language standard. Use fgets instead:
fgets( nameOfStudents, sizeof nameOfStudents, stdin );
Secondly, while( !feof( fp ) ) is always wrong. On input from fp, it will loop one time too often. On output to fp, it is meaningless.
You can use the result of fgets to control your loop:
while ( fgets( nameOfStudents, sizeof nameOfStudents, stdin ) )
{
...
}
When you're done entering data from the terminal, signal an EOF using either CtrlZ or CtrlD (depends on your platform).
Third, main returns int, not void; use
int main( void )
instead.
Finally, change
for (; i < strlen(namesOfStudents); i++)
{
fprintf(Points, "%c", namesOfStudents[i]); //To write student name to file
}
to
fprintf( Points, "%s", nameOfStudents );
to write the student name to the file.
There are other problems, but make those changes and see if that doesn't help.
Related
I am attempting to create a program where you input 2 numbers and then print out the first number to the power of the second number.
I tried using a while loop to say that if the numbers you input are two, then you keep repeating the program, otherwise if you input more than 2, you end the loop and print out that you input too many numbers.
However, the code still works if I input more than two, and I assume this is because the scanf function ignores anything other than the first two numbers I input.
How do I fix this program so that it works as I had intended?
#include <stdio.h>
#include <math.h>
int main(void)
{
float x, exp;
printf("Please enter a number followed by the power ");
printf("you want to raise it to: ");
while(scanf("%f%f", &x, &exp) == 2)
{
printf("%f\n", pow(x, exp));
printf("Enter the next pair of numbers:\n");
}
printf("You entered too many numbers!\n");
return 0;
}
User input is tricky. Get input as a string, and loop on that. Just keep in mind that the user may enter each input one at a time. Either require it to be correct (user types two numbers followed by Enter) or take effort to handle multiple correct inputs (user types one number followed by Enter and then another number followed by Enter). Here we will require both inputs on the same line:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
float x, exp;
printf("Please enter a number followed by the power ");
printf("you want to raise it to: ");
char s[1000];
while (fgets(s, sizeof(s), stdin))
{
if (sscanf(s, "%f %f", &x, &exp) != 2)
{
puts("Invalid input, my dude.");
break; // Stop running if user supplies fewer than two valid inputs
}
else
{
printf("%f\n", pow(x, exp));
}
printf("Enter the next pair of numbers:\n");
}
return 0;
}
This requires the user to terminate the stream to quit, BTW, by pressing ^Z,Enter on Windows or ^D on Linux. You could easily add additional methods to terminate in the loop (for example, terminate if s is empty or sscanf returns 0), but this is not necessary.
EDIT: There are other issues too. For example, what if the user enters more than two inputs on a line. Should I detect that? Again, for programs like this, it is ok to assume that inputs will be valid unless your assignment specifically requires you to detect error conditions.
EDIT 2: If you wish to catch a more than two items entered error, you must make sure that sscanf() consumed the entire line. Fortunately there is an easy way to do that. Change line 15 to:
int n;
if ((sscanf(s, "%f %f %n", &x, &exp, &n) != 2) || (s[n] != '\0'))
What that does is skip all whitespace after the second float to either end of string or the next available item in the string and returns the index of that position in n.
After that we only need to verify that the end of string condition is what was found.
If the user types more than two numbers this will not be an error. They will be stored in the input buffer and read in the next call of scanf.
Pay attention to that the user can type two numbers on the same line or in different lines.
In fact you can not prevent the user to enter on one line numerous numbers. But you can check that at most two lines there are entered two numbers.
So you need to split the input.
The first number will be read using scanf and the second number will be read using fgtes.
Here is a demonstration program.
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("Please enter a number followed by the power ");
printf("you want to raise it to: ");
while ( 1 )
{
float x, exp;
if ( scanf( "%f ", &x ) != 1 ) break;
char s[20];
if ( !fgets( s, sizeof( s ), stdin ) ) break;
int n;
if ( sscanf( s, "%f %n", &exp, &n ) != 1 || s[n] != '\0' ) break;
printf("%f\n", pow(x, exp));
printf("Enter the next pair of numbers: ");
}
puts( "You entered too many or too few numbers!" );
return 0;
}
Its output might look like
Please enter a number followed by the power you want to raise it to: 1 2
1.000000
Enter the next pair of numbers: 2
3
8.000000
Enter the next pair of numbers: 4
5 6
You entered too many or too few numbers!
Simply put, your code will always continue. This is just because of how scanf works:
Scanf scans input from stdin. When scanf reaches the end of stdin and still hasn't scanned everything it expected to scan, it waits until the user sends a newline (presses enter). In other words, so long as you enter valid floats, your scanf will never return a value lower than the expected float count.
On the other end, once scanf is finished with scanning stdin, it immediately evaluates the variables and returns. This means that there is still some input left in stdin that has not yet been read. In fact, when scanf next runs, it will resume scanning exactly where it left off. Take this sample code:
int main()
{
int x,y;
int ct = scanf("%d%d",&x,&y);
printf("%d (%d,%d)\n",ct,x,y);
scanf("%d",&x);
printf("%d\n",x);
}
If you compile and run this, try inputting three ints at once. The second scanf will immediately terminate because it is reading the third integer that was inputted.
If you are trying to get a specific number of inputs, I would suggest scanning the user's input as a string and then using sscanf (scanf for strings). You could also check for the number of spaces in the string, then, to determine if there are too many inputs. If you want to get a little tricky, you could continue to use scanf but then check whether bytes are remaining in stdin before you continue. Here is a good answer that will help if you want to keep using scanf as is, but checking whether stdin is empty.
There is another issue with your code though; what happens when a user inputs something other than a float? But that is a different question entirely (and one where my personal suggestion would be to analyze the entire scanned string).
The problem with using scanf is that it treats all whitespace characters (e.g. spaces and newline characters) as equal. For example, scanf won't care whether the numbers you entered are on the same line or not.
If scanf is asked to read two numbers, but the user instead enters three numbers on the same line, then your first call to scanf will only read the first two numbers and leave the third number on the input stream, so that the next scanf call in the next loop iteration will read it as the next first number. This is not what you want.
Therefore, for line-based user input, it is probably better not to use scanf. Instead, it makes more sense to always read exactly one line per loop iteration. You can do this with the function fgets.
After using fgets to read a line of input, two of the other answers use sscanf to convert both numbers at once. However, you can also convert one number at a time using strtof:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <stdbool.h>
int main(void)
{
//we want to provide the user with a different prompt the first time,
//so we must remember whether it is the first time
bool first = true;
//infinite loop
while ( true )
{
float x, exp;
char line[100];
char *p, *q;
//prompt user for input
if ( first )
{
printf(
"Please enter a number followed by the power "
"you want to raise it to: "
);
//remember to use a different prompt next time
first = false;
}
else
{
printf("Enter the next pair of numbers: ");
}
//attempt to read one line of input
if ( fgets( line, sizeof line, stdin ) == NULL )
{
//break out of infinite loop
break;
}
//attempt to find newline character
p = strchr( line, '\n' );
//make sure entire line was read in
if ( p == NULL && !feof(stdin) )
{
//only accept missing newline character on end-of-file
if ( !feof(stdin) )
{
int c;
printf( "Line too long for input buffer!\n" );
//discard remainder of line
do
{
c = getchar();
} while ( c != EOF && c != '\n' );
continue;
}
}
else
{
//remove newline character by overwriting it with null character
*p = '\0';
}
//start parsing at start of line
p = line;
//attempt to convert first number
x = strtof( p, &q );
//determine whether conversion of first number succeeded
if ( p == q )
{
printf( "Conversion of first number failed!\n" );
continue;
}
//continue parsing at end of first number
p = q;
//attempt to convert second number
exp = strtof( p, &q );
//determine whether conversion of second number succeeded
if ( p == q )
{
printf( "Conversion of second number failed!\n" );
continue;
}
//verify that remainder of line is either empty or only
//consists of whitespace characters
for ( p = q; *p != '\0'; p++ )
{
if ( !isspace( (unsigned char)*p ) )
{
printf( "Unexpected character found after second number!\n" );
//we cannot use the "continue" keyword here, because
//we want to continue to the next iteration of the
//outer loop, not the inner loop
goto continue_outer_loop;
}
}
//print result
printf( "Input accepted, the result is: %f\n", pow(x, exp) );
continue_outer_loop:
continue;
}
return 0;
}
This program has the following behavior:
Please enter a number followed by the power you want to raise it to: abc
Conversion of first number failed!
Enter the next pair of numbers: 10
Conversion of second number failed!
Enter the next pair of numbers: 10 abc
Conversion of second number failed!
Enter the next pair of numbers: 10 20
Input accepted, the result is: 100000000000000000000.000000
Enter the next pair of numbers: 10 20 30
Unexpected character found after second number!
As you can see, the program correctly rejects the input if it contains a third number.
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);
}
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.
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.
I want to create a text file using C which would keep on adding score every time the code is run without deleting the last record. Unfortunately, when I run the code, All it does is run the printf statement and create a file score.txt, but doesn't write anything into it, instead it just crashes.
Here's the code:
int main()
{
FILE *score;
score = fopen("score.txt", "w");
fclose(score);
int s;
char n;
printf("You got a high score!\nPlease enter score: ");
scanf("%d", &s);
printf("\nPlease enter your name: ");
scanf("%s", &n);
fprintf(score,"%d", s);
fprintf(score,"%d", n);
printf("\nData Stored into score.txt\n");
return 0;
}
Multiple issues here.
After fclose(score);, you're trying to use fprintf(score,"%d", s);. Why? Maybe you want to move fclose(score); before return 0;
Always put a success check on the return value of fopen(). Also, as per your requirement, keep on adding score every time the code is run without deleting the last record you need to fopen() in append mode. Check more about the modes and their usage here.
scanf("%s", &n); is wrong. Here what you want is an array, not a single char. Consider changing your char n; to char n[32]; or something. [Note: once n is array, change the scanf() to scanf("%s", n);]
fprintf(score,"%d", n); is wrong. Do not use incompatible format specifier. for a string, it should be %s. [Even in your case, n is char. There's no way the format specifier should be %d.]
There are few problems with the code given above.
You need to open the file in append mode, if you need to add the new score without deleting the old one.
You have to write the score to file before doing an fclose.
char n can hold only a single char. If your intention is to read a proper name with more characters, you need a char array, like char name[100].
The code given below gives a proper way to append to a file.
FILE *score;
char name[100];
int nScore;
// Open the file
score = fopen("score.txt", "a+");
if(!score)
{
printf("Failed to open");
return 1;
}
// Get user inputs
printf("You got a high score!\nPlease enter score: ");
scanf("%d", &nScore);
printf("\nPlease enter your name: ");
scanf("%s", name);
//Write to file
fprintf(score, "Name: %s Score: %d\n", name, nScore);
// Close the file
fclose(score);
printf("\nData Stored into score.txt\n");
return 0;
Note also that the name n cannot be stored as a char. It must be either a char [] or a char *. This is probably what's causing your crash, though #SouravGhosh is also correct - basically there are (at least) two bugs in your code.
E.g.
char n[80]; // or any other reasonable value, or learn dynamic memory allocation
scanf("%s", n);
I'm trying to make a program in C which tracks the books borrowed by a student. I am having a hard time in accessing pointers with files. When I use files, I don't usually you fscanf( ), instead I use the usual scanf. I have this data struct:
typedef struct{
char fName[24], mInitial, lName[16];
}nameType;
typedef struct{
unsigned long idNo;
nameType studName;
char course[8];
int yrLevel;
books borrowedBooks;
int bksCtr;
}student;
typedef struct{
student *studs;
int studCtr;
}studList;
I have created two functions as of now, which is addStudToFile(void), which adds students to the file, and displayStudsFromFile(void), which basically prints out the students that were added in the file. These are my newbie function code:
void addStudToFile(void)
{
FILE *fp;
studList myStud;
fp = fopen("students.db", "w");
if(fp!=NULL){
/* ask for student details and adds these to the file */
printf("Enter ID number: ");
fflush(stdin);
scanf(,"%lu", &myStud.studs->idNo);
printf("Enter First Name: ");
fflush(stdin);
gets(myStud.studs->studName.fName);
printf("Enter Last Name: ");
fflush(stdin);
gets(myStud.studs->studName.lName);
printf("Enter Middle Initial: ");
fflush(stdin);
scanf("%c", &(myStud.studs->studName.mInitial));
printf("Enter Course: ");
fflush(stdin);
gets(myStud.studs->course);
printf("Enter Year: ");
fflush(stdin);
scanf("%d", &(myStud.studs->yrLevel));
fwrite(&myStud, sizeof(studList),1,fp);
fclose(fp);
}
}
and
void displayStudsFromFile(void)
{
FILE *fp;
studList myStud;
fp = fopen("students.db", "r");
if(fp!=NULL){
while (fread(&myStud, sizeof(studList), 1, fp)){
printf("%lu\t %s, %s %s\t %s-%d", myStud.studs->idNo, myStud.studs->studName.lName,
myStud.studs->studName.fName, myStud.studs->studName.mInitial,
myStud.studs->course, myStud.studs->yrLevel);
printf("borrowed %d books", myStud.studs->bksCtr);
}
fclose(fp);
}
}
Now, my problem here is in accessing my List which is myStud. In my addStudToFile( ) function, everytime I input my ID number, my program stops working. Why does it stops working? Do I have to malloc something? Or is my accessing in scanf() wrong? Another situation where I encounter my program to stop working again, is when I call my display function. It displays something, but alien/garbage values.
Here is a screenshot on where I encountered my problem in my scanning function:
And here is on my display function:
I hope someone can help me with this. Thanks!
Your hunch is right, you do need to malloc something :)
typedef struct{
student *studs;
int studCtr;
}studList;
Here's your problem. You're defining studs as a pointer to a student struct, but you are not actually allocating any memory for it, so you can later reference it with the -> operator.
You can either allow for a preset number of entries, so you could then define studs like,
student studs[10];
to allow for 10 entries, or in addStudToFile() you could ask the user to input how many entries he would like to give. In this case you would leave the definition as it is and as soon as you have the user input do:
myStud.studs = (student *) malloc( sizeof(student) * how_many );
There may be more bugs along the code you have posted, but for the time being the above is what keeps you back.
edit: if you follow the malloc() route, before returning from addStudToFile() for whatever reason you should make sure you call
free(myStud.studs);
or you get a memory leak...
Update
All right, going further down, when you fwrite() everything, remember, you malloc()ed the memory for studs. sizeof(studlist) is computed at compile time and can't possibly know of the additional memory used at run time. In addition, the two memory regions are not guaranteed to be continuous, so still, one fwrite wouldn't cut it.
With your code structured as it is, you would be better off fwrite()ing the studCtr first, then the memory you malloced for studs.
For the displayStudsFromFile() since there is just a loop there and nothing is really stored for later, I'd just use
student myStud;
ie, use just one instance of student structure instead of a studlist. In this scenario you do one fread() to read in the studCtr from the disk file and then use that to loop around fread() for one student object at a time into myStud. Within that loop you print the fields of interest like so:
printf("borrowed %d books", myStud.bksCtr);
Hope this will get you going... First steps in C are a bit tough :D
myStud.studs is a pointer to a student, but I don't see where you're actually allocating that student. You need to malloc a student before you can do things like &myStud.studs->idNo.
In short, don't write pointers to files, they will be meaningless later on.
The typical approach is to write out the count of the items first, then loop over each item in the list and write them out individually.
On the reader end:
read the number of items.
Allocate enough memory to hold all the items.
Read each item in.
along with the problems mentioned already,
this function has its' own set of troubles.
I have inserted '<--' and a comment at each problem
fflush(stdin) though works on some implementations, it's still undefined behaviour.
According to the standard, fflush only works with output/update streams
( for your code, since the printf format strings do not end in '\n'
( which would have forced the actual output to occur
( change these lines to 'fflush(stdout)'
A ' ' in a scanf() format string will consume any white space found at that
point in the input. Therefore, for almost all cases, the first char in
the format string should be: ' '. Then newlines, spaces, etc
will be consumed, as if they were never there. It is even correct to
use the leading ' ' when there is no white space to consume.
gets() is depreciated and will corrupt/overrun a input buffer, so NEVER
use gets, rather, use fgets(), where the amount of input can be limited
and similar good things.
void addStudToFile(void)
{
FILE *fp;
studList myStud;
fp = fopen("students.db", "w");
if(fp!=NULL)
{
/* ask for student details and adds these to the file */
printf("Enter ID number: ");
fflush(stdin); <-- change to stdout
scanf(,"%lu", &myStud.studs->idNo);
<-- change format string to: " %lu"
<-- add check of returned value to assure operation successful
printf("Enter First Name: ");
fflush(stdin); <-- change to stdout
gets(myStud.studs->studName.fName);
<-- replace gets with fgets() +appropriate parms)
<-- add check of returned value to assure operation successful
printf("Enter Last Name: ");
fflush(stdin); <-- change to stdout
gets(myStud.studs->studName.lName);
<-- replace gets with fgets() +appropriate parms)
<-- add check of returned value to assure operation successful
printf("Enter Middle Initial: ");
fflush(stdin); <-- change to stdout
scanf("%c", &(myStud.studs->studName.mInitial));
<-- replace format string with " %c"
<-- add check of returned value to assure operation successful
printf("Enter Course: ");
fflush(stdin); <-- change to stdout
gets(myStud.studs->course);
<-- replace gets with fgets() +appropriate parms
<-- add check of returned value to assure operation successful
printf("Enter Year: ");
fflush(stdin); <-- change to stdout
scanf("%d", &(myStud.studs->yrLevel));
<-- change format string to: " %d"
<-- add check of returned value to assure operation successful
fwrite(&myStud, sizeof(studList),1,fp);
<-- add check of returned value to assure operation successful
fclose(fp);
<-- add else clause so use knows what happened. I.E.
} else { perror( "fopen failed for write"); exit(EXIT_FAILURE);
} // end if
} // end function: addStudToFile
Here are my comments, prefixed by '<--'
void displayStudsFromFile(void)
{
FILE *fp;
studList myStud;
fp = fopen("students.db", "r");
if(fp!=NULL)
{
while (fread(&myStud, sizeof(studList), 1, fp))
<-- add check of returned value to assure operation successful
{
printf("%lu\t %s, %s %s\t %s-%d",
myStud.studs->idNo,
myStud.studs->studName.lName,
myStud.studs->studName.fName,
myStud.studs->studName.mInitial,
myStud.studs->course,
myStud.studs->yrLevel);
printf("borrowed %d books", myStud.studs->bksCtr);
}
fclose(fp);
<-- to let user know about error
<-- insert: }else{ perror( "fopen failed for read"); exit(EXIT_FAILURE);
} // end if
} // end function: displayStudsFromFile
i create a really simple coding and it got no errors but when it run, i cant put input in the 'age' side.
#include <stdio.h>
#include <conio.h>
struct baby
{
char name[2][30];
char sex[2][7];
char birthday[2][12];
};
struct parents
{
char nama[2][30];
int age[2];
};
struct momdad
{
struct parents father;
struct parents mother;
};
struct momdad info;
struct baby newborn;
int main()
{
int i;
for(i=0;i<2;i++)
{
printf("\nEnter baby's name %d: ",i+1);
gets(newborn.name[i]);
printf("Enter baby's sex %d (Female/Male): ",i+1);
gets(newborn.sex[i]);
printf("Enter baby's birthday %d (dd/mm/yyyy): ",i+1);
gets(newborn.birthday[i]);
printf("Enter father's name %d: ",i+1);
gets(info.father.nama[i]);
printf("Enter father's age %d: ",i+1);
gets(info.father.age[i]);
printf("Enter mother's name %d: ",i+1);
gets(info.mother.nama[i]);
printf("Enter mother's age %d: ",i+1);
gets(info.mother.age[i]);
}
printf("\n\n\tNEW BORN BABY IN KUANTAN HOSPITAL");
printf("\n\n===============================================");
for(i=0;i<2;i++)
{
printf("\n\nBaby name: %s",newborn.name[i]);
printf("\nSex: %s",newborn.sex[i]);
printf("\nBirthday: %s",newborn.birthday[i]);
printf("\n\nFather name: %s",info.father.nama[i]);
printf("\nFather age: %s",info.father.age[i]);
printf("\n\nMother name: %s",info.mother.nama[i]);
printf("\nMother age: %s",info.mother.age[i]);
printf("\n\n----------------------------------------------");
}
getch();
}
this is my declaration that i think is wrong but i dont know how.
int age[2];
and the input will be putting in here
printf("Enter father's age %d: ",i+1);
gets(info.father.age[i]);
n in here
printf("Enter mother's age %d: ",i+1);
gets(info.mother.age[i]);
i'm still new in programming sorry for asking this simple question
Never use gets(). It cannot be used safely, and as of 2011 it's been removed from the language.
In a comment, you mention calling fflush(stdin);. The behavior of fflush is undefined for input streams. Some implementations define the behavior, but depending on that will make your program non-portable -- and you don't need it anyway.
The simplest way to read input data is to use scanf(), but that has some of its own problems. For example, if you use scanf("%d", &n); and type 123, it will consume the 123 and leave anything following it (such as a newline) waiting to be read.
A better way to read input is to use fgets to read a line of text, then sscanf to parse the data from the input line. It re
Here's an example:
#define MAX_LEN 200
char line[MAX_LEN];
int num;
printf("Enter an integer: ");
fflush(stdout);
if (fgets(line, MAX_LEN, stdin) == NULL) {
fprintf(stderr, "Error reading line\n");
exit(EXIT_FAILURE);
}
if (sscanf(line, "%d", &num) != 1) {
fprintf(stderr, "Error parsing integer from line\n");
exit(EXIT_FAILURE);
}
printf("The number is %d\n", num);
I call fflush(stdout) after the first printf to ensure that the prompt actually appears. stdout can be line-buffered, meaning that output won't appear until you've printed an entire line. The fflush isn't always necessary, but it's a good idea.
The fgets call reads a full line of input or MAX_LEN characters if the line is longer than that. (gets has no way to specify the maximum input size, so no matter how big your target array is, it can always read more and clobber random memory.) fgets returns a null pointer if there was a problem, and I check for that.
sscanf is similar to scanf, but it reads data from a string in memory, not from standard input. (There's also fscanf, which reads from a specified file.) It returns the number of items that it successfully scanned, so a value other than 1 would indicate an error.
I suggest reading the documentation for all these functions; I haven't covered everything they do. In fact, you should read the documentation for any standard library function you use.