C array of structs giving strange behaviour - c

I am new to programming in C so I have started making a simple project. I am having an issue with the below code, which seems to be something related to the way memory is managed in C but I'm not sure.
I have a 1280x720 array of Particles which I fill with zeros and with "none". Then I fill in a single entry at (1,1). Finally I print out all the 'particles' that are not "none". The strange behaviour comes from the fact that when I do this I get an output of:
721 0 sand 1 1 sand
Clearly the second value should be there, but the first should not. I have tried with different values of x,y and it always adds 720 to x, and subtracts 1 from y.
#include <stdio.h>
#include <string.h>
typedef struct {
char name[10];
int colour;
} Particle;
Particle particles[1280][720];
void main() {
//Fill in the 1280 x 720 array with 0's and None
for (int y=0; y<720; y++) {
for (int x=0; x<1280; x++) {
particles[y][x].colour = 0x000000;
strcpy(particles[y][x].name, "none");
}
}
//Copy in 1 pixel of sand
strcpy(particles[1][1].name, "sand");
particles[1][1].colour = 0xFFFF00;
//Print out all the pixels that are not none, which should
//just print out a single pixel at (1,1)
for (int y=0; y<720; y++) {
for (int x=0; x<1280; x++) {
if (strcmp("none",particles[y][x].name) != 0) {
printf("%d %d %s\n",x,y,particles[y][x].name);
}
}
}
}
Sorry if this is a simple question. Thanks in advance.

Each rows of the array particles have only 720 elements, so particles[y][x] is out-of-range when x >= 720. Accessing out-of-range element invokes undefined behavior.
Quote from N1570 J.2 Undefined behavior:
An array subscript is out of range, even if an object is apparently accessible with the
given subscript (as in the lvalue expression a[1][7] given the declaration int
a[4][5]) (6.5.6).
Allocate enough elements to avoid buffer overrun. It seems you should use
Particle particles[720][1280];
instead of
Particle particles[1280][720];
It is better to define the width and height as macro to avoid typo:
#include <stdio.h>
#include <string.h>
#define WIDTH 1280
#define HEIGHT 720
typedef struct {
char name[10];
int colour;
} Particle;
Particle particles[HEIGHT][WIDTH];
void main() {
//Fill in the WIDTH x HEIGHT array with 0's and None
for (int y=0; y<HEIGHT; y++) {
for (int x=0; x<WIDTH; x++) {
particles[y][x].colour = 0x000000;
strcpy(particles[y][x].name, "none");
}
}
//Copy in 1 pixel of sand
strcpy(particles[1][1].name, "sand");
particles[1][1].colour = 0xFFFF00;
//Print out all the pixels that are not none, which should
//just print out a single pixel at (1,1)
for (int y=0; y<HEIGHT; y++) {
for (int x=0; x<WIDTH; x++) {
if (strcmp("none",particles[y][x].name) != 0) {
printf("%d %d %s\n",x,y,particles[y][x].name);
}
}
}
}

Related

C: how to give 2D Array to a function

