C++: How to iterate over a text in a std::string line by line with STL?

15,617

Solution 1

Why do you keep the text in your source file? Keep it in a separate text file. Open it with std::ifstream and iterate over it with while(getline(...))

#include <iostream>
#include <fstream>

int main()
{
   std::ifstream  fin("MyText.txt");
   std::string    file_line;
   while(std::getline(fin, file_line))
   {
      //current line of text is in file_line, not including the \n 
   }
}

Alternatively, if the text HAS to be in a std::string variable read line by line using std::istringstream in a similar manner

If your question is how to put the text lexially into your code without using +, please note that adjacent string literals are concatenated before compilation, so you could do this:

std::string text = 
   "Line 1 contents\n"
   "Line 2 contents\n"
   "Line 3 contents\n";

Solution 2

Use Boost.Tokenizer:

std::string text("foo\n\nbar\nbaz");

typedef boost::tokenizer<boost::char_separator<char> > line_tokenizer;
line_tokenizer tok(text, boost::char_separator<char>("\n\r"));

for (line_tokenizer::const_iterator i = tok.begin(), end = tok.end();
     i != end ; ++i)
    std::cout << *i << std::endl;

prints

foo
bar
baz

Note that it skips over empty lines, which may or may not be what you want.

Solution 3

If you want to loop line by line, as you say, why would splitting the text at line breaks not be exactly what you want?

You didn't post code showing how you're doing it, but your approach seems correct to accomplish what you said you wanted. Why does it feel inferior?

Share:
15,617
Jan Deinhard
Author by

Jan Deinhard

Updated on June 19, 2022

Comments

  • Jan Deinhard
    Jan Deinhard almost 2 years

    I have a text in a std::string object. The text consists of several lines. I want to iterate over the text line by line using STL (or Boost). All solutions I come up with seem to be far from elegant. My best approach is to split the text at the line breaks. Is there a more elegant solution?

    UPDATE: This is what I was looking for:

    std::string input;
    // get input ...
    std::istringstream stream(input);
    std::string line;
    while (std::getline(stream, line)) {
      std::cout << line << std::endl;
    }
    
    • Chris Pfohl
      Chris Pfohl over 13 years
      Are you looking for "more elegant" like C#'s foreach "foreach( string line in lines)"? What exactly have you tried. C++ could feel 'inelegant' if you're used to dynamic or higher level languages, but in C++ "elegant" is never just handed to you, you usually have to program elegance yourself.
    • Jerry Coffin
      Jerry Coffin over 13 years
      It might not be quite an exact duplicate, but you might also want to look at: stackoverflow.com/questions/1567082/…
    • Wolf
      Wolf about 10 years
      It would be better to answer your own question instead of updating it. Updating may be confusing for future reader...
  • Björn Pollex
    Björn Pollex over 13 years
    If you really need to work with a std::string, you can wrap it in a std::stringstream and apply Armen's solution.
  • visual_learner
    visual_learner over 13 years
    If the data is already a string, you could just use std::stringstream in the same manner.
  • Jan Deinhard
    Jan Deinhard over 13 years
    I'd rather use some STL build-in solution. AFAIK line endings are platform-dependent so I'd like to avoid that solution if possible.
  • KevenK
    KevenK over 13 years
    @Fair: That (along with your current code) seems like information that should have been in the original question. It's a valid concern and can be addressed, but only if you address it head-on :)
  • Jan Deinhard
    Jan Deinhard over 13 years
    @Armen: The text is going to be fetched from the web. Of course I could write it into a file and then read it again. I came up with that solution too. I'd rather have it in memory all the time ... if possible :)
  • visual_learner
    visual_learner over 13 years
    @Fair - I'm not sure about C++, but C stdio functions convert \r\n to \n on reading (unless told not to) and \n to \r\n on writing on systems that don't play nice. Line ending platform-dependency is a small thing to be worried about here.
  • Jan Deinhard
    Jan Deinhard over 13 years
    To be honest I don't really have working code yet. I made some solutions up in my mind :) But I'll add some code in a moment.
  • Armen Tsirunyan
    Armen Tsirunyan over 13 years
    @Fair: I don't get it, really. How are you reading the text from the web? Does the text already contain line breaks? If so, then I don't see the problem, if not, then maybe you want to add them wherever you think appropriate. Also note that getline can take a third parameter - the character that denotes the end of line. Default is '\n' but you can change that
  • Armen Tsirunyan
    Armen Tsirunyan over 13 years
    Isn't using boost::tokenizer for something that can be done with getline sort-of like killing a sparrow with a nuke?
  • Fred Foo
    Fred Foo over 13 years
    Depends on what the OP wants to do. This solution is quite short and it yields a pair of iterators that can be handed to STL algorithms.
  • Jan Deinhard
    Jan Deinhard over 13 years
    @Armen: Thanks for the pointer! The std::istringstream variant is the "elegance" I was looking for. By the way: I read the text from the web with libcurl.