Solved

calling getline from inside ifstream dervied class object 's member func?

Posted on 2001-08-28
21
449 Views
Last Modified: 2008-02-01
hi ,
I am trying to call
getline(istream& is, string& str, char delim = '\n') from a member function of my class derived from ifstream.
I am not able to understand the compiler error generated (using CC on sunOS 5.6 ).
 Error: Could not find a match for std::basic_istream<char, std::char_traits<char>>::getline(std::basic_istream<char, std::char_traits<char>>, std::basic_string<char, std:

this is the line :
 getline(*ptrifile, tempstring, '\n') ;
here is the code :
class myifstream:public ifstream{
 public :
    void file_replace(ofstream &, string &,string &) ;
   myifstream(const char *name):ifstream(name){} ;
 
};
 
int main(int argc,char *argv[])
{
 ...
 ..
 const char *filename=argv[1] ;

 string old,newstring;
 old = argv[2] ;
 newstring = argv[3] ;

 myifstream ifile(filename) ;
 if (!ifile) {cout << "error opening ifile"<<endl ;
  return 0 ;
   }

 ifile.file_replace(ofile,old,newstring) ;

}

void myifstream::file_replace(ofstream &ofile,string &old,string &newstring) {
 
 string tempstring ;
 istream *ptrifile;
 ptrifile =dynamic_cast<istream *> (this) ;

 while((*ptrifile).good()){
 getline(*ptrifile, tempstring, '\n') ;

...
..
}

0
Comment
Question by:angrish
21 Comments
 
LVL 4

Expert Comment

by:AssafLavie
ID: 6431306
You're not supposed to inherit from ifstream. It is not a polymorphic type. It doesn't even have a virtual destructor.
In what way are you trying to extend it? You are probably better off oding it by inheriting from stream_buf or by using fstream as a member of your class (composition).
0
 
LVL 8

Expert Comment

by:mnashadka
ID: 6431770
Did you make sure that you included <string> ?
0
 

Author Comment

by:angrish
ID: 6435175
hi AssafLavie,
 Is it actuall illegal to derive from ifstream ?
I am just trying to extend it so that I can replace a string throughout the file.
Also could you tell me some refernce(online) where I can know which class can(should ) be derived from.
thanks.



--hi mnashadka,
yes <string> is included.
thanks.
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6447301
Is there a reason to derive at all?  It seems to complicate the issue uneccessarily.  

Why not simply read a line, check for and replace the text, then output the result?

-- Dan
0
 

Author Comment

by:angrish
ID: 6447426
hi Dan,
I already implemented the thing without deriving it and went fine too..
but I just want to see if it can be done this way.(and where I am going wrong !).
maybe there's some conceptual mistake I am making from which I can learn.
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6448321
I like that in a programmer!  Here is my idea.  Just override the getline fn.  In the override, replace the parts that need replacement before returning.

#include <iostream>
#include <fstream>
using namespace std ;

class ifstreamWithReplace : public ifstream {
public :     // ctor
    ifstreamWithReplace ( string& sFile, string& sOld, string& sNew )
        : ifstream(sFile.c_str()), m_sTextToReplace(sOld),m_sReplacementText(sNew) {};

    ifstreamWithReplace& getline( char* pBuf, int nLen, char delim='\n' ) ;
    string m_sTextToReplace;
    string m_sReplacementText;
};

ifstreamWithReplace& ifstreamWithReplace::getline( char* pBuf, int nLen, char delim /*='\n'*/ )
{
    ifstream::getline(pBuf, nLen, delim );
    string s= pBuf;
    int n;
    while ( (n=s.find(m_sTextToReplace,0)) != -1 ) {
        s.replace(n,m_sTextToReplace.length(),m_sReplacementText );
    }
    strcpy( pBuf, s.c_str() );
    return( *this );
}


int main(int argc,char *argv[])
{
    string sInFile, sOutFile, sTextToReplace, sReplacementText;
//  sInFile=  argv[1] ;
//  sOutFile= argv[2] ;
//  sTextToReplace= argv[3] ;
//  sReplacementText= argv[4] ;

    sInFile=  "c:\\temp\\infile.txt";
    sOutFile= "c:\\temp\\outfile.txt";
    sTextToReplace= "e";
    sReplacementText= "EEEE";

    ifstreamWithReplace infile( sInFile, sTextToReplace, sReplacementText ) ;
    if (!infile) {cout << "error opening infile"<<endl ;
        return 0 ;
    }
    ofstream outfile( sOutFile.c_str() ) ;
    if (!outfile) {cout << "error opening outfile"<<endl ;
        return 0 ;
    }
    char szBuf[1000];
    while( infile.getline(szBuf, sizeof(szBuf)) ) {
        outfile.write(szBuf, strlen(szBuf) );
        outfile.write("\n", 1);
    }

    return 1;
}
=----------==-=-=-=-=-=-=-=-=-=-=-
There are several unsafe and/or stupid things I'm doing, but I wanted to leave some of the fun for you:

1) if the szBuf is too small for the final text, you are hosed.  Write some guard logic or use an expandable buffer or someting.

2) I think the find-and-replace logic will misfire if the replace string is a subset of the find string.  Again, that is an implementation detail I figgered to leave to you.