I want to pass a 2D array already filled with chars to a different method to do something with it.
Background: I am trying to implement GameOfLife. And I have already successfully implement the gameboard with a random amount of living cells. But now I want to pass the board(Array) to a different method to continue working with it. How to do so?
//wow das wird hurenshon
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
void spielStarten(int x, int amountOfLiving){
char feld[x][x];
for(int i = 0; i < x; i++){
for(int j = 0; j < x; j++){
feld[i][j] = 'o';
}
}
for(int i = 0; i < amountOfLiving; i++){
int a = (rand()%x);
int b = (rand()%x);
feld[a][b] = 'x';
}
printf("Gameboard: \n");
for(int i = 0; i < x; i++){
for(int j = 0; j < x; j++){
printf("%c ", feld[i][j]);
}
printf("\n");
}
spielRun(feld);
}
void spielRun(char feld[][]){
int neighbCount;
char feldNew[][] = feld[][];
for(int i = 0; i < x; i++) {
for(int j = 0; j < x; j++) {
checkForNeighbours(feld[x][y]);
// in progress
}
}
}
int main(int argc, char* argv[]){
srand(time(NULL));
int x = 16;
if(argc < 2 || argc > 3){
printf("2. Argument eine Zahl fuer Feldgroesse eingeben\n");
printf("1. Argument eine Zahl 0-10 fuer ungefähre prozentuale Belegung mit lebenden
Zellen eingeben \n");
return 0;
}
if(argv[2] != NULL){
x = atoi(argv[2]);
}
int i;
i = atoi(argv[1]);
i = (x^2)*(0,1*i);
spielStarten (x,i);
return 0;
}
In the last line of the Method "Spiel starten" i want to give the array to the next Method "spielRun".
Edit: thanks to an other user I found this struture:
void printarray( char (*array)[50], int SIZE )
But it doesn't work for me since I can´t hardcode the number, because the arraysize depends on a user input.
thanks!
The difficulty here is that the size of your array is not known statically (once upon a time, your code would even not compile for the same reason).
That, combined with the fact that 2D-arrays are not arrays of 1D arrays (contrarily to what happen when you malloc a int ** and then every int * in it), and so it doesn't make sense not to specify the size when passing it to a function.
When using arrays of arrays (technically, pointers to a bunch of pointers to ints), like this
void f(int **a){
printf("%d %d %d\n", a[0][0], a[1][0], a[0][1]);
}
int main(){
int **t=malloc(10*sizeof(int *));
for(int i=0; i<10; i++) t[i]=malloc(20*sizeof(int));
f(t);
}
That code is useless, it prints only unitialized values. But point is, f understands what values it is supposed to print. Pointers arithmetics tells it what a[1] is, and then what a[1][0] is.
But if this 2D-array is not pointers to pointers, but real arrays, like this
void f(int a[][20]){
printf("%d %d %d\n", a[0][0], a[1][0], a[0][1]);
}
int main(){
int t[10][20];
f(t);
}
Then, it is essential that the called function knows the size (or at least all sizes, but for the first dimension) of the array. Because it is not pointers to pointers. It is an area of 200 ints. The compiler needs to know the shape to deduce that t[5][3] is the 5×20+3=103th int at address t.
So, that is roughly what is (better) explained in the link that was given in comments: you need to specify the size.
Like I did here.
Now, in your case, it is more complicated, because you don't know (statically) the size.
So three methods. You could switch to pointers to pointers. You could cast your array into a char * and then do the index computation yourself (x*i+j). Or with modern enough C, you can just pass the size, and then use it, even in parameters, declaration
void f(int x, int a[][x]){
printf("%d %d %d\n", a[0][0], a[1][0], a[0][1]);
}
int main(){
int t[10][20];
f(t);
}
Anyway, from an applicative point of view (or just to avoid segfault) you need to know the size. So you would have had to pass it. So why not pass it as first parameter (Note that the function in which you have this size problem, spielRun, does refers to a x, which it doesn't know. So, passing the size x would have been your next problem anyway)
So, spielRun could look like this (not commenting in other errors it contains)
void spielRun(int x, char feld[][x]){
int neighbCount;
char feldNew[][] = feld[][]; // Other error
for(int i = 0; i < x; i++) {
for(int j = 0; j < x; j++) {
checkForNeighbours(feld[i][j]); // Corrected one here
// in progress
}
}
}
And then calls to this spielRun could be
spielRun(x, feld);
Note that I address only the passing of array of size x here. There are plenty of other errors, and, anyway, it is obviously not a finished code. For example, you can't neither declare a double array char newFeld[][] = oldFeld[][]; nor affect it that way. You need to explicitly copy that yourself, and to specify size (which you can do, if you pass it).
I am also pretty sure that i = (x^2)*(0,1*i); does not remotely what you expect it to do.

how to change the value stored in a VLA which is in a struct

I have the following structure im using to encode a PPM file with a message using steganography:
typedef struct{
char code[CODE_LENGTH];
COMMENT *commentPPM;
int width, height, max;
COLOR (*colorValues)[];
} PPM;
and the color:
typedef struct{
unsigned char red, green, blue;
} COLOR;
and method:
PPM *encode(char *text, PPM *img){
//tested
printf("entered encode\n");
PPM *newPPM;
newPPM = duplicate(img);
printf("duplicated ppm\n");
int x,y, currentChar, textLength;
textLength = strlen(text);
////
for(currentChar = x = y = 0; currentChar < textLength; currentChar++){
printf("the current character is %c\n", *(text+currentChar));
//between 1 and the width
x += (rand() % (newPPM->width -1)) + 1;
printf("generated %d for x\n",x);
if(x >= newPPM->width){
printf("%d is greater than width(%d)\n",x,newPPM->width);
x -= newPPM->width;
printf("%d is the new x\n", x);
y++;
printf("incremented y to be %d\n", y);
}
newPPM->colorValues[y][x].red = text[currentChar]; //error (1)
printf("changed the value of color[%d][%d].red, to be %d, which is %c\n",y,x, text[currentChar], text[currentChar]);
}
return newPPM;
}
How do you access for example "red" within the pointer to the 1d array seen at (1)?
Edit: I get the error message:
"error: invalid use of array with unspecified bounds
newPPM->colorValues[y][x].red = text[currentChar];"
Edit 2: I'm hearing that I cannot access the elements of colorValues in
typedef struct{
char code[CODE_LENGTH];
COMMENT *commentPPM;
int width, height, max;
COLOR (*colorValues)[];
} PPM;
as it hasn't got the width specified so i cant determine the offset. However I this is just a pointer to a flexible array member is getting assigned a type
ppmFile->colorValues = getColors(fd, ppmFile->width, ppmFile->height);
COLOR (*getColors(FILE *fd, int width, int height))[]{
COLOR (*colors)[width] = (COLOR(*)[width]) malloc(sizeof(COLOR[height][width]));
int i,j;
for(i = 0; i < height; i++) {
for(j = 0; j < width; j++) {
fscanf(fd,"%d %d %d", &colors[i][j].red, &colors[i][j].green, &colors[i][j].blue);
}
}
return colors;
}
which has got the width specified. So if I'm understanding correct when I am passing this back to be stored in the struct i am "losing" the offset (width). However When I am in the encrypt method, I have access to the width, height, and current x and y positions, surely there is a way of telling the compiler that this flexible array member has the offset of width,I did do this in the printColors method and it worked fine (see bellow), why cant I tell the compiler that the values stored in newPPM->colorValues have the offset of width?
void printColors(int width, int height, COLOR (*colors)[width]){
int n, j;
for(n = 0; n < height; n++) {
for(j = 0; j < width; j++) {
printf("%d %d %d\n", colors[n][j].red, colors[n][j].green, colors[n][j].blue);
}
}
}
is there a way of casting the newPPM->colorValues to tell it to have the offset width? Like I did with colors in printColors
You're probably getting an error like:
prog.c:10:14: error: subscript of pointer to incomplete type 'struct foo []'
thing->foos[0][0].bar;
~~~~~~~~~~~^
1 error generated.
For reference, the above is the output of compiling this code:
struct foo { int bar; };
struct baz {
struct foo (*foos)[];
};
int main () {
struct baz * thing;
thing->foos[0][0].bar;
return 0;
}
(Live)
What the compiler is trying to tell you is that it cannot compute the offset needed to access subsequent elements of the outer array. The reason is that it doesn't know the size of the array elements (as they're of incomplete type, that is lacking size information).
Basically, it's trying to compute (the following is a pseudo language, not C)
thing + offset(foos) + 0 * sizeof(struct foo[]) + 0 * sizeof(struct foo) + offset(bar)
but it can't because it doesn't know sizeof(struct foo[]).
The root of this issue is that your trying to have a pointer to a variable length array in the first place. Changing the member to
struct foo (*foos)[42];
"solves" this by giving the arrays dome size.
If you want a 2D array just make it 1D, appending all inner arrays. (Of course this works only if they're of the same size, i.e. if you want a rectangular 2D array)
struct foo * grid = malloc (sizeof (struct foo) * rows * columns);
// access using grid [c * rows + r]
You can access 2D data in a 1D array by calculating the array index formula yourself.
buf[ width*y + x ];
where width needs to be the stride in units of the buffer type.

Reading pixels into array for struct crashes program

So basically I have a struct Pixel:
struct Pixel {
int r;
int g;
int b;
} Pixel;
To store RGB values from a file like this:
0
240
233
2
234
42
Where each 3 values is the red, green and blue value respectively.
Now i've created an array of fixed width and height (I already know the image width and height), so here is the code I have so far:
#define WIDTH 640
#define HEIGHT 480
//new array of WIDTH rows, HEIGHT columns
struct Pixel *rgbArray[WIDTH][HEIGHT];
int x, y;
for(y = 0; y < HEIGHT; y++) {
for(x = 0; x < WIDTH; x++) {
struct Pixel *newPixel;
fscanf(fd, "%d\n%d\n%d\n", &newPixel->r, &newPixel->g, &newPixel->b);
rgbArray[x][y] = newPixel;
}
}
It crashes without error, can anyone help me figure out why? I hope it's not something simply stupid ;_;.
Thanks in advance
First problem
struct Pixel *newPixel;
is uninitialized and dereferencing it with the inderiction operator -> is undefined behavior which might explain your crash, you don't seem to need a pointer so
struct Pixel newPixel;
should be fine, and then
if (fscanf(fd, "%d%d%d", &newPixel.r, &newPixel.g, &newPixel.b) == 3)
rgbArray[x][y] = newPixel;
else
handle_error();
provided that
struct Pixel rgbArray[WIDTH][HEIGHT];

read data from struct into 2d array c

I'm trying to plot coordinates to a map using a 2d Array. The data for the coordinates has been entered by the user and held in a structure. This is a snippet of code taken out of my main program.
#include <stdio.h>
#include <stdlib.h>
char map[5][10]={
"..........",
"..........",
"..........",
"..........",
".........."
};
struct coord{
int x;
int y;
};
int loop, n, i;
struct coord mg[3];
int main(){
for(loop=0;loop<3;loop++){
printf("\n\nEnter MAGENTA X coordinate 0:\n");
scanf("%d",&mg[loop].x);
printf("\nEnter MAGENTA Y coordinate:\n");
scanf("%d",&mg[loop].y);
}
printf("Struct contains:\n");
for(loop=0;loop<3;loop++){
printf("\tx %d,%d y\n",mg[loop].x,mg[loop].y);
}
/*AS SUGGESTED IN ANSWER BELOW (PAUL92),I HAVE DONE THIS BUT GET AN ERROR*/
n=3;
i=0;
for (i = 0; i < n; i++) {
map[mg.y][mg.x] = 'x';
}
getchar();
return(0);
}
The error I get is
testing.c:35:13: error: member reference base type 'struct coord [3]' is not a
structure or union map[mg.y][mg.x] = 'x';
~~^~
What I'm trying to achieve is getting the coordinates held in struct to then be assigned to the correct element in the array i.e. if the user enters 3(x),5(y) then the element map[4][2] will hold this an display and 'x'.
I am not sure I have understood exactly what you want, but if you want just to mark the points on the map with an 'x' for example, you can to iterate over the points:
for (int i = 0; i < n; i++) {
map[mg.y][mg.x] = 'x';
}
where n is the number of points.
Of course, this is after you initialize the map.

Flipping Vertices with C

I am trying to flip an image in C vertically so if the image is < it will end up > and my function includes
//Setting the struct up for the pixel's
struct pixel
{
unsigned char red;
unsigned char green;
unsigned char blue;
};
//Setting the struct up for the Image Type and scanning in the pxiels into an array
struct ImageType
{
char ppImage[3];
char comment[256];
char newlinechar;
int width, height;
int maxColor = 255;
struct pixel image[100][100];
};
//Function in order to flip the image, going from the left most pixel flipping with the right most
void MirrorVertical(struct ImageType imgur)
{
int x,y;
const int middle = imgur.width / 2;
struct pixel tmp;
struct *pixel p;
for(y=0; y < imgur.height; ++y)
{
p = tmp + y * imgur.width;
for(x=0; x < middle; ++x)
{
tmp = p[x];
p[x] = p[imgur.width - 1 - x];
p[imgur.width - 1 - x] = tmp;
}
}
}
I got my structs to work but for some reason my function will not output it, I am scanning in the image into from a struct so....
//Scanning in the pixels for the first image
for(i=imageA.height-1; i <= 0; i--)
{
for(j=0; j < imageA.width; j++)
{
scanf("%hhu", &imageA.image[i][j].red);
scanf("%hhu", &imageA.image[i][j].green);
scanf("%hhu", &imageA.image[i][j].blue);
}
}
What am I doing wrong in my function?
It should be
for(x=0; x < width; x++)
{
for(y = 0; y < height/2; y++)
{
temp = imgur.image[x][y];
imgur.image[x][y] = imgur.image[x][height-y-1]
imgur.image[x][height-y-1] = temp;
}
}
}
Shouldn't this: for(i=imageA.height-1; i <= 0; i--) be for(i=imageA.height-1; i >= 0; i--)? (in the "scanning in the pixels for the first image" code)
I imagine your compiler must be complaining about
struct pixel tmp;
struct *pixel p;
for(y=0; y < imgur.height; ++y)
{
p = tmp + y * imgur.width;
You are adding a struct to an int and allocating the result to a pointer. How is it supposed to work?
EDIT now that you have updated your question with "better" code and it's still not working, here are a few things you could / should change.
You declare a variable tmp then try to access temp. Recipe for failure
You pass the entire struct imgur to the function. That means "make a copy of everything". You should really pass a pointer to the object - change the prototype to reflect that, and access the elements as imgur->height etc
You never declare the variables height and width in your MirrorVertical function
(minor) you compute the value height - 1 - y twice per inner loop - 20000 times in total. If you swap the inner and outer loops and compute it just once (and assign to a new variable newY) you can save a little bit of time (not sure it it's really more efficient since you end up looping over X which might destroy cache coherence instead, especially with big images).
My compiler (and the C standard) complains about the statement int maxColor = 256; in the definition of the struct; you cannot initialize a value in the typedef.
Miscellaneous other errors thrown by the compiler.
I took the liberty of fixing many of them - that leads to the following code which appears to compile and run; now all you need is add your "input image" and "output image" functions (maybe).
#include <stdio.h>
//Setting the struct up for the pixels
struct pixel
{
unsigned char red;
unsigned char green;
unsigned char blue;
};
//Setting the struct up for the Image Type and scanning in the pixels into an array
struct ImageType
{
char ppImage[3];
char comment[256];
char newlinechar;
int width;
int height;
int maxColor; // cannot initialize this here; removed "=256"
struct pixel image[100][100];
};
//Function in order to flip the image, going from the left most pixel flipping with the right most
void MirrorVertical(struct ImageType *imgur) // using a pointer to the struct
{
int x,y, height, width; // added declaration of height, width
// const int middle = imgur->width / 2; // removed, not used
struct pixel tmp; // use same name here and in loop
height = imgur->height; // initialize once - save a redirect later
width = imgur->width; // ditto
for(y = 0; y < imgur->height/2; y++) // made this the outer loop
{
int newY = height - y - 1; // so we only compute it once
for(x=0; x < imgur->width; x++)
{
tmp = imgur->image[x][y]; // use "tmp" not "temp"
imgur->image[x][y] = imgur->image[x][newY];
imgur->image[x][newY] = tmp;
}
}
}
// a simple main program… this doesn't really do anything except call the function
int main(void) {
struct ImageType i1;
// … need to add code to import the image
MirrorVertical(&i1); // note - passing POINTER to i1, not the entire struct
// … need to add code to export the image
}
Let me know if that works.

Resources