REVERSING A STRING

A few days ago, someone was asking for a C++ code that can Print the words in a string in reverse order. i.e if input is : good morning how are you then the output must be : you are how morning good, but couldn't reply him at that time and couldn't find his post now. I figured out this code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <alok.h>
using namespace std;
struct node
{
    char data[10];
    node *next;
};
class queue
{
    node *front;
    node *rear;
    public:
        queue()
        {
            front=rear=NULL;
        }
        void push(char []);
        void disp();
        ~queue();
};
void queue::push(char data[10])
{
    node *newptr=new node;
    strcpy(newptr->data,data);
    if(front==NULL && rear==NULL)
    {
        front=newptr;
        rear=newptr;
    }
    else{
            newptr->next=rear;
            rear=newptr;
        }
}
void queue::disp()
{
   if(rear)
    {
          node *temp=rear;
          while(temp)
          {
              cout<<temp->data<<' ';
              temp=temp->next;
          }
          cout<<"\n";
    }
    else
    {
           cout<<"Is Empty\n";
    }
}
queue::~queue()
{
node *temp=front;
while(temp)
{
node *p=temp;
temp=temp->next;
delete(p);
}
}
int main()
{
    queue q;
    char str[50];
    cout<<"\n Enter the string :";
    gets(str);
    ofstream ofile;
    ofile.open("text.txt",ios::out);
    ofile<<str;
    ofile.close();
    ifstream ifile("text.txt",ios::in);
    char temp[10];
    do
    {
        ifile>>temp;
        q.push(temp);
    }while(!ifile.eof());
    ifile.close();
    q.disp();
    return 0;
    q.~queue();
}


But it seems to be too long. So, I need suggestions on this for some improvements and to make it short.
Couldn't you just put all the words in a STL container and iterate backwards, use a deque and push front everything, or use std::reverse on a STL container.

I don't know about STL containers. :)
Well you pretty much recreated one in your code :P A queue is part of the STL.
http://www.cplusplus.com/reference/stl/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <algorithm>
using namespace std;

int main()
{
	string input = "";
	cout << "Enter a string: " << flush;
	getline(cin, input);

	stringstream ss(input);
	string tempString = "";
	vector<string> words;
	while (ss >> tempString)
	{
		words.push_back(tempString);
	}
	
	reverse(words.begin(), words.end());

	for (int i = 0; i < words.size(); i++)
	{
		cout << words[i] << ' ';
	}


	cin.ignore();
	return 0;

}
Yanson's code shows me that I have to study C++ more.

@giblit,
can you write the code with STL containers?? So that I can read it.
Thanks to both of you.
Seems like a stack would be more appropriate for this than a queue.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <stack>
#include <iostream>
#include <string>

using sstack = std::stack<std::string>;

sstack stack_em_up(std::istream& is)
{
    sstack result;

    std::string token;
    while (is >> token)
        result.emplace(token);

    return result;
}

void break_em_down(sstack s)
{
    while (!s.empty())
    {
        std::cout << s.top() << ' ';
        s.pop();
    }
}

int main()
{
    break_em_down(stack_em_up(std::cin));
}


http://ideone.com/i6xZkJ
The STL is just the Standard Template Library. It's just a collection of things like linked lists, queues, etc. I wouldn't consider std::string or any of the streams part of the STL, but those are also very useful here. Here's another way to solve this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream> // std::cin & std::cout
#include <sstream>  // std::istringstream
#include <string>   // std::string & std::getline
#include <stack>    // std::stack

int main()
{
  std::string line, word;
  std::stack<std::string> words;// std::stack<T> is hwo 

  std::getline(std::cin, line); // Get a full line of text

  std::istringstream iss(line); // Put the line in a custom stream
  while ( iss.good() )          // while the stream is still valid
  {
    iss >> word;                // extract another word
    words.push(word);           // puts it on the top of the stack
  }

  while ( !words.empty() )           // self-explanitory
  {
    std::cout << words.top() << ' '; // get the top word
    words.pop();                     // removes top word
  }
}


If you want to learn the STL, start with one container. Most people learn std::vector first.
http://www.cplusplus.com/reference/vector/vector/
Learn:
1. How to define a std::vector (std::vector<int>)
2. How to push_back() elements
3. How to access elements with [] or .at()
4. How to iterate through elements with std::vector<T>::iterator.
5. How to insert/erase elements.

The functions/methods I've used above are also all documented on this site with great examples. Whenever you decide you need to use a container, refer to the reference and figure out how to use it with the examples.
From <string>
std::getline: (function) http://www.cplusplus.com/reference/string/string/getline/
std::string: (class) http://www.cplusplus.com/reference/string/string/string/
From <iostream>
std::cin: (object) http://www.cplusplus.com/reference/iostream/cin/
std::cout: (object) http://www.cplusplus.com/reference/iostream/cout/
- operator<< http://www.cplusplus.com/reference/ostream/ostream/operator%3C%3C/
From <sstream>
std::istringstream: (class) http://www.cplusplus.com/reference/sstream/istringstream/
- constructor http://www.cplusplus.com/reference/sstream/istringstream/istringstream/
- operator>> http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/
- good() http://www.cplusplus.com/reference/ios/ios/good/
From <stack>
std::stack: (class) http://www.cplusplus.com/reference/stack/stack/
- constructor http://www.cplusplus.com/reference/stack/stack/stack/
- push http://www.cplusplus.com/reference/stack/stack/push/
- top http://www.cplusplus.com/reference/stack/stack/top/
- pop http://www.cplusplus.com/reference/stack/stack/pop/
Last edited on
Hey cool, I just read that std::stack just wraps another STL container and doesn't have it's own instantiation. I guess it just provides a abstracted layer for the std::deque (double-ended queue)
Stewbond wrote:
I wouldn't consider std::string or any of the streams part of the STL
They definitely are, string is a typedef (or alias) for something like basic_string<char>
And here's my version using only the STL.
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <iterator>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

