File Handling Operations in c - c

I have been working on the following bit of code and am having trouble with my file handling operations.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void)
{
int lineCount=0;
char line[200];
char *lineArray[lineCount];
char *CityName[20];
double longitudinal[10];
double latitudinal[10];
int serialno[10];
char *token;
const char j=' ';
int x=0,p=0;
FILE *file;
file=fopen("chota.txt","r");
if(file==NULL)
{
printf("file is not opened properly\n");
return -1;
}
//below one to give total number of lines.
while ((fgets(line,sizeof(line),file)) != NULL)
{
lineCount++;
}
lineArray = (char *)malloc(sizeof(char *)*lineCount);
rewind(file);
printf("The total number of cities in the file is: %d\n",(lineCount-1));
fgets(line,sizeof(line),file);//moves file pointer to beg of 2nd line
while ((fgets(line,sizeof(line),file)) != NULL)
{
lineArray[p]=malloc(strlen(line));//1st bunch of memory allocated
strcpy(lineArray[p],line);
printf("%s\n",lineArray[p]);
token = strtok(lineArray[p],j);
//printf("%s\n",token);
serialno[p]=atoi(token);
printf("%d\n",serialno[p]);
x=1;
/* walk through other tokens */
while( token != NULL )
{
//printf( " %s\n", token );
if((x%4)==1)
{
//longitudinal[p] =malloc(strlen(token));
longitudinal[p] =atof(token);
}
else if((x%4)==2)
{
//latitudinal[p]=malloc(strlen(token));
latitudinal[p]=atof(token);
}
else if((x%4)==3)
{
CityName[p] = malloc(strlen(token));
strcpy(CityName[p],token);
printf("%s\n",CityName[p]);
}
token = strtok(NULL, j);
x++;
} //end of inner while
p++;
}//end of outer while
}//end of main
The file that I am using is:
City_No Latitude Longitude City_Name
1 12.58 77.38 Bangalore
2 14.18 74.55 JogFalls
3 15.09 76.55 Bellary
4 26.48 84.33 Bettiah
5 25.37 85.13 Patna
6 19.18 84.51 Berahampur
7 20.15 85.51 Bhuvneshwar
8 25.30 90.30 Shillong
The problem is that I have been trying this for the past few days and I keep getting errors. I am not getting anywhere with debugging and cannot figure out where I am going wrong.

The array is better declared and allocated like this:
char **lineArray;.
lineArray = (char **)malloc(sizeof(char *) * (lineCount-1));
strtok take a string as second argument.
Replace const char j=' '; by const char *j=" ";
Get rid of the first strtok:
lineArray[p]=malloc(strlen(line));//1st bunch of memory allocated
strcpy(lineArray[p],line);
printf("%s\n",lineArray[p]);
//token = strtok(lineArray[p],j);
//printf("%s\n",token);
//serialno[p]=atoi(token);
//printf("%d\n",serialno[p]);
x=1;

Related

Program Hangs when printing contents of array in loop

