cout output overlaps in console

Hi everyone,

I have been learning C++ recently, and decided to write a small program to practice a bit. I want my program to:

1. Pick a word "randomly" in a test file;
2. mix the letters of that word "randomly";
3. Ask the user to find the original word (5 tries).

My program uses 3 functions, although only two a relevant to this topic:

A - This function picks a word randomly in a file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
string pigeUnMot(string chemin)
{
    int nbMots(0);
    int nbAleatoire;
    string motChoisit;

    ifstream flux(chemin.c_str());

     if(flux)
     {
        while(getline(flux, motChoisit))
        {
            nbMots++;
        }

        ifstream flux(chemin.c_str());
        
        srand(time(0));
        nbAleatoire = rand() % nbMots;
        nbAleatoire++;
        for(int i(0); i < nbAleatoire; i++)
        {
            getline(flux, motChoisit);
        }
    }
    else
    {
        cout << "ERREUR: Impossible d'ouvrir le fichier en lecture." << endl;
    }

    return motChoisit;
}


B - This function mixes up the letters of a word:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
string melangeLettres(string mot, int const longueur)
{
    srand(time(0)); 

    int position; 
    string motMelange;

    for(int i(0); i < longueur - 1; i++)
    {
        position = rand() % mot.size(); 
        motMelange.push_back(mot[position]); 
        mot.erase(position, 1);
    }
        motMelange.push_back(mot[0]);

        return motMelange;
}


I also have another function which calculates an average, but it works fine. Here is my main:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <iostream>
#include <fstream>

#include <string>
#include <ctime>
#include <cstdlib>
#include <vector>

using namespace std;

int main()
{
    string motMystere; 
    string motMelange; 
    string motReponse; 
    string dictionnaire("files/dico.txt"); 
    int nbEssais(5); 
    vector<int> moyenne; 
    double moyenneCumul; 
    char decision; 

    do
    {

    motMystere = pigeUnMot(dictionnaire); // Picks a word

    motMelange = melangeLettres(motMystere, motMystere.size()); // Mixes the word

    cout << "Quel mot mystère se cache derrière: " << motMelange << "?" << endl << endl; // Here is my problem!

        do
        {
        cout << "Le mot mystère est: ";
        getline(cin, motReponse);

            if(motReponse.size() == 0)
            {
                cout << endl << "Mauvais perdant(e)!! ;-P" << endl;
                --nbEssais;
                cout << "Il vous reste " << nbEssais << " essais!" << endl << endl;
            }
            else if(motReponse.size() != motMystere.size()) 
            {
                cout << endl << "Attention! Le mot mystère est composé de " << motMystere.size() << " lettres!" << endl;
                --nbEssais;
                cout << "Il vous reste " << nbEssais << " essais!" << endl << endl;
            }
            else if(motReponse != motMystere)
            {
                cout << endl << "Oups! Mauvaise réponse. Essayez à nouveau: " << endl;
                --nbEssais;
                cout << "Il vous reste " << nbEssais << " essais!" << endl << endl;
            }
            else
            {
            }
        }
        while((motReponse != motMystere || motReponse.size() == 0) && nbEssais != 0);

        if(nbEssais == 0)
        {
            moyenne.push_back(nbEssais);
            moyenneCumul = moyenneVector(moyenne); 
            cout << endl << endl << "Vous avez perdu!!" << endl << endl << "Votre moyenne est de " << moyenneCumul << " points.";
            nbEssais = 5;
        }
        else 
        {
            moyenne.push_back(nbEssais);
            moyenneCumul = moyenneVector(moyenne); 
            cout << endl << endl << "Félicitations! Vous avez trouvé le mot mystère!!" << endl << endl << "Votre moyenne est de " << moyenneCumul << " points.";
            nbEssais = 5;
        }

        do
        {
            cout << endl << endl << "Voulez-vous rejouer? (o/n)";
            cin >> decision;
            cin.ignore(); 
        }
        while(decision != 'o' && decision != 'O' && decision != 'n' && decision != 'N');

    }
    while(decision == 'o' || decision == 'O');

    return 0;
}


When I run this, I get the following console output:


RNGFLIEZE?uel mot mystère se cache derrière: I

Le mot mystère est:


The non mixed word is: INFLIGEREZ. I would like the output to be:


