Solved

problem reading all data from a text file

Posted on 2004-09-27
19
296 Views
Last Modified: 2010-05-18
Hi,
I have a code that is supposed to read all data from a text file and output it to the console.  This is the code
#include <iostream>
using std::cout;
using std::cerr;
using std::endl;
using std::cout;
#include <fstream>
using std::ifstream;
#include <string>
using std::string;
using std::getline;
#include <cstdlib>


//name of disk file for sigthings data
const char IN_FILE_NAME[] ="excursion.txt";
const int MAX_SIGHT = 100;

//sightings struct
struct Sighting
{
      int aDate;
      string aType;
      string aLocation;
      int number;
};
//function to read sightings from IN_FILE_NAME
int readSighting(Sighting sightings[]);
//display headings for Sightings functions
void displayNames(void)      ;                                                                                 

int main(void)
{
      Sighting sightings[MAX_SIGHT];
      int numSight;
      // read sightings
      numSight=readSighting(sightings);
      displayNames()      ;                                                                                 

      //output data to console
      for(int i=0; i<numSight; i++)
      {
            cout <<sightings[i].aDate<<" "
                  <<sightings[i].aType<<" "
                  <<sightings[i].aLocation<<" "
                  <<sightings[i].number<<" "<<endl;
      }
      return 0;
}
      //read sighting data from external file
      //return no of sightings

int readSighting(Sighting sightings[])
{
      ifstream inFile;
      int idx =0;
      inFile.open(IN_FILE_NAME);
      if (inFile.fail())
      {
            cerr<< "File " << IN_FILE_NAME
                  << " could not be opened" << endl;
            exit (1);
      }
      inFile>> sightings[idx].aDate
            >>sightings[idx].aType
            >>sightings[idx].aLocation
            >>sightings[idx].number;
      
      while (!inFile.eof() && !inFile.fail())
      {
            idx++;
            inFile >> sightings[idx].aDate
                  >>sightings[idx].aLocation
                  >>sightings[idx].aType
                  >>sightings[idx].number;
      }
      inFile.close();
      return idx;
}

//display headings for Sightings functions
void displayNames(void)                                                                                      
{                                                                                                                   
      cout<<"   Sightings\t\t\t\t\t\t\t"<<endl;                                      
      cout<<"   Date\t\tBird Type\tLocation  Number of Birds"<<endl;  
}                                          

and header file
                                                #ifndef CONST_H
#define CONST_H

#include <string>

using std::string;


const int MAX_SIZE = 10 ;      // Number of bird types & the number of locations
const int BIRD_SIZE = 20 ;     // For printing
const int LOCATION_SIZE = 20 ; // For printing

const int LINES_PER_PAGE = 15;  // To pause the display

const int MENU_CHOICES = 5;

// The species of birds

const string BIRD_TYPE[MAX_SIZE] = { "pelicans", "wood ducks", "black ducks", "whistling ducks",
                                                      "magpie geese", "king fishers", "water fowl", "dab chicks",
                                                      "spoon bills", "cormorants" } ;
// The locations
const string LOCATIONS[MAX_SIZE] = { "Awonga Dam", "Fairburn Dam", "Tinaroo Dam", "Ivanhoe Dam",
                                                      "Lake Victoria", "Burnett River", "Burdekin River",
                                                      "Pioneer River", "Mary River", "Fitzroy River" } ;

#endif
and text file
      27/05/2004,cormorants,Fitzroy River,70000
