-1

So I'm creating a program which translate any word into "Malang slang". It's basically just a reversal of the letters in a word except for "ng".

Everything to plan, except when I encounter this problem. When I input a word with length of nine or ten, the program shows additional characters to the screen:

1. Translate to/from Malang slang
2. Exit
Choose your option: 1

Insert your sentence/word here: tenletters
Malang slang: srettelnet╨o

Malang Slang Translator
1. Translate to/from Malang slang
2. Exit
Choose your option: 1

Insert your sentence/word here: nineletter
Malang slang: rettelenin╨o

//How it should be:
Malang Slang Translator
1. Translate to/from Malang slang
2. Exit
Choose your option: 1

Insert your sentence/word here: tenletters nineletter
Malang slang: srettelnet rettelenin

The code that I use is this:

#include <iostream>
#include <string.h>
#include <sstream>
using namespace std;

void ignoreLine()                                                       //ignore line
{
    cin.clear();
    cin.ignore(100, '\n');
}

void clearArray(string word, char* reversed_word)                       //function to clear char array
{
    for(int i = 0; i < sizeof(reversed_word)+1; i++)
        reversed_word[i] = NULL;
}

void swapChar(char* char1, char* char2)                                 //Swaps char
{
    char temp = *char1;
    *char1 = *char2;
    *char2 = temp;
}

void reverseWord(string word, char* reversed_word)                      //function to reverse words [used inside tokenizer]
{
    clearArray(word, reversed_word);

    for(int i = 0, j = word.size() - 1; i < word.size(); i++, j--)
        reversed_word[j] = word[i];

    for(int i = 0; i < word.size() - 1; i++)
    {
        if((reversed_word[i+1] == 'n' || reversed_word[i+1] == 'N') && (reversed_word[i] == 'g' || reversed_word[i] == 'G'))
            swapChar(&reversed_word[i], &reversed_word[i+1]);
    }
}

void tokenizer(string sentence, char* reversed_word)                    //function to tokenize/separate strings per spaces
{                                                                       //using stringstream
    stringstream ss(sentence);
    string word;

    cout << "Malang slang: ";
    while(ss >> word)
    {
        reverseWord(word, reversed_word);
        cout << reversed_word << ' ';
    }
    cout << endl << endl;
}

void translateMalang()
{
    string sentence;
    fflush(stdin);                                                      //Clears buffer

    cout << "\nInsert your sentence/word here: ";
    getline(cin, sentence);
    if(sentence.empty())                                                //If no input, return to main menu
    {
        cout << "No words inputted." << endl;
        return;
    }

    char reversed_word[sentence.size()];                                //declare reversed_word variable as char array

    tokenizer(sentence, reversed_word);                                 //execute tokenizer function
}

void mainMenu(bool* finished)
{
    int option = 0;
    cout << "Malang Slang Translator\n1. Translate to/from Malang slang\n2. Exit\nChoose your option: ";
    cin >> option;

    switch(option)
    {
    case 1:
        translateMalang();
        break;
    case 2:
        *finished = 1;
        break;
    default:
        cout << "Invalid input!" << endl << endl;
        break;
    }
}

int main()
{
    bool finished = 0;

    while(!finished)
    {
        while(cin.fail())
        {
            ignoreLine();
            cout << "Please enter an integer!" << endl;
        }

        mainMenu(&finished);
    }

    return 0;
}

Does anyone know why this happens and what's the solution for this? Thanks!

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • 2
    Consider the type of `reversed_word ` and look at `std::cout << sizeof(char*);`. (Why didn't you stick to `std::string`?) – molbdnilo Mar 27 '22 at 08:50
  • 1
    *"When I input a word with length of nine or ten,"* -- This might be true, but if your example code was supposed to demonstrate this, it failed. (A ten-letter word, such as "nineletter" does not become a nine-letter word simply because it contains "nine" as a substring. You might want to consider using a different example for your demonstration.) – JaMiT Mar 27 '22 at 08:57
  • 1
    `char reversed_word[sentence.size()];` This is not valid C++. [Why aren't variable-length arrays part of the C++ standard?](https://stackoverflow.com/questions/1887097/why-arent-variable-length-arrays-part-of-the-c-standard) – Camwin Mar 27 '22 at 08:59
  • ` sizeof(reversed_word)` is not the length of the array but the size of the pointer type. I believe, that is not what you want :-) – Klaus Mar 27 '22 at 09:05
  • I see, then a big part of the problem with my code is my inconsistency with my data types? Thanks for the answers. (Btw, yes, the example I used wasn't a 9-letter word, I miscounted) – Giga Hidjrika A A Mar 27 '22 at 12:46

1 Answers1

2

This call of the function fflush with the input stream

fflush(stdin);

has undefined behavior.

In this declaration

char reversed_word[sentence.size()];

there is declared a variable length array. Variable length arrays are not a standard C++ feature. Actually there is no sense to declare the variable length array. You could deal as usually with an object of the type std::string.

For example to reverse the string stored in the object word you could use the standard algorithm std::reverse

std::reverse( std::begin( word ), std::end( word ) );

It is also easy to reverse a string in place using a for loop. For example

for ( std::string::size_type i = 0, n = word.size(); i < n / 2; i++ )
{
    std::swap( word[i], word[n - i - 1] );
}

Moreover the array does not contain a string because it is not ended with the terminating zero character '\0'. So this statement

cout << reversed_word << ' ';

invokes undefined behavior.

Pay attention to that there is already standard function std::swap that allows to swap two objects.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335