11 Replies - 9153 Views - Last Post: 03 August 2011 - 10:50 PM Rate Topic: -----

#1 riddinon24z  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 22
  • Joined: 22-July 11

Read a text file into a linked list

Posted 02 August 2011 - 06:58 PM

The text file contains this:

Quote

Fred Flintstone 38 Male
Barney Rubble 36 Male
Wilma Flintstone 37 Female
Betty Rubble 36 Female
Pebbles Flintstone 4 Female
Bam-Bam Rubble 3 Male
Dino Flintstone 2 Male
Mr. Slate 57 Male
Hoppy Rubble 1 Male
Great Gazoo 11 Unknown


There are tabs(not spaces) before and after the numbers. I have tried reading the data into a linked list two different ways. Both unsuccessful so far, obviously. Here is my code for the first method. This is the way I would like to do it because I think that it is more efficient than the second:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#define LENGTH_OF_INPUT 35

typedef int KEY_TYPE;
typedef struct
{
    char* name;
    KEY_TYPE age;
    char* gender;
}DATA;

typedef struct nodeTag
{
    DATA character;
    struct nodeTag* link;
}NODE;

NODE* buildList (NODE* pList);
bool getData (FILE* pData, DATA character);
NODE* insertNode (NODE*pList, NODE* pPre, DATA character);
void printList (NODE* pList);

int main(void)
{
    NODE* pList;

    pList = NULL;

    pList = buildList (pList);

    printList (pList);

    return 0;
}

NODE* buildList (NODE* pList)
{
    FILE* pData;
    NODE* pPre;
    DATA character;

    pPre = NULL;

    if ((pData = fopen("lab6data.txt", "r"))==NULL)
    {
        printf("Error opening text file.\n");
        exit (100);
    }

    while (getData(pData, character));
    {
        pList = insertNode (pList, pPre, character);
    }

    if (fclose(pData) == EOF )
	{
	printf("Error closing lab6data.txt\n");
	exit (300);
	}

    return pList;
}

bool getData (FILE* pData, DATA character)
{
    char input [LENGTH_OF_INPUT];
    char name [LENGTH_OF_INPUT];
    char gender [LENGTH_OF_INPUT];


    if (!feof(pData))
    {
        while (fgets(input, 34, pData))
        {
            sscanf(input, "%19[^\t]%d %[^\n]", name, &character.age, gender);

            character.name = calloc(strlen(name) + 1, sizeof(char));
            strcpy(character.name, name);

            character.gender = calloc(strlen(gender) + 1, sizeof(char));
            strcpy(character.gender, gender);
        }
        return true;
    }

    else
    {
        return false;
    }

}

NODE* insertNode (NODE*pList, NODE* pPre, DATA character)
{
    NODE* pNew;

    if (!(pNew = (NODE*)malloc(sizeof(NODE))))
    {
        printf("Memory overflow in insert\n");
        exit(200);
    }

    pNew->character = character;

    pNew->link = NULL;

        if (pList == NULL)
        {
            pList = pPre = pNew;
        }
        else
        {
            pPre->link = pNew;
            pPre = pNew;
        }
    return pList;
}

void printList (NODE* pList)
{
    NODE* pWalker;

    pWalker = pList;
    printf ("\nList contains:\n");

    while (pWalker)
    {
        printf ("%s %d %s\n", pWalker->character.name, pWalker->character.age, pWalker->character.gender);
        pWalker = pWalker->link;
    }
    printf ("<End of List>\n\n");
    return;
}


This is the code for the alternate method, but I would rather know how to use the first. Still, any tips would be appreciated for either of the two.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define LENGTH_0F_ARRAY 10
#define LENGTH_OF_INPUT 35

typedef int KEY_TYPE;
typedef struct
{
    char* name;
    KEY_TYPE age;
    char* gender;
}DATA;

typedef struct nodeTag
{
    DATA character;
    struct nodeTag* link;
}NODE;

NODE* buildList (NODE* pList);
void getData (DATA* pChar);
NODE* insertNodes(NODE* pList, NODE* pPre, NODE* pCur, DATA* pChar);
void printList (NODE* pList);

int main(void)
{
    NODE* pList;

    pList = NULL;

    pList = buildList (pList);

    printList (pList);

    return 0;
}

NODE* buildList (NODE* pList)
{
    DATA* pChar;
    NODE* pPre;
    NODE* pCur;

    pPre = NULL;
    pCur = NULL;
    pChar = calloc(LENGTH_0F_ARRAY, sizeof(DATA));

    getData(pChar);

    pList = insertNodes(pList, pPre, pCur, pChar);

    return pList;
}