int main() {
	vector<string> v;
	copy(istream_iterator<string>(cin), istream_iterator<string>(), back_inserter(v));
	copy(v.rbegin(), v.rend(), ostream_iterator<string>(cout, " "));
}
aalok wrote:
Yanson's code shows me that I have to study C++ more.

By the way, mastery of the STL doesn't indicate mastery of C++. C++ is not the STL. Knowing C++ means you know the syntax and semantix associated with creating objects/classes, using initializer lists, different types of inheritance/casting, being able to implement various design patterns, and template meta-programming.

The STL is just a library, if you find it confusing, you're welcome to try any number of other libraries. Qt has a good library with a QString class, QFile, QVector, etc. It aligns closely with the STL so familiarity with one will help with the other. Boost is another very good library, but can be tough to handle for beginners as it prioritizes functionality over simplicity.

You could also make your own libraries too!

naraku9333's code is only 3 lines long, but there is a ton of stuff there. That code demonstrates knowledge of the STL and C++. If you know C++, but not the STL, it'll take some time to read this, but it's still possible using STL references.

Here's an explanation:
line 10 vector<string> v;
This one is pretty simple, you're making a vector of strings. v is an object of class vector. vector uses a template parameter of a string type.

line 11 copy(istream_iterator<string>(cin), istream_iterator<string>(), back_inserter(v));
This line is much tougher. I read general->Specific. So I would start with the copy function:
http://www.cplusplus.com/reference/algorithm/copy/
It takes three parameters, The first two are iterators of the same type. The second is an iterator for a different type. Really, everything between parameter 1 and 2 are copied into parameter 3.

Parameter 1:
istream_iterator<string>(cin)
Here we are making an object without assigning it to something we can handle. It's a temporary object which is inserted as a parameter into copy. The object is not available at any other time in the main function. The object is an istream_iterator templated with a string.
http://www.cplusplus.com/reference/iterator/istream_iterator/
It is instantiated with cin, calling the "initialization" constructor described here:
http://www.cplusplus.com/reference/iterator/istream_iterator/istream_iterator/
That makes the object point to the first <string> in cin. The object uses operator++ to get the next element<string>.

Parameter 2:
istream_iterator<string>()
This is just like parameter 1, but instead of calling the initialization constructor and setting the iterator to the first element of cin, we are calling the default constructor. According to the reference this "Constructs an end-of-stream istream iterator". This satisfies the second parameter of copy().

Parameter 3:
back_inserter(v)
The back_inserter function returns an iterator to the end of the vector. As per http://www.cplusplus.com/reference/iterator/back_inserter/. If this is set to something, then it pushes the object into the vector.

Now we have all three iterators, two source iterators and a destination. Now we can see that we've "tokenized" the input into a vector.

line12 copy(v.rbegin(), v.rend(), ostream_iterator<string>(cout, " "));
This is another interesting line. We're copying all data between v.rbegin() and v.rend() into ostream_iterator<string>(cout, " "));. but what does that mean?

Parameter 1:
v is a vector<string>. Vector's method v.rbegin() is described here:
http://www.cplusplus.com/reference/vector/vector/rbegin/
It returns a reverse iterator which means it points to the last <string> in v. When incremented, it move backwards through the vector towards the start.

Parameter 2:
The first element of the vector v is where we want to stop copying. v.rend() gives us this element. So copy is going from the last element of the vector, to the first element.

Parameter 3:
ostream_iterator<string>(cout, " "). This is very similar to istream_iterator<string(cin) from line 11. See: http://www.cplusplus.com/reference/iterator/ostream_iterator/. We're creating a temporary object again which is fed to the copy function. It is of type ostream_iterator. An ostream_iterator is an object which allows us to write to a stream using iterators. So when copy() writes and increments the destination iterator, it's actually writing to a stream. The constructor we are calling is the initialization constructor (like in the last line):
http://www.cplusplus.com/reference/iterator/ostream_iterator/ostream_iterator/
This initializer constructor has two parameters, the first is the stream object which will be written to. In this case it's cout. The second parameter is the delimiter. This means we will put a space between each string.

As you can see there is a lot going on in just 3 lines. Mastery of C++ will let you read this and understand this. You can only write this if you are familiar with these methods in the STL. As you continue to code, your familiarization with that specific library will increase and you'll be more comfortable writing this stuff. Just take the time to read it first and really understand why it works. Note, you don't need to use STL, you can use Qt, boost, or some other library too.
It is best to think of the C++ programming language and the standard C++ library as an indivisible whole. Learning C++ involves learning to use its standard library - the very first hello world program uses the library. And learning to use the standard C++ library teaches one a lot about the C++ language.

Koenig and Moo devote two chapters in their 'Ruminations on C++' to explain why library and language are inseparable - 'Library design is language design' (25) and 'Language design is library design' (26).

The part of the standard library that has containers, iterators and algorithms is sometimes called 'STL'. (The name comes from Stepanov's STL library which had immense influence on the design of this part, and many other parts of the standard C++ library.) The standard library is a lot bigger than that particular subset.
mastery of the STL doesn't indicate mastery of C++.

i didn't say that, i meant that i still lack in many fields in C++.
Topic archived. No new replies allowed.