Hi guys,

I posted earlier today and had my problem resolved in record time, which was great as I had been struggling with the final elements of an assignment. Having received a preview automarking I found that I had one small error. Essentially, the read() function which follows takes an input file and reads the contents into a 2d vector - a vector of boolean vectors. Preceding the series of 1s and zeroes are the number of rows and columns. For example:

4 4
0011
1100
1001
0110

My function works perfectly as long as the number of rows and columns matches the actual number of rows and columns which are presented in the data. However, if one provides a file such as this:

3 5
11011
11011

It sets the extra row to a series of 1s:

MY VERSION WHICH IS INCORRECT
3 5
11011
11011
11111

CORRECT VERSION WHICH I AM TRYING TO ACHIEVE

3 5
11011
11011
00000

Here is the code:

void bitmap::read(string filename)
{
	ifstream infile;	// declare ifstream object
	
	infile.open(filename.c_str());
    
	infile >> numrows >> numcols;
		
	grid.clear();	// before reading in new values must clear grid
	
	grid.resize(numrows, vector <bool> (numcols,false));	// resize grid with new dimensions
    
	char ch;   // read in as char 
		  
	for(int i = 0; i < numrows; i++)	// cycle through rows
	{

		for(int j=0; j < numcols; j++)	// cycle through columns
        {

                 infile >> ch;
				
				grid.at(i).at(j) = ch-'0';	
         }

	} 
	
}

I am having difficulty moving forward at the moment because as far as I can tell any extra values should be set to false as I did so when I resized the vector, setting *all* the values to false. My suspicion is that somehow I am misunderstanding the inner for loop which assigns the values. As ever any help would be greatly appreciated.

Kind regards,

Daniel

Dani AI

Generated

Nice follow-up from — the symptom you saw is exactly what happens when an extraction fails: the stream goes bad and the last-read value is reused by your loop. Two practical fixes: check the stream result after each extraction, or read whole lines and parse them. Reading lines is usually simpler and more robust for grid-style input.

Try this pattern: read the header with >>, consume the remainder of that line, then call std::getline once per expected row. Trim a trailing \r (Windows files), copy up to numcols characters, and leave any missing characters as the false defaults you already set. Example:

void bitmap::read(const std::string& filename) {
    std::ifstream in(filename.c_str());
    if (!in) throw std::runtime_error("cannot open file");

    int rows = 0, cols = 0;
    if (!(in >> rows >> cols)) throw std::runtime_error("bad header");
    grid.assign(rows, std::vector<bool>(cols, false));

    std::string line;
    std::getline(in, line); // consume end of header line
    for (int r = 0; r < rows; ++r) {
        if (!std::getline(in, line)) break; // missing rows -> leave defaults false
        if (!line.empty() && line.back() == '\r') line.pop_back();
        int limit = std::min(cols, static_cast<int>(line.size()));
        for (int c = 0; c < limit; ++c) {
            if (line[c] == '1') grid[r][c] = true;
            else grid[r][c] = false; // treat anything else as 0 or validate as needed
        }
    }
}

Why this helps: getline won’t silently reuse the last character on EOF, so incomplete files simply leave defaults intact. If you prefer strict parsing, detect short rows or missing lines and report an error instead of silently padding. Note: vector<bool> is a bit-packed specialization — fine for simple stores, but use vector<char> or vector<uint8_t> if you need true element references or predictable performance.

Suggested tests: header mismatches (fewer rows/cols), short lines, extra characters, and CRLF files. This approach will stop the stray "11111" row and make behavior deterministic for the automarker.

Recommended Answers

All 2 Replies

If you're at the end of file, then infile >> ch will return end of file, and ch will remain unchanged. So you get whatever char you last successfully read repeated for all the times input fails.

Like this IIRC

if ( infile >> ch ) {
} else {
  // end of the show, exit the loops
}

Thankyou Salem!!! As a newbie who aspires to becoming an accomplished programmer, this site is truly fantastic. This is a wonderful learning tool. Thanks again, mate.

PS: As a sign of respect I am going to research the int main() vs void main() issue .

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.