-- Dan
0
 

Author Comment

by:angrish
ID: 6452694
Hi Dan,
thanks,
I tried out something too.I just declared the function( to replace) as a friend function and things go fine if I pass the the ifstream to the friend function.
 file_replace(ifile,ofile, old, newstring) ;

here is what my class looks like ..

class myifstream:public ifstream{
 public :
 friend    void file_replace(ifstream &, ofstream &, string &,string &) ;
   myifstream(const char *name):ifstream(name){} ;
 
};
I use getline as getline(ifile, tempstring, '\n') ;
and thing go well.

however the problem comes when I declare the above function as a public member fxn of my class (derived from ifstream).
void file_replace(ofstream &, string &,string &) ;
called as..
ifile.file_replace(ofile,old,newstring) ;

the problem comes when we try to call * getline() *.this is not the getline in the fstream but the one that is a non member function in the string library.
istream& getline(istream is, String& str, char delim = '\n').
the entire problem burns down to this :
how do I invoke this function from inside the function
file_replace() when I invoke it as a public member.
ifile.file_replace().
I tried to use the this pointer.
 istream *ptrifile;
 ptrifile =dynamic_cast<istream *> (this) ;

and then  getline(*ptrifile, tempstring, '\n') ;
but I get the compiler error:
Could not find a match for std::basic_istream<char, std::char_traits<char>>::getline(std::basic_istream<char, std::char_traits<char>>, std::basic_string<char, std::char_traits<char>, std::allocator<char>>, char)
.
Any clues ?
(although the "friend function" approach works fine too.)
- Is it something to do with the type cast I used ?
If I could get some insight into why only this particular method does not work ,that would be really nice.
thanks and regards,
angrish.





0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6453901
>> istream *ptrifile;
>> ptrifile =dynamic_cast<istream *> (this) ;
>> and then  getline(*ptrifile, tempstring, '\n') ;

I find these member fns:

istream& getline( char* pch, int nCount, char delim = '\n' );
istream& getline( unsigned char* puch, int nCount, char delim = '\n' );
istream& getline( signed char* psch, int nCount, char delim = '\n' );

...but  I don't see one that defines a fn in which the first parameter is istream*  So that could explain the compiler error.

-- Dan
0
 

Author Comment

by:angrish
ID: 6476462
hi,
this is not the member function getline() from the istream class but the NON-MEMBER function designed to work with strings.(related to the <string>) .


istream& getline (istream& is, string& str, char delim = '\n');

thanks,


0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6477357
The compiler first looks for a member fn named getline and finds one.  It checks all the overloads and can't find one that matches the parmaters.

The fn you are trying to call is a member of the string class, so try:

   string::getline( is, s, '\n' );

-- Dan
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 49

Expert Comment

by:DanRollins
ID: 6496276
hi angrish,
Do you have any additional questions?  Do any comments need clarification?

-- Dan
0
 

Author Comment

by:angrish
ID: 6496490
yes Dan ..
the string :: getline approach does not work, because getline is not a member of string.

It is a non member function.
I am quoting from a URL :-

http://www.msoe.edu/eecs/ce/courseinfo/stl/string.htm
....
In addition to member functions of the string class, some non-member functions are designed to work with strings; the most common of these is:

getline istream& getline (istream& is, string& str, char delim = '\n');
Reads characters from an input stream into a string, stopping when one of the following things happens.......etc...
-----------------------
so how do I pass the 1st argument to it (the ref. to istream ) when it is called from inside another member function of the object derived from istream ?
I tried different types of casts on the "this" pointer but no success.
Pls suggest .

thanks.

0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6497590
so try:

  string::getline( is, s, '\n' );

-- Dan
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6516012
hi angrish,
Do you have any additional questions?  Do any comments need clarification?

-- Dan
0
 

Author Comment

by:angrish
ID: 6526179
hi Dan,
yes, it's the same as I mentioned in my previous mail..
that getline is NOT a MEMBER of string.
so string::getline() is not possible.
regards,