Hi, i am using the MinGW C Compiler with Code::Blocks and my code hangs when trying to print the contents of an array (well it is a custom data type).
For a quick summary: the program is taking the contents of a txt file and splits
the string up into individual words using a custom data type called a stringArray (the name explains itself). It then should print each word of the file to the user.
The problem is, it hangs and gives me the usual "[PROGRAM NAME HERE] is not responding." After pressing cancel it gives me this result:
Process returned -1073741819 (0xC0000005) execution time : 3.861 s
Press any key to continue.
I am a sort of beginner.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
typedef struct stringArray
{
char *string;
}stringArray;
const char delim[2] = " ";
int string_to_array(char *filecontents)
{
char *token;
token = strtok(filecontents, delim);
int i;
int dirtyContentsLength;
stringArray newContents[100];
for(i = 0; i < 100; i++)
{
newContents[i].string = "";
}
i = 0;
while (token != NULL)
{
newContents[i].string = token;
i++;
token = strtok(NULL, delim);
}
return newContents;
}
int open_file(char filename[30])
{
char *file_contents;
long input_file_size;
FILE *input_file = fopen(filename, "rb");
fseek(input_file, 0, SEEK_END);
input_file_size = ftell(input_file);
rewind(input_file);
file_contents = malloc(input_file_size * (sizeof(char)));
fread(file_contents, sizeof(char), input_file_size, input_file);
fclose(input_file);
return file_contents;
}
int lex(char filecontents[30])
{
char *tok = "";
int state = 0;
char *string = "";
}
int main(int argc, char *argv[] )
{
const char *cleanContents;
char *messyContents;
char input[30];
printf("What is the filename? ");
scanf("%s", input);
messyContents = open_file(input);
cleanContents = string_to_array(messyContents);
int contentsLength = sizeof(cleanContents) / sizeof(cleanContents[0]);
int i;
for(i = 0; i < contentsLength; i++)
{
printf("%s\n", cleanContents[i]);
}
printf("Done");
return 0;
}
You have multiple problems with your code:
string_to_array() is declared to return an int, but in reality it is returning a stringArray
Same with open_file() function, Declared to return an int, but actually returning a char*
string_to_array is returning an element that was declared locally. This means that once the function is returned, that memory is no longer valid, but it has passed it on to the caller.
Your structure name is misleading. A char* is a character array (a string). Thus the name charArray would be more appropriate. For the structure to be a string array it has to be a char**, ie an array of character arrays (array of strings)
Int the printf() in the main() function you are not passing the string (thus a compilation warning is generated)
You are not initializing memory to all 0. This is ideal as otherwise the memory will contain random data which will be interpreted as a string untill the first null terminator (\0 encountered)
The following code is a modified working version of what you are trying to achieve with comments about each change:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
typedef struct stringArray
{
char *string;
}stringArray;
const char delim[2] = " ";
// Now string_to_array takes the memory location to write output to as a first parameter so that the
// memory will reside in the callers scope (refer to problem 3 above)
// Additionally return type was now set to void (refer to problem 1)
void string_to_array(stringArray newContents[100], char *filecontents)
{
char *token;
token = strtok(filecontents, delim);
int i;
int dirtyContentsLength;
for(i = 0; i < 100; i++)
{
newContents[i].string = "";
}
i = 0;
while (token != NULL)
{
newContents[i].string = token;
i++;
token = strtok(NULL, delim);
}
// return now was removed. result written directly in memory passed as parameter by the caller.
}
// open_file changed to return a char* (refer to problem 2)
char* open_file(char filename[30])
{
char *file_contents;
long input_file_size;
FILE *input_file = fopen(filename, "rb");
fseek(input_file, 0, SEEK_END);
input_file_size = ftell(input_file);
rewind(input_file);
file_contents = malloc(input_file_size * (sizeof(char)));
fread(file_contents, sizeof(char), input_file_size, input_file);
fclose(input_file);
return file_contents;
}
int lex(char filecontents[30])
{
char *tok = "";
int state = 0;
char *string = "";
}
int main(int argc, char *argv[] )
{
stringArray cleanContents[100];
// Initializing memory to all 0s (refer to problem 6)
memset(cleanContents, 0 ,sizeof(cleanContents));
char *messyContents;
char input[30];
printf("What is the filename? ");
scanf("%s", input);
messyContents = open_file(input);
string_to_array(cleanContents, messyContents);
int contentsLength = sizeof(cleanContents) / sizeof(cleanContents[0]);
int i;
for(i = 0; i < contentsLength; i++)
{
// Checking that at least one character is present in the string before printing it...
if (cleanContents[i].string[0])
{
// Printing the string within the 'stringArray'. (refer to problem 5)
printf("%s\n", cleanContents[i].string);
}
}
printf("Done\n");
return 0;
}

Why do I keep getting a "warning: comparison between pointer and integer error"?

