Thread: Read file line, search for string, get string position

  1. #1
    Registered User
    Join Date
    Mar 2014
    Posts
    12

    Read file line, search for string, get string position

    Hi,

    I´m pretty much a beginner in C++, although I have some basic knowledge of C.

    I´m looking for a way to do this:

    test.txt:
    Code:
    bird=animal
    fish=animal
    dog=animal
    - read every line of this file
    - search every line for "fish="
    - check if it is followed by "animal"
    - if so, replace "animal" with "being"

    What I have so far is this:
    Code:
    int main(){
    
        string str;
        
        ofstream writefile;
        writefile.open("test.txt");
        writefile << "bird=animal\n"
                "fish=animal\n"
                "dog=animal\n"
                "";
        
        ifstream readfile;
        readfile.open("text.txt");
        getline(readfile,str);
    
    
        // what goes here?
        
    
        writefile.close();
        readfile.close();
        system("pause");
    }
    How do I get it to do the rest?

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by taifun
    - search every line for "fish="
    - check if it is followed by "animal"
    - if so, replace "animal" with "being"
    If I understand this correctly, matching lines with only contain "fish=animal". If so, it might be easier to check every line for "fish=animal" and replace the entire matching line with "fish=being". You can make use of a while loop:
    Code:
    while (getline(readfile, str))
    {
        // ...
    }
    To actually check for "fish=animal", you can make use of the std::string's operator==. For replacing the line... just change what is written back to the file, e.g., if you are storing lines read in a std::vector<std::string>, make "fish=animal" be the corresponding entry in the vector to be written back to file later.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Mar 2014
    Posts
    12
    Quote Originally Posted by laserlight View Post
    If I understand this correctly, matching lines with only contain "fish=animal". If so, it might be easier to check every line for "fish=animal" and replace the entire matching line with "fish=being". You can make use of a while loop:
    Code:
    while (getline(readfile, str))
    {
        // ...
    }
    Thanks, makes sense.

    But what if the line contained:
    cat=animal;fish=animal;rabbit=animal;...unknown content...
    I would need to look for "fish=animal", and replace it with "fish=being" without deleting the rest of the line.

    Is there a beginner-friendly way of searching a line for a string, and insert/replace with another string?

    Quote Originally Posted by laserlight View Post
    To actually check for "fish=animal", you can make use of the std::string's operator==. For replacing the line... just change what is written back to the file, e.g., if you are storing lines read in a std::vector<std::string>, make "fish=animal" be the corresponding entry in the vector to be written back to file later.
    So each time the while loop gets a line, I compare str with "fish=animal"? Something like this?
    Code:
    bool loop=true;
    while (getline(readfile, str)&&loop==true)
    {
        if(str=="fish=animal"){
    
               // how would I go about replacing the string in the file?
               // do I need to read the whole file, change a string, then replace the whole file?
               // or is there a premade way to replace only one single line?
    
               loop=false;    // abort reading new lines
        }
    
    }

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by taifun
    But what if the line contained:
    cat=animal;fish=animal;rabbit=animal;...unknown content...
    I would need to look for "fish=animal", and replace it with "fish=being" without deleting the rest of the line.
    Well, then you need to be clear as to the file format. Like, here's another example:
    Code:
    catfish=animal;fish=animals
    Do you do nothing, or do you end up with:
    Code:
    catfish=being;fish=beings
    ?

    Without a properly specified file format, according to what you wrote in post #1, the answer is yes.

    EDIT:
    Quote Originally Posted by taifun
    Is there a beginner-friendly way of searching a line for a string, and insert/replace with another string?
    std::string has find and replace member functions that may be applicable.
    Last edited by laserlight; 03-23-2014 at 04:19 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User
    Join Date
    Nov 2013
    Posts
    107
    It depends on the format of the data being feed in, i.e how the data is presented in the text file you are reading into the stream. If the data consistently in the same format like a CVS comma delimited file it's a straightforward task of reading the data in line by line and performing some string manipulation on the string, depending on what you want to extract, store or replace.

    Analysing a string like this is called Lexical Analysis and storing the result of your string manipulation is called parsing, and there is no magic involved. You are looking for common points(delimiters) in the data(string) that you use to split the data into consistent sections.

    It's usually a good idea to trim any whitespace either side of the input. Then you can use the while loop the read the data in.

    You will then have to loop through the string character by character to find and build up the pattern you are looking to find or use the string 'find' function to find a string.
    Last edited by jim_0; 03-23-2014 at 05:06 AM.

  6. #6
    Registered User
    Join Date
    Mar 2014
    Posts
    12
    There is no data yet, I´m trying to understand what is possible, and I would create any files according to this.

    So let´s assume I have a file like this:
    Code:
    cat=animal;fish=animal;rabbit=animal;
    cow;horse=being;
    dog;mouse;sheep;
    How would the code look like for using ; as delimiter to read, append, insert, and replace strings in this file?

    I tried to find a good tutorial on file handling, but they are either too short (only simple read,write) or way too complex for me to understand yet.
    Some code examples for possible operations would be much appreciated!

  7. #7
    Registered User
    Join Date
    Mar 2014
    Posts
    12
    Quote Originally Posted by laserlight View Post
    Well, then you need to be clear as to the file format. Like, here's another example:
    Code:
    catfish=animal;fish=animals
    Got it, so in this case I would need to read from line beginning to first delimiter ;
    then analyze the string and do something with it. So only "fish=animal" would be used.


    Quote Originally Posted by laserlight View Post
    std::string has find and replace member functions that may be applicable.
    Do you have a basic code for this, or know a complete, but easy to understand tut on this topic?

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by taifun
    There is no data yet, I´m trying to understand what is possible, and I would create any files according to this.
    Out of curiosity, but why do you want to do this?

    Quote Originally Posted by taifun
    So let´s assume I have a file like this:
    That's an example of file content. We can infer the file format, but then you can just as easily say "But what if the line contained..."

    See what I mean? I inferred the file format from what you described in post #1, but apparently I was wrong. So, going by my assumptions, I can reply to your "But what if the line contained" with: "the file content does not follow the file format, so stop parsing an inform the user of an error".

    Quote Originally Posted by taifun
    How would the code look like for using ; as delimiter to read, append, insert, and replace strings in this file?
    It depends on what you are trying to do. For example, maybe we shall store each string delimited by the ';' as a separate entry in a std::vector:
    Code:
    std::vector<std::string> tokens;
    std::string token;
    while (getline(readfile, token, ';'))
    {
        tokens.push_back(token);
    }
    Now, we manipulate the std::vector, and eventually write the tokens back to file.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    Nov 2013
    Posts
    107
    Well there are a few ways to do this. Your goal is to create a function that takes into every possible situation that the format of the data can be in. I would start with your first example and assume the data is perfectly regular such as,

    bird=animal
    fish=animal
    dog=animal

    In this case the delimiter is a newline, also called a linefeed (lf), which can be written as \n.

    However reading the data in a loop using getline takes care of this for you.

    So in your example the common delimiter is the '=' character.

    So you need to use the string function find_first_of, this return the position of the character you are looking for.

    Like,

    Code:
    int i = 0;
    while (getline(readfile, str))
    {
         i = str.find_first_of("=");
         if(str.substr(0, i ) == "bird" && str.substr(i, str.length() - i) == "animal"){
        //Do Stuff
        }
      }

  10. #10
    Registered User
    Join Date
    Mar 2014
    Posts
    12
    Quote Originally Posted by laserlight View Post
    Out of curiosity, but why do you want to do this?
    Non scholae, sed vitae discimus, right?
    I´m trying to learn C++, no particular reason. Why this specifically? I tend to get stuck on small things. And filehandling always comes in handy.

    Quote Originally Posted by laserlight View Post
    That's an example of file content. We can infer the file format, but then you can just as easily say "But what if the line contained..."
    See what I mean? I inferred the file format from what you described in post #1, but apparently I was wrong. So, going by my assumptions, I can reply to your "But what if the line contained" with: "the file content does not follow the file format, so stop parsing an inform the user of an error".

    I´m trying to learn the the code for:
    - searching a given string inside a line
    - appending a string to the line
    - deleting a string within a line
    - inserting a string into a line

    Quote Originally Posted by laserlight View Post
    It depends on what you are trying to do. For example, maybe we shall store each string delimited by the ';' as a separate entry in a std::vector:
    Code:
    std::vector<std::string> tokens;
    std::string token;
    while (getline(readfile, token, ';'))
    {
        tokens.push_back(token);
    }
    Now, we manipulate the std::vector, and eventually write the tokens back to file.
    Ok, so I put this into a file:
    Code:
        ifstream readfile;
        readfile.open("text.txt");
        vector<string> tokens;
        string token;
        int i=0;
        while (getline(readfile, token, ';'))
        {
            tokens.push_back(token);
            i++;
        }
        readfile.close();
        
        for(int j=0; j<i;j++){
        cout << tokens[j] << endl;
        }
    But I get no output...

  11. #11
    Registered User
    Join Date
    Mar 2014
    Posts
    12
    Quote Originally Posted by jim_0 View Post
    test1.txt:
    Code:
    bird=animal
    fish=animal
    dog=animal

    Code:
    int i = 0;
    while (getline(readfile, str))
    {
         i = str.find_first_of("=");
         if(str.substr(0, i ) == "bird" && str.substr(i, str.length() - i) == "animal"){
        //Do Stuff
        }
      }
    I tried this:
    Code:
        ifstream readfile;
        readfile.open("test1.txt");
        
        int i = 0;
        string str;
        while (getline(readfile, str))
        {
             i = str.find_first_of("=");
             if(str.substr(0, i ) == "bird" && str.substr(i, str.length() - i) == "animal"){
                str=str.substr(i, 9);
                cout << str << endl;
            }
        }
    But no output either...

    What would the str.length() in
    Code:
             if(str.substr(0, i ) == "bird" && str.substr(i, str.length() - i) == "animal"){
    return in this case?
    Last edited by taifun; 03-23-2014 at 06:16 AM.

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by taifun
    But I get no output...
    I tested your code and got output, so perhaps you did something wrong, or your input file is empty.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #13
    Registered User
    Join Date
    Mar 2014
    Posts
    12
    @jim_0:
    I get output "=animal" with:
    Code:
    str.substr(i+1, 9)
    but with
    Code:
    str.substr(i+2, 9)
    I get nothing again.

  14. #14
    Registered User
    Join Date
    Mar 2014
    Posts
    12
    Quote Originally Posted by laserlight View Post
    I tested your code and got output, so perhaps you did something wrong, or your input file is empty.
    ...used "text.txt" instead of "test.txt"

    Works, thanks!

    Now I have:
    Code:
        ifstream readfile;
        readfile.open("test.txt");
        vector<string> tokens;
        string token;
        int i=0;
        while (getline(readfile, token, ';'))
        {
            tokens.push_back(token);
            i++;
            
            int k = token.find_first_of("=");
            if(k>=1){
            cout << token.substr(0, k ) << endl <<
            token.substr(k+1) << endl;
            }
            else cout << token.substr(0) << endl;
        }
        readfile.close();
        
        for(int j=0; j<i;j++){
        cout << tokens[j] << endl;
        }
    Thanks guys!

    How would I go about inserting something into this file?
    Code:
    cat;fish;rabbit;
    cow;horse;
    dog;mouse;sheep;
    I would like to insert "=animal" after every animal (==before every ';').
    Last edited by taifun; 03-23-2014 at 07:04 AM.

  15. #15
    Registered User
    Join Date
    Mar 2014
    Posts
    12
    I tried this:
    Code:
        fstream file("test.txt",ios::in|ios::out|ios::ate);
        vector<string> tokens;
        string token;
        int i=0;
        while (getline(file, token, ';'))
        {
            tokens.push_back(token);
            i++;
            
            int k = token.find_first_of("=");
            if(k>=1){
            cout << token.substr(0, k ) << endl <<
            token.substr(k+1) << endl;
            }
            else{
                cout << token.substr(0) << endl;
                k = token.find_first_of(";");
                file.seekp(k);
                file.write("=animal",7);
                // I tried: file.insert("=animal",7); but getting an error
            }
        }
        file.close();
        
        for(int j=0; j<i;j++){
        cout << tokens[j] << endl;
        }
    But no output.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. How can a mulitline string be read line by line
    By cdroid in forum C Programming
    Replies: 2
    Last Post: 03-07-2014, 09:26 AM
  2. Replies: 4
    Last Post: 05-08-2009, 04:25 AM
  3. Read command line and write to file or string
    By miiisuuu in forum C Programming
    Replies: 1
    Last Post: 10-21-2007, 11:39 AM
  4. String Search with command line arguments
    By goron350 in forum C Programming
    Replies: 5
    Last Post: 11-29-2004, 05:56 PM
  5. How to read empty string from command line
    By BruceLeroy in forum C++ Programming
    Replies: 8
    Last Post: 08-07-2004, 05:20 PM