Problem while opening a file in C on linux - c
I'm having problems with my C program which works perfectly on Windows but not on Linux. I use the following method for reading line by line a file:
char * getLineOfAnySize(FILE* fp, size_t typicalSize, int *endOfLineDetected,size_t *nrOfCharRead){
char *line; // buffer for our string
int ch; // we will read line character by character
size_t len = 0; // number of characters read (character counter)
size_t lineSize = typicalSize; // initial size of the buffer allocated for the line
*nrOfCharRead = 0;
if(!fp) return NULL; // protection
// allocating the buffer
line = realloc(NULL, sizeof(char)*lineSize); // expected size of the line is pathHead to typicalSize
if (!line) return line; // protection, if we fail to allocate the memory we will return NULL
while (1) { // loop forever
ch = fgetc(fp); // getting character by character from file
if (ch == '\n') break; // end of line detected - breaking the loop
if( ch == EOF) {
*endOfLineDetected = 1;
break; // end of file detected - breaking the loop
}
line[len++] = ch; // store the character in the line buffer, increase character counter
if (len == lineSize){ // we reached the end of line buffer (no more room)
lineSize = lineSize + 64; // we have to increase the line size
line = realloc(line, sizeof(char)*(lineSize)); // line buffer has new size now
if (!line) return line; // if we fail to allocate memory we will return NULL
}
if( (len == 0) && *endOfLineDetected){ // empty file
*endOfLineDetected = 1;
break;
}
}
line[len++] ='\0'; // ending the string (notice there is no '\n' in the string)
*nrOfCharRead = len;
return line; // return the string
}
The workflow of my program is the following: I gave in input a path, the file correspondent to the path contains in each line others file path that I read with the function above and put into a structure. On each i apply the KMP algorithm to get the occurrences of a string.
The problem comes in my program when I try to open the files that correspond to the paths I saved earlier:
FILE *fp = NULL;
fp = fopen(list->path, "r");
if(fp == NULL){
fprintf(stderr, "Cannot open %s, exiting. . .\n", list->path);
exit(1);
}
On the screen is displayed:
, exiting ...
This is so weird because of file opening problem the output should be:
Cannot open "list->path content", exiting. . .
Even though I don't know why it gives me this error while opening the path read from the input file. During compiling there's no problem. I was thinking about buffer problems derived by the function "getLineOfAnySize. I'm not a Linux user, I was just trying to run the program in order to make sure it will run on both OS. Don't think about design issues or logical issues because on Windows everything works perfectly. Big up to everyone who will help me! Please ask further information about the code if needed.
EDIT:
The content of the input file is:
/home/xxx/Scrivania/find/try
/home/xxx/Scrivania/find/try1
Note that find is the directory of the project.
The following is a sample of my program in order to make more sense of variable and construct:
foo.c :
#include "foo.h"
FILE *fInput = NULL;
FILE *fp = NULL;
char *line1;
char *line2;
int endOfLineDetected = 0;
size_t nrOfCharRead = 0;
char ch;
fWord *w = NULL;
fWord *wordHead = NULL;
fWord *wordTail = NULL;
fList *list = NULL;
fList *listHead = NULL;
fList *listTail = NULL;
fPath *pathHead = NULL;
fPath *pathTail = NULL;
fPosition *positionHead = NULL;
fPosition *head = NULL;
fPosition *current = NULL;
char * getLineOfAnySize(FILE* fp, size_t typicalSize, int *endOfLineDetected,size_t *nrOfCharRead);
int main(int argc, char *argv[]){
fInput = fopen(argv[1], "r"); //the file that contains the path of the file in which search.
if(fInput == NULL){
fprintf(stderr, "Cannot open %s, exiting. . .\n", argv[1]);
exit(1);
}
while(!endOfLineDetected){ //read line by line the input file in order to save the path in a structure
line1 = getLineOfAnySize(fInput,128,&endOfLineDetected,&nrOfCharRead);
fList *node = malloc (sizeof(fList));
node->path = line1;
node->next = NULL;
if(listHead == NULL){
listHead = listTail = node;
}else{
listTail = listTail->next = node;
}
}
list = listHead;
fclose(fInput);
do{
fWord *app = malloc(sizeof(fWord));
printf("Insert the word to search: ");
scanf("%s", app->word);
app->totalOccurences = 0;
app->p = NULL;
app->next = NULL;
if(wordHead == NULL){
wordTail = wordHead = app;
}else{
wordTail = wordTail->next = app;
}
printf("Do you want to insert another word? (Y/N): ");
scanf(" %c", &ch);
}while(ch == 'y' || ch == 'Y');
w = wordHead;
while(w != NULL){
while(list != NULL){
w->p = malloc(sizeof(fPath));
w->p->fileOccurrences = 0;
w->p->path = list->path;
w->p->position = NULL;
w->p->next = NULL;
if(pathHead == NULL){
pathTail = pathHead = w->p;
}else{
pathTail = pathTail->next = w->p;
}
fp = fopen(w->p->path, "r");
if(fp == NULL){
fprintf(stderr, "Cannot open %s, exiting. . .\n", w->p->path);
exit(1);
}
int countLine = 0;
endOfLineDetected = 0;
while(!endOfLineDetected){
line2 = getLineOfAnySize(fp,128,&endOfLineDetected,&nrOfCharRead);
int n = strlen(line2);
int m = strlen(w->word);
w->p->fileOccurrences = w->p->fileOccurrences + KMP(line2, w->word, n, m, countLine, w->p);
countLine = countLine + 1;
}
w->totalOccurences = w->totalOccurences + w->p->fileOccurrences;
w->p->position = getHead();
w->p = w->p->next;
list = list->next;
fclose(fp);
}
w->p = pathHead;
list = listHead;
w = w->next;
pathHead = NULL;
}
w = wordHead;
while(w != NULL){
printf("WORD %s \r\n", w->word);
printf("TOTAL %d \r\n", w->totalOccurences);
pathHead = w->p;
while(w->p != NULL){
printf("FILE %s \r\n", w->p->path);
printf("OCCURENCES %d \r\n", w->p->fileOccurrences);
positionHead = w->p->position;
while (w->p->position != NULL){
printf("%d %d\r\n", w->p->position->line, w->p->position->character);
w->p->position = w->p->position->next;
}
w->p->position = positionHead;
w->p = w->p->next;
}
w->p = pathHead;
w = w->next;
}
w = wordHead;
printf("\r\n");
freeMemory();
freeKMP();
return 0;
}
char * getLineOfAnySize(FILE* fp, size_t typicalSize, int
*endOfLineDetected,size_t *nrOfCharRead){
char *line; // buffer for our string
int ch; // we will read line character by character
size_t len = 0; // number of characters read (character counter)
size_t lineSize = typicalSize; // initial size of the buffer allocated for the line
*nrOfCharRead = 0;
if(!fp) return NULL; // protection
// allocating the buffer
line = realloc(NULL, sizeof(char)*lineSize); // expected size of the line is pathHead to typicalSize
if (!line) return line; // protection, if we fail to allocate the memory we will return NULL
while (1) { // loop forever
ch = fgetc(fp); // getting character by character from file
if (ch == '\n') break; // end of line detected - breaking the loop
if( ch == EOF) {
*endOfLineDetected = 1;
break; // end of file detected - breaking the loop
}
line[len++] = ch; // store the character in the line buffer, increase character counter
if (len == lineSize){ // we reached the end of line buffer (no more room)
lineSize = lineSize + 64; // we have to increase the line size
line = realloc(line, sizeof(char)*(lineSize)); // line buffer has new size now
if (!line) return line; // if we fail to allocate memory we will return NULL
}
if( (len == 0) && *endOfLineDetected){ // empty file
*endOfLineDetected = 1;
break;
}
}
line[len++] ='\0'; // ending the string (notice there is no '\n' in the string)
*nrOfCharRead = len;
return line; // return the string
}
// Function to implement KMP algorithm
int KMP(const char* X, const char* Y, int m, int n, int line, fPath *app){
int count = 0;
// next[i] stores the index of next best partial match
int next[n + 1];
for (int i = 0; i < n + 1; i++)
next[i] = 0;
for (int i = 1; i < n; i++){
int j = next[i + 1];
while (j > 0 && Y[j] != Y[i])
j = next[j];
if (j > 0 || Y[j] == Y[i])
next[i + 1] = j + 1;
}
for (int i = 0, j = 0; i < m; i++){
if(X[i] == Y[j]){
if (++j == n){
count = count + 1; //conta le occorrenze della parola nella riga in input
fPosition *node = malloc (sizeof(fPosition));
node->line = line;
node->character = i - j + 1;
node->next = NULL;
if(head == NULL){
current = head = node;
}else{
current = current->next = node;
}
app->position = current;
}
}
else if (j > 0) {
j = next[j];
i--; // since i will be incremented in next iteration
}
}
return count;
}
fPosition * getHead(){ //rimette il puntatore alla testa della lista
fPosition *app = head;
head = NULL;
return app;
}
void freeKMP(){
free(head);
free(current);
}
void freeMemory(){
list = listHead;
fList *tempL = NULL;
while(list != NULL){
tempL = list;
list = list->next;
free(tempL);
}
w = wordHead;
fWord *tempW = NULL;
fPath *tempP = NULL;
fPosition *tempO = NULL;
while(w != NULL){
while(w->p != NULL){
while(w->p->position != NULL){
tempO = w->p->position;
w->p->position = w->p->position->next;
free(tempO);
}
tempP = w->p;
w->p = w->p->next;
free(tempP);
}
tempW = w;
w = w->next;
free(tempW);
}
free(w);
free(line1);
free(line2);
free(wordHead);
free(wordTail);
free(listHead);
free(listTail);
free(pathHead);
free(pathTail);
free(positionHead);
}
foo.h:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct fileList{
char *path;
struct fileList *next;
};
struct filePath{
char *path;
int fileOccurrences;
struct OccurrencesPosition *position;
struct filePath *next;
};
struct fileWord{
char word[50];
int totalOccurences;
struct filePath *p;
struct fileWord *next;
};
struct OccurrencesPosition{
int line;
int character;
struct OccurrencesPosition *next;
};
typedef struct filePath fPath;
typedef struct fileWord fWord;
typedef struct OccurrencesPosition fPosition;
typedef struct fileList fList;
fPosition * getHead();
int KMP(const char* X, const char* Y, int m, int n, int line, fPath *app);
void freeMemory();
void freeKMP();
Maybe also the way I free memory isn't correct.
This is not a full answer, but a hint for further analysis.
I tested the program with the input file contents as shown in the question and entered one or two words.
If the first file does not exist, I get an error message as expected:
Cannot open /home/yuripaoloni/Scrivania/find/try, exiting. . .
Then I modified the input file to list two files that exist on my system and get an error message
Cannot open , exiting. . .
I extended the code that tries to open the file to get more output:
fp = fopen(w->p->path, "r");
if(fp == NULL){
fprintf(stderr, "Cannot open %s, exiting. . .\n", w->p->path);
perror("fopen");
exit(1);
} else {
printf("Successfully opened %s\n", w->p->path);
}
This prints
$ ./foo input
Insert the word to search: foo
Do you want to insert another word? (Y/N): y
Insert the word to search: bar
Do you want to insert another word? (Y/N): y
Insert the word to search: baz
Do you want to insert another word? (Y/N): n
Successfully opened /home/username/tmp/try
Successfully opened /home/username/tmp/try1
Cannot open , exiting. . .
fopen: No such file or directory
Apparently your program tries to open a third file after the existing file names. w->p->path might be a NULL pointer or may point to an empty string.
The same error occurs when I enter only one word. I did not further analyze the error.
To find out why your program tries to open a file with an empty name, you can run it in a debugger or add more output to see how many loop cycles are executed when processing the lists and which data you find.
Related
Read txt file to linked list C
i tried to save my linked list to txt file and load it later . its for a movie editor project. the nodes: // Frame struct typedef struct Frame { char* name; unsigned int duration; char* path; } Frame; // Link (node) struct typedef struct FrameNode { Frame* frame; struct FrameNode* next; } FrameNode; and i saved it in this way: path duration name path duration name path duration name path duration name ... \n between the data. this is my function: FrameNode* loadVideo() { FrameNode* head = NULL; FrameNode* newNodeFrame = NULL; FrameNode* newFrame = NULL; FILE* f = NULL; char pathP[STR_LEN] = ""; char file[1024] = { 0 }; char c; char path[1000] = ""; char name[1000] = ""; char duration[STR_LEN] = ""; int i = 0; int j = 0; printf("Enter the path of file to load: ( .txt)\n"); myFgets(pathP); f = fopen(pathP, "r"); if (f == NULL) { printf("Error opening file\n"); return; } while ((c = (char)fgetc(f)) != EOF) { file[i] = c; i++; } fclose(f); for (i = 0; i < strlen(file); i++) { while (file[i] != '\n') { path[j] = file[i]; i++; j++; } j = 0; i++; while (file[i] != '\n') { duration[j] = file[i]; i++; j++; } j = 0; i++; while (file[i] != '\n') { name[j] = file[i]; i++; j++; } j = 0; newFrame = craeteFrame(name, atoi(duration), path); FrameNode* newFrameNode = (FrameNode*)malloc(sizeof(FrameNode)); newFrameNode->frame = newFrame; newFrameNode->next = NULL; insertAtEnd(&head, newFrameNode); } return head; } its not perfect and it's very ugly.. someone has better option? thanks. ..if you have some changes to offer to me about the save in the file its will be good to
Use fgets() to read whole lines at a time. You would still have to deal with memory allocation to hold the contents of those line then. However, most POSIX-compliant operating systems also provide the function getline() which reads a line into a buffer it will allocate automatically for you.
C program for steganography
Relatively new to programming, been assigned to a task to create a C program to encode and decode 2 ppm images to receive a secret message. I've came up with code but its not getting past the image format if statement in the getPPM function. Any tips on what changes I could make to my code? Also in my main(), am I passing in the correct parameters? typedef struct NODE { char *val; struct NODE *next; } NODE; /* Stores the RGB values of a pixel */ typedef struct Pixel { int red; int green; int blue; } Pixel; /* Stores the contents of a PPM file */ typedef struct PPM { char *format; NODE *comments; int width, height; int max; Pixel *arr; } PPM; NODE *copy(NODE *first) { NODE *second = NULL, *previous = NULL; while (first != NULL) { NODE *temp = (NODE *)malloc(sizeof(NODE)); temp->val = first->val; temp->next = NULL; if (second == NULL) { second = temp; previous = temp; } else { previous->next = temp; previous = temp; } first = first->next; } return second; } //Copy the PPM File Returning Pointer struct PPM* createPPM(PPM *old) { PPM* new = (PPM *)malloc(sizeof(PPM)); strcpy(new->format, old->format); new->comments = copy(old->comments); new->height = old->height; new->width = old->width; new->max = old->max; new->arr = (Pixel *)malloc(old->height * old->width * sizeof(Pixel)); memcpy(new->arr, old->arr, old->height * old->width * sizeof(Pixel)); return new; } /* Returns the PPM struct from the file fd */ PPM *getPPM(FILE *fd) { PPM *image = (PPM *)malloc(sizeof(PPM)); image->format = (char *)malloc(MAX_LEN); fgets(fd, MAX_LEN, image->format); sscanf(fd, "%s", image->format); if (strcmp(image->format, "P3") != 0) { printf("Invalid Image Type"); exit(0); } char c = getc(fd); image->comments = (NODE*)malloc(sizeof(NODE)); NODE *temp = image->comments; while ((c = getc(fd)) == '#') { fseek(fd, -1, SEEK_CUR); char str[50]; fgets(str, 50, fd); temp->val = (char*)malloc(strnlen(str, 50)); strcpy(temp->val, str); temp->val[strlen(temp->val) - 1] = 0; temp->next = (NODE*)malloc(sizeof(NODE)); temp = temp->next; temp->next = NULL; } fseek(fd, -1, SEEK_CUR); fscanf(fd, "%d", &image->width); fscanf(fd, "%d", &image->height); fscanf(fd, "%d", &image->max); image->arr = (Pixel*)malloc(image->height * image->width * sizeof(Pixel)); int t = 0; int j = 0; while (j < image->height * image->width) { t = fscanf(fd, "%d", &image->arr[j].red); t = fscanf(fd, "%d", &image->arr[j].green); t = fscanf(fd, "%d", &image->arr[j].blue); j = j + 1; } return image; } PPM *loadPPMFromFile(char *filename) { FILE *file; /* TODO: step 1, open the file */ file = fopen("C:\\Users\\Olivia\\source\\repos\\f28hs-2020-21-cwk1-c\\PPMfiles", "r"); /* step 2: Check that file has been loaded correctly; show error otherwise*/ if (file != NULL) { PPM *ppm; /* ODO: step 3, get the PPM data from the file with the getPPM function */ getPPM(file); if (ppm == NULL) { /* TODO: step 4, display error if file cannot been parsed into a PPM struct*/ printf("File cannot be parsed.\n"); } /* TODO: step 5, close the file */ fclose(file); /* step 6: return the PPM */ return ppm; } else { fclose(file); return NULL; } } /* Prints a PPM struct in the format of a PPM file */ void showPPM(PPM *ppm) { printf("%s\n", ppm->format); //print format //print comments NODE *n = ppm->comments; while (n->next != NULL) { printf("%s\n", n->val); n = n->next; } //print width, height and max printf("%d %d\n%d\n", ppm->width, ppm->height, ppm->max); //print the array containing the pixels int j; for (j = 0; j < ppm->height * ppm->width; ++j) { printf("%d %d %d\n", ppm->arr[j].red, ppm->arr[j].green, ppm->arr[j].blue); } return; } /* Encodes text into red field of PPM Returns the encoded PPM */ PPM *encode(char *text, PPM *i) { PPM *str = createPPM(i); int random; srand((unsigned)time(NULL)); int randMax = (i->height * i->width) / (strlen(text) + 1); random = rand() % randMax; if (random < 1) { random = 1; } int k = 0; int j = random; //Red fields swapped with ASCII int while (k < strlen(text)) { if (str->arr[j].red == text[k]) { j = j + 1; // if the values are the same we encode in the next pixel. } else { str->arr[j].red = text[k]; k = k + 1; j = j + random; } } return str; } /* Compares 2 PPM structs and decodes the message hidden within Returns the decoded message if the images have the same dimensions Returns NULL otherwise */ char *decode(PPM *i1, PPM *i2) { int i = 0; int j = 0; char *str = (char*)malloc(sizeof(char)); while (i < i1->height * i1->width) { if (i1->arr[i].red != i2->arr[i].red) { str[j] = i2->arr[i].red; j = j + 1; } i = i + 1; } str = realloc(str, i); return str; printf("%s", str); } /* TODO: Question 3 */ int main(int argc, char *argv[]) { /* check arguments */ switch (argc) { case 2: /* TODO: not enough arguments, print an error message */ printf("Not enough arguments. \n"); break; case 3: if (strcmp(argv[1], "e") == 0) { //Argument "e" - encode PPM PPM *ppm = loadPPMFromFile(argv[2]); createPPM(ppm); /*Check that PPM is valid; continue if it is, exit otherwise */ if (ppm != NULL) { PPM *encodedPPM; /* TODO: encode the ppm with the text and assign to encodedPPM */ encodedPPM = encode(argv[2], encodedPPM); /*Check that no error occured*/ if (encodedPPM == NULL) { return EXIT_FAILURE; } else { /* TODO: print a confirmation that encoding was successful */ printf("Encoding successful. \n"); /* TODO: print the PPM to standard output with showPPM */ showPPM(encodedPPM); return EXIT_SUCCESS; } } else { return EXIT_FAILURE; } } else { printf("Unrecognised or incomplete command line.\n"); return EXIT_FAILURE; } break; case 4: if (strcmp(argv[1], "d") == 0) { //Argument "d" - decode PPM PPM *comparisonPPM; PPM *encodedPPM; /* TODO: get comparison file filename from argv, load it with loadPPMFromFile then assign to comparisonPPM */ comparisonPPM = loadPPMFromFile(argv[2]); /* TODO: get encoded file filename from argv, load it with loadPPMFromFile then assign to encodedPPM */ encodedPPM = loadPPMFromFile(argv[2]); /*Check both PPMs are valid; continue if so, exit otherwise */ if (comparisonPPM != NULL && encodedPPM != NULL) { char *decodedMsg; /* TODO: decode the encodedPPM with the comparisonPPM and assign to decodedMsg */ decodedMsg = decode(encodedPPM, comparisonPPM); /*Check that the message has been decoded*/ if (decodedMsg != NULL) { /* TODO: print a confirmation message that the message was decoded */ printf("Decoded message:\n"); /* TODO: print the decoded message */ printf("%p",decodedMsg); return EXIT_SUCCESS; } else { return EXIT_FAILURE; } } else { return EXIT_FAILURE; } } else { fprintf(stderr, "Unrecognised or incomplete command line.\n\n"); return EXIT_FAILURE; } break; default: fprintf(stderr, "Unrecognised or incomplete command line.\n\n"); return EXIT_FAILURE; } }
"Also in my main(), am I passing in the correct parameters?" Yes, they are correct. "not getting past the image format if statement in the getPPM function" There are several issues with getPPM. Overwriting c in the statements following this one: char c = getc(fd); is already covered in comments. In the following: sscanf(fd, "%s", image->format); if (strcmp(image->format, "P3") != 0) { Because sscanf() will pick up the new line if there is one, strcmp() will fail the comparison for "P3". Suggestions are to do 1 or more of the following: running in a debugger, place a break point at the if and view value of image->format place if(image->format != NULL) printf("%s", image->format) after sscanf() if you suspect \n or \r\n may be in the buffer, use image->format[strcspn(image->format, "\r\n")] = 0; to remove them. Regarding the following, suggest you read the documentation on each C function, eg fgets(): This: fgets(fd, MAX_LEN, image->format); scanf(... Should be if(fgets(image->format, MAX_LEN, fd) != NULL) { scanf(... (Argument positions changed, and test before trying to use buffer.) Aside: Because this is C, following malloc statements PPM* image = (PPM*)malloc(sizeof(PPM)); image->format = (char*)malloc(MAX_LEN); are more correctly written as PPM* image = malloc(sizeof(*image)); image->format = malloc(MAX_LEN); (Cast is removed from malloc() and note sizeof argument in the first statement. apply as applicable throughout your code.
Pre-order Fill a tree from file
I was wondering if you could help me out I'm really stuck on this code I wrote. I'm supposed to pre-order fill a tree from a file that is structured in the following way. Hello goodbye yes ' ' <- This is an actual space in the file no end of file When ever there is a space I wanna return back to the node previous and go right and return whenever it reaches EOF. So the text above would be structured in the following way hello goodbye null no right child yes no This function is supposed to fill my tree in preorder. I'm grabbing the data using my readFile function here char *readFile(FILE *fp) { int c = 0; int i = 0; size_t capacity = 10; char *arr = NULL; char* temp = NULL; arr = (char*) malloc(capacity * sizeof(char)); while (((c = fgetc(fp)) != '\n') && (c != EOF)) { if(capacity == (i+2)) { capacity *= 2 ; temp = (char*)realloc(arr,capacity * sizeof(char)); /*Assigns Address to newly allocated array*/ arr = temp; } arr[i] = c; i++; } arr[i-1] = '\0'; if(arr[0] == '\r') /* Line spaces to move up*/ { printf("Got here SPACE\n"); arr[0] = ' '; } else if(c == EOF)/*if its an end of file return*/ { printf("Got here EOF \n"); arr[0] = ' '; } return arr; } My recursive algorithm to fill the tree is called populate. I'm not really that great at recursion but I've walked though my code multiple times and can't see what's obviously wrong. Currently it seems I can only print the root. Trying to read the left or right root data gives me an immediate seg fault void populate(FILE *fp,struct node *root) { char *data = readFile(fp); if(data[0] == ' ') /*possible issues with usingn null charater? */ /*statement is true for both EOF and spaces*/ { return; } printf("Creating Node\n"); if(root == NULL) { root = createNode();/* create the current root */ root->data = data;/*assign data*/ } printf("%s\n",data); populate(fp,root->left); populate(fp,root->right); } my main int main(int argc, char *argv[]) { FILE *fp; node *root = createNode(); fp = fopen("qa.db","r+"); if(fp == NULL) { printf("File not open"); } populate(fp,root); if(root == NULL){ printf("Equal to NULL\n"); } printTree(root); /*check = checkFile(fp)*/ fclose(fp); return 0;
How do i ignore newline in .txt file in c
i am reading in from a text file and storing each element into a linked list. however when the program reaches a return char or newline the program returns an error. reading from text file and storing into structs. I notice the error when i print each struct to the screen the program prints the last struct before the return char then quits. int main(int argc, const char * argv[]) { printf("Hello!\n"); char filename[] = "artist.txt"; print_artists(read_artists(filename)); return 0; } struct artist *read_artists(char *fname) { int maxlen = 225; int artid = 0; int altartid = 0; int pc = 0; char artname[80]; char data[maxlen]; int valid = 0; // 0 acts as true 1 acts as false int checkresult = 0; //checks result of sscanf struct artist *temphead = create_artist(0,0,0,"0"); FILE *fp = fopen(fname ,"r"); if (fp != NULL) { while (fgets(data,maxlen,fp)) { checkresult = sscanf(data,"%d\t%[^\t\n]\n",&artid,artname); if (checkresult == 2) { struct artist *b = NULL; b = create_artist(artid,altartid,pc,artname); temphead = add_artist(temphead,b); } else { printf("error checkresult = %d\n",checkresult); printf("break out of loop valid = 1\n"); valid = 1; // acts as boolean variable break; //breaks out of the while(fgets) } } fclose(fp); return (temphead); } else { fclose(fp); printf("File Error\n"); return (NULL); } } void print_artists(struct artist *head) { if (head != NULL) { struct artist *temp = head; while (temp -> next != NULL) { print_artist(temp); temp = temp -> next; } print_artist(temp); } } this is the output the text file i am reading from
When you reach the blank line before Bodenstandig, the sscanf will not match and you will exit the while loop at the "break". If sscanf does not return 2, you should check to see if the line is empty and if so skip and read the next line. Or just skip the check and ignore bad lines. The while(fgets(...) condition will become false at the end of the file, so you don't need to exit on a bad line. if (checkresult == 2) { .... } else { continue; // will go back to top while(fgets(...)) }
Read line by line into linked list
I want to put each line in a text file in a node in a linked list. I have managed to write out the text line by line, but when I try to store the line in a node, only the last line of the text is saved in all the nodes. Any idea what I'm doing wrong? #include <stdio.h> #include <stdlib.h> struct list { char *line; struct list *next; }; int main(void) { FILE *f; f = fopen("text.txt", "r"); if (f == NULL) exit("ERROR\n"); struct list n1, n2, n3, n4; struct list *pointer = &n1; n1.line = NULL; n1.next = &n2; n2.line = NULL; n2.next = &n3; n3.line = NULL; n3.next = &n4; n4.line = NULL; n4.next = 0; int nodenr = 0; int buf[50]; while(fgets(buf, sizeof(buf), f) != NULL) { printf("%s", buf); ++nodenr; if (nodenr == 1) { n1.line = buf; } else if (nodenr == 2) { n2.line = buf; } else if (nodenr == 3) { n3.line = buf; } else if (nodenr == 4) { n4.line = buf; } } while (pointer != 0) { printf("%s\n", pointer->line); pointer = pointer->next; } fclose(f); }
Your problem occurs because all your nodes' line pointer point to the buf buffer, so all will have the last line you read into it. You have to assign a copy of the buffer for each node when you read it, not the buffer pointer itself.
I maybe have a problem buf is pointer, so if you change value in fgets, then it change everywhere... But in this case there should be the last line everywhere... I am not so good in C programming, so sorry if it is bad answer