27/05/2004,dab chicks,Fitzroy River,12
27/05/2004,pelicans,Fitzroy River,16
29/05/2004,magpie geese,Pioneer River,44
29/05/2004,spoon bills,Pioneer River,7
29/05/2004,wood ducks,Pioneer River,29
29/05/2004,cormorants,Pioneer River,41
31/05/2004,magpie geese,Burdekin River,96
02/06/2004,wood ducks,Tinaroo Dam,30
02/06/2004,spoon bills,Tinaroo Dam,13
02/06/2004,king fishers,Tinaroo Dam,2
03/06/2004,dab chicks,Tinaroo Dam,15
08/06/2004,pelicans,Awonga Dam,26
08/06/2004,black ducks,Awonga Dam,6
15/06/2004,spoon bills,Burnett River,14
15/06/2004,water fowl,Burnett River,52
15/06/2004,dab chicks,Burnett River,16
21/06/2004,black ducks,Fairburn Dam,21
21/06/2004,wood ducks,Fairburn Dam,29
28/06/2004,cormorants,Ivanhoe Dam,27


It compiles and builds and executes but the output to the screen is not right
         Sightings
   Date         Bird Type       Location  Number of Birds
27 /05/2004,cormorants,Fitzroy River,70000 27
Press any key to continue
can anyone tell me where I am going wrong please? I realise it's something to do with the comma seperated values but how do I get it to not read the comma?

Kaz              



0
Comment
Question by:KazIT
  • 12
  • 6
19 Comments
 
LVL 55

Expert Comment

by:Jaime Olivares
Comment Utility
Take a look to the split() function in this question:
http://www.experts-exchange.com/Programming/Programming_Languages/Cplusplus/Q_20188299.html
You can use this way:

     string strLine;
     while (!inFile.eof())
     {
          idx++;

          getline(inFile,strLine,'\n');
          if(!strLine.length())
               break;
       
           list<string> tokens=split(input);

          sightings[idx].aDate = atoi(tokens[0].c_str());  // still have to make some date conversion here
          sightings[idx].aLocation = tokens[1];
          sightings[idx].aType = tokens[2];
          sightings[idx].number = atoi(tokens[3].c_str());
     }


list<string> split(string& source,char delim=',')
{
    list<std::string> tokens;
    string::iterator left=source.begin();
    string::iterator right;
    bool all_done=false;
    while (!all_done)
    {
     right=std::find(left, source.end(),delim);
     tokens.push_back(string(left,right));
     if (right==source.end()) all_done=true;
     else left=right;
     left++; // skip over deliminator
    }
    return tokens;
}
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
Hi Kaz,

maybe you should use readSighting from one of my previously posted comments:

//****************************************************************
//read a Sighting variable from a text file and return a variable
//of type Sighting
Sighting* readSighting(Sighting& sightings,ifstream& inFile)
{    
     string temp;
     sightings.aDate=fileInputDate(inFile);
     if(inFile.fail())
          return NULL;

     inFile.getline(sightings.aType,20,',');
     if(inFile.fail())
          return NULL;
     inFile.getline(sightings.aLocation,20,',');
     if(inFile.fail())
          return NULL;
     inFile>>sightings.number;
     if(inFile.fail())
          return NULL;
     std::getline(inFile, temp);
     if(inFile.fail())
          return NULL;
     
     return &sightings;
}

My output is ok with that.

Regards, Alex



0
 

Author Comment

by:KazIT
Comment Utility
Jaime, thanks for the reply.

Alex,
I have tried using that code... I have had to amend my sighting struct to string not char as per specifications.  So now I'm trying to rewrite the sighting.cpp and header file to
accomodate the change.  

Kaz
0
 

Author Comment

by:KazIT
Comment Utility
I just created a new project to practise changing it before I amend the main code.
the errors I'm getting are
Compiling...
Sighting.cpp
C:\Documents and Settings\Karen Stedman\My Documents\UNI\COIT11134\Birds\Birds\Sighting.cpp(27) : error C2664: 'class std::basic_istream<char,struct std::char_traits<char> > &__thiscall std::basic_istream<char,struct std::char_traits<char> >::getlin
e(char *,int)' : cannot convert parameter 1 from 'class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >' to 'char *'
        No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
C:\Documents and Settings\Karen Stedman\My Documents\UNI\COIT11134\Birds\Birds\Sighting.cpp(30) : error C2664: 'class std::basic_istream<char,struct std::char_traits<char> > &__thiscall std::basic_istream<char,struct std::char_traits<char> >::getlin
e(char *,int)' : cannot convert parameter 1 from 'class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >' to 'char *'
        No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
