c - iterating through field from txt file causes segmentation fault - c

So I'm creating a program called convert.c that takes in data from a csv file and writes the data to a new textfile called data.bin (but with alterations to the original csv file). One field/column of the csv file in particular contains a column of integers, which were written to the data.bin file. In my analyzeInjuries.c file, I'm trying to write a program that reads in the data.bin file and calculates the total number of integers within that specific column (representing the total number of injuries caused by hurricanes).
I calculated the total number of injuries in my convert.c file and printed it in the terminal. It worked, however when I try to do the same in the analyzeInjuries file, it prints a value of 0. I'm not sure why this is happening as the getfield function and calculations worked fine in convert.c.
I believe there is something wrong with the line char *two = getfield(buf, 2); because when I attempt to print all values in field two, it causes a segmentation fault. Any help with this would be extremely appreciated. I'm really confused as to what went wrong in the analyzeInjuries.c file.
analyzeInjuries.c:
int numDisast= 0;
while (fgets (buf, lineCount, fd)) {
char *second = getfield (buf, 2); //printing second field causes seg fault
int field = POINTER2INT(second);
numDisast = numDisast + field;
}
printf("%d\n", numDisast);
return 0;
}
The image below is a screenshot of the data.bin file. The red line indicates the field I'm trying to find the sum of.

I assume that by "printing third field causes seg fault" you mean trying to print second variable.
getfield() returns NULL if it doesn't find the field and because it uses , as a separator and your data.bin doesn't use ,, then it will always return NULL. Then when you try to print it, it will crash.
Beside that you are not really summing values in the column. Your POINTER2INT macro does not convert a string to an integer. You probably want to use atoi() instead.
EDIT
First: you should check for NULL in you loop:
char *second = getfield (buf, 3);
if (second) {
printf("found field: %s\n", second);
numDisast = numDisast + atoi(second);
}
else {
printf("field not found\n");
}
Second: your data.bin looks like it might use tabs instead of , as the separator. You could change "," to "\t" in your call to strsep() and see if it helps.

Related

How can I print a part of a file when I reach it?