0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6529173
It works!  string:: just says to use the static fn.  But perhaps you are doing something strange -- I don't understand whay you are not using my original code.  Perhaps you could explain.  But doing that will only give me a chance to say "but there is a better way.." so instead...

Post your code and use comments to show what is happening.  Look at the code I posted.  Do the same thing, but add:

// this doesn't work

otherwise we'll get nowhere.

-- Dan
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6529333
You don't really want to try very hard do you?  You know, a successful virus writer needs to be able do some kinda technical stuff.  Ya know, read specs and such icky bunk.  Maybe you should ask that nerdy guy over there in the lunchroom....

But I'll cut you some slack.

As the document clearly states, says, after the PE signature, there is a 20-byte COFF-file header.  After that comes the Optional Header.  Offset 16 of that is a four-byte field named AddressOfEntryPoint.  Hmmm, I wonder if that has anything to do with the Entry Point of the program.  Unlikely, but, what the heck... lets take a little looksee.  Those four bytes in my little test EXE are F0 B8 01 00.

But that can't possibly be a file offset!  The doc says that it is one of those mysterious RVAs Oh No!  What are those letters mixed in the the numbers?  Oh ya, hex or voodoo numbers, something like that.  Anyway, the file is not 4038590720 bytes long! Hmmm... I wonder if perhaps the number are reversed... a nerdy guy once talked about Intel and "Big Indians"  It was all so confusing...

-- Dan
0
 

Author Comment

by:angrish
ID: 6529649
here is the code ...

#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
using namespace std ;

class myifstream:public ifstream{
 public :
 //fxn to do the replacement.
  void file_replace(ofstream &, string &,string &) ;
 //ctor
  myifstream(const char *name):ifstream(name){} ;
 
};
 
int main(int argc,char *argv[])
{
 if(argc != 4){cout <<"usage : sub file oldstring newstring"<<endl ;
 return 0 ;
  }
 const char *filename=argv[1] ;

 string old,newstring;
 old = argv[2] ;
 newstring = argv[3] ;
 
 //open the derived input file stream
 myifstream ifile(filename) ;
 if (!ifile) {cout << "error opening ifile"<<endl ;
  return 0 ;
   }
 //open output file stream.
 ofstream ofile("output") ;
 if (!ofile){cout <<"error opening outfile"<<endl ;
  }  
 //call the file_replace member fxn of the derived //(mifstream)
 //we pass the output file stream and the strings.

 ifile.file_replace(ofile,old,newstring) ;

}

//-------------------------------
//the function should read from the derivedifstream object calling it ,
//do the replacement and write to the output file.
//-------------------------------------
void myifstream::file_replace(ofstream &ofile,string &old,string &newstring) {
 
 string tempstring ;
 istream *ptrifile;
 //upcast the "this" ptr (myistream *) to the (istream *) ptr
 ptrifile =dynamic_cast<istream *> (this) ;

 while((*ptrifile).good()){
 
 // THIS DOES NOT WORK !! ...
 string::getline(*ptrifile, tempstring, '\n') ;
 
 //This also does NOT WORK..
  getline(*ptrifile, tempstring, '\n') ;
//we can use the getline function like this if we donot //use file_replace as a member function and pass the the //ifstream object to it.
//why is using the "this"  pointer giving a problem.


 
 string :: size_type pos=tempstring.find(old,0) ;
 
 //do the replacement part..
 while (pos != string :: npos){
 
 tempstring.replace(pos, old.length(), newstring) ;

 pos = tempstring.find(old,pos) ;
 }
  ofile << tempstring << '\n' ;

 }

}
0
 
LVL 49

Accepted Solution

by:
DanRollins earned 150 total points
ID: 6529865

void myifstream::file_replace( ofstream &ofile, string &old, string &newstring )
{
    string sTmp;
    string::size_type pos;

    while( good() ) {
        std::getline( *this, sTmp, '\n') ;
        pos= sTmp.find(old,0) ;
        while ( pos != -1 ) {
            sTmp.replace( pos, old.length(), newstring );
            pos= sTmp.find( old, pos ) ;
        }
        ofile << sTmp << '\n' ;
    }
}

-- Dan
0
 

Author Comment

by:angrish
ID: 6535119
thanks!
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6535151
I appologize for my post dated 10/04 It was meant for a different question  It must have been confusing to you.  Sorry.

-- Dan
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

What is C++ STL?: STL stands for Standard Template Library and is a part of standard C++ libraries. It contains many useful data structures (containers) and algorithms, which can spare you a lot of the time. Today we will look at the STL Vector. …
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 goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…

757 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

20 Experts available now in Live!

Get 1:1 Help Now