Error executing cl.exe.

Sighting.obj - 2 error(s), 0 warning(s)
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
Try the changes below. Don't forget to change prototypes in sightings.h as well.

//****************************************************************
//to read a Date in the format dd/mm/yyyy from a txt file
//and return a variable of type int

int fileInputDate(ifstream& inFile)
{
     string strDate;
     
     Date tempDate;
         
     tempDate.day=01;
     tempDate.month=01;
     tempDate.year=2004;
     int count=0;
     int temp=0;
     
     while(count!=3)
     {
          int i=0;
          int multiple=1;
          if(count<=1)
          {
              std::getline(inFile,strDate,'/');
          }
          else
          {
               std::getline(inFile,strDate,',');
          }
          char ch;
          int length=strDate.length();
          int strLength=(strDate.length()) -1;
          while(i!=(length/2))
          {
               ch=strDate[i];
               strDate[i]=strDate[strLength];
               strDate[strLength]=ch;
               i++;
               strLength--;
          }
          i=0;
          temp=0;
          while(strDate[i]!='\0')
          {
               temp += (strDate[i]-48) *multiple;
               multiple*=10;
               i++;
          }
          if(count==0)
          {
               tempDate.day=temp;
          }
          if(count==1)
          {
               tempDate.month=temp;
          }
          if(count==2)
          {
               tempDate.year=temp;
          }
          count++;
     }
     
     return(tempDate.day + tempDate.month*100 + tempDate.year*10000);
}
//****************************************************************
//to display a Date  variable in an acceptable format
void outputDate(int date)
{
     // int date = myDate.day + myDate.month*100 +myDate.year*10000 ;
     char cdate[9];
     itoa(date, cdate, 10);     // convert to string
     string sdate = cdate;
     cout<<sdate.substr(6, 2) <<"/"<<sdate.substr(4,2)<<"/"<<sdate.substr(0,4);
}
//****************************************************************




//****************************************************************
//read a Sighting variable from a text file and return a variable
//of type Sighting
Sighting* readSighting(Sighting& sightings,ifstream& inFile)
{    
     string temp;
     sightings.aDate=fileInputDate(inFile);
     if(inFile.fail())
          return NULL;

     std::getline(inFile, sightings.aType, ',');
     std::getline(inFile, sightings.aLocation, ',');
     inFile>>sightings.number;
     if(inFile.fail())
        return NULL;
     
     return &sightings;
}

Regards, Alex

0
 

Author Comment

by:KazIT
Comment Utility
Compiling...
Date.cpp
c:\documents and settings\karen stedman\my documents\uni\coit11134\birds\birds\date.cpp(25) : error C2556: 'int __cdecl fileInputDate(class std::basic_ifstream<char,struct std::char_traits<char> > &)' : overloaded function differs only by return typ
e from 'struct Date __cdecl fileInputDate(class std::basic_ifstream<char,struct std::char_traits<char> > &)'
        c:\documents and settings\karen stedman\my documents\uni\coit11134\birds\birds\date.h(17) : see declaration of 'fileInputDate'
c:\documents and settings\karen stedman\my documents\uni\coit11134\birds\birds\date.cpp(25) : error C2371: 'fileInputDate' : redefinition; different basic types
        c:\documents and settings\karen stedman\my documents\uni\coit11134\birds\birds\date.h(17) : see declaration of 'fileInputDate'
Error executing cl.exe.

Date.obj - 2 error(s), 0 warning(s)
These are the errors that come up Alex.
0
 

Author Comment

by:KazIT
Comment Utility
struct Sighting      
{
       Date aDate;
       string aType;
       string aLocation;
       int number;
};
this is my sighting struct now (amended)
0
 

Author Comment

by:KazIT
Comment Utility
the code for date shouldn't need changing should it?
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
Ok, change Date functions back to

