0
\$\begingroup\$

I made this Pig Latin translator in C++ and I was wondering what I could improve and what is good about it.

I used the stringstream class to get the individual words.

#include <iostream>
#include <vector>
#include <sstream>
std::string translate(std::string word){
   if(word.length() > 1){
       word += word[0];
       word[0] -= word[0];
       word += "ay";
   }
   return word;
}
int main(){
    std::vector<std::string> v;
    std::string str = "Hello the world has ended";
    std::stringstream stringStream(str);
    for(int i = 0; i < str.length(); i++){
        std::string currentWord;
        stringStream >> currentWord;
        v.push_back(currentWord);
    }

for(int i = 0; i < v.size(); i++){
    std::cout << translate(v[i]) + " ";
}

std::cout << std::endl;

}
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Your implementation is incorrect. It doesn't trap words starting with vowels or words starting with compound consonants(eg. "th") as special cases. \$\endgroup\$
    – user33306
    Dec 1, 2017 at 3:54
  • 4
    \$\begingroup\$ word[0] -= word[0];: AHHHHHHHHHHHH!!! \$\endgroup\$
    – user128454
    Dec 1, 2017 at 3:57
  • \$\begingroup\$ The only thing I have to add to Loki's answer is that you should separate IO and logic. Keep your IO in main() and the processing of the string should be in another function. That other function should return a string which then can call cout in main. This way the code is usable in other contexts. \$\endgroup\$
    – Snowbody
    Dec 2, 2017 at 7:27

1 Answer 1

2
\$\begingroup\$

Couple of issues:

This appends the first letter of the word onto the end.

       word += word[0];

Since I don't know what "PigLatin" is I can't tell if this is correct. A comment about what is the expected translation is really required so we can understand if this is correct behavior.

This sets the first letter to 0.

       word[0] -= word[0];

Note: NOT the character 0 but the number zero which is an unprintable character (there are no glyphs that represent the number 0). Note the character 0 is represented by the number 48 (in ASCII or UTF-8).

Did you want to remove the first character from the string?

word = word.substr(1); // Gets the substring from 1 to the end.
                       // Assigns it to the variable word.

Adds the string "ay" to the end of word.

       word += "ay";

Sure. Sounds reasonable. But need to understand the expected behavior/

You have a string. Which you are converting into a sequence of words and storing in v.

    std::vector<std::string> v;

But the only thing you do with v is loop over it and get each word to call translate() with. Why not remove the middle man and not use the container at all.

Here You are creaging a loop as long as the string. But each iteration you are taking a word from the string.

    for(int i = 0; i < str.length(); i++){

So this will have a lot of blank words on the end. A better way is to read words from the stream until there are no more words in the stream.

    while (stringStream >> currentWord) {
        // Do stuff with currentWord
    }

Avoid the use of std::endl.

std::cout << std::endl;

Its probably not doing any harm here. But its a bad habit. The difference between \n and std::endl is that std::endl also flushes the buffer. Manually forcing a buffer flush is usually incorrect. The buffers will auto flush at the optimal time. Program inserted flushing is usually wrong and is a major cause of eniffciency in C++ code.

I would refactor the inner loop like this:

    while (stringStream >> currentWord) {
        std::cout << translate(std::move(currentWord)) + " ";
    }
    std::cout << "\n";

Notice the std::move() this moves an object to the function (saves a copy). So at the translate() needs to be changed slightly.

std::string translate(std::string&& word)
{                                ^^  bind a moved parameter.
   // stuff.
   return word;
}
\$\endgroup\$
2
  • \$\begingroup\$ When you say "bind a moved parameter" what do you mean. I am reasonably new to C++. \$\endgroup\$
    – Asher
    Dec 2, 2017 at 7:24
  • \$\begingroup\$ When you use std::move() to pass a parameter to a function it will find functions that will accept the parameter with && on it. \$\endgroup\$ Dec 2, 2017 at 9:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.