I am new with C, I'm having a problem with this code, I am trying to print when I reach a specific part of a text file, but it doesn't print anything. Here is the code:
while(!feof(f)){
fgets(temp, 150, f);
if(temp=='****'){
printf("%s\n", temp);
}
}
In order to compare two string, you have to use strcmp function:
if(strcmp(temp,"****")==0 ) { ....
otherwise you will just comparing two pointers
I believe what you really want to use is strstr()
This returns a pointer to the first occurrence of a string inside another string.
https://www.tutorialspoint.com/c_standard_library/c_function_strstr.htm
//while there are still lines to read , print if desired line has been read
while(fgets(temp, 150, f))
{
//if beggining mark is found print
if(strstr(temp, "****")!=NULL) printf("%s\n" , temp)
}
Note: 150 should be replaced by a MAXIMUM_LINE_SIZE variable. This variable should be populated with the maximum line size from the file that you are reading from. If a line is longer than this max size you could miss the desired string if "****" is over 150 characters into the line.

Segmentation fault, scanf

We have an assignment which is to take characters from a file, shift it a given value to the right(it'll make sense in the code) and then store that new value in a new file, but I seem to be running into a segmentation fault, which as far as I know means I'm trying to access memory outside of the memory I have been allocated? I'm very new to C and I managed to debug this code up until this point and I honestly don't know where to go. I don't even quite understand what the issue is.
#include<stdio.h>
//Get Shift amount
//Get ifilename
//Get ofilename
//open them
//Get characters one at a time from input
//Process and shift by shift amount
int main()
{
int i;//loop value
char a[62]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";//Variable with every value
int sa = 0;//Store Shift value
char ofile[30];//contain the name of output file
char ifile[30];//contain name of input file
char value;//Value to keep the current value in
printf("How far in ascii values would you like to shift?\n");
scanf("%i", sa);//Get shift
printf("What is the name of your input file located in this directory?");
scanf("%s", ifile);//get input name
printf("What would you like to name your new file?\n Do note that it will overwrite the current file named this!");
scanf("%s", ofile);//Get output name
FILE *oIfile = fopen(ifile, "r"), *oOfile = fopen(ofile, "w");
while(value = fscanf(oIfile, "%c", value) != EOF)//Check to ensure that you never reach the end of the file
{
for(i=0; i<62; i++)//loop through the list of all characters
{
if(value == a[i])//check to see if the value from the input file matches with which letter
{
value = a[i+sa] % 62;//incrase the value by the shift amount, check if its longer than 62, add remainder
break;//break the for loop so we can restart the while loop with the next letter
}
}
fprintf(oOfile, "%c");//print the new value to the output file
}
fclose(oIfile);//close input file
fclose(oOfile);//close output file
}
is this issue due to my approach to scanf?
Apart from passing the address to scanf (scanf("%i",&sa) which you would have to do (Also it would be correct to check the return value of it) - you need to correct a few things:-
It should be (value = fscanf(oIfile, "%c", value)) != EOF. != has higher precedence than = so this is needed to get the correct result.
Also a[(i+sa)%62]=... is the right way to do things. Because otherwise it will access array index out of bound for certain values of sa leading to undefined behavior.
fprintf(stream,"%c",charvariable) this would be the use for fprintf.
The value is over written with what is being returned by the value that fscanf returns. You should use other temporary variable or even better simply do like this while(fscanf(oIfile, "%c", value)!=EOF). But to have more checks you need to do somehting like
int c;
while((c=fscanf(oIfile, "%c", value))!=EOF)
You got segmentation fault here by passing the value of sa instead of its address in scanf.
scanf take an address as a parameter. Try this;
scanf("%i", &sa);//Get shift

How do use fgets to find if this line exists in .csv file? (C)

Hi I'm tyring to use fgets in a C program to see whether or not a name exists in a line in a .csv file. If it does, then it saves it in an array then returns it. Right now, it saves everything line from the .csv file and I'm not sure why.
C file:
void FindRecord(char *filename, char *name, char record[]) {
char *temp = record; //temp save record
FILE *q = fopen(filename, "r"); //check that ths inputed .csv file exists
if (q == NULL ) { //if it doesn't, then print error message and exit
printf("This .csv does not exist");
exit(1); //terminate with error message
}
while(!feof(q)) { //while I'm not at the end of the file
fgets(temp, 1000, q); //Reads a line # a time
for (int i = 0; i < 1000; i++) {
if(temp[i] == *name) {
record[i] = temp[i];
name++;
}
}
printf("%s", record);
}
fclose(q);
}
.csv file:
Kevin, 123-456-7890
Sally, 213-435-6479
Megan, 415-336-8790
Right now whats happening when I run the program is that it returns the 3 lines. I want iso that if *name points to the name "Kevin" and it comes with temp, it'll just return: Kevin, 123-456-7890
Right now whats happening when I run the program is that it returns the 3 lines.
I don't see how that's possible. You have only one array in which to return a result. I could believe that your code prints all three lines, but it will return only the last.
I want iso that if *name points to the name "Kevin" and it comes with temp, it'll just return: Kevin, 123-456-7890
Well, your code has several problems in that regard. Among the most significant are:
Although it performs some character-by-character comparisons, it has no code anywhere to reject lines that fail to match.
It sets temp to point to the same array as record, and then reads each line into that array. This will overwrite that array even in the event that no match is found, and if a match is found on a line other than the last one read then the actual match will be lost.
It modifies the name pointer as it attempts to match, with no mechanism for resetting it in the event of a partial match.
When trying to match the name, it blithely scans past the , delimiter in the input line and, if it comes to them, the string terminators in the name and the input string.
while (!feof(file)) is always wrong.

Replace value in string with another from another string

I've been stuck for a while now. The program i'm writing basically changes the false words with the correct ones from the dictionary. However, when i run the program, it gives me no warnings or errors, but it doesn't display anything. Can you please help me?
#include<stdio.h>
#include<ctype.h>
#include<string.h>
int main(void){
char fname[20],word[2500], dictn[50];
int i,j;
float len1, len2;
FILE *inp, *dict, *outp, *fopen();
fpos_t pos1, pos2;
dict= fopen("dictionary.txt", "r");
printf("Enter the path of the file you want to check:\n");
scanf("%s", fname);
inp= fopen(fname, "r");
for(i=0;(fscanf(inp, "%s", word) != EOF); i++){
for(j=0;fscanf(dict, "%s", dictn) != EOF; j++){
fgetpos(inp, &pos1);
fgetpos(dictn, &pos2);
len1=(float)strlen(word);
len2=(float) strlen(dictn);
if(len1<=(0.6*len2)){
fsetpos(dictn, &pos1);
}
if(strncmp(word, dictn, 1)==0){
fsetpos(dictn, &pos1);
}
if(strcmp(word, dictn)==0){
fsetpos(dictn, &pos1);
}
}
printf("%s ", word);
}
fclose(inp);
fclose(dict);
return(0);
}
You can use
sprintf(word, "%s ", dictn);
If your code is working with printf it should work with sprintf, provided you don't overflow "word", including the NULL termination, so you might have to resize "word" if it is smaller than dictn.
First of all, I'm assuming you have created arrays word and dictn with enough size to hold the maximum length string any of your files.
First fault:
In loops you've created, i represents number of strings in input file and j represents number of strings in dictionary. word is your input string variable and dictn is your dictionary string variable. But you want to retrieve and alter word's ith or dictn's jth character. This may cause an error because there can be a case like this:
Suppose there are 10 words at inp file and 100 words at dictn. And in your loops, i have value of 8 and j have value of 88. Corresponding these i and j values, word has string value of, say, apple and dictn has string value of apple also. So this means apple is the 8th word at input file and 88th word at dictionary file. And if one of those if conditions was satisfied, compiler tries to apply a statement like word[i]=dictn[j];. This means word[8] = dictn[88]; for this example. But both of those string have apple as values which consists only 5 characters! And this will cause an error since you've tried to retrieve 88th character of a 5-length string and assign it to the 8th character of a 5-length string. So your code is wrong, it will only work for some cases which will be a rare situation.
Second fault:
I assume you want to read whole dictionary file for every word in input file but you will be able to read it for only first word of input file since you don't reopen it or set position indicator at the beginning of dictionary file after you read whole dictionary.
Third fault:
Your first if statement will never be reached assuming you have created len1 and len2 variables as integers. Because in your if statement, there is a multiplication of a decimal number and an integer which will return 0 as a result and since fscanf() ignores whitespaces, len1 and len2 will be at least 1.
Fourth fault:
Also your else if statement will never be reached because if a string has same value with another, their first character will also be equal to each other and your if statement where you compare their first characters will be also accepted.
Actually, I would write a code as solution but first of all you need to correct things up which are logically wrong because I do not know what you are really try to achieve by your code -just because I commented with full of assumptions-. But I can provide you some guidelines:
Convert your len1 and len2 variables from int to float and cast values which return from strlen() functions to float.
Reopen your dict file for every iteration of outside loop. (And do not forget not to close it).
To change your inp file, you can use a fpos_t type of variable to track your position indicator of your inp file (fgetpos() to get current position and fsetpos() to change position with value of fpos_t variable. You can search them.) and type the word with fprintf() or fputs() to that location to change that string.

strstr C function is functioning abnormally

For the C project coming up, the goal is to read in a CSV file with the first two lines listing the row and column lengths like
attributes: 23
lines: 1000
e,x,y,n,t,l,f,c,b,p,e,r,s,y,w,w,p,w,o,p,n,y,p
e,b,y,y,t,l,f,c,b,n,e,c,s,s,w,w,p,w,o,p,n,s,m
e,x,f,y,t,l,f,w,n,w,t,b,s,s,w,w,p,w,o,p,n,v,d
e,s,f,g,f,n,f,c,n,k,e,e,s,s,w,w,p,w,o,p,k,v,u
The thing is, I don't know if future file inputs will be of the same row/column lengths, so I'm implementing a determineFormat function to read those first two lines, which will be used for building the data structures.
In order to do this, I need to match a substring to the current line. If it matches, then fscanf is used to read in the line and extract the length integers. However, this code isn't working, as the entire strstr function is getting skipped over in ddd.
int lineCount, attrCount; //global variables
void determineFormats(FILE *incoming){
char *curLine= emalloc(CLINPUT);
int i;
char *ptr=NULL;
for (i=0; i<2; i++){
if (fgets(curLine, CLINPUT, incoming) != NULL){
ptr= strstr(curLine, "attrib"); //this line is skipped over
if (ptr!= NULL)
fscanf(incoming, "attributes: %d", &attrCount);
else
fscanf(incoming, "lines: %d", &lineCount);
}
}
printf("Attribute Count for the input file is: %d\n", attrCount);
printf("Line count is: %d\n", lineCount);
}
My thinking for the if/else block is since there are only two lines of interest to this function, and they're both at the head of the file, just scan each line and test if the string matches. If it does, then the non-null conditional is run, otherwise the other conditional is executed. However, in this case, the strstr function is getting skipped.
Extra Info
Some of the comments made me go back and double check.
CLINPUT is defined to be 100, or roughly 40% again the number of characters to read from each line.
This is the output from ddd when ptr= strstr(curLine, "attrib"); is called:
0xb7eeaff0 in strstr () from /lib/libc.so.6
Single stepping until exit from function strstr,
which has no line number information.
Once this happens, the line indicator disappears, and single stepping (F5) from that point returns to the calling function.
strstr is working good. Problem is that fscanf will read next line since current already read.
Here's more correct way
for (i=0; i<2; i++){
if (fgets(curLine, CLINPUT, incoming) != NULL){
if (strstr(curLine, "attributes:")) {
sscanf(curLine, "attributes: %d", &attrCount);
} else if (strstr(curLine, "lines:")) {
sscanf(curLine, "lines: %d", &lineCount);
}
}
}

Resources