Image loading function not working - c++

Alright, so I've been working on a project, and have come to this problem. I get this message when running my program:
Unhandled exception at 0x76fa15de in programmingproj.exe: 0xC0000005: Access violation reading location 0x00000000.
Here is the code that Visual Studio says is the errors:
float **LoadImg(const char *filename)
{
float **data = { 0 };
char *buf = new char[32];
std::string buf2;
std::ifstream filebuf(filename);
filebuf.getline(buf, 32);
// Reiterate over each pixel, very inefficient, needs to be fixed.
for (int x = 0; x < (IMAGE_SIZE_X - 1); x++)
{
for (int y = 0; y < (IMAGE_SIZE_Y - 1); y++)
{
filebuf.getline(buf, 32);
// Only copy the values.
for (int i = 8; i < 32; i++)
{
if (buf[i] != '\t' && buf[i] != ' ')
{
buf2 += buf[i];
}
}
// Set the pixel's value.
data[x][y] = (float)strtodbl(buf2);
}
}
filebuf.close();
return data;
}
Here is a sample of the format I'm trying to read:
x y Value
1 1 0
1 2 0
1 3 0
1 4 0
1 5 10.159
1 6 5.225
1 7 1.337
1 8 0
1 9 0
1 10 0
I only need to load the value field into the proper pixel (x, y).
The strtodbl function is just a quick thing i wrote up to replace atof and/or strtod.
EDIT: IMAGE_SIZE_X and IMAGE_SIZE_Y are just constants for the size of the image (97x56).

You've declared data as a pointer to a pointer, and you're using data but you've never allocated space and set data to point to it. You must do that before you try to read/write what data is supposed to point to.

Related

Converting grid-based level in string form into a 2D array in C++?

I've been completely lost on this one for the past day or so so I hope some of you may be able to figure it out.
So basically I have a string of a grid-based level that I want to convert to a 2D array of numbers, but the conversion is not working properly. Now I do know a two things:
I am reading the txt file correctly and
Through some testing I know that when I manually set the values, objects render where they should so it can't be that (I use OpenGL if in any way that's relevant).
Any and all help/feedback would be appreciated and thanks in advance!
The level txt file looks like this:
0
0
0
0
0
0
0
00000000
But this is the output (it should align with the zero-es in the txt file).
This is the code I use for the conversion (keep in mind that both xSize and ySize are 8):
levelDat = new char* [xSize];
int atIndex = 0;
for (int x = 0; x < xSize; x++) {
levelDat[x] = new char[ySize];
for (int y = 0; y < ySize; y++) {
if (level[atIndex] != '\n') {
levelDat[x][y] = level[atIndex];
}
atIndex++;
}
}
for (int x = 0; x < xSize; x++) {
for (int y = 0; y < ySize; y++) {
if (levelDat[x][y] != AIR) {
blockDat.push_back(x * BLOCK_SIZE);
blockDat.push_back(y * BLOCK_SIZE);
switch (levelDat[x][y]) {
case DIRT:
blockDat.push_back(1);
break;
default:
blockDat.push_back(0);
break;
}
}
}
}
Okay I fixed it. I changed level[atIndex] to row.push_back(level[y*xSize+x]) since I wasn't reading the level array in the correct order.

How to decode the value of the variable that stores the value returned from glm::value_ptr()?

if I have this snippet code:
glm::mat4 someMatrix(1.0f);
GLfloat * a = glm::value_ptr(someMatrix);
How can I decode the values from the variable 'a'. I know the value is someMatrix but jus for curiosity is possible I could get the same Matrix value by decoding the variable a? I tried with this:
std::cout<<"value: "<< a <<"\n"; // It throws me the address : 0x7fff609e91f0
std::cout<<"value: "<< *a <<"\n"; // It gives me this value: 8.88612e-39
But I don't know how to get the matrix and its values. This question might be meaningless because obviously I already know the value of the matrix but just for curiosity I want to know if is possible to decode. Anyway. Thanks in advance.
By "decoding" I'm assuming you're referring to reading each individual element of the matrix.
If it's for the purpose of printing you can do:
glm::mat4 someMatrix(1.0f);
std::cout << glm::to_string(someMatrix) << std::endl;
If you insist on using the result of glm::value_ptr.
glm::mat4 someMatrix(1.0f);
GLfloat *a = glm::value_ptr(someMatrix);
for (int j = 0; j < 4; ++j) {
for (int i = 0; i < 4; ++i) {
std::cout << a[j * 4 + i] << " ";
}
std::cout << std::endl;
}
Which for someMatrix would print:
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1

Understanding copy of 2D arrays

