Is there an easier way?

I would like to know if there is a shorter / easier way:

  • Split the input string with words
  • Enter tokens in reverse order in stdout

There are two limitations: no libraries and no loops

#include <string> #include <iterator> #include <iostream> #include <algorithm> #include <sstream> #include <deque> void list_string_elements(std::string s) { using namespace std; istringstream iss (s); deque<string> v; copy(istream_iterator<string>(iss), istream_iterator<string>(), front_inserter(v)); copy(v.begin(),v.end(),ostream_iterator<string>(cout,"\n")); } 
+8
c ++ stl
source share
3 answers

A small abbreviation, we can get rid of the copy thanks to the constructor of the deque iterator:

 void list_string_elements(std::string s) { using namespace std; istringstream iss (s); deque<string> v(istream_iterator<string>(iss), (istream_iterator<string>())); copy(v.rbegin(),v.rend(),ostream_iterator<string>(cout,"\n")); } 

Pay attention to additional parsers around istream_iterator<string>() to avoid the most unpleasant parsing.

+7
source share

No, because you need to keep the words until the last one is selected. It’s harder to try marking back.

Also, you cannot use std::copy_backward because std::istream_iterator not bidirectional (input only).

std::deque perfect for this task. You could also use vector + back_inserter and copy from v.rbegin() to v.rend() in ostream_iterator .

In addition, the simplest string tokenization logic is expressed using istringstream .

Basically, it looks like you can't do much better.

The only religious thing is that I cannot stand using namespace even in the scope area.

My suggestion, with the same number of lines:

 #include <algorithm> #include <iostream> #include <iterator> #include <sstream> #include <string> #include <vector> void output_tokens(const std::string& str) { typedef std::istream_iterator<std::string> in_iterator; typedef std::ostream_iterator<std::string> out_iterator; std::istringstream in(str); std::vector<std::string> buffer(in_iterator(in), (in_iterator())); std::copy(buffer.rbegin(), buffer.rend(), out_iterator(std::cout, "\n")); } 

Important change: You need an extra pair of parentheses around in_iterator() to prevent the entire expression from being parsed as a function declaration. @ Steve Jessop's answer has the same problem. See this erroneous example to witness a drawing error message that occurs due to such confusion.

+5
source share

It's good that your teacher encourages the use of the correct C ++ functionality, but for fun, I would argue that using copy just moves the loop further up the stack ... I would argue that recursion is the real way of doing this without using an explicit loop, which something like below ...

 #include <iostream> #include <string> typedef std::string::const_iterator iterator; void print_reverse(iterator s, iterator i, iterator e) { // last word if (i == e) { if (s != i) std::cout << std::string(s, i) << std::endl; return; } std::string word; if (*i == ' ') { // have word here word.assign(s, i); s = ++i; } else ++i; // recursively call print_reverse(s, i, e); if (!word.empty()) std::cout << word << std::endl; } int main(void) { std::string foo ("foo bar bof bob"); print_reverse(foo.begin(), foo.begin(), foo.end()); } 
+2
source share

All Articles