Hugetanks
Hugetanks

Reputation: 21

How to fix the random character outputs in C++?

When I get string input by using char arrays and I cycle through them with a for loop, my code always has random character outputs that should not be there.

I have tried debugging my code, by checking the output at various stages, but I can't find the reason for what is happening.

    int k, s, counter = 0;
    char word[21];

    std::cin>>k;
    std::cin.getline(word,21);
    for (int i = 0; word[i] != ' '; i++)
    {
        s = 3*(i + 1) + k;
        std::cout<<s;
        for (int k = 0; k < s; k++)
        {
            word[i]--;
            if (word[i] < 'A')
               word[i] = 'Z';
        }
    std::cout<<word[i];
    }

When I type in 3 to get the value of k, I already get the output "URORIFCFWOQNJCEBFVSPMJNKD" when I should not get any output.

Upvotes: 0

Views: 1084

Answers (2)

Martin Konrad
Martin Konrad

Reputation: 1095

std::cin >> k; is reading an integer only. It does not read the trailing line break. The documentation of the >> operator says

The extraction stops if one of the following conditions are met:

  • a whitespace character [...] is found. The whitespace character is not extracted.

As Just Shadow pointed out this line break is causing the getline() call to return an empty string.

You can ignore any number of line breaks by calling

std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

BTW: Looking at your outer for loop I would be concerned that you might read beyond the end of word if the string doesn't contain any whitespaces. The following solution fixes that as well:

#include <iostream>
#include <limits>

int main() {
    int k, s, counter = 0;
    char word[21];

    std::cin >> k;
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    std::cin.getline(word, 21);
    for (int i = 0; i < sizeof(word) && word[i] != ' '; i++)
    {
        s = 3 * (i + 1) + k;
        std::cout<<s;
        for (int k = 0; k < s; k++)
        {
            word[i]--;
            if (word[i] < 'A')
               word[i] = 'Z';
        }
        std::cout << word[i];
    }
}

Upvotes: 0

Just Shadow
Just Shadow

Reputation: 11921

The problem is that the buffer is not flushed before using getline.
Because of that when you hit enter after entering a number, that enter (character '\n') is passed to getline(), and at that point getline ends his work by leaving the word empty.

The solution to this is simple: Flush the buffer before getline.

Here is the complete solution:

#include <iostream>

int main() {
    int k, s, counter = 0;
    char word[21];

    std::cin>>k;

    // Clear the buffer
    std::cin.clear();
    while (std::cin.get() != '\n') 
    {
        continue;
    }

    std::cin.getline(word,21);

    std::cout<<"TEST>"<<word<<"<TEST"<<std::endl<<std::flush;

    for (int i = 0; word[i] != ' '; i++)
    {
        s = 3*(i + 1) + k;
        std::cout<<s;
        for (int k = 0; k < s; k++)
        {
            word[i]--;
            if (word[i] < 'A')
               word[i] = 'Z';
        }

        // Use std::flush to forcefully print current output.
        std::cout<<word[i]<<std::flush;
    }
}

Notes:

  • I've used the buffer clearing mechanism described there. You might use another, but the idea is the same
  • If you comment the 4 lines of that buffer clearing part, you'll notice that as soon as you type "3" and hit enter, you see an output like "TEST><TEST" which means that the word inside it, is empty.
  • Consider using std::flush while using cout if you want forcefully print the output before the for cycle ends.

Upvotes: 1

Related Questions