I am trying to switch cols and rows of a 2D array by using a temp array and replace original array with temp using std::copy at the end. But std::Copy copying only first row and rest are showing same old values in original array. Also the statement array = {}; is not clearing indexes to 0.
// Clear array to 0 (issue: This has no effect at all)
array[arrayRowSize][arrayColSize] = {};
// Copy array (issue: only first row is copied, rest of original still has old values)
std::copy(&tempArray[0][0], (&tempArray[0][0])+arrayColSize*arrayRowSize, &array[0][0]);
Can anyone take a look at my code and tell me what I am doing wrong ? Please add some details about how it actually work, and suggest if there is anything we can improve.
#include <iostream>
#include <cstdint>
using namespace std;
bool IsIntegerInputValid (int16_t arrayData, int8_t arrayLimit)
{
// Entered input is a non-digit, negative number or > arrayLimit ?
if ( cin.fail() || arrayData < 0 || arrayData > arrayLimit )
{
// Clear error flag and input buffer
cin.clear();
cin.ignore();
cout << "Invalid input, Please try again" << endl;
return false;
}
return true;
}
int main()
{
const uint8_t kMaxArraySize = 10;
int16_t array[kMaxArraySize][kMaxArraySize] = {};
int16_t arrayRowSize = 0;
int16_t arrayColSize = 0;
// Get array size
while (1)
{
cin >> arrayRowSize;
if ( IsIntegerInputValid ( arrayRowSize, kMaxArraySize) )
{
while (1)
{
cin >> arrayColSize;
if ( IsIntegerInputValid ( arrayColSize, kMaxArraySize) )
{
break; // Got valid size
}
}
break; // Got valid size
}
}
// Get array input
for (int i = 0; i < arrayRowSize; ++i)
{
for (int j = 0; j < arrayColSize; ++j)
{
cin >> array[i][j];
if ( !IsIntegerInputValid (array[i][j], kMaxArraySize) )
{
--i; // Try again
}
}
}
// Copy rows to cols and cols to rows
int16_t tempArray[kMaxArraySize][kMaxArraySize] = {};
for (int i = 0; i < arrayColSize; ++i)
{
for (int j = 0; j < arrayRowSize; ++j)
{
tempArray[i][j] = array[j][i];
cout << tempArray[i][j] << ' ';
}
cout << endl;
}
array[arrayRowSize][arrayColSize] = {}; // Clear array to 0 (issue: This has no effect at all)
// Copy array (issue: only first row is copied, rest of original still has old values)
std::copy(&tempArray[0][0], (&tempArray[0][0])+arrayColSize*arrayRowSize, &array[0][0]);
return 0;
}
Thanks
array[arrayRowSize][arrayColSize] = {}; // Clear array to 0 (issue: This has no effect at all)
This accesses the table element at next out of bounds row of array and next out of bounds column of that row (if the row had any column that werent out of bounds). The behaviour is undefined. The last index that can be accessed is array[arrayRowSize - 1][arrayColSize - 1]. Assigning to an element out of bounds does nothing along the lines of clearing the array.
To set all elements of an array to zero, I would use:
std::memset(array, 0, sizeof array);
That said, you're about to overwrite all values, so this appears to be pointless.
std::copy(&tempArray[0][0], (&tempArray[0][0])+arrayColSize*arrayRowSize, &array[0][0]);
This assumes that the lines are stored contiguously in memory. And if that were true, this would work just fine. However, since you've allocated A large array, and use only part of each row, there are unused parts of the rows between.
An example: You allocate a 7x7 array, then use only a 3x3 array within it. The memory layout could be following:
|-----| <- a row
AAAXXXXBBBXXXXCCCX...
|-------| <- first 9 elements
A represents first row, B represents second ...
X represents unused part of the array.
Now, if you copy 9 contiguous elements as if they were all elements of your array, you would get AAAXXXXBB, which contains plenty of unused elemnets, and not all of used elements.
Since your rows are not contiguous, you must copy each row separately. Or you could copy the entire array including the unused portions.
The copy doesn't work because sizes of your aray is not the same as kMaxArraySize.
copy tries to copy array as one dimensional array. but in your case 2d array coverted to 1d can have a lot of zeros inside.
if you've choosen size 3, 3 the your array will be like :
1 2 3 0 0 0 0 0 0 0
4 5 6 0 0 0 0 0 0 0
7 8 9 0 0 0 0 0 0 0
......
for 1d representation it will look like:
1 2 3 0 0 0 0 0 0 0 4 5 6 0 0 0 0 0 0 0 7 8 9 0 0 0 0 0 0
but copy will take only 9 first records.

C/C++. input line of numbers

