0

I am working on a program that can process structure items in linkedlist/nodes. I have most of the functions running fine, however am stuck on how to read from a txt file into a structure (the readFromFile function). I have been reading around but am still quite confused, mainly on how to write this as a function instead of in main, and also reading into a structure

any help would be appreciated.

EDIT: I cannot seem to get the functions in the answers to work at the moment, so I am changing to trying to make the program read from txt in main. I could open the file, but the problem is: How do I read data into my linked list?

(code has been modified)

The text file I am reading from is formatted like this:


#1 Flat Blade Screwdriver
12489
36
.65
1.75
#2 Flat Blade Screwdriver
12488
24
.70
1.85
#1 Phillips Screwdriver
12456
27
0.67
1.80
#2 Phillips Screwdriver
12455
17
0.81
2.00
Claw Hammer
03448
14
3.27
4.89
Tack Hammer
03442
9
3.55
5.27
Cross Cut Saw
07224
6
6.97
8.25
Rip Saw
07228
5
6.48
7.99
6" Adjustable Wrench
06526
11
3.21
4.50

My program so far:

#include "stdafx.h"
#include <stdlib.h>

typedef struct inventory
{
    char invName[36];
    int  invPartNo;
    int  invQOH;
    float invUnitCost;
    float invPrice;
}stock;

struct  NODE
{
    union
    {
        int  nodeCounter;
        void  *dataitem;
    }item;
    struct NODE *link;
};

struct NODE *InitList();
void DisplayNode(struct inventory *);
struct inventory * ReadData(FILE *);
void DisplayList(struct NODE *);
struct NODE* GetNode(FILE *);
void  Add2List(struct NODE *, struct NODE *);
struct NODE* SearchList(struct NODE *, int );
void  DeleteNode(struct NODE *, int );


int main(int argc, char* argv[])
{
    struct NODE *header;
    header = InitList();

    char ch, file_name[25];
   FILE *fp;

   printf("Enter the name of file you wish to see\n");
   gets(file_name);

   fp = fopen(file_name,"r"); // read mode

   if( fp == NULL )
   {
      perror("Error while opening the file.\n");
      exit(EXIT_FAILURE);
   }

   printf("The contents of %s file are :\n", file_name);

   while( ( ch = fgetc(fp) ) != EOF )
   {
      //what to put here?
   }

   fclose(fp);
   DisplayList(header);



    return 0;
}

struct NODE *InitList()
{
    struct NODE *temp = (struct NODE*)malloc(sizeof NODE);

    temp->item.nodeCounter = 0;
    temp->link = NULL;
    return temp;
}


void  Add2List(struct NODE *start, struct NODE *NewNode)
{
    struct NODE *current = start;

    while (current->link != NULL)
        current = current->link;

    current->link = NewNode;
    NewNode->link = NULL;

    start->item.nodeCounter++;
}


struct NODE* GetNode(FILE *fptr)
{
    struct NODE *temp = (struct NODE*)malloc(sizeof NODE);

    temp->item.dataitem = ReadData(fptr);
    temp->link = NULL;

    return temp;
}


void DisplayList(struct NODE *start)
{
    struct NODE *current = start->link;

    while (current != NULL)
    {
        DisplayNode((struct inventory *)current->item.dataitem);
        current = current->link;

    }
}


void DisplayNode(struct inventory *stuff)
{
    /*
    char invName[36];
    int  invPartNo;
    int  invQOH;
    float invUnitCost;
    float invPrice;
    */

    printf("Name: %s", stuff->invName);
    printf("Part Number: %d", stuff->invPartNo);
    printf("Quantity on hand: %d", stuff->invQOH);
    printf("Unit Cost: %0.2f", stuff->invUnitCost);
    printf("Price %0.2f", stuff->invPrice);
}


struct inventory * ReadData(FILE *fptr)
{
    struct inventory *temp = (struct inventory *)malloc(sizeof inventory);

    if(fptr==stdin)
        printf("Enter item name: ");
    fscanf_s(fptr, "%s", temp->invName);
    if(fptr==stdin)
        printf("Enter item part number: ");
    fscanf_s(fptr, "%d", &temp->invPartNo);
    if(fptr==stdin)
        printf("Enter item quantity on hand: ");
    fscanf_s(fptr, "%d", &temp->invQOH);
    if(fptr==stdin)
        printf("Enter item unit cost: ");
    fscanf_s(fptr, "%f", &temp->invUnitCost);
    if(fptr==stdin)
        printf("Enter item price: ");
    fscanf_s(fptr, "%f", &temp->invPrice);

    return temp;
}

struct NODE* SearchList(struct NODE *start, int oldData)
{
    struct NODE* current = start;
    struct inventory * st = (struct inventory *)current->link->item.dataitem;

    while (st->invPartNo != oldData && current != NULL)
    {
        current = current->link;
        if(current->link)
            st = (struct inventory *)current->link->item.dataitem;
    }
    return current;
}