//****************************************************************
//to read a Date in the format dd/mm/yyyy from a txt file
//and return a variable of type Date
Date fileInputDate(ifstream& inFile)
{
     string strDate;
     
     Date tempDate;
         
     tempDate.day=01;
     tempDate.month=01;
     tempDate.year=2004;
     int count=0;
     int temp=0;
     
     while(count!=3)
     {
          int i=0;
          int multiple=1;
          if(count<=1)
          {
              std::getline(inFile,strDate,'/');
          }
          else
          {
               std::getline(inFile,strDate,',');
          }
          char ch;
          int length=strDate.length();
          int strLength=(strDate.length()) -1;
          while(i!=(length/2))
          {
               ch=strDate[i];
               strDate[i]=strDate[strLength];
               strDate[strLength]=ch;
               i++;
               strLength--;
          }
          i=0;
          temp=0;
          while(strDate[i]!='\0')
          {
               temp += (strDate[i]-48) *multiple;
               multiple*=10;
               i++;
          }
          if(count==0)
          {
               tempDate.day=temp;
          }
          if(count==1)
          {
               tempDate.month=temp;
          }
          if(count==2)
          {
               tempDate.year=temp;
          }
          count++;
     }
     
     return tempDate; // (tempDate.day + tempDate.month*100 + tempDate.year*10000);
}
//****************************************************************
//to display a Date  variable in an acceptable format
void outputDate(Date myDate)
{
     int date = myDate.day + myDate.month*100 +myDate.year*10000 ;
     char cdate[9];
     itoa(date, cdate, 10);     // convert to string
     string sdate = cdate;
     cout<<sdate.substr(6, 2) <<"/"<<sdate.substr(4,2)<<"/"<<sdate.substr(0,4);
}
//****************************************************************

Regards, Alex

0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 

Author Comment

by:KazIT
Comment Utility
ok...i've changed the date function back to what it was...it executes but the output from text file reads
          Bird Watching Records Program
        ---------------------------------------------------

        1. View sightings from the last excursion

        2. Update the records with the latest sightings

        3. View sightings of a particular type of bird

        4. View sightings of birds in a particular location

        5. View all sightings

        0. Exit

        ---------------------------------------------------

Please enter your selection:  1
Date            Bird Type       Location        NumberOfBirds
--------------------------------------------------------------------

27/05/2004      cormorants      Fitzroy River   70000
27/67/2003      dab chicks      Fitzroy River   12
27/67/2003      pelicans        Fitzroy River   16
29/67/2003      magpie geese    Pioneer River   44
29/67/2003      spoon bills     Pioneer River   7
29/67/2003      wood ducks      Pioneer River   29
29/67/2003      cormorants      Pioneer River   41
31/67/2003      magpie geese    Burdekin River  96
02/68/2003      wood ducks      Tinaroo Dam     30
02/68/2003      spoon bills     Tinaroo Dam     13
02/68/2003      king fishers    Tinaroo Dam     2
03/68/2003      dab chicks      Tinaroo Dam     15
08/68/2003      pelicans        Awonga Dam      26
08/68/2003      black ducks     Awonga Dam      6
15/68/2003      spoon bills     Burnett River   14
15/68/2003      water fowl      Burnett River   52
15/68/2003      dab chicks      Burnett River   16
21/68/2003      black ducks     Fairburn Dam    21
21/68/2003      wood ducks      Fairburn Dam    29
28/68/2003      cormorants      Ivanhoe Dam     27

Total numbers of birds sighted 70496
--------------------------------------------------------------------

Press Enter to Continue ///see how the dates are now not valid dates
0
 

Author Comment

by:KazIT
Comment Utility
this is the date function that we amended the other week that was working before
void outputDate(Date myDate)
{
      int date = myDate.day + myDate.month*100 +myDate.year*10000 ;
      //check if valid date
      if(date <19000000 || date > 21000000)
      {
            cout<< "00/00/0000";
            return;
      }
      char cdate[9];
      itoa(date, cdate, 10);     // convert to string
      string sdate = cdate;
      cout<<sdate.substr(6, 2) <<"/"<<sdate.substr(4,2)<<"/"<<sdate.substr(0,4);
}
//****************************************************************
0
 

