Link to home
Start Free TrialLog in
Avatar of KazIT
KazIT

asked on

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              



Avatar of Jaime Olivares
Jaime Olivares
Flag of Peru image

Take a look to the split() function in this question:
https://www.experts-exchange.com/questions/20188299/Split-function-like-in-Perl.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;
}
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



Avatar of KazIT
KazIT

ASKER

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
Avatar of KazIT

ASKER

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)
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

Avatar of KazIT

ASKER

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.
Avatar of KazIT

ASKER

struct Sighting      
{
       Date aDate;
       string aType;
       string aLocation;
       int number;
};
this is my sighting struct now (amended)
Avatar of KazIT

ASKER

the code for date shouldn't need changing should it?
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

Avatar of KazIT

ASKER

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
Avatar of KazIT

ASKER

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);
}
//****************************************************************
Avatar of KazIT

ASKER

//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?
Avatar of KazIT

ASKER

back in a while.
ASKER CERTIFIED SOLUTION
Avatar of itsmeandnobodyelse
itsmeandnobodyelse
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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

Avatar of KazIT

ASKER

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.
Avatar of KazIT

ASKER

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

Kaz
Avatar of KazIT

ASKER

thankyou so much yet again. Alex.
>>>> i changed getline(inFile, temp); to std::getline(inFile, temp);

Either that or have a  

    using namespace std;

below your include statements.

Regards, Alex