Search code examples
c++stringvectorwords

Get a word from a string, change it, and put it back to the correct place


I am trying to receive an input, whatever it may be. Do something to the word, and then cout the word back to the user. Here is the thing, I cannot restrict the user from entering whatever they want, so I have to deal with the consequences. Before you guys start accusing me, no, its not a homework.

I have to keep the words in their respective places. So if someone writes

> "  he*llo !w3rld  ."

I have to keep the metacharacters in their places.

So lets say the change was just to scramble. It has to output

> "  eh*olo !w3ldr  ."

What I want to do with the word once I retrieve it is not relevant. The only problem I'm having is actually recognizing the word, doing something to it and returning it.

To make you understand better here is my below code

int main(){

string str;
cout<<"Enter a string: ";
getline(cin, str);
cout<<endl;
str= str + " ";


int wordFirstLetter = 0;
int currentWordLen = 0;
int p=0;
while((unsigned)p <str.length())
{
    if (isalpha(str[p])) // if letter
 { 
    str[p] = tolower(str[p]);
    currentWordLen++;
 }

  else if(!isalpha(str[p])) { //if no letter    

cout <<change(str.substr(wordFirstLetter,currentWordLen)) + " ";
wordFirstLetter = p+1;
//currentWordLen++;

currentWordLen = 0;

}
p++;

//cout<<wordFirstLetter<<" "<<currentWordLen<<endl;
}

return 0;
}

As you can see here I am running a a function called change on the substring every time the space in the array of the string is not a letter. But this fails miserably, because if the sentence starts with a space or has multiple spaces then the program crashes.

I have been looking around and thinking a lot about this. There needs to be two states, where I find a letter and where I don't. If I find something before I even hit one letter I can print it out.

I need to preserve that letter in some other space while I keep looking inside the sentence. When I hit something that is not a letter I need to change the word and print it along with whatever I hit and then reset the space and keep going. I just can't get around my head the functional way of doing this.

There is no need to use regular expressions, I feel it would be overkill. So please do not come to me with modern regex libraries and try to teach them to me and since I am not writing in pearl where regex is integrated I have no use for them. And there is no need to use Finite state machines.

I feel like this is such an easy thing but I just can't hit the spot.

In another thread someone suggested the below code to find words

std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}


std::vector<std::string> split(const std::string &s, char delim) {
    std::vector<std::string> elems;
    split(s, delim, elems);
    return elems;
}

It got a lot of positive reviews but I don't know how to implement that and work with what I want.

I will edit as you guys ask me questions. Thanks


Solution

  • You can do something like that :

    #include <vector>
    #include <string>
    #include <iostream>
    
    std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {  
        std::stringstream ss(s);
        std::string item;
        while (std::getline(ss, item, delim)) {
            if ( item.lenght() > 0) {   // This checks if the string is not empty, to filter consecutive white space.
                elems.push_back(item);
            }
        }
        return elems;
    }
    
    std::string doSomething(const std::string original) {
        // do whatever you want with original which is a word.
        return modified; // where modified is std::string
    }
    
    int main() {
        std::string input;
        std::vector<string> listOfWords;
    
        std::cout << "Input your phrase :" << std::endl;
        std::cin >> input;
    
        split(input, " ", &listOfWords);
    
        for(int i = 0; i < listOfWords.size(); i++) {
            std::cout << "Input was : " << listOfWords[i]
                      << "now is : " << doSomething(listOfWords[i]);
        }
    
    }