Quel mot mystère se cache derrière: IRNGFLIEZE?

Le mot mystère est:


Also, when I enter the correct word, I tells me I'm missing one letter...

I really don't understand what is happening here, and why this is not working. Any help would be greatly appreciated.

Last edited on
That is very weird. What compiler are you using?
I'm using the GNU GCC compiler.
Another weird thing about this code: in the pigeUnMot function, if I check the size of the motChoisit string, I get this:

Adding a cout:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
string pigeUnMot(string chemin)
{
    int nbMots(0);
    int nbAleatoire;
    string motChoisit;

    ifstream flux(chemin.c_str());

     if(flux)
     {
        while(getline(flux, motChoisit))
        {
            nbMots++;
        }

        ifstream flux(chemin.c_str());

        srand(time(0));
        nbAleatoire = rand() % nbMots;
        nbAleatoire++;

        for(int i(0); i < nbAleatoire; i++)
        {
            getline(flux, motChoisit);
        }
    }
    else
    {
        cout << "ERREUR: Impossible d'ouvrir le fichier en lecture." << endl;
    }
    cout << "Voici le " << motChoisit; // Picked word output
    cout << endl << motChoisit.size() << endl; // size of picked word output
    return motChoisit;
}


Console output, for these cout:


Voici le RAMOLLIREZ
11


This is weird because I got a 10 letters word, not 11...

Any help would be gladly appreciated, I'm starting to get crazy on this...
Have you tried restarting your computer?
Hi,

I have finally found a solution to my problems. I decided to post it here, in case somebody else runs into similar issues.

1. The extra character problem

As I mentioned in my last post, there was an extra character in the string returned by the pigeUnMot() function. I did some testing, and found out that the last character always was a "\r" (carriage return character).

Now, about the getline() functon:


Extracts characters from is and stores them into str until the delimitation character delim is found (or the newline character, '\n', for (2)).


On some other post, I found that depending on your OS, the newline sequences in texts files vary.
- In Windows, the newline sequence is "\r\n";
- In GNU/Linux, the newline sequence is "\n";
- In MacOS, the newline sequence is "\r".

The text file I use in this code (dico.txt), comes from a Windows environment. However, I am compiling this code on a GNU/Linux environment, which means that the getline() function will take everything up to the "\n" character, including the "\r" character. In other words, in my example above, with RAMOLIREZ, the getline() function actually took RAMOLIREZ\r, and stopped at the "\n", which explains the 11 character count, although there are truly only 10 letters in the word.

2. The overlapping console output problem

So in every string my pigeUnMot() function returns, there is a "\r" character (carriage return). When I cout these strings, the computer is told: "print the letters in the string, and then make a carriage return". In other words: "print the letters in the string, and then put the cursor back at the beginning of the line."

No wonder why everything is overlapping...

3. Solutions to this issue

I have found two solutions to this issue:
1) Systematically remove the last character of each string before printing it to the console. For example, in my case, I added the line:

motChoisit.pop_back();

at the end of my pigeUnMot function. This removes the last character in the string. In this case, it removes the unwanted "\r" character.

2) Use the dos2unix program proposed by Duoas. Haven't tried this option yet, but I will very soon!

Hope this will help somebody not loose days on this, as I have.

@fabtasticwill: thanks for your support!

Sources
---
1) getline() function: http://www.cplusplus.com/reference/string/string/getline/
2) Different OS newline sequences: http://www.cplusplus.com/forum/general/51349/#msg279286 (Duoas's intervention)
3) dos2unix link: http://linux.die.net/man/1/dos2unix

EDIT: Just been reading the dos2unix man pages, and found this interesting paragraph:

In DOS/Windows text files a line break, also known as newline, is a
combination of two characters: a Carriage Return (CR) followed by a
Line Feed (LF). In Unix text files a line break is a single character:
the Line Feed (LF). In Mac text files, prior to Mac OS X, a line break
was single Carriage Return (CR) character. Nowadays Mac OS uses Unix
style (LF) line breaks
.



EDIT 2: Just tried dos2unix program. Works like a charm! I read in that manual that it can work both ways, too. I prefer this solution, as it makes your program more portable, and simplifies the code.

Cheers!
Last edited on
Topic archived. No new replies allowed.