Paula
Paula

Reputation: 87

C++/QT - File reading stops unexpectedly. Everything else is working as it should

I have a very strange issue. I have this code, which is supposed to loop until the end of the file. But it only loops exactly two times. It never finishes the while, but it reaches the end of the "if" or "else" sentence (depending on the file content).
Everything else is working "good", the numbers that are supposed to be going in are going in, and everything seems to be working until it doesn't reach the end of the while. This is a futoshiki game. The code is supposed to read each line, treat it as a string, and then break it down into chars, which in turn are casted into integers (except for one char, being a less-than or greater-than sign), which make up the position of the cells or the positions between the signs. Then it uses that data to either add a new cell to the board or a new sign between cells.
The first line of a file is the size of the board.
This issue happens with several different files of different sizes, always on the second iteration. I'm running Linux by the way if it makes any difference.

int MainWindow::charToInt(char letter)
{
    int number = letter;
    return number - 48;
}

void MainWindow::locateInBoard(string data, board gameboard)
{
    if (data.size()==3){
        int number = charToInt(data[2]);
        pair<int,int> coordinate(charToInt(data[0]), charToInt(data[1]));
        gameboard.addCell(number,true,coordinate);
    }
    else{
        pair<int,int> firstCoordinate(charToInt(data[0]), charToInt(data[1]));
        pair<int,int> secondCoordinate(charToInt(data[2]), charToInt(data[3]));
        gameboard.addSign(firstCoordinate, secondCoordinate, data[4]);
    }
}

void MainWindow::getBoardFromFile(QString newString, board* ptToBoard)
/*
    Each board has a file. The name of the file is determined by the size of the
    board to play, the difficulty and the number of board. The text file contains the
    sign and numbers of the board. Let's say the number 3 is in position (2,1), then the
    file should contain a line "213". For signs, if there is a > between (3,3) and (3,4),
    the file should have a line "3334>"
*/
{
    QFile file(newString);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)){
        return;
    }
    QTextStream in(&file);
    QString line = in.readLine();
    size = line.toInt();
    board gameboard(size);
    string stdline;
    while (!in.atEnd()) {
        line = in.readLine();
        stdline = line.toStdString();
        locateInBoard(stdline,gameboard);
    }
    *ptToBoard = gameboard;
}

And this is the relevant code of "board".

board::board(int n)
{
    boardSize = n;
    gameboard = new cell*[boardSize];
    for (int i = 0; i<boardSize; i++){
        gameboard [i] = new cell[boardSize];
    }
    pair<int,int> newPosition;
    for (int i = 0; i<boardSize; i++){
        newPosition.first = i;
        for (int j = 0; j<boardSize; j++){
            newPosition.second = j;
            gameboard[i][j].setPosition(newPosition);
        }
    }
}

void board::addCell(int number, bool fixed, pair<int,int> position)
{
    cell newCell(number,fixed,position);
    gameboard[position.first][position.second] = newCell;
}

void board::addSign(pair<int,int> firstPosition, pair<int,int> secondPosition, char sign)
{
    cell firstCell = gameboard[firstPosition.first][firstPosition.second];
    cell secondCell = gameboard[secondPosition.first][secondPosition.second];
    gameRules.setUnequality(firstCell,secondCell,sign);
}

I know it's not pretty, but I should've handed this in Wednesday and it's three am Thursday and I really don't care anymore if it's pretty or hard-coded as long as it's working.

Thanks a lot for your help, I'm really desperate here.

Upvotes: 0

Views: 108

Answers (1)

Alex P
Alex P

Reputation: 1609

Take a look at the signature of your locateInBoard method:

void MainWindow::locateInBoard(string data, board gameboard)

That's passing the board by value. So all changes made to the board in locateInBoard are applied to a local copy, which will just get thrown away when the function completes.

Try pass-by-reference instead:

void MainWindow::locateInBoard(string data, board & gameboard)

In addition, I'm worried about this:

board gameboard(size); // created locally
// ... lots of processing ...
*ptToBoard = gameboard; // copy using assignment operator

This is something that can work, but you have to make sure your board class correctly supports copying data. C++ generates default assignment operators if you don't write your own, but they don't work for anything other than trivial structures. You'll likely need to implement your own assignment operator or change your code to avoid using assignment or a copy constructor.

Here's a quick alternative that avoids needing to figure out how to write your own operator=:

board * MainWindow::getBoardFromFile(QString newString)
{
    // ...
    board * gameboard = new board(size);
    // ... do all of your stuff ...
    // you'll need to change your existing code to use -> instead of .
    // if you get an error, return 0 or throw an exception
    return gameboard;
}

(If you don't want to support copy constructors and operator=, it's good practice to write your own anyway — just make them do nothing and markthem private in your header. This'll allow the compiler to help you catch unintended copying.)

Upvotes: 2

Related Questions