void getData (DATA* pChar)
{
    FILE* pData;
    int charIndex;
    char input [LENGTH_OF_INPUT];
    char name [LENGTH_OF_INPUT];
    char gender [LENGTH_OF_INPUT];

    if ((pData = fopen("lab6data.txt", "r"))==NULL)
    {
        printf("Error opening text file.\n");
        exit (100);
    }

    charIndex = 0;
    while (charIndex<LENGTH_0F_ARRAY && fgets(input, 34, pData))
    {
        sscanf(input, "%19[^\t]%d %[^\n]", name, &pChar[charIndex].age, gender);

        pChar[charIndex].name = calloc(strlen(name) + 1, sizeof(char));
        strcpy(pChar[charIndex].name, name);

        pChar[charIndex].gender = calloc(strlen(gender) + 1, sizeof(char));
        strcpy(pChar[charIndex].gender, gender);

        charIndex++;
    }

    if (fclose(pData) == EOF )
	{
	printf("Error closing lab6data.txt\n");
	exit (200);
	}

	return;

}

NODE* insertNodes(NODE* pList, NODE* pPre, NODE* pCur, DATA* pChar)
{
    int charIndex;
    NODE* pNew;

    if (!(pNew = (NODE*)malloc(sizeof(NODE))))
    {
        printf("Memory overflow in insert\n"),
        exit(300);
    }

    for (charIndex = 0; charIndex < LENGTH_0F_ARRAY; charIndex++)
    {
        pNew->character = pChar[charIndex];
        pNew->link = NULL;

        if (pList == NULL)
        {
            pList = pPre = pNew;
        }
        else
        {
            pPre->link = pNew;
            pPre = pNew;
        }
    }

    return pList;

}

void printList (NODE* pList)
{
    NODE* pWalker;

    pWalker = pList;
    printf ("\nList contains:\n");

    while (pWalker)
    {
        printf ("%s %d %s\n", pWalker->character.name, pWalker->character.age, pWalker->character.gender);
        pWalker = pWalker->link;
    }
    printf ("<End of List>\n\n");
    return;
}

This post has been edited by riddinon24z: 02 August 2011 - 07:13 PM


Is This A Good Question/Topic? 0
  • +

Replies To: Read a text file into a linked list

#2 jimblumberg  Icon User is online

  • member icon


Reputation: 3989
  • View blog
  • Posts: 12,308
  • Joined: 25-December 09

Re: Read a text file into a linked list

Posted 02 August 2011 - 07:38 PM

Does this code compile without errors? If not post the complete error messages exactly as they appear in your development environment.

In the following snippet:
typedef struct
{
    char* name;
    KEY_TYPE age;
    char* gender;
}DATA;


Why are you using pointers instead of arrays? You have defined #define LENGTH_OF_INPUT 35 so why not use char name[LENGTH_OF_INPUT];?

If the program runs have you checked to see if you are parsing the input correctly? Does your structure match the file data?

Jim
Was This Post Helpful? 0
  • +
  • -

#3 riddinon24z  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 22
  • Joined: 22-July 11

Re: Read a text file into a linked list

Posted 02 August 2011 - 07:46 PM

The compiler I am using is codeblocks. I am not getting any errors or warnings for either of the two methods. The output for the first is a line of basically "garbage" and the second one prints the last line of the text file over and over again.

I have actually used the code in the past and when I print the contents of the structure for the second method, it matches the data in the file. Oh and the reason I am using dynamic memory allocation for the name and gender is because my teacher told us to do so.
Was This Post Helpful? 0
  • +
  • -

#4 riddinon24z  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 22
  • Joined: 22-July 11

Re: Read a text file into a linked list

Posted 02 August 2011 - 08:14 PM

I'm just thinking out loud. What I'm trying to do is read one line of data from the text file into a node. Then insert that node into my list and put that entire process into a loop until all lines are read. Do I have the right idea, looking at my code from method 1?

This post has been edited by riddinon24z: 02 August 2011 - 08:15 PM

Was This Post Helpful? 0
  • +
  • -

#5 jimblumberg  Icon User is online

  • member icon


Reputation: 3989
  • View blog
  • Posts: 12,308
  • Joined: 25-December 09

Re: Read a text file into a linked list

Posted 02 August 2011 - 08:46 PM

Quote

I'm just thinking out loud. What I'm trying to do is read one line of data from the text file into a node. Then insert that node into my list and put that entire process into a loop until all lines are read.


That sounds like a good plan. You might want to insure that you are reading the file properly. You can do this by printing out each item to the screen and place some kind of delimiter between the fields so you can tell if each item is reading correctly.