Need to input data about multiple structure variables (format - 3 groups of 2 numbers in one line). Used "for" and custom input function (also it calculates some parameters). Now tryed to use "std::cin" :
typedef struct {
short width;
short height;
short left;
short top;
int S;
short orientation;
} Rectangle;
bool input_rectangle(Rectangle* rect) {
short width;
short height;
std::cin >> width >> height;
(*rect).width = width;
(*rect).height = height;
(*rect).S = width * height;
(*rect).top = 0;
(*rect).left = 0;
if(width>height) {
(*rect).orientation = HORIZONTAL;
}
else {
(*rect).orientation = VERTICAL;
}
return width!=0 || height!=0;
}
int main() {
Rectangle* rectangles = new Rectangle[RECTANGLES_COUNT];
...
while(1) {
...
for(int i=0;i<RECTANGLES_COUNT;i++) {
will_continue = will_continue || input_rectangle(&rectangles[i]);
}
if(!will_continue) {
break;
}
else {
int S = calculate(rectangles);
}
...
}
}
It give wrong result. Tryed to add debug output to "calculate" :
for(int i=0;i<RECTANGLES_COUNT;i++)
std::cout << rectangles[i].width << " x " << rectangles[i].height << " = " << rectangles[i].S << "\n";
Example of result.
4 16 6 6 5 10 #my input
4 x 16 = 64 #right
0 x 0 = 0 #??? Must be 6 x 6 = 36
0 x 0 = 0
646 x 6 = 36
0 x 0 = 0
0 x 0 = 0
365 x 10 = 50
0 x 0 = 0
0 x 0 = 0
How can I improve it? Also I tryed to use scanf("%hd %hd", &width, &height); (may ise pure C in this task), but it give same result.
Used g++ compiler / (gcc for pure C version)
From your debug output code, I'm gathering that for your test purposes RECTANGLES_COUNT is actually defined to 3.
Also, since it is able to perform any kind of computations, and given that the || operator is subject to lazy-evaluation, you must be initializing will_continue to false.
What's happening is when your first input (i=0) is in fact valid (i.e. width or height is not 0), will_continue gets set true. Then since true || anything must be true, input_rectangle is no longer called (lazy-evaluation) for i=1,2,... So only rectangle[0] gets set in that loop. When you latter call your debug output in calculate, you show all 3 rectangles' width/height/S including 2 that have presumably been initialized to 0 (and remain to their initial value).
I'm guessing (though not shown) that int S = calculate(rectangles) might in fact assigns the sum of rectangle[i].S (which happens to be equal to rectangle[0].S, since the others are 0s) to S which you are then printing. That would explain the lines containing 646 (64 followed by 6 x 6) and 365 (36 followed by 5 x 5).
I'm guessing what you wanted was probably more along the lines of:
...
while(1) {
...
bool will_continue = false;
for(int i=0;i<RECTANGLES_COUNT;i++) {
will_continue = input_rectangle(&rectangles[i]);
if (!will_continue) {
break;
}
}
if(!will_continue) {
break;
}
else {
int S = calculate(rectangles);
}
...
}
return width!=0 || height!=0;
should be
return width!=0 && height!=0;

How do I work with nested vectors in C++?

I'm trying to work with vectors of vectors of ints for a sudoku puzzle solver I'm writing.
Question 1:
If I'm going to access a my 2d vector by index, do I have to initialize it with the appropriate size first?
For example:
typedef vector<vector<int> > array2d_t;
void readAPuzzle(array2d_t grid)
{
for(int i = 0; i < 9; i++)
for(int j = 0; j < 9; j++)
cin >> grid[i][j];
return;
}
int main()
{
array2d_t grid;
readAPuzzle(grid);
}
Will seg fault. I assume this is because it is trying to access elments of grid that have not yet been initialized?
I've swapped out grid's declaration line with:
array2d_t grid(9, vector<int>(9, 0));
And this seems to get rid of this seg fault. Is this the right way to handle it?
Question 2:
Why is it that when I try to read into my grid from cin, and then print out the grid, the grid is blank?
I'm using the following code to do so:
void printGrid(array2d_t grid)
{
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
{
cout << grid[i][j] + " ";
}
cout << endl;
}
}
void readAPuzzle(array2d_t grid)
{
for(int i = 0; i < 9; i++)
for(int j = 0; j < 9; j++)
cin >> grid[i][j];
return;
}
int main()
{
array2d_t grid(9, vector<int>(9, 0));
printGrid(grid);
readAPuzzle(grid);
printGrid(grid);
}
And I attempt to run my program like:
./a.out < sudoku-test
Where sudoku-test is a file containing the following:
3 0 0 0 0 0 0 0 0
5 8 4 0 0 2 0 3 0
0 6 0 8 3 0 0 7 5
0 4 1 0 0 6 0 0 0
7 9 0 0 2 0 0 5 1
0 0 0 9 0 0 6 8 0
9 3 0 0 1 5 0 4 0
0 2 0 4 0 0 5 1 8
0 0 0 0 0 0 0 0 6
The first call to printGrid() gives a blank grid, when instead I should be seeing a 9x9 grid of 0's since that is how I initialized it. The second call should contain the grid above. However, both times it is blank.
Can anyone shed some light on this?
Q1: Yes, that is the correct way to handle it. However, notice that nested vectors are a rather inefficient way to implement a 2D array. One vector and calculating indices by x + y * width is usually a better option.
Q2A: Calculating grid[i][j] + " " does not concatenate two strings (because the left hand side is int, not a string) but instead adds the numeric value to a pointer (the memory address of the first character of the string " "). Use cout << grid[i][j] << " " instead.
Q2B: You are passing the array by value (it gets copied) for readAPuzzle. The the function reads into its local copy, which gets destroyed when the function returns. Pass by reference instead (this avoids making a copy and uses the original instead):
void readAPuzzle(array2d_t& grid)