Penhzull
Penhzull

Reputation: 25

Reading from file into linked list in C

I have to read from a text file which has a format :

TRMMMYQ128F932D901-SEP-SOQMMHC12AB0180CB8<SEP>Faster Pussy cat-SEP-Silent Night

This is my code for writing into linked list and then printing it:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma warning(disable:4996)

typedef struct song {
char *id;
char *songId;
char *artist;
char *title;
struct song *nextSong;
} song;

char *strdup(const char *c)
{
char *dup = malloc(strlen(c) + 1);

if (dup != NULL)
    strcpy(dup, c);

return dup;
}

int main()
{
FILE *fp;
char line[400];
char *item;

song *root = NULL;
song *current = NULL;

int i = 0;

fp = fopen("C:\\Users\\DelicAnte\\Desktop\\unique_tracks.txt", "r");

if (!fp) {
    fprintf(stderr, "Cannot be opened");
}
printf("starting");
while (fgets(line, sizeof(line), fp)) {

    if (root == NULL) {

        root = malloc(sizeof(song));
        /*root->id = strtok(line, "<SEP>");
        root->songId = strtok(NULL, "<SEP>");
        root->artist = strtok(NULL, "<SEP>");
        root->title = strtok(NULL, "<SEP>");*/

        item = strtok(line, "<SEP>");
        root->id = strdup(item);

        item = strtok(NULL, "<SEP>");
        root->songId = strdup(item);

        item = strtok(NULL, "<SEP>");
        root->artist = strdup(item);

        item = strtok(NULL, "\n");
        root->title = strdup(item);

        root->nextSong = NULL;

    }
    else {

        current = root;
        if (current != NULL) {
            while (current->nextSong != NULL) {
                current = current->nextSong;
            }
        }
        /*current = malloc(sizeof(song));
        current->id = strtok(line, "<SEP>");
        current->songId = strtok(NULL, "<SEP>");
        current->artist = strtok(NULL, "<SEP>");
        current->title = strtok(NULL, "<SEP>");*/


        current->nextSong = malloc(sizeof(song));
        current = current->nextSong;

        item = strtok(line, "<SEP>");
        current->id = strdup(item);
        //current->id = malloc(strlen(item) + 1);
        //strcpy(current->id, item);

        item = strtok(NULL, "<SEP>");
        current->songId = strdup(item);
        //current->songId = malloc(strlen(item) + 1);
        //strcpy(current->songId, item);

        item = strtok(NULL, "<SEP>");
        current->artist = strdup(item);
        //current->artist = malloc(strlen(item) + 1);
        //strcpy(current->artist, item);

        item = strtok(NULL, "\n");
        current->title = strdup(item);
        //current->title = malloc(strlen(item) + 1);
        //strcpy(current->title, item);

        current->nextSong = NULL;

        printf("%d\n", i);
        i++;

    }

}

fclose(fp);

current = root;

if (current != NULL) {
    while (current->nextSong != NULL) {
        printf("%s %s\n", current->artist, current->title);
        current = current->nextSong;
    }
    printf("%s %s %s %s\n", current->id, current->songId, current->artist, current->title);
}
else {
    printf("NULA JE");
}


system("pause");
return 0;
}

But I get really wierd output of incomplete strings.

Upvotes: 1

Views: 2071

Answers (1)

Barmak Shemirani
Barmak Shemirani

Reputation: 31599

strtok(line, "<SEP>"); will look for character delimiters which include <, S, E, P, >

Use strstr if you need to search for "<SEP>" string

Otherwise change the delimiter to ; and define the data as follows:

TRMMMYQ128F932D901;SOQMMHC12AB0180CB8;Faster Pussy cat;Silent Night

Your linked list is repeating the same code. You can simplify as follows and add error handling:

char *sep = ";";
while(fgets(line, sizeof(line), fp)) 
{
    current = malloc(sizeof(song));
    current->nextSong = NULL;

    item = strtok(line, sep);
    if(!item) break;
    current->id = strdup(item);
    item = strtok(NULL, sep);
    if(!item) break;
    current->songId = strdup(item);
    item = strtok(NULL, sep);
    if(!item) break;
    current->artist = strdup(item);
    item = strtok(NULL, sep);
    if(!item) break;
    current->title = strdup(item);

    if(root)
        current->nextSong = root;
    root = current;
}
fclose(fp);

In addition, when printing the code walk through the list and print every valid element as follows:

if(root) 
{
    current = root;
    while(current != NULL)
    {
        printf("%s %s %s %s\n", 
          current->id, current->songId, current->artist, current->title);
        current = current->nextSong;
    }
}

This code does not free any of the memory allocated. You can do that for the next step.

Upvotes: 1

Related Questions