Jim
Was This Post Helpful? 0
  • +
  • -

#6 riddinon24z  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 22
  • Joined: 22-July 11

Re: Read a text file into a linked list

Posted 02 August 2011 - 08:56 PM

Ok. Here's what I came up with. I changed the type of the getData function from bool to void. Don't know whether or not that was a good idea. I took the fgets function from getData and put it into the while loop of the buildList function. I also put a printf statement to print each line of data each time the getData function runs. Sorry if I worded that incorrectly. When I execute, the print statement prints the last line in the text data. I don't understand why it doesn't start with the first line and just jumps to the last. As for my linked list output, it's just "garbage" basically. Right now I'm just worrying about reading the first line of data into a node. I also allocated the memory for the data in each incoming node. I'm not getting any errors or warnings. I don't really have a question. I don't know what to think.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define LENGTH_OF_INPUT 35

typedef int KEY_TYPE;
typedef struct
{
    char* name;
    KEY_TYPE age;
    char* gender;
}DATA;

typedef struct nodeTag
{
    DATA character;
    struct nodeTag* link;
}NODE;

NODE* buildList (NODE* pList);
void getData (FILE* pData, DATA line, char input []);
NODE* insertNode (NODE*pList, NODE* pPre, DATA line);
void printList (NODE* pList);

int main(void)
{
    NODE* pList;

    pList = NULL;

    pList = buildList (pList);

    printList (pList);

    return 0;
}

NODE* buildList (NODE* pList)
{
    char input [LENGTH_OF_INPUT];
    FILE* pData;
    NODE* pPre;
    DATA line;

    pPre = NULL;

    if ((pData = fopen("lab6data.txt", "r"))==NULL)
    {
        printf("Error opening text file.\n");
        exit (100);
    }

    while (fgets(input, 34, pData));
    {
        getData(pData, line, input);
        pList = insertNode (pList, pPre, line);
    }

    if (fclose(pData) == EOF )
	{
	printf("Error closing lab6data.txt\n");
	exit (300);
	}

    return pList;
}

void getData (FILE* pData, DATA line, char input [])
{
    char name [LENGTH_OF_INPUT];
    char gender [LENGTH_OF_INPUT];

    sscanf(input, "%19[^\t]%d %[^\n]", name, &line.age, gender);

    line.name = calloc(strlen(name) + 1, sizeof(char));
    strcpy(line.name, name);

    line.gender = calloc(strlen(gender) + 1, sizeof(char));
    strcpy(line.gender, gender);

    printf("%s %d %s", line.name, line.age, line.gender);


    return;
}

NODE* insertNode (NODE*pList, NODE* pPre, DATA line)
{
    NODE* pNew;

    if (!(pNew = (NODE*)malloc(sizeof(NODE))))
    {
        printf("Memory overflow in insert\n");
        exit(200);
    }

    pNew->character.name = calloc(strlen(line.name) + 1, sizeof(char));
    pNew->character.gender = calloc(strlen(line.gender) + 1, sizeof(char));

    pNew->character = line;
    pNew->link = NULL;

    if (pPre == NULL)
    {
        pNew->link = NULL;

        if (pList == NULL)
        {
            pList = pPre = pNew;
        }
        else
        {
            pPre->link = pNew;
            pPre = pNew;
        }
    }

    return pList;
}

void printList (NODE* pList)
{
    NODE* pWalker;

    pWalker = pList;
    printf ("\nList contains:\n");

    while (pWalker)
    {
        printf ("%s %d %s\n", pWalker->character.name, pWalker->character.age, pWalker->character.gender);
        pWalker = pWalker->link;
    }
    printf ("<End of List>\n\n");
    return;
}


This post has been edited by riddinon24z: 02 August 2011 - 08:57 PM

Was This Post Helpful? 0
  • +
  • -

#7 jimblumberg  Icon User is online

  • member icon


Reputation: 3989
  • View blog
  • Posts: 12,308
  • Joined: 25-December 09

Re: Read a text file into a linked list

Posted 02 August 2011 - 09:14 PM

I would change line 82 from:
printf("%s %d %s", line.name, line.age, line.gender);
To:
printf("~%s~%d~%s~", line.name, line.age, line.gender);
And make sure that you are reading the lines correctly in the function.

Also this snippet has a couple of problems:
    while (fgets(input, 34, pData));
    {
        getData(pData, line, input);
        pList = insertNode (pList, pPre, line);
    }


How have you defined the getData function?
void getData (FILE* pData, DATA line, char input []);

