Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

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

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

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
angrish
Asked:
angrish
1 Solution
 
AssafLavieCommented:
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
 
mnashadkaCommented:
Did you make sure that you included <string> ?
0
 
angrishAuthor Commented:
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
Industry Leaders: 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!

 
DanRollinsCommented:
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
 
angrishAuthor Commented:
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
 
DanRollinsCommented:
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
 
angrishAuthor Commented:
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
 
DanRollinsCommented:
>> 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
 
angrishAuthor Commented:
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
 
DanRollinsCommented:
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
 
DanRollinsCommented:
hi angrish,
Do you have any additional questions?  Do any comments need clarification?

-- Dan
0
 
angrishAuthor Commented:
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
 
DanRollinsCommented:
so try:

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

-- Dan
0
 
DanRollinsCommented:
hi angrish,
Do you have any additional questions?  Do any comments need clarification?

-- Dan
0
 
angrishAuthor Commented:
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
 
DanRollinsCommented:
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
 
DanRollinsCommented:
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
 
angrishAuthor Commented:
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
 
DanRollinsCommented:

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
 
angrishAuthor Commented:
thanks!
0
 
DanRollinsCommented:
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

Become an Android App Developer

Ready to kick start your career in 2018? Learn how to build an Android app in January’s Course of the Month and open the door to new opportunities.

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