Author Comment

by:KazIT
Comment Utility
//display a single Sighting variable in an acceptable format
void displayOneSighting(Sighting sightings)
{
      outputDate(sightings.aDate);
      cout<<"\t"<<sightings.aType<<"\t"
            <<sightings.aLocation<<"\t"
            <<sightings.number<<endl;
}
could it be this function?
0
 

Author Comment

by:KazIT
Comment Utility
back in a while.
0
 
LVL 39

Accepted Solution

by:
itsmeandnobodyelse earned 500 total points
Comment Utility
I guess it's fileInputDate, that is wrong.

I changed readSightings so it reading whole line and parsing all fields. So fileInputDate is obsolete. You need that enum in sightings.h:

enum SightingField { SF_DAY, SF_MONTH, SF_YEAR, SF_TYPE, SF_LOCATION, SF_NUMBER };


//****************************************************************
//read a Sighting variable from a text file and return a variable
//of type Sighting
Sighting* readSighting(Sighting& sightings,ifstream& inFile)
{    
     string temp;
     getline(inFile, temp);

     int pos    = 0;
     int field  = 0;  // day
     for (int i = 0; i <= temp.length(); ++i)
     {
         if (i >= temp.length() || temp[i] == '/' || temp[i] == ',')
         {
             string sub = temp.substr(pos, i - pos);
             pos = i+1;
             switch(field)
             {
             case SF_DAY:
                 sightings.aDate.day = atoi(sub.c_str());
                 break;
             case SF_MONTH:
                 sightings.aDate.month = atoi(sub.c_str());
                 break;
             case SF_YEAR:
                 sightings.aDate.year = atoi(sub.c_str());
                 break;
             case SF_TYPE:
                 sightings.aType = sub;
                 break;
             case SF_LOCATION:
                 sightings.aLocation = sub;
                 break;
             case SF_NUMBER:
                 sightings.number = atoi(sub.c_str());
                 break;
             }
             field++;
         }

     }
     return &sightings;
}
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
If you don't want to use atoi() take that instead:

int strToNum(const char* pstr)
{
    int n = 0;
    int s = 1;
    int i = 0;
    for ( i = 0; pstr[i] != '\0'; ++i )
    {
        // check negative
        if (n == 0 && s == 1 && pstr[i] == '-')
        {
            s = -1;
        }
        // ignore leading white spaces
        else if (n == 0 && pstr[i] >= '\0' && pstr[i] <= ' ')
        {
        }
        // check digits
        else if (pstr[i] >= '0' && pstr[i] <= '9')
        {
            n = (n * 10) + (pstr[i] - '0');    
        }
        else
        {
            break;
        }
    }
    return s * n;
}

Regards, Alex

0
 

Author Comment

by:KazIT
Comment Utility
ompiling...
Sighting.cpp
C:\Documents and Settings\Karen Stedman\My Documents\UNI\COIT11134\Birds\Birds\Sighting.cpp(23) : error C2667: 'getline' : none of 2 overload have a best conversion
C:\Documents and Settings\Karen Stedman\My Documents\UNI\COIT11134\Birds\Birds\Sighting.cpp(23) : error C2668: 'getline' : ambiguous call to overloaded function
Error executing cl.exe.

Sighting.obj - 2 error(s), 0 warning(s)
sorry Alex but this is what happens when i implement the first post of yours.
0
 

Author Comment

by:KazIT
Comment Utility
i changed getline(inFile, temp);
to        std::getline(inFile, temp);
and it seems to execute ok.

Kaz
0
 

Author Comment

by:KazIT
Comment Utility
thankyou so much yet again. Alex.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
Comment Utility
>>>> i changed getline(inFile, temp); to std::getline(inFile, temp);

Either that or have a  

    using namespace std;

below your include statements.

Regards, Alex



0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now