void  DeleteNode(struct NODE *start, int oldData)
{
    struct NODE *current, *oldNode;

    current = SearchList( start, oldData);
    oldNode = current->link;
    current->link = oldNode->link;
    free(oldNode);
    start->item.nodeCounter -= 1;
}
Brian
  • 187
  • 5
  • 15
  • You should remove the InventoryItem declaration — you don't seem to use it. You should avoid messing around with `void *` in the union in the NODE type. You're going to be storing `struct inventory *`; use that type so you don't have to write as many casts. – Jonathan Leffler Apr 21 '14 at 06:41

3 Answers3

1

You can use fscanf() and fgets() to read the data as,

void readFromFile( )
{
   stock array[20];
   int i,j;
   i=0;
   fp = fopen("input.txt", "r");
   if( fp != NULL ){
      while ( !feof(fp ) ){
         fgets(array[i].invName,sizeof array[i].invName,fp);
         fscanf(fp,"%d %d %f %f ",&array[i].invPartNo,&array[i].invQOH,&array[i].invUnitCost,&array[i].invPrice);
         i++;
      }
}

The array[] will have the data and i will be number of struct data read.
Here all spaces in fscanf() are put to skip the [enter] character since the data is in different lines.
read about fscanf() with its format matching and fgets() it can help in reading files.
To avoid feof() can use,

while (fgets(array[i].invName,sizeof array[i].invName,fp)) {
  fscanf(fp,"%d %d %f %f ",&array[i].invPartNo,&array[i].invQOH,&array[i].invUnitCost,&array[i].invPrice);
         i++;   
}

for This particular file format.

LearningC
  • 3,182
  • 1
  • 12
  • 19
  • 1
    [“while( !feof( file ) )” is always wrong](http://stackoverflow.com/questions/5431941/while-feof-file-is-always-wrong) – Lee Duhem Apr 21 '14 at 06:39
  • The numeric conversions skip leading space (including newlines) anyway. The trailing space in the format is appropriate where the data is never read interactively (as here). It is wholly inappropriate in the data is ever read interactively; it demands a non-blank character (or EOF) after the fourth number. – Jonathan Leffler Apr 21 '14 at 06:44
  • it says fp is not declared so i added a FILE *fp; however, the code will not compile, as it gives me the error: fatal error C1075: end of file found before the left brace '{' at 'c:\users\brian\documents\visual studio 2010\projects\linkedlistread\linkedlistread\linkedlistread.cpp(208)' was matched Any idea how to fix this? – Brian Apr 21 '14 at 06:46
  • @LeeDuhem ok i added code to avoid `feof()`. thankyou – LearningC Apr 21 '14 at 06:52
  • My main problem is adding it to a linked list using node, else I wouldn't be able to use my other methods on the data I read in – Brian Apr 21 '14 at 07:24
  • @user3011161 then make the data filed to be of `struct inventory` type and copy the read struct to that data field – LearningC Apr 21 '14 at 08:04
1

The algorithm:

  1. Open the text file in 'text' 'read' mode.
  2. Create an array of stock structures, if you know number of items beforehand, else use a linked list with each node of type stock.
  3. To read data from file to corresponding field you can use fscanf .
  4. When you think you have finished reading data, close the file.

Notes:

  1. The file pointer is automatically incremented so you need not worry about incrementing it to read next set of data.
  2. Do not forget to close the file.
  3. To check whether the file handling functions are working fine, do check the return value of all the functions.

Important:

Since your invPartNo field in the file has integer data starting with 0, you may not want to read it as integer, otherwise it will be treated as "octal number" not a decimal number.

0xF1
  • 6,046
  • 2
  • 27
  • 50
0

Your _tmain could look like below, this code assumes that the contents in the file are complete (i.e. contains the correct number of lines):

int _tmain(int argc, _TCHAR* argv[])
{   struct NODE *header = InitList();
    if (argc > 1)
    {   FILE *f;
        if ((f = fopen(argv[1], "rt") == NULL)
        {   printf(_T("Could not open file %s\n"), argv[1]);
            return 1;
        }
        while (!feof(f))
            Add2List(header, GetNode(f));
        fclose(f);
    }
    else
    {   int  PCounter = 2;
        while (PCounter--)
            Add2List(header,GetNode(stdin));
    }

    DisplayList(header);

    return 0;
}

EDIT: Run the program from the command-prompt and pass the file name as a parameter

Edward Clements
  • 5,040
  • 2
  • 21
  • 27
  • it gives me _TCHAR* incompatible with parameter of type constant char at the f = fopen(argv[1], "rt") also, where in here would I be able to specify the text file I'd open. – Brian Apr 21 '14 at 06:57
  • It looks like you are not compiling with Unicode, so your `tmain` should look like `int main(int argc, char* argv[])`; you specify the file name as a command-line parameter at the command prompt – Edward Clements Apr 21 '14 at 07:06
  • how do I do the command-line parameter? sorry I am very new to programming – Brian Apr 21 '14 at 07:09
  • at the command prompt, enter something like `programname filename` – Edward Clements Apr 21 '14 at 07:10
  • unfortunately I cannot get this to compile properly. I have decided to just read in main for simplicity sake, but still having trouble reading into a struct to add to my list – Brian Apr 21 '14 at 07:32