Reputation: 297
Software splits a file into three files, male, female and erroneous. The text file is formatted:
First name, Last name, Age, Gender... But is delimited by space.
example.txt looks like this:
Tim Smith 18 M
Jonathon Jones 26 M
Kathy Black 13 F
Sarah Saxby 28 F
I've already gotten it to split based on Male or Female, but I'm struggling to get it to work based on age... Here's the code, any help is much appreciated.
/*
* C program to split lines of text according to gender and age
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
/* Function declarations */
int isMale(char gender, int age);
int isFemale(char gender, int age);
/* Returns true (1) if the character in the last field is M and age is 4-18 */
int isMale(char gender, int age)
{
if (gender == 'M' && age<=18 && age>=5)
{
// printf("Male %i \n", age);
return 1;
}
return 0;
}
/* Returns true (1) if the character in the last field is F and age is 4-18 */
int isFemale(char gender, int age)
{
if (gender == 'F')
{
// printf("Female %i \n", age);
return 1;
}
return 0;
}
int main()
{
/* File pointer to hold reference to different files */
FILE * fPtrIn, // Input file
* fPtrMale, // Males of school age
* fPtrFemale, // Females of school age
* fPtrMisc; // Data not within the given parameters
// Open all files to perform read/write.
fPtrIn = fopen("data/example.txt", "r");
fPtrMale = fopen("data/males.txt" , "w");
fPtrFemale = fopen("data/females.txt" , "w");
fPtrMisc = fopen("data/erroneus.txt", "w");
// current_char is the current character being read
char current_char;
// hoping that too long lines won't come
char line[300], line_parse[300];
// Last field is where gender is stored, ret is the token used for strtok()
char *last_field, *ret;
// 0 or 1, if the age is outside or within the age limits
int age;
int field_count = 0;
// fopen() return NULL if unable to open file in given mode
if(fPtrIn == NULL || fPtrMale == NULL || fPtrFemale == NULL || fPtrMisc == NULL)
{
// Unable to open file, exit program print result
printf("Unable to open file.\n");
printf("Check file exists and permissions are correct.\n");
exit(EXIT_FAILURE);
}
// File open success message
printf("File opened successfully. \n\n");
// Read an integer and store read status in success.
while (fgets(line, sizeof(line), fPtrIn) != NULL)
{
// Copy the line for parsing
strcpy(line_parse, line);
// Separate the line into tokens
last_field = ret = strtok(line_parse, " ");
while (ret != NULL)
{
age = 0;
last_field = ret;
printf("%s \n", ret);
if (field_count == 2)
{
age = atoi(ret);
}
field_count++;
if (field_count == 4)
{
field_count = 0;
}
ret = strtok(NULL, " ");
}
// Get the first character of the last field
if (last_field == NULL) current_char = '\0';
else current_char = last_field[0];
// Write each line to a separate file
if (isMale(current_char, age))
fputs(line, fPtrMale);
else if (isFemale(current_char, age))
fputs(line, fPtrFemale);
else
fputs(line, fPtrMisc);
}
// Close each file
fclose(fPtrIn);
fclose(fPtrMale);
fclose(fPtrFemale);
fclose(fPtrMisc);
printf("Data written to files successfully. \n");
return(0);
}
Upvotes: 1
Views: 73
Reputation: 16540
the following proposed code:
fopen()
perror()
when fopen()
fails to output both the error message and the text reason the system thinks the error occurred to stderr
.caveat: OP should add check to assure enough fields found in each input line. The proposed code already handles when too many fields found in input line.
and now, the proposed code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include <ctype.h>
#define MAX_LINE_LEN 300
#define MAX_FIELD_LEN 50
struct lineFields
{
char firstName[ MAX_FIELD_LEN ];
char lastName[ MAX_FIELD_LEN ];
int age;
char gender;
};
/* Function declarations */
int isMale(char gender, int age);
int isFemale(char gender, int age);
/* Returns true (1) if the character in the last field is M and age is 4-18 */
int isMale(char gender, int age)
{
if (gender == 'M' && age<=18 && age>=5)
{
// printf("Male %i \n", age);
return 1;
}
return 0;
}
/* Returns true (1) if the character in the last field is F and age is 4-18 */
int isFemale(char gender, int age)
{
if (gender == 'F' && age<=18 && age>=5)
{
// printf("Female %i \n", age);
return 1;
}
return 0;
}
int main( void )
{
/* File pointer to hold reference to different files */
FILE * fPtrIn, // Input file
* fPtrMale, // Males of school age
* fPtrFemale, // Females of school age
* fPtrMisc; // Data not within the given parameters
// Open all files to perform read/write.
fPtrIn = fopen("data/example.txt", "r");
if( !fPtrIn )
{
perror( "fopen to read input file failed" );
exit( EXIT_FAILURE );
}
fPtrMale = fopen("data/males.txt" , "w");
if( !fPtrMale )
{
perror( "fopen to write male file failed" );
exit( EXIT_FAILURE );
}
fPtrFemale = fopen("data/females.txt" , "w");
if( !fPtrFemale )
{
perror( "fopen to write female file failed" );
exit( EXIT_FAILURE );
}
fPtrMisc = fopen("data/erroneus.txt", "w");
if( !fPtrMisc )
{
perror( "fopen to write not of school age file failed" );
exit( EXIT_FAILURE );
}
char line[ MAX_LINE_LEN ];
char line_parse[ MAX_LINE_LEN ];
while( fgets( line, sizeof(line), fPtrIn ) )
{
// Copy the line for parsing
strcpy(line_parse, line);
struct lineFields fields;
int fieldCount = 0;
// Separate the line into tokens
char * token = strtok(line_parse, " ");
while ( token )
{
printf( "%s \n", token );
switch( fieldCount )
{
case 0:
strcpy( fields.firstName, token );
break;
case 1:
strcpy( fields.lastName, token );
break;
case 2:
fields.age = atoi( token );
break;
case 3:
fields.gender = token[0];
break;
default:
printf( "too many fields in input: %s\n", line );
break;
}
fieldCount++;
token = strtok( NULL, " " );
}
// Write each line to a separate file
if ( isMale( fields.gender, fields.age ) )
fputs(line, fPtrMale);
else if ( isFemale( fields.gender, fields.age ) )
fputs(line, fPtrFemale);
else
fputs(line, fPtrMisc);
}
// Close each file
fclose(fPtrIn);
fclose(fPtrMale);
fclose(fPtrFemale);
fclose(fPtrMisc);
printf("Data written to files successfully. \n");
return(0);
}
Upvotes: 1