Read data from file into structure

2019-09-16 02:30发布

问题:

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;
}

回答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.



回答2:

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.



回答3:

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



标签: c file-io struct