Search code examples
c++filefilestreampeek

C++ peek giving value 'ÿ' (ifstream)


My code first of all:

int GetHighScore(string name)
{
    int highScore = 0;
    ifstream fin;
    char textInFile[50];1

    fin.open(name + ".txt", ios::in);

    if (fin.fail())
    {
        // Old piece of code
        highScore = 0;
    }
    else
    {
        while (fin.good())
        {
            fin >> textInFile;
            for each (char var in textInFile)
            {
                if (var == '#')
                {
                    char c = fin.peek();

                    if (c == '1')
                    {
                        char score = fin.peek();
                        highScoreLvl1 = (int)score;
                    }
                    else if (c == '2')
                    {
                        char score = fin.peek();
                        highScoreLvl2 = (int)score;
                    }
                    else if (c == '3')
                    {
                        char score = fin.peek();
                        highScoreLvl3 = (int)score;
                    }
                }
            }
        }
        //fin >> highScore;
    }


    // Return the high score found in the file
    return highScoreLvl1;
}

It detects the '#', but then c gets assigned the value 'ÿ' when it performs the peek operation. What it should give is the number '1', '2' or '3' (in char form); but it doesn't for some reason, and I can't see why... :/

Here's what the file looks like:

level#12level#22level#32

The first number represents the level, and the second number is the score achieved on that level.


Solution

  • If your file contains the only string 'level#12level#22level#32' then it's read into textInFile in fin >> textInFile operator. When you meet '#' character in the string you're trying to peek character from the file stream but there is nothing to peek, that's why -1 (end of file) is returned.

    To fix this you need to take next character from textInFile string, not from the file. Here is example code:

    int GetHighScore(string name)
    {
        int highScore = 0;
        ifstream fin;
        char textInFile[50];
    
        fin.open(name + ".txt", ios::in);
    
        int highScoreLvl1, highScoreLvl2, highScoreLvl3;
    
        if (fin.fail())
        {
            // Old piece of code
            highScore = 0;
        }
        else
        {
            while (fin.good())
            {
                fin >> textInFile;
                bool bPrevIsHash = false;
                size_t nLength = strlen(textInFile);
                for (size_t i = 0; i + 2 < nLength; ++i)
                {
                    if (textInFile[i] == '#')
                    {
                        if (textInFile[i + 1] == '1')
                        {
                            highScoreLvl1 = (int)textInFile[i + 2];
                        }
                        else if (textInFile[i + 1] == '2')
                        {
                            highScoreLvl2 = (int)textInFile[i + 2];
                        }
                        else if (textInFile[i + 1] == '3')
                        {
                            highScoreLvl3 = (int)textInFile[i + 2];
                        }
                    }
                }
            }
        }
    
    
        // Return the high score found in the file
        return highScoreLvl1;
    }
    

    And there are several other issues with your code:

    1. You return value of highScoreLvl1 that could be left uninitialized because there can be no '#' in the string. And probably you mean to return max value of highScoreLvl1, highScoreLvl2 or highScoreLvl3.
    2. You're assigning value of char converted to int. In this case you will not get value of 1, 2, etc. You'll get ordinal of ASCII character, e.g. 0x31 (49) for '1', 0x32 (50) for 2, etc. If you need digit value you can do following trick: highScoreLvl1 = textInFile[i + 2] - '0';