Reputation: 41
This program is suppose to read a pipe delimited file into array of structures.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN_LINE 160
#define LEN_NAME 40
#define MAX_LINES 60
#define LEAGUE_NAME 5
#define PARK_NAME 35
#define TEAM_ADDRESS 40
#define TEAM_CITY 30
#define TEAM_STATE 5
#define ZIP_CODE 10
#define PHONE_NUMBER 30
#define WEB_ADDRESS 25
#define LEN_TEAM 60
typedef struct
{
char leagueName[LEAGUE_NAME + 1];
char teamName[LEN_NAME + 1];
char parkName[PARK_NAME + 1];
char teamAddress[TEAM_ADDRESS + 1];
char teamCity[TEAM_CITY + 1];
char teamState[TEAM_STATE + 1];
char zipCode[ZIP_CODE + 1];
char phoneNumber[PHONE_NUMBER + 1];
char webAddress[WEB_ADDRESS + 1];
} team_t;
void displayTeams( team_t teams[], int count);
int main( void )
{
team_t teams[LEN_TEAM] = { 0 };
FILE *filePtr;
int index, count;
char line[LEN_LINE + 1] = {0};
char *startPtr, *endPtr;
filePtr = fopen( "MLBteams.txt", "r" );
if ( filePtr == NULL )
{
printf("Error in opening file\n");
}
else
{
index = 0;
while ( index < LEN_TEAM && fgets( line, sizeof( line ), filePtr ) )
{
startPtr = line;
endPtr = strchr(startPtr, '|');
strncpy( teams[index].leagueName, startPtr, endPtr - startPtr );
startPtr = endPtr + 1;
endPtr = strchr(startPtr, '|');
strncpy( teams[index].teamName, startPtr, endPtr - startPtr );
startPtr = endPtr + 1;
endPtr = strchr(startPtr, '|');
strncpy( teams[index].parkName, startPtr, endPtr - startPtr );
startPtr = endPtr + 1;
endPtr = strchr(startPtr, '|');
strncpy( teams[index].teamAddress, startPtr, endPtr - startPtr );
startPtr = endPtr + 1;
endPtr = strchr(startPtr, '|');
strncpy( teams[index].teamCity, startPtr, endPtr - startPtr );
startPtr = endPtr + 1;
endPtr = strchr(startPtr, '|');
strncpy( teams[index].teamState, startPtr, endPtr - startPtr );
startPtr = endPtr + 1;
endPtr = strchr(startPtr, '|');
strncpy( teams[index].zipCode, startPtr, endPtr - startPtr );
startPtr = endPtr + 1;
endPtr = strchr(startPtr, '|');
strncpy( teams[index].phoneNumber, startPtr, endPtr - startPtr );
startPtr = endPtr + 1;
endPtr = strchr(startPtr, '|');
strncpy( teams[index].webAddress, startPtr, endPtr - startPtr );
index++;
}
fclose( filePtr );
count = index;
displayTeams(teams, count);
}
return 0;
}
void displayTeams( team_t teams[], int count)
{
int index;
for ( index = 0; index <= count - 1; index = index + 1)
{
printf("LEAGUE: %s\nTEAM: %s\nPARKNAME: %s\nADDRESS: %s\nCITY: %s\nSTATE: %s\nZIPCODE: %i\nPHONE#: %s\nWEBADDRESS: %s\n\n",
teams[index].leagueName, teams[index].teamName, teams[index].parkName,
teams[index].teamAddress, teams[index].teamCity, teams[index].teamState,
teams[index].zipCode, teams[index].phoneNumber, teams[index].webAddress);
}
}
I am using this to try and read this file.
A|Baltimore Orioles|Oriole Park|333 West Camden Street|Baltimore|MD|21201|(410) 685-9800|orioles.com
A|Boston Red Sox|Fenway Park|4 Yawkey Way|Boston|MA|02215|(617) 267-9440|redsox.com
N|St. Louis Cardinals|Busch Stadium|700 Clark Street|St. Louis|MO|63102|(314) 345-9600|cardinals.com
N|Washington Nationals|Nationals Park|1500 South Capitol Street, SE|Washington|DC|20003-1507|(202) 675-6287|nationals.com
Here is a few lines(its 30 teams in total). Well when I run the program it crashes immediately and gives me no error messages.I would appreciate if someone could explain to me why the code isn't working.My guess is that I am using strncpy function incorrectly.
Upvotes: 1
Views: 681
Reputation: 53016
You guess right! You need to manually '\0'
terminate strings in this case, so using memcpy()
might be better even in terms of clarity.
string[endPtr - startPtr] = '\0';
for each string
in question.
Upvotes: 0
Reputation: 1526
In the given code it doesn't seem to be important to preserve the original strings. I'd suggest revising it to use strtok(), which modifies the original string by sticking NUL's in it as it goes. Specifically it puts a NUL character where the first delimiter is found, so then you can just use strcpy to copy the token. Then strtok with NULL will go back to the original string and find the next token for you. Read all about strtok() on the web.
while (index < LEN && fgets(line, sizeof(line), filePtr))
{
char* token = strtok(line, "|");
strcpy(teams[index].leagueName, token);
token = strtok(NULL, "|");
strcpy(teams[index].parkName, token);
// and so forth
}
Now the problem I haven't solved, and you should, is that the supplied text could be too long for the field and neither your original nor my suggested code addresses this. Perhaps
token = strtok(line, "|");
if (strlen(token) > LEAGUE_NAME) token[LEAGUE_NAME]=0;
strcpy(teams[index].leagueName, token);
Also your strchr() results, and in my prototype code above, the strtok() results, are not checked. If the input line is wider than expected, your limited by count fgets() call could truncate the line and leave out a delimiter. The strchr or strtok result would be NULL and that would stop your program.
Upvotes: 1