C++ Problem

MarkLuvsCS

Senior member
Jun 13, 2004
740
0
76
Hello everyone,

I've spent a few hours trying to get part of my program working so i can move forward with my project but I've become stuck and I'm not quite sure where I'm going wrong. If you have any advice, I would greatly appreciate it. The following code is using a dummy text file "grid.txt".

While on my laptop just before I got home it was printing the first line with numbers in the 40s, then every line after that was printing what looked to be the max negative double number for each item after that. When I tried to recompile on desktop after getting home it doesn't display anything. I must be missing a minor error somewhere for that problem.

grid.txt shown below
Code:
0 0 0 0 0
1 0 0 1 1
0 1 0 1 1
0 1 0 1 0
1 0 1 0 1


Code:
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main () 
{
	ifstream blobFile;
	blobFile.open ("grid.txt");

	int rows = 0;
	int coloumns = 0;

	string lineBuffer;	//	buffer to temp store a string 

	if(blobFile.is_open())
		{
			while(!blobFile.eof())
			{
				getline(blobFile,lineBuffer);
				rows += 1;
			}
			coloumns = ((lineBuffer.size()) / 2) + 1; //input contains 0s and 1s separated by spaces. This will give the right number taking away the spaces between the numbers.
		
			/*------------------------------------------------------------------------------------------------

			Dynamically allocate the memory for the array based on the dimensions found in the previous search.

			-------------------------------------------------------------------------------------------------*/
			int **blobGrid;
			blobGrid = new int *[rows];

			for(int i = 0; i < rows; i++)
				blobGrid[i] = new int [coloumns];
			
			/*------------------------------------------------------------------------------------------------

			We need to reset the beginning of the seek function for the file to position 0 to go to next check

			-------------------------------------------------------------------------------------------------*/
			
			blobFile.seekg(0, ios::beg);
			while(!blobFile.eof())
			{
				int temp = 0;
				int temp2 = 0;
				string tempLine; 
				getline(blobFile, tempLine);
			
				/*---------------------------------------------------------

				getting each character of string tempLine and storing the
				int (0 or 1) if its not a space char.

				----------------------------------------------------------*/

				for(int i = 0; i<tempLine.length(); ++i)
				{
					if(i != ' ')
						{
							blobGrid[temp][temp2] = int(tempLine.at(i));
							temp2 += 1;
						}
				}
				temp += 1;
			}
		
		/*---------------------------------------------------------

		printing the contents of the array

		----------------------------------------------------------*/

		for(int i = 0; i < rows; i++)
			{
			for(int j = 0; j < coloumns; j++)
				{
				cout << blobGrid[i][j] << " ";
				}
			cout << endl;
			}

		} //end of blobFile.open()
		blobFile.close();

	cin.get(); // keep the window open so I can see what was last in console
	cin.get();
}
 

Merad

Platinum Member
May 31, 2010
2,586
19
81
Are you familiar with ASCII and how characters are represented in memory? Without really dissecting your code it sounds like you're probably reading the character '0' and directly casting it to an int instead of converting it. '0' is represented in memory by the numeric value 48. Use a function like atoi to convert integer value in string form to an int, or if you know this will just be a single digit, you can use if statements:

Code:
char c = /* stuff */;
int value;

if (c == '0')
  value = 0;
else if (c == '1')
  value = 1;
// ...
 

purbeast0

No Lifer
Sep 13, 2001
53,764
6,645
126
im not really following exactly what is going on, but your for loop is not going to do anything at all.

Code:
for(int i = 0; i<tempLine.length(); ++i)
{
	if(i != ' ')
	{
		blobGrid[temp][temp2] = int(tempLine.at(i));
		temp2 += 1;
	}
}

that if statement is going to be hit all the time, because i is an int that is going to be 0, 1, 2, ..., etc. and it will always be not equal to the space character.
 

MarkLuvsCS

Senior member
Jun 13, 2004
740
0
76
Thank you Merad and purbeast. I can't believe i missed that if error, and I wasn't thinking through the conversion of chars to int. I had actually started using chars but switched everything to ints thinking it should work was a mistake. I cleaned up that block of code and used

Code:
char c;

for(int i = 0; i<tempLine.length(); ++i)
		{
			c = tempLine.at(i);
			if(c == '0')
				{
					blobGrid[temp2][temp] = 0;
					temp2 += 1;
				}
			else if (c == '1')
				{
					blobGrid[temp2][temp] = 1;
					temp2 += 1;
				}
		}
 

Pia

Golden Member
Feb 28, 2008
1,563
0
0
I've spent a few hours trying to get part of my program working so i can move forward with my project but I've become stuck and I'm not quite sure where I'm going wrong. If you have any advice, I would greatly appreciate it.
Basically any time you are dynamically allocating memory with 'new', you are asking to get burned. Your code already leaks all the memory it allocates. Use std::vector instead of arrays. Then you also don't have to read the file twice; vectors expand as you push more stuff into them. For picking out the numbers you can use stringstream.
Code:
vector< vector<int> > grid;
while (!blobFile.eof()) {
  getline(blobFile,lineBuffer);
  stringstream lineSS(lineBuffer);
  int i;
  vector<int> line;
  while(lineSS >> i) line.push_back(i);
  grid.push_back(line);
}
There's your grid (grid[1][0] is 1, and so forth), only this time no memory will be leaked. This is the plain way of writing this code; using standard library algorithms and iterators would make the code even shorter and possibly slightly more efficient.

By the way, what compiler are you using? If it happens to support the C++11 standard, the code can be further tidied up. For instance, printing the grid would become this:
Code:
for(const auto& row : grid) {
  for(int i : row)
    cout << i << " ";
  cout << endl;
}
 

MarkLuvsCS

Senior member
Jun 13, 2004
740
0
76
Thanks for the information Pia!

I'm using VS2012, but I'm still getting used to all it's capabilities. I love breakpoints and stepping through, they've helped me tremendously with this project. I will give your suggestion a try, it certainly looks considerably easier. I ran into with my setup was trying to pass my grid to a recursive function so I'll happily give this a try.

To pass the vector by reference to a function to allow manipulation, would i just need to have
void blah(&grid, x ,y). That is where I've gotten myself stuck.

Thanks again Pia!
 
Last edited:

Pia

Golden Member
Feb 28, 2008
1,563
0
0
To pass the vector by reference to a function to allow manipulation, would i just need to have
void blah(&grid, x ,y). That is where I've gotten myself stuck.
No, to pass by reference you define the function as "void blah(vector<vector<int>>& grid, int x, int y) {...}", and calling it looks like "blah(grid, x, y);". Unfortunately, in C++ nothing at the call site indicates whether the argument is by reference or not. You just have to know or check.

A function call "blah(&grid, x, y);" could be valid C++ as well. It just means something entirely different. "&" means reference only in one specific place in C++: while defining the type of a function argument, like I do above. Here in "&grid" the "&" is instead an address operator. "&grid" is the address of "grid", in other words, a pointer. But then, for "blah(&grid, x, y);" to be valid, the function would have to be defined as taking such a pointer: "void blah(vector<vector<int>>* grid, int x, int y) {...}". That is actually how you "pass by reference" in C, because pointers are the closest thing to references C has. In C++ we always want to use references unless we have a specific reason to use a pointer.
Thanks again Pia!
Happy to help!