You are passing the structure into the function by value, that means that any changes made in the function are lost when you return from the function. You probably should be passing the function a pointer to the structure.

You first need to insure that you are reading the file correctly.

Jim
Was This Post Helpful? 1
  • +
  • -

#8 riddinon24z  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 22
  • Joined: 22-July 11

Re: Read a text file into a linked list

Posted 02 August 2011 - 09:31 PM

Oh I guess I kinda forgot c programming 101. So that means my insertNode function will also be affected by your advice. I changed the type of the getData function again but this time to my structure type DATA. My output is now this:

Quote

Great Gazoo 11 Unknown
List contains:
Great Gazoo 11 Unknown
<End of List>

Process returned 0 (0x0) execution time : 0.151 s
Press any key to continue.


Why does it jump to the last line? Might it help if I changed the type of getData back to bool like my original way? I'll try it.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define LENGTH_OF_INPUT 35

typedef int KEY_TYPE;
typedef struct
{
    char* name;
    KEY_TYPE age;
    char* gender;
}DATA;

typedef struct nodeTag
{
    DATA character;
    struct nodeTag* link;
}NODE;

NODE* buildList (NODE* pList);
DATA getData (FILE* pData, DATA line, char input []);
NODE* insertNode (NODE* pList, NODE** pPre, DATA line);
void printList (NODE* pList);

int main(void)
{
    NODE* pList;

    pList = NULL;

    pList = buildList (pList);

    printList (pList);

    return 0;
}

NODE* buildList (NODE* pList)
{
    char input [LENGTH_OF_INPUT];
    FILE* pData;
    NODE* pPre;
    DATA line;

    pPre = NULL;

    if ((pData = fopen("lab6data.txt", "r"))==NULL)
    {
        printf("Error opening text file.\n");
        exit (100);
    }

    while (fgets(input, 34, pData));
    {
        line = getData(pData, line, input);
        printf("%s %d %s", line.name, line.age, line.gender);
        pList = insertNode (pList, &pPre, line);
    }

    if (fclose(pData) == EOF )
	{
	printf("Error closing lab6data.txt\n");
	exit (300);
	}

    return pList;
}

DATA getData (FILE* pData, DATA line, char input [])
{
    char name [LENGTH_OF_INPUT];
    char gender [LENGTH_OF_INPUT];

    sscanf(input, "%19[^\t]%d %[^\n]", name, &line.age, gender);

    line.name = calloc(strlen(name) + 1, sizeof(char));
    strcpy(line.name, name);

    line.gender = calloc(strlen(gender) + 1, sizeof(char));
    strcpy(line.gender, gender);

    return line;
}

NODE* insertNode (NODE* pList, NODE** pPre, DATA line)
{
    NODE* pNew;

    if (!(pNew = (NODE*)malloc(sizeof(NODE))))
    {
        printf("Memory overflow in insert\n");
        exit(200);
    }

    pNew->character.name = calloc(strlen(line.name) + 1, sizeof(char));
    pNew->character.gender = calloc(strlen(line.gender) + 1, sizeof(char));

    pNew->character = line;
    pNew->link = NULL;

    if (pList == NULL)
    {
        pList = (*pPre) = pNew;
    }
    else
    {
        (*pPre)->link = pNew;
        (*pPre) = pNew;
    }

    return pList;
}

void printList (NODE* pList)
{
    NODE* pWalker;

    pWalker = pList;
    printf ("\nList contains:\n");

    while (pWalker)
    {
        printf ("%s %d %s\n", pWalker->character.name, pWalker->character.age, pWalker->character.gender);
        pWalker = pWalker->link;
    }
    printf ("<End of List>\n");
    return;
}


This post has been edited by riddinon24z: 02 August 2011 - 09:48 PM

Was This Post Helpful? 0
  • +
  • -

#9 riddinon24z  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 22
  • Joined: 22-July 11

Re: Read a text file into a linked list

Posted 03 August 2011 - 06:22 PM

View Postriddinon24z, on 03 August 2011 - 03:14 AM, said:

I'm just thinking out loud. What I'm trying to do is read one line of data from the text file into a node. Then insert that node into my list and put that entire process into a loop until all lines are read. Do I have the right idea, looking at my code from method 1?


If instead I tried to insert the nodes in numerical order based on the age, which would be new->.character.age, is it illogical or incorrect for me to have my if statement the opposite of my while loop statement for checking the values?

