0

This code here is for reversing words in a string. The problem is that it only reverses the first word in the string. When I ran a trace I found that it is stopping after encountering the statement if(s[indexCount] == '\0') break;

Why the code is getting null character every time the first word is reversed even though some other character is present after the first word.

#include <iostream>
using namespace std;
int main()
{
    string s;
    char tchar;
    int indexCount=0,charCount=0,wordIndex;
    cin>>s;
    while(1){
        if(s[indexCount]==' ' && charCount==0) continue;
        if(s[indexCount]==' ' || s[indexCount]=='\0' ){
            wordIndex=indexCount-charCount;
            charCount=indexCount-1;
            while(charCount!=wordIndex && charCount>wordIndex){
                tchar=s[wordIndex];
                s[wordIndex]=s[charCount];
                s[charCount]=tchar;
                charCount--;
                wordIndex++;
            }
            if(s[indexCount] == '\0') break;
            indexCount++; charCount=0;
        }
        else{
            charCount++;
            indexCount++;
        }
    }
    cout<<"\nReveresed words in the string : \n\t"<<s<<endl;
   return 0;
}

Also I'm using while(1). Does it make this a bad code?

Rishab
  • 1,901
  • 2
  • 18
  • 34
  • You might want to change it to `while(true)`. I wouldn't exactly say it is "bad" but if you can, you should put a clear condition inside the `while` clause. That way, when you look at the loop, it says right there what conditions the loop is operating under. – Weak to Enuma Elish Nov 09 '15 at 04:36
  • For what input did you receive bad results? – fghj Nov 09 '15 at 04:38
  • What is the difference between reversing the whole string and reversing the words in the string? – ramana_k Nov 09 '15 at 04:38
  • @ThomasG Example: `test seq` -> `tset qes` vs `test seq` -> `qes tset` – fghj Nov 09 '15 at 04:41
  • @user1034749 For any string. Try your own string and you will get only the first word reversed not the second one. Its encountering null character after first word. No idea why. – Rishab Nov 09 '15 at 04:44
  • It looks like a space is the delimiter when reading input into a string. I copied this and ran it, and the value in the string was only the first word. – Weak to Enuma Elish Nov 09 '15 at 04:45
  • I try, this `string s = "test seq of words";` and get output `tset qes fo sdrow`, may be problem in how you get input, try use `std::getline` – fghj Nov 09 '15 at 04:45
  • @user1034749 What the hell?? Why am I not getting it? Try any online compiler it shows only one word reversed. What are u using?? – Rishab Nov 09 '15 at 04:50
  • Just set `s` to some value in program, not use `cin >> s`, because of `cin >> s` just read only one word, because of reading stop on space. – fghj Nov 09 '15 at 04:51
  • @user1034749 got it. :) – Rishab Nov 09 '15 at 04:53

3 Answers3

0

The problem indeed lies with the method of input. cin >> string_variable will consider whitespace to be a delimiter. That is why only the first word is being entered. Replace cin >> s; with getline(cin, s); and it will work correctly.

Weak to Enuma Elish
  • 4,622
  • 3
  • 24
  • 36
0

First of all I want to point out that

cin >> stringObject;

will never ever read space character! so inserting My name is geeksoul will cause above code to read only My and leave everything else in the buffer!

To read space character you should use getline function like this

std::getline(std::cin, stringObject);

read about getline

Second The standard doesn't say that in case of an std::string '\0' is any special character. Therefore, any compliant implementation of std::string should not treat '\0' as any special character. Unless of course a const char* is passed to a member function of a string, which is assumed to be null-terminated.

If you really want to check your string with null terminating character then you should consider using stringObject.c_str() which converts your C++ style string to old school C style string!

Check this for c_str

Finally this might be helpful for you!

Deepanshu
  • 488
  • 6
  • 18
  • [This](http://stackoverflow.com/a/6077274/4756309) answer indicates that the asker's code will work as expected with regards to null termination. – Weak to Enuma Elish Nov 09 '15 at 05:01
  • @JamesRoot but the point is will std::string will always terminate with `'\0'` and the answer is no! – Deepanshu Nov 09 '15 at 05:07
  • The comment thread in that answer explain it as well. Firstly, in this case it is irrelevant if it is actually stored in memory there, as the asker isn't trying to modify the index with the '\0' in it. Secondly, `operator[]` returns a reference to the same data as `c_str`, so there has to be a null terminating character. However, this is assuming c++11. – Weak to Enuma Elish Nov 09 '15 at 05:11
  • @JamesRoot http://stackoverflow.com/a/11752722/3881047 but still if you can use `\0` as any other character so `\0` null is not a special character http://stackoverflow.com/a/11752711/3881047 for C++ string so I will **vote against using `\0`** to check a C++ string terminates or not! – Deepanshu Nov 09 '15 at 05:36
  • 1
    My point was simply that it is null terminated, so looping until `operator[]` returns a '\0' is not going to overrun the bounds of the string. I don't disagree that the presence of a '\0' doesn't mean the end of a `std::string`. – Weak to Enuma Elish Nov 09 '15 at 05:47
0

Quick tip. If you reverse all characters in the whole strings, and then all characters between each pair of consecutive spaces, you will achieve the same result, with way simple code, like this: (Note, this may not compile or be slightly buggy (haven't compiled or anything), but should convey the basic idea)

void reverseWords(std::string& aString) {
    std::reverse(aString.begin(), aString.end());
    size_t lastSpaceIndex = 0;
    for (size_t index = 0; index != aString.size(); ++index) {
        if (aString[index] == ' ') {
             std::reverse(aString.begin() + lastSpaceIndex + 1, aString.begin() + index);
             lastSpaceIndex = index;
        }
    }
}
Tomasz Kaminski
  • 900
  • 7
  • 14