In my assignment I was given two functions to write
int openFileFromConsole(FILE *fp)
It takes an empty file pointer as input to the function using call by reference. And updates the pointer to point to the appropriate HDD address. IMPORTANT: Later, it asks the user through the console to provide the name and also asks for the file open type: "w", "r", "a" and UPDATES the file pointer. It returns 1 if succeeded, or 0 if fails.
void saveStudentGradeInfoTofile(FILE *fp)
This function gets the student info and saves it first into the student data-type (which is struct but disguised using typedef) then saves it to file. The student information is being provided by the register through the console. This takes the file pointer by reference as input and update the file using fprint.
This program is supposed to open a file through console depending on the user input then collect information and store them to a struct and save it to that file.I have written the two functions(correctly I think?).But I am having a hard time implementing them to main() since the first one is an int type function.Any help would be appreciated.
typedef struct student {
char name[50];
char id [20];
int score;
}student;
int openFileFromConsole(FILE *fp);
void saveStudentGradeInfoTofile(FILE *fp);
int main()
{
return 0;
}
int openFileFromConsole(FILE *fp){
char filePath[100],fileOpenType[10];
printf("Enter Path name: ");
scanf("%s", filePath);
printf("Enter file open type w, r or a: ");
scanf("%s", fileOpenType);
fp = fopen(filePath,fileOpenType);
if(fp != NULL) {
printf("File has been opened");
return 1;
}
else printf("File not found");
return 0;
}
void saveStudentGradeInfoTofile(FILE *fp){
int numOfStudent ;
student s[100];
printf ("Get the number of students :");
scanf("%d",&numOfStudent);
for(int i = 0; i < numOfStudent; i++) {
printf("\nEnter ID number:");
scanf(" %s",s[i].id);
printf("Enter name: ");
scanf("%s,",s[i].name);
printf("Enter score: ");
scanf("%d",&s[i].score);
fprintf(fp,"id : %s, Name: %s, score =%d\n",s[i].id,s[i].name,s[i].score);
printf("\n");
}
}
the posted code has a few problems.
it does not follow the axiom: only one statement per line and (at most) one variable declaration per statement. The result is the code is much more difficult to understand, debug, maintain.
The calls to system functions need to have their returned values checked to assure the operation was successful.
To modify where a pointer, located in the calling function, points, the pointer must be passed as a 'pointer to a pointer'.
when calling any of the scanf() family of functions, when using the '%s' input conversion specifier, always include a MAX CHARACTERS modifier that is 1 less than the length of the input buffer, so the user cannot overrun the input buffer. Such overrun results in undefined behavior and can lead to a seg fault event.
when using the '%s' input conversion specifier, insert a space before the specifier to consume any leading 'white space', like any newline sequence.
always cleanup when exiting a program. Do not leave the cleanup to the OS.
when working with numeric values that will never be less than 0, it is best to use size_t rather than int
The posted code is never reading from the student grade info file, so should never be opened with r
the 'mode' in a call to fopen() is always a string, even if it is only a single char, so needs to be written as "w" not just a w
the code contains lots of 'magic' numbers. 'magic' numbers are numbers with no basis. Such numbers make understanding, debugging, etc much more difficult than necessary. Suggest using an enum statement or #define statements to give those 'magic' numbers meaningful names, then use those meaningful names throughout the code.
for ease of readability and understanding, consistently indent the code. indent after every opening brace '{'. unindent after every closing brace '}'. Suggest using 4 spaces for each indent level as that is visible even with variable width fonts.
it is a poor programming practice to combine a 'struct' definition with a 'typedef'. code them separately.
when posting code, include the needed header file statements, so we do not have to guess what your code actually uses.
for ease of readability and understanding, separate code blocks (for, if, else, while, do...while, switch, case, default) via a single blank line. Separate functions by 2 or 3 blank lines (be consistent).
While modern compilers will handle the duplication of names, as modern compilers keep the struct names in a separate namespace from the typedef names, it is a poor programming practice that easily leads to confusion. Suggest keeping names unique (although that was not followed in this answer.
Here is a possible implementation of the desired functionality:
#include <stdio.h> // fopen(), fclose(), perror(), FILE
#include <stdlib.h> // exit(), EXIT_FAILURE
enum {
MAX_NAME_LEN =50,
MAX_ID_LEN =20,
MAX_PATH_LEN =100,
MAX_TYPE_LEN =10,
MAX_NUM_STUDENTS =100
};
struct student
{
char name[ MAX_NAME_LEN ];
char id [ MAX_ID_LEN ];
int score;
};
typedef struct student student;
int openFileFromConsole(FILE **fp);
void saveStudentGradeInfoTofile(FILE *fp);
int main( void )
{
FILE * fp = NULL;
int openStatus = openFileFromConsole(&fp);
if( 0 == openStatus )
{
saveStudentGradeInfoTofile( fp );
}
fclose( fp );
return 0;
} // end function: main
int openFileFromConsole(FILE **fp)
{
char filePath[ MAX_PATH_LEN ];
char fileOpenType;
printf("Enter Path name: ");
if( 1 != scanf("%100s", filePath) )
{
perror( "scanf for file path failed" );
exit( EXIT_FAILURE );
}
// implied else, scanf successful
printf("Enter file open type w, r or a: ");
if( 1 != scanf(" %c", &fileOpenType) )
{
perror( "scanf for file open type failed" );
exit( EXIT_FAILURE );
}
// implied else, scanf successful
char buffer[ MAX_TYPE_LEN ];
buffer[0] = '\"';
buffer[1] = fileOpenType;
buffer[2] = '\"';
buffer[3] = '\0';
*fp = fopen(filePath, buffer);
if( *fp )
{
return 1;
}
else
{
perror( "fopen failed" );
return 0;
}
} // end function: openFileFromConsole
void saveStudentGradeInfoTofile(FILE *fp)
{
size_t numOfStudent;
student s[ MAX_NUM_STUDENTS ];
printf ("Get the number of students :");
if( 1 != scanf("%lu",&numOfStudent) )
{
perror( "scanf for number of students failed:" );
fclose( fp );
exit( EXIT_FAILURE );
}
// implied else, scanf successful
for( size_t i = 0; i < numOfStudent; i++)
{
printf("\nEnter ID number:");
if( 1 != scanf(" %19s",s[i].id) )
{
perror( "scanf for student ID failed" );
fclose( fp );
exit( EXIT_FAILURE );
}
// implied else, scanf successful
printf("Enter name: ");
if( 1 != scanf(" %49s,",s[i].name) )
{
perror( "scanf for student ID failed" );
fclose( fp );
exit( EXIT_FAILURE );
}
// implied else, scanf successful
printf("Enter score: ");
if( 1 != scanf("%d",&s[i].score) )
{
perror( "scanf for student Score failed" );
fclose( fp );
exit( EXIT_FAILURE );
}
// implied else, scanf successful
fprintf(fp,"id : %s, Name: %s, score =%d\n",
s[i].id,
s[i].name,
s[i].score);
printf("\n");
} // end while
} // end function: saveStudentGradeInfoToFile
Just in case you want to pass the file path as an argument to your program
int main(int c /* argument counter */, char *v[] /*argument list */)
{
FILE *fp;
if(c >= 2) {
char *path = v[1]; /* this is the second argument (the first one, v[0], is the program's name): ./foo myfile.txt */
fp = fopen(path, "your mode goes here");
/* ... */
}
}
Related
first, I defined one struct.
struct book_record{
char book_name[52];
char publisher_name[32];
char name[32];
int publishing_year;
int page;
};
and I made a cord like this.
FILE* book_data = fopen("book.txt", "rt");
FILE* book_file = fopen("book2.txt","wt");
int input, i, j;
fscanf(book_data, "%d", &input);
struct book_record *m[input];
for(i=0; i<input; i++){
m[i] = (struct book_record *)malloc(sizeof(struct book_record));
}
enter
I don't feel this cord have problem. but my teacher said me that this cord have big problem.
teacher says because "input" is not initialized, struct record *m[input] has an error.
but I think I clearly declare input by 'fscanf' before *m[input].
I can't understand my teacher's said. Help me.
int input, i, j;
At this point, none of input, i, or j have any particular value; their contents are indeterminate.
Yes, you are attempting to read a value for input before using it:
fscanf(book_data, "%d", &input);
struct book_record *m[input];
but the fscanf operation can fail - if the first character in the book_data stream isn't a decimal digit or if there's a problem with the stream, then fscanf won't assign anything to input and it will still have that indeterminate value (which could be positive, negative, zero, very large, etc.).
fscanf returns the number of items successfully converted and assigned or EOF if it sees an end-of-file or error - in this case, you're expecting to read 1 item, so fscanf should return 1 on success. You should check that return value before using input:
if ( fscanf( book_data, "%d", &input ) != 1 )
{
fputs( "Error reading input from book_data, exiting\n", stderr );
exit( 0 );
}
struct book_record *m[input];
If for any reason that fscanf operation fails, we'll exit the program before trying to use input.
You should also make sure the fopen calls succeed as well before trying to use those streams:
FILE* book_data = fopen("book.txt", "rt");
if ( !book_data )
{
fputs( "Could not open book.txt, exiting...\n", stderr );
exit( 0 );
}
FILE* book_file = fopen("book2.txt","wt");
if ( !book_file )
{
fputs( "Could not open book2.txt, exiting...\n", stderr );
fclose( book_data );
exit( 0 );
}
So I want to save the best 3 scores of the game and to put them on a file. But for some reason when I read the file the best scores are 53,32,32. Not using name for now, just the 3 scores. And also I'm not familiarized with files.
typedef struct score{
unsigned char score[3];
//char name[20];
} SCORES;
This is how I'm saving.
void guardar_highscore (SCORES top){
FILE *f;
f = fopen ("/var/www/html/highscore3.txt","wb");
if (f ==NULL)
perror ("nope2"),exit (1);
fprintf(f,"%d \n %d \n %d \n",top.score[0],top.score[1],top.score[2]);
fclose(f);
}
This is how I'm reading it to the struct.
SCORES ler_highscore (){
SCORES top={0};
int i=0;
char line[20];
FILE *f;
f = fopen ("/var/www/html/highscore3.txt","rb");
if (f ==NULL)
perror ("nope"), exit (1);
while(fgets(line,20, f) != NULL){
sscanf (line, "%c", &top.score[i]);
i++;
}
fclose(f);
return top;
}
typedef struct score{
unsigned char score[3];
//char name[20];
} SCORES;
Scores are generally numbers, so it doesn't make much sense to store them as a single character. The problem becomes clear when you notice that you're writing them as integers (and with an extra space)...
fprintf(f,"%d \n %d \n %d \n",top.score[0],top.score[1],top.score[2]);
But you're reading them as characters...
sscanf (line, "%c", &top.score[i]);
53, 32, 32 looks suspiciously like the ASCII numbers for 5 and two spaces. If you write the character 5 as a number you'll get 53. That's because the character 5 is the number 53. Have a look at the ASCII table to see why.
The solution is to use integers consistently.
typedef struct {
int score[3];
} Scores;
Note that ALL_CAPS is generally reserved for constants, not types.
guardar_highscore remains basically the same, though I've cleaned it up some.
// The filename is now a variable so its used consistently
// and can be used in error messages.
const char Score_File[] = "highscore3.txt";
void guardar_highscore(const Scores *top) {
FILE *fd = fopen (Score_File,"wb");
if (fd == NULL) {
// A more informative error message than "nope".
fprintf( stderr, "Could not open '%s' for writing: %s\n", Score_File, strerror(errno) );
exit(1);
}
// Loop instead of repeating the formatting. This makes adding more
// scores easier.
// Note the stray whitespace is gone.
for( int i = 0; i < 3; i++ ) {
fprintf(fd, "%d\n", top->score[i]);
}
fclose(fd);
}
ler_highscore() changes to read as integers. It also only reads three lines to protect against overflowing the 3 element list if the file is unexpectedly large. It's good practice to never trust your input.
Scores ler_highscore() {
// This is the proper way to initialize a struct,
// each field must be initialized separately.
// A bare {0} happens to work because the struct is
// currently just a list, and if it doesn't you're
// going to overwrite all the elements anyway.
Scores top = { .score = {0} };
// No reason to skimp on the size of the line buffer.
char line[1024];
FILE *fd = fopen(Score_File, "rb");
if (fd == NULL) {
// Again, more informative error message.
fprintf( stderr, "Could not open '%s' for reading: %s", Score_File, strerror(errno) );
exit (1);
}
// Read 3 lines, no more. Otherwise we'll overflow memory.
for( int i = 0; i < 3; i++ ) {
// Use `sizeof(line)` rather than repeating the number.
// It avoids mistakenly letting them go out of sync.
if( fgets(line, sizeof(line), fd) == NULL ) {
fprintf( stderr, "Not enough scores in %s\n", Score_File );
break;
}
// Read one integer per line.
sscanf(line, "%d", &top.score[i]);
}
fclose(fd);
return top;
}
I'm writing a program that simulates a platform where users can register. In register function I ask the user for his username and the program should create a new file with username as file name to store his password and other data for other functions. Problem here is that fopen returns NULL which means that it can't be created.
void Register()
{
char name[11];
char password[11];
char aux[11];
system("cls");
FILE *fp=fopen("Users.txt","a+"); //I've created this .txt, just has one user which is admin
if (fp==NULL){
printf("\nFile cant be opened");
getchar();
return;
}
printf("Write a new username (no more than 10 characters, no spaces) ");
fflush(stdin);
fgets(name,sizeof(name),stdin);
getchar();
do{
if((fgets(aux,sizeof(aux),fp))!=NULL){ //Checks is reading lines
if ((strcmp(name,aux))==0){ //Username already exists
printf("\nUsername already exists, try another: ");
fflush(stdin);
fgets(name,sizeof(name),stdin);
rewind(fp); //Takes pointer to the beginning
}
}
}while(!(feof(fp)));
fseek(fp,0,SEEK_END); //Takes pointer to end
fprintf(fp,"%s",name);
fclose(fp);
fp=fopen(name,"w"); /*THIS IS WHERE IT FAILS, RETURNS NULL*/
if (fp==NULL){
printf("\nFile cant be opened");
getchar();
return;
}
printf("\nChoose a password(no more than 10 characters): ");
fflush(stdin);
fgets(password,sizeof(password),stdin);
getchar();
fprintf(fp,"%s\n",name);
fprintf(fp,"%s",password);
fclose(fp);
printf("\nUser successfully registered\nName: %s\nPassword: %s",name,password);
getchar();
}
I've already tried with another method. For example, use strcpy() to copy name to a new array and then strcat() to add ".txt" but it doesn't work either. Like this:
[...]
char aux2[20];
strcpy(aux2,name);
strcat(aux2,".txt");
fp=fopen(aux2,"w"); /*FAILS TOO */
if (fp==NULL){
printf("\nFile cant be opened");
getchar();
return;
}
Can't figure out what is going wrong. Hope you can help me
List of problems:
You have not declared fp (at least in shown code) before trying to use it.
Change line to:
FILE *fp=fopen("Users.txt","a+");
You have not declared nombre. Add line:
char nombre[11];//to match size of name
(Or, you may have meant to use name?)
Everywhere it exists in your code, comment out the line:
//fflush(stdin);
Change the line
fp=fopen(name,"w"); /*THIS IS WHERE IT FAILS, RETURNS NULL*/
to:
fp=fopen(name,"w+"); /*THIS IS WHERE IT FAILS, RETURNS NULL*/
the question was not clear about the actual format of the data within the file. So I decided to use a format of name password for each line of the file.
Here is a version of the code that cleanly compiles and performs the desired function.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void Register( void );
void Register( void )
{
char name[11];
char password[11];
char aux[11];
system("cls");
printf("Write a new username (no more than 10 characters, no spaces) ");
if( !fgets(name,sizeof(name),stdin) )
{
fprintf( stderr, "fgets for user name failed" );
exit( EXIT_FAILURE );
}
// implied else, fgets successful
// code should remove trailing new line, if any
char *newline;
if( (newline = strchr( name, '\n' ) ) )
{
*newline = '\0';
}
FILE *fp=fopen("Users.txt","a+"); //I've created this .txt, just has one user which is admin
if ( !fp)
{
perror("fopen for Users.txt for read/write failed");
getchar();
exit( EXIT_FAILURE );
}
// implied else, fopen successful
while( fgets(aux,sizeof(aux),fp) )
{ //Checks is reading lines
// separate out the name field
char *token = strtok( aux, " " );
if( token )
{
if ((strcmp(name,aux))==0)
{ //Username already exists
printf("\nUsername already exists, try another: ");
rewind(fp); //Takes pointer to the beginning
}
}
}
// name not already in file
printf("\nChoose a password(no more than 10 characters): ");
if( !fgets(password,sizeof(password),stdin) )
{
perror( "fgets for password failed" );
fclose( fp ); // cleanup
exit( EXIT_FAILURE );
}
// implied else, fgets successful
//remove trailing newline
if( (newline = strchr( password, '\n' ) ) )
{
*newline = '\0';
}
fprintf(fp,"%s %s\n",name, password);
fclose(fp);
printf("\nUser successfully registered\nName: %s\nPassword: %s",name,password);
getchar();
} // end function: Register
Just figured it out, I had to change the line
if((fgets(aux,sizeof(aux),fp))!=NULL){ //Checks is reading lines
And instead use fscanf() just like this:
if((fscanf(fp,"%s",&aux)==1){ //Checks if is reading a string (a line)
I have an input data file called "TEST.txt". it contains id numbers, names, grades of three different exams of ten students. I'm trying to make a program that reads these input data, calculates the mean value of exams for each student, and writes again id numbers,names, averages, of students whose averages are >=45.5 into output file called "RESULT.TXT" using structures.
I think I am able to read my input data with the structure I defined. I want to know what can I do for finding the averages of exams (one,two, and three), setting the condition of writing average values, and writing ids,names, and averages into RESULTS.TXT.
Here is my code until now.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
typedef struct student{
char name[30];
int id;
int exam1;
int exam2;
int exam3;
}STUDENT;
int main(){
int sum=0;
int i=0;
double mean[10];
STUDENT test[10];
FILE *fRead;
fRead=fopen("TEST.txt","r+");
if((fRead=fopen("TEST.txt","r"))==NULL){
printf("File could not be opened\n");
}
while(!feof(fRead)){
fscanf(fRead,"%d%s%d%d%d",&(test[i].id),test[i].name,&(test[i].exam1),&(test[i].exam2),&(test[i].exam3));
printf("\n%s\n",test[i].name);
i++;
}
return 0;
}
the following code:
is one possible way to perform the desired function:
cleanly compiles
uses fscanf() properly
does not use undesireable functions like feof()
is appropriately commented
performs appropriate error checking
does not include unnecessary header files
will handle any number of students in the input file, including 0 students
and now the code
#include <stdio.h> // fopen(), fscanf(), fclose()
#include <stdlib.h> // exit(), EXIT_FAILURE
#define MAX_NAME_LEN (29)
struct student
{
char name[MAX_NAME_LEN+1]; // +1 to allow for NUL terminator byte
int id;
int exam1;
int exam2;
int exam3;
};
int main( void )
{
struct student test;
FILE *fRead = NULL;
FILE *fWrite = NULL;
if((fRead=fopen("TEST.txt","r"))==NULL)
{
perror("fopen for read of Test.txt failed");
exit( EXIT_FAILURE );
}
// implied else, fopen successful
if( (fWrite = fopen( "RESULT.TXT", "w" )) == NULL )
{
perror( "fopen for write of RESULT.TXT failed" );
exit( EXIT_FAILURE );
}
// implied else, fopen successful
while( 5 == fscanf(fRead,"%d %" MAX_NAME_LEN "s %d %d %d",
&(test.id),
test.name,
&(test.exam1),
&(test.exam2),
&(test.exam3)) )
{
printf("\n%s\n",test.name);
float sum = (float)test.exam1 + test.exam2 + test.exam3;
float mean = sum / 3.0f;
if( 45.5f < mean )
{
fprintf( fWrite, "%d %s %d %d %d %2.2f\n",
test.id,
test.name,
test.exam1,
test.exam2,
test.exam3,
mean );
} // end if
} // end while
fclose( fRead );
fclose( fWrite );
//return 0; == not needed when returning from 'main' and value is zero
} // end function: main
I have made a few changes to the code you have written,
1. I have used loop instead of array of structure, the constant defines the number of students to scan.
I have created an fOut pointer for RESULT.txt, which I opened in append mode.
I created a condition, where if mean > 45.5, the details of the students will be printed in RESULT.txt.
P.S. I checked the program with 1 input in test file. Test it with multiple line inputs, should work fine.
#include <stdio.h>
#include <stdlib.h>
//constant for number of students, can be changed according to requirement
#define numOfStudents 10
typedef struct student{
char name[30];
int id;
int exam1;
int exam2;
int exam3;
}STUDENT;
int main(){
double sum=0;
int i=0;
double mean;
STUDENT test;
FILE *fRead;
//File pointer for output
FILE * fOut;
//File for output in append mode
fOut = fopen("RESULT.txt", "a+");
fRead=fopen("TEST.txt","r+");
if(fRead == NULL)
{
printf("File could not be opened\n");
}
//check if the file is successfully opened for appending
if(fOut == NULL)
{
printf("File could not be opened for printing\n");
}
for(i; i < numOfStudents; i++)
{
fscanf(fRead,"%d%s%d%d%d",&(test.id),test.name,&(test.exam1), &(test.exam2), &(test.exam3));
//calculates mean
sum = test.exam1 + test.exam2 + test.exam3;
mean = sum / 3.0;
//Condition for mean to be printed to output file
if(mean > 45.5)
{
fprintf(fOut, "%d %s %d %d %d", (test.id),test.name, (test.exam1),(test.exam2),(test.exam3 ));
fprintf(fOut, "\n");
}
if(feof(fRead))
{
break;
}
}
fclose(fRead);
fclose(fOut);
return 0;
}
I'm trying to learn how to manipulate txt files in C at the moment. This program should read in population.txt (http://pastebin.com/Q5fNRuJG), find the highest population and display it, make a file with populations of greater than 1 million, make a file with all the irish cities, and print the total population. It only creates empty files, and prints the total population (now also prints most populous city). Can anyone help?
The program (compiled in Borland):
//Program that filters and processes data with fscanf()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
main()
{
FILE *fp;
FILE *ireland;
FILE *mmplus;
int pop;
int highest_pop=0;
char country[50];
char city[50];
int total_pop=0;
fp = fopen("population.txt","r");
ireland = fopen("ireland_pop.txt","w");
mmplus = fopen("greater_than_1MM.txt","w");
//Checking if the file opened correctly
if (fp==NULL)
{
printf("Cannot open file.\n");
exit(1);
}//End if
//Scanning fp row by row
while (fscanf(fp, "%s" "%s" "%i", country, city , &pop) != EOF)
{
//Getting the total population
total_pop=total_pop+pop;
//Storing the highest pop
if (pop > highest_pop)
{
highest_pop=pop;
}//End if
//Finding 1 million+ cities
if(pop>=1000000)
{
fprintf(mmplus,"%s %s %d\n",country,city,pop);
}//End if
//If the city is in Ireland
if (strcmp("ireland",country) == 0)
{
fprintf(ireland,"%s %s %d\n",country,city,pop);
}//End if
}//End while
rewind(fp); //Fix 1
while (fscanf(fp, "%s" "%s" "%d", country, city , &pop) != EOF)
{
//Finding the city with the highest population
if (pop == highest_pop)
{
printf("The city with the highest population is %s, %s, with a population of %d",city, country, pop);
}//End if
}//end while
printf("The total population of all the cities is %d.",total_pop);
getchar();
fclose(fp);
fclose(ireland);
fclose(mmplus);
}
The first time I ran your program I got empty files. The second time I ran it I got correct output. The third time I got one correct file and one incorrect file.
I think I may have typed ctrl-C to end the program. So I made a couple of changes to the last few lines of the program - adding newline to the output, and closing the files before waiting for input. After that, it works every time, but I can't explain everything.
fclose(fp);
fclose(ireland);
fclose(mmplus);
printf("The total population of all the cities is %d.\n",total_pop);
getchar();
return 0;
here is one way to implement the algorithm
//note: the system function: perror()
// outputs the strerror() message,
// the first parameter text, etc
//Program that filters and processes data with fgets() and sscanf()
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // strcpy(), strlen()
#include <unistd.h> // unlink()
int main()
{
FILE *fp = NULL; // input
FILE *ireland = NULL; // list irish cities
FILE *mmplus = NULL; // list cities > 1million population
int pop;
char country[50];
char city[50];
int total_pop=0;
int maxPopulation = 0;
char maxPopulationCity[50] = {'\0'};
char maxPopulationCountry[50] = {'\0'};
char buffer[200]; // input work area
if( NULL == (fp = fopen("population.txt","r") ) )
{ // then, fopen failed
perror( "fopen for population.txt failed" );
exit( EXIT_FAILURE );
}
// implied else, fopen successful
if( NULL == (ireland = fopen("ireland_pop.txt","w") ) )
{ // then, fopen failed
perror( "fopen for ireland_pop.txt failed" );
fclose(fp); // cleanup
exit( EXIT_FAILURE );
}
// implied else, fopen successful
if( NULL == (mmplus = fopen("greater_than_1MM.txt","w") ) )
{ // then, fopen failed
perror( "fopen for greater_than_1MM.txt failed" );
fclose(fp); // cleanup
fclose(ireland);
unlink("ireland_pop.txt");
exit( EXIT_FAILURE );
}
// implied else, fopen successful
//Scanning fp row by row
while ( fgets( buffer, sizeof buffer, fp ) )
{
// this code makes the following assumptions
// 1) city is all one word
// (I.E, no 'st paul'
// 2) country is all one word and 'ireland' is always lower case
// (I.E. no 'Ireland' and no 'United States'
// 3) pop contains no ',' and is always positive
// 4) data item delimiters are only ' ', \t
if( 3 != sscanf(buffer, " %s %s %i", country, city , &pop) )
{
//calculate the total population
total_pop += pop;
//Storing the highest pop found so far
if (pop >maxPopulation)
{
maxPopulation=pop; // save new largest population
strcpy( maxPopulationCity, city ); // save new city
strcpy( maxPopulationCountry, country ); // save new country
}//End if
//Finding 1 million+ cities
if(pop>=1000000)
{
fprintf(mmplus,"%s %s %d\n",country,city,pop);
}//End if
//If the city is in Ireland
if (strcmp("ireland",country) == 0)
{
fprintf(ireland,"%s %s %d\n",country,city,pop);
}//End if
if( buffer[strlen(buffer)-1] != '\n' )
{ // then, input line to long for buffer[]
// read chars until newline consumed
while( '\n' != getchar() ) ;
}// end if
} // end if
}//End while
printf("The city with the highest population is %s, %s, with a population of %d",
maxPopulationCity,
maxPopulationCountry,
maxPopulation);
printf("The total population of all the cities is %d.",total_pop);
getchar();
fclose(fp);
fclose(ireland);
fclose(mmplus);
return(0);
} // end function: main