Does anyone know why my program doesn't read from my delimited file? I thought it would print everything from my delimited file after the program ran through my printPropertyListing() method at the bottom but instead it gives me the error message warning "warning: comparison between pointer and integer". It's telling me the error is on the beginning line of my for loop in the main method. Any solutions please?
Here is what my delimited file looks like:
123 Cherry Tree Drive#330#Condo#2#1#275900#Toronto#
14 Leaside Lane#N/A#House#4#2#445500#Brampton#
2478 Waterfront Avenue#N/A#House#5#3#899900#Mississauga#
7 Lucky Lane#1206#Condo#3#2#310000#Toronto#
51 West Street#32#Townhouse#4#2#450000#Brampton#
193 Crystal Road#1519#Condo#1#1#250750#Toronto#
3914 Tangerine Terrace#N/A#House#3#1#427750#Mississauga#
10 Redding Road#N/A#House#4#2#512350#Toronto#
76 Old School Avenue#227#Townhouse#3#2#475000#Toronto#
90 Brookhaven Terrace#N/A#House#4#2#512750#Brampton#
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char buildingType[10];
int numBedrooms;
int numBathrooms;
}Propertylisting;
typedef struct {
Propertylisting propertylisting;
char address[100];
char unitNum [10];
char city [50];
int listPrice;
} Listing;
void parseListings(FILE *in, Listing listing[], int arraySize);
void printPropertyListing(Listing l);
int main()
{
Listing listing[10];
FILE *fp = fopen("PropertyListings.txt", "r");
if (fp == NULL)
{
printf("Could not open file!");
exit(1);
}
else
{
parseListings(fp, listing, 10);
if (listing == 0)
{
printf("No Property data found.");
exit(1);
}
printf("\nNumber of listings in file: %d\n\n", listing);
int i;
for (i = 0; i < listing; i++)
{
printPropertyListing(listing[i]);
printf("\n");
}
fclose(fp);
}
return 0;
}
void parseListings(FILE *in, Listing listing[], int arraySize)
{
// Holds the current index of the Listing array
int n = 0;
// Set value as empty string
char line[256];
// A token pointer that the strtok() function returns
char *token;
char *delimiter = "#";
while (!feof(in)&& n > arraySize)
{
fgets(line, 256, in);
// Read the address
token = strtok(line, delimiter);
strcpy(listing[n].address, token);
// Read the unitNum
token = strtok(NULL, delimiter);
strcpy(listing[n].unitNum, token);
// Read the building typede
token = strtok(NULL, delimiter);
strcpy(listing[n].propertylisting.buildingType, token);
token = strtok(NULL, delimiter);
int numBedrooms = strtol(token, NULL, 10);
listing[n].propertylisting.numBedrooms = numBedrooms;
token = strtok(NULL, delimiter);
int numBathrooms = strtol(token, NULL, 10);
listing[n].propertylisting.numBathrooms = numBathrooms;
token = strtok(NULL, delimiter);
int listPrice = strtol(token, NULL, 10);
listing[n].listPrice = listPrice;
token = strtok(NULL, delimiter);
strcpy(listing[n].city, token);
n++;
}
return n;
}
void printPropertyListing(Listing l)
{
printf("%s %s %s\n%s %d %d %d\n\n",
l.address,
l.unitNum,
l.city,
l.propertylisting.buildingType,
l.propertylisting.numBedrooms,
l.propertylisting.numBathrooms,
l.listPrice);
}
The problem is in your for loop:
for (i = 0; i < listing; i++)
i is of type int and listing is of type Listing [10];
As pointed out by others, your listing variable is an array (which is actually a pointer to the start of a block of memory being used as an array). This means you are attempting to compare a pointer to an int, which does not make sense.
It looks like you are trying to compare to the size of the array, and since your parseListings function already returns the number of listings it has parsed, you can instead do the following:
int numListings = parseListings(fp, listing, 10);
if (numListings == 0) {
printf("No Property data found.");
exit(1);
}
printf("\nNumber of listings in file: %d\n\n", numListings);
int i;
for (i = 0; i < numListings; i++) {
printPropertyListing(listing[i]);
printf("\n");
}
You will note that I changed a few other locations where you were also using the listing variable, but I suspect you had wanted to check against the number of listings.
In addition to this, there is the points which Jens made about other bugs in your program, which would make this the perfect time to learn about the while 1: ... break; paradigm.
while (n < arraySize) {
fgets(line, 256, in);
if(feof(in)) {
break;
}
Credit to other people for pointing out all of these bugs; I have just attempted to formulate all of their responses into a single coherent guide to things you should consider for improving this code specifically and all of your code in general.
Edit: additionally, the return type of parseListing should be changed to int in order to match the fact that you return n;

How to use strtok() to read from a text file and create structs?

Given a text file:
I Angelina Jolie 1 7728323
I Mel Gibson 3 7809606 7733889 7724609
I Robert Redford 2 7721170 7731959
I Jennifer Aniston 4 2188989 2189898 2181020 2183456
I Jami Gertz 4 7734404 7774012 7773023 7921492
I Brad Pitt 2 7774017 7878485
R Sylvester Stallone 0
I Victoria Principal 3 7933045 7771234 7820987
R Jennifer Aniston 0
R Sean Penn 0
I Kevin Costner 1 7874014
Q
I need to read each line, separate the values by spaces, and create structs of each one. My current code is:
int main(){
int y;
FILE *data;
char action;
char line[100];
int counter = 0;
int index = 0;
struct number{
int phoneNumber;
struct number *next;
};
struct contact{
char fName[10];
char lName[10];
struct number *start;
};
struct number numbers[50];
struct contact directory[10];
if((data=fopen("hw6data.txt", "r")) != NULL){
while(fscanf(data, "%s", line) != EOF){
char s[2] = " ";
char *token;
token = strtok(line, s);
while(token != NULL){
if(counter==0){
if(s == "I") {
if(counter==1){
strcpy(directory[index].fName, s);
}
if(counter==2){
strcpy(directory[index].lName, s);
}
}
}
token = strtok(NULL, s);
}
}
}
for(y = 0; y < 10; y++){
printf("%s ", directory[y].fName);
printf("%s\n", directory[y].lName);
}
fclose(data);
return 1;
}
I'm trying to create a struct for each phone contact. The I or R indicates whether I should insert the contact or remove it. The directory is an array that contains up to 10 contacts. I can hold a total of 50 numbers. Each contact struct holds a pointer that should point to the first number in the numbers array of number structs. I'm creating an array-based linked list. I thought this code should create the contact structs. It compiles, but when I run it I get:
��f
�
ɷ�
�E
�����
�
��
.N=�
|�X�|���^�
�
Segmentation fault
Help?
An example that parse the "I" lines and print what's was read :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
int y;
FILE *data;
char action;
char line[100];
int counter = 0;
int index = 0;
struct contact{
char fName[10];
char lName[10];
};
struct contact directory[10];
if((data=fopen("hw6data.txt", "r")) != NULL){
while(fgets(line,sizeof(line),data)){
char s[2] = " ";
char *token = strtok(line, s);
while(token != NULL) {
if(strcmp(token,"I")==0) {
counter = 0;
}
if(counter==1) {
strcpy(directory[index].fName, token);
}
if(counter==2) {
strcpy(directory[index].lName, token);
index++;
}
counter++;
token = strtok(NULL, s);
}
}
}
for(y = 0; y < index; y++){
printf("%s ", directory[y].fName);
printf("%s\n", directory[y].lName);
}
fclose(data);
return 1;
}
If it helps...
A few problems I can see just at a glance (not necessarily a complete list):
The line while (fscanf(data, "%s", line) != EOF) does not read in an entire line at a time (which appears to be your intent, since you named your variable line). You probably want to do while (fgets(data, 100, line) != NULL) instead.
You can't do string comparison in C as if (s == "I"). If you're just checking the first character, you can do if (s[0] == 'I') (note that single quote marks ('') are used here to denote a character literal, versus the double quote marks ("") used to denote string literals.
You have if (counter == 1) and if (counter == 2) nested inside if (counter == 0), so those conditions will never be true, unless you modify counter at some point after the if (counter == 0) and before the if (counter == 1).
counter and index are never being incremented, so your entire while loop is having no effect whatsoever on the directory array. This is why you get garbage when you try to print out its values.

How to get position of delimited separated string in C

How do i get the position of delimited separated string?
My text file looks like
at:x:25:25:Batch jobs daemon:/var/spool/atjobs:/bin/bash
avahi:x:109:111:User for Avahi:/var/run/avahi-daemon:/bin/false
beagleindex:x:110:112:User for Beagle indexing:/var/cache/beagle:/bin/bash
My C code looks like
#include<stdio.h>
int main(int argc, char *argv[])
{
char *str, *saveptr;
char ch[100];
char *sp;
FILE *f;
int j;
char searchString[20];
char *pos;
f = fopen("passwd", "r");
if (f == NULL)
{
printf("Error while opening the file");
}
while (fgets(ch, sizeof ch, f)!= NULL)
{
/*printf("%s\n", ch); */
for (j = 1, str = ch; ; j++, str= NULL)
{
char *token = strtok_r(str, ": ", &saveptr);
if (token == NULL)
break;
//printf("%s---\n---", token);
printf("%s",token);
}
}
fclose(f);
well, using strtok(str, ": ", will split your string on spaces as well as colons, which is probably not what you want. In addition, strtok treats multiple consecutive delimiter characters as a single delimiter (so it will never return an empty string between two colons), which is not what you want for parsing passwd.
Instead, you probably just want to use strchr:
while (fgets(ch, sizeof ch, f)!= NULL) {
char *token, *end;
for (j = 1, token = ch; token; j++, token = end) {
if ((end = strchr(token, ':'))) *end++ = 0;
...do something with token and j
I do not think you have to use strtok() just to get the position of a token separated by delimiters, rather simply walk through each line, and do a char by char comparison for the delimiter... (hope this will help you)
I prepared an input file called GetDelimPosition.txt:
at:x:25:25:Batch jobs daemon:/var/spool/atjobs:/bin/bash
avahi:x:109:111:User for Avahi:/var/run/avahi-daemon:/bin/false
jamil:x:25:25:Batch jobs daemon:/var/spool/atjobs:/bin/bash
javier:x:109:111:User for Avahi:/var/run/avahi-daemon:/bin/false
jiame:x:25:25:Batch jobs daemon:/var/spool/atjobs:/bin/bash
jose:x:109:111:User for Avahi:/var/run/avahi-daemon:/bin/false
And used the following code: (of course you will modify as needed)
#include <ansi_c.h>
//edit this line as needed:
#define FILE_LOC "C:\\dev\\play\\GetDelimPosition.txt"
int main(void)
{
FILE * fp;
char ch[260];
int line=-1;
int position[80][100]={0}; //lines x DelimPosition
memset(position, 0, 80*100*sizeof(int));
int i=-1,j=0, k=0;
int len;
fp = fopen(FILE_LOC, "r");
while (fgets(ch, sizeof ch, fp)!= NULL)
{
line++; //increment line
len = strlen(ch);
for(j=0;j<len;j++)
{
if(ch[j] == ':')
{
position[line][k] = j+1;//position of token (1 after delim)
k++; //increment position index for next token
}
}
k=0; //getting new line, zero position index
}
fclose(fp);
return 0;
}
To get the following results: (rows are lines in file, columns are positions of each token. First token is assumed at position 0, and not reported)

C - Storing Values from text into Arrays

I'm trying to store different values that are taken from a file line by line. The lines in the text file read as something shown below
100000,player1,long title name
300000,someotherplayer,another long title name
45512845,thisplayer,one more long title name
I want to store each value that is comma separated into three different arrays, (int)number, (str)player_name, (str)title_name.
I have some code below, but it doesn't compile.
ptr_file=fopen("text.txt", "r");
char buffer[1000];
int line;
line = 0;
while(fgets(buffer, sizeof(buffer), ptr_file) != NULL){
char number[line]=strtok(buffer, ",");
char player_name[line]=strtok(NULL, ",");
char title_name[line]=strtrok(NULL, ",");
}
Can someone give me some advice on this?
So, there are a couple of issues with your code,
You open the file in mode "o" which I'm not really sure what it is, I suspect you want "r"
strtok returns a char * which you cannot assign to a char[].
One the second run through the loop you will overwrite the data in buffer.
I would do something like this:
struct player {
int number;
char player_name[64];
char title_name[256];
};
int main(void) {
FILE *ptrfile=fopen("text.txt", "r");
char buffer[1000];
int line;
struct player players[16];
line = 0;
if(ptrfile==NULL) return 0;
while(fgets(buffer, sizeof(buffer), ptrfile) != NULL){
if(strcmp(buffer, "") == 0) return 0;
char *number=strtok(buffer, ",");
char *player_name=strtok(NULL, ",");
char *title_name=strtok(NULL, ",");
players[line].number=atoi(number);
strcpy(players[line].player_name, player_name);
strcpy(players[line].title_name, title_name);;
line++;
}
fclose(ptrfile);
return 0
}
function strtok return a pointer, so it should be
char* p = strtok(...)
Check the reference here
This is something I did that was similar to what you seem to be doing. The problem you will find is that you want to make each value into a char* but you have to malloc each one then you can connect this char* into the array. It would also just be easier to do that with the numbers to then turn them into int later on.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char *msg[100];
char temp[100];
int length, i;
int num = 0;
while((scanf("%s", &temp[0]) != EOF))
{
length = strlen(temp);
msg[num] = malloc((length+1 )* sizeof(char));
strcpy(msg[num], temp);
num++;
}
printf("There are %d words in the this input.\n", num);
for(i = 0; i < num; i++)
{
printf("%s\n", msg[i]);
}
return 0;
}
The thing with the malloc is that you will have to have each one unique because the words are all different sizes. I know this example isn't exactly what your doing but it will get you in the right direction.

Resources