[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 322
  • Last Modified:

problem reading all data from a text file

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
KazIT
Asked:
KazIT
  • 12
  • 6
1 Solution
 
Jaime OlivaresCommented:
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
 
itsmeandnobodyelseCommented:
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
 
KazITAuthor Commented:
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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
KazITAuthor Commented:
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
 
itsmeandnobodyelseCommented:
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
 
KazITAuthor Commented:
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
 
KazITAuthor Commented:
struct Sighting      
{
       Date aDate;
       string aType;
       string aLocation;
       int number;
};
this is my sighting struct now (amended)
0
 
KazITAuthor Commented:
the code for date shouldn't need changing should it?
0
 
itsmeandnobodyelseCommented:
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
 
KazITAuthor Commented:
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
 
KazITAuthor Commented:
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
 
KazITAuthor Commented:
//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
 
KazITAuthor Commented:
back in a while.
0
 
itsmeandnobodyelseCommented:
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
 
itsmeandnobodyelseCommented:
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
 
KazITAuthor Commented:
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
 
KazITAuthor Commented:
i changed getline(inFile, temp);
to        std::getline(inFile, temp);
and it seems to execute ok.

Kaz
0
 
KazITAuthor Commented:
thankyou so much yet again. Alex.
0
 
itsmeandnobodyelseCommented:
>>>> 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

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 12
  • 6
Tackle projects and never again get stuck behind a technical roadblock.
Join Now