NODE* getDataAndInsert (FILE* pData)
{
    NODE* pList;
    DATA line;
    char input [LENGTH_OF_INPUT];
    char name [LENGTH_OF_INPUT];
    char gender [LENGTH_OF_INPUT];

    pList = NULL;

    while (fgets(input, 34, pData))
    {
        sscanf(input, "%19[^\t]%d %[^\n]", name, &line.age, gender);

        line.name = calloc(strlen(name) + 1, sizeof(char));
        strcpy(line.name, name);

        line.gender = calloc(strlen(gender) + 1, sizeof(char));
        strcpy(line.gender, gender);

        pList = insertNode (pList, line);
    }

    return pList;
}

NODE* insertNode (NODE* pList, DATA line)
{
    NODE* pNew;
    NODE* pPre;
    NODE* pCur;

    if (!(pNew = (NODE*)malloc(sizeof(NODE))))
    {
        printf("Memory overflow in insert\n");
        exit(200);
    }

    pNew->character.name = calloc(strlen(line.name) + 1, sizeof(char));
    pNew->character.gender = calloc(strlen(line.gender) + 1, sizeof(char));
    pNew->character = line;

    pPre = NULL;
    pCur = pList;

	printf("%d\n", pNew->character.age);

    while ((pNew->character.age > pPre->character.age) && (pCur->link != NULL))
    {
        traverse (&pPre, &pCur);
    }

    if (pNew->character.age <= pPre->character.age)
    {
        pNew->link = pPre->link;
        pPre->link = pNew;
    }

    else if (pCur == NULL)
    {
        pNew->link = NULL;
        pList = pNew;
    }

    return pList;
}

void traverse (NODE** pPre, NODE** pCur)
{
    *pPre = (*pCur);
    *pCur = (*pCur)->link;

    return;
}


Was This Post Helpful? 0
  • +
  • -

#10 riddinon24z  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 22
  • Joined: 22-July 11

Re: Read a text file into a linked list

Posted 03 August 2011 - 06:39 PM

I changed a portion of the insertNode function. Am I not accounting for every situation?
while ((pNew->character.age < pPre->character.age) && (pCur->link != NULL))
    {
        traverse (&pPre, &pCur);
    }

    if (pNew->character.age >= pPre->character.age)
    {
        pNew->link = pPre->link;
        pPre->link = pNew;
    }

    else if (pCur->link == NULL)
    {
        pNew->link = pCur->link;
        pPre->link = pNew;
    }

    else if (pList == NULL)
    {
        pNew->link = NULL;
        pList = pNew;
    }

    else
    {
        ;
    }

    return pList;

This post has been edited by riddinon24z: 03 August 2011 - 06:55 PM

Was This Post Helpful? 0
  • +
  • -

#11 riddinon24z  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 22
  • Joined: 22-July 11

Re: Read a text file into a linked list

Posted 03 August 2011 - 07:46 PM

I keep coming back to something like this:

pPre = NULL;
    pCur = pList;

	printf("%d\n", pNew->character.age);

    while ((pNew->character.age < pPre->character.age) && (pCur->link != NULL))
    {
        traverse (&pPre, &pCur);
    }

    if (pNew->character.age > pPre->character.age)
    {
        pNew->link = pPre->link;
        pPre->link = pNew;
    }

    else if (pPre == NULL)
    {
        pNew->link = pList;
        pList = pNew;
    }

    else if (pCur->link == NULL)
    {
        pNew->link = pCur->link;
        pCur->link = pNew;
    }

    else
    {
        ;
    }

    return pList;



The first part of the if statement inserts in the middle of the list. The second part inserts to an empty list or before the first node. And the third part inserts at the end. Or at least that's the goal.
Was This Post Helpful? 0
  • +
  • -

#12 riddinon24z  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 22
  • Joined: 22-July 11

Re: Read a text file into a linked list

Posted 03 August 2011 - 10:50 PM

Am I making this way more complicated than it should be? Would it help if I initialized pPre and pCur to something else and go from there instead of this?

pPre = NULL;
    pCur = pList;

	printf("%d\n", pNew->character.age);

    while ((pNew->character.age > pCur->character.age) && (pCur != NULL) && (pList != NULL))
    {
        traverse (&pPre, &pCur);
    }

    if ((pPre == NULL) || (pList == NULL))
    {
        pNew->link = pList;
        pList = pNew;
    }

    else if ((pPre != NULL) && (pNew->character.age > pPre->character.age))
    {
        pNew->link = pPre->link;
        pPre->link = pNew;
    }

    else if (pCur == NULL)
    
    {
        pNew->link = pCur->link;
        pCur->link = pNew;
    }

    else
    {
        ;
    }

    pPre = NULL;
    pCur = NULL;

    return;

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1