I have a simple program that makes a 2d array of a struct. I want to know how to manipulate the struct's attributes. This is my attempt; i keep getting Segmentation fault, the problem happens in the fillarr method;
My problem is that i don't quite understand how to manipulate the data once it is in a 2D array. I understand that arrays are pointers, my assumption at first was that i could do something like
arr[h][w]->one = 'b';
Which i now know is obviously wrong because the compiler really doesn't like it.
Now, when i try
arr[h][w].one = 'a'
The compiler doesn't complain about that syntax, but this is where my segmentation fault triggers.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char one;
char two;
};
typedef struct node node;
node** makeArr(int h, int w) {
printf("Making arr\n");
node** output = (node**)malloc(sizeof(node*) * h);
for (int i = 0; i < h; i++) {
output[i] = (node*)malloc(sizeof(node) * w);
}
return output;
}
void killarr(node **arr, int h, int w) {
printf("Killing arr\n");
for (int i = 0; i < h; i++) {
free(arr[i]);
}
free(arr);
}
void fillarr(node **arr, int h, int w) {
printf("Filling arr\n");
char x = 'a';
for (int i = 0 ; i < h; i++) {
for(int m = 0; m < w; m++){
arr[h][w].one = x++; // <- here exactly
arr[h][w].two = x++; // <- here too
}
}
}
int main(int argc, char *argv[]) {
int h = 10;
int w = 10;
node **arr = makeArr(h, w);
fillarr(arr, h, w);
killarr(arr, h, w);
}
Each time through the inner loop you're accessing arr[h][w]. But since h and w are the array bounds, you're accessing out of bounds, leading to undefined behavior.
You likely meant:
arr[i][m].one = x++;
arr[i][m].two = x++;
Related
So, I had been trying to write the code for the Small Triangles, Large Triangles problem of C in Hackerrank. Before, I state what problem I'm facing, I'll attach the question-
I only wrote the sort_by_area, swap and area functions here. The rest of it was given and unchangeable. The code I've written is getting executed properly but the structures aren't getting sorted correctly. Here is the expected output & my output-
I just cannot figure out why it is getting such weirdly swapped. If anyone could help, would mean a lot.
My code is-
#include <stdlib.h>
#include <math.h>
struct triangle
{
int a;
int b;
int c;
};
typedef struct triangle triangle;
void sort_by_area(triangle* tr, int n) {
int i, j, swapped;
for (i = 0; i < n-1; i++)
{
swapped = 0;
for (j = 0; j < n-i-1; j++)
{
if (area(tr[j].a, tr[j].b, tr[j].c) > area(tr[j+1].a, tr[j+1].b, tr[j+1].c))
{
swap(&tr[j], &tr[j+1]);
swapped = 1;
}
}
if (swapped == 0)
break;
}
}
void swap(struct triangle **xp, struct triangle **yp)
{
struct triangle *temp = *xp;
*xp = *yp;
*yp = temp;
}
int area(int a, int b, int c){
int p=(a+b+c)/2;
int q=p*(p-a)*(p-b)*(p-c);
return sqrt(q);
}
int main()
{
int n;
scanf("%d", &n);
triangle *tr = malloc(n * sizeof(triangle));
for (int i = 0; i < n; i++) {
scanf("%d%d%d", &tr[i].a, &tr[i].b, &tr[i].c);
}
sort_by_area(tr, n);
for (int i = 0; i < n; i++) {
printf("%d %d %d\n", tr[i].a, tr[i].b, tr[i].c);
}
return 0;
}```
Enable all warnings
This quickly led to swap() swapping pointers and not data.
// Corrected - swap data
void swap(struct triangle *xp, struct triangle *yp) {
struct triangle temp = *xp;
*xp = *yp;
*yp = temp;
}
Function order
Move area(), swap() definitions before calling them.
Area
(int) sqrt(q) may return the same value for different qs.
Example: (int) sqrt(100), (int) sqrt(110), (int) sqrt(120)
All return 10. Sorting will not certainly sort according to area.
Simple return the square of the area. Mathematically, sorting by area squared same as area.
int area_squared(int a, int b, int c){
int p=(a+b+c)/2;
int q=p*(p-a)*(p-b)*(p-c);
// return sqrt(q);
return q;
}
Although one could code using double, let us stay with integers.
Watch out for a+b+c as odd as odd/2 forms a truncated quotient.
Perhaps return the square of the area, scaled each side by 2?
int area_squared2(int a, int b, int c){
a *= 2; b *= 2; c *= 2;
// a+b+c is certianly even
int p=(a+b+c)/2;
int q=p*(p-a)*(p-b)*(p-c);
return q;
}
A remaining concern is int overflow. Consider long long math.
long long area_squared2LL(int a, int b, int c){
long long aa = a * 2LL;
long long bb = b * 2LL;
long long cc = c * 2LL;
long long pp = (aa+bb+cc)/2;
long long qq = pp*(pp-aa)*(pp-bb)*(pp-cc);
return qq;
}
Tip: Allocate by referenced data, not type
Easier to code right, review and maintain.
// triangle *tr = malloc(n * sizeof(triangle));
triangle *tr = malloc(sizeof *tr * n);
if (tr == NULL) {
// use tr
...
free(tr);
tr = NULL;
}
I'm new to C Programming and want to focus on learning dynamic allocation. As a learning opportunity for me, I'm trying to create a function that returns a double-pointer for a 2D array of structs. I've been referencing tutorials that generally refer to what is mentioned here in approach #3.
I can see that the tutorial assigns integer values no problem, but I'm not sure how that translates with structs.
Here's my code so far:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
const int HEIGHT = 64;
const int WIDTH = 96;
struct Tile
{
char type;
bool armed;
struct Tile* up;
struct Tile* right;
struct Tile* down;
struct Tile* left;
};
struct Tile** createTileMap(unsigned int w, unsigned int h)
{
struct Tile** map = (struct Tile **)malloc(w * sizeof(struct Tile *));
for (int x = 0; x < w; x++)
{
map[x] = (struct Tile *)malloc(h * sizeof(struct Tile));
for (int y = 0; y < h; y++)
{
map[x][y] = (struct Tile){.type = '_', .armed = false, .up = NULL,
.right = NULL, .down = NULL, .left = NULL};
}
}
}
int main(int argc, char* argv[])
{
struct Tile** map = createTileMap(WIDTH, HEIGHT);
for (int x = 0; x < WIDTH; x++)
{
for (int y = 0; y < HEIGHT; y++)
{
printf(" (%d, %d): ", x, y);
printf("%c", map[x][y].type);
}
printf("\n");
}
return 0;
}
This code segfaults, and I'm not too sure why. Any help is appreciated.
As indicated by EOF, I simply forgot to actually return the address. Fortunately my other code was fine, though!
I am playing around with pointers and structs. This is the program I have been messing with. I am getting a segfault error and I am not sure why. I have looked through it for awhile but can't seem to pinpoint the issue. Can someone explain it to me?
EDIT: in createArray I am getting a segfault at *purp[i][j] = '1';
#include <stdio.h>
#include <stdlib.h>
struct purple_struct{
int x;
int y;
char **purp;
};
void print(int x, int y){
printf("%d %d\n", x, y);
return;
}
void createArray(char*** purp, int x, int y){
int i, j;
for (i = 0; i < x; ++i){
for (j = 0; j < y; ++j){
*purp[i][j] = '1';
}
}
return;
}
int main(){
int i, j;
struct purple_struct dog;
dog.x = 3;
dog.y = 4;
dog.purp = (char **)malloc(dog.x * sizeof(char *));
for (i = 0; i < dog.x; ++i){
dog.purp[i] = (char *)malloc(dog.y * sizeof(char));
}
createArray(&dog.purp, dog.x, dog.y);
for (i = 0; i < dog.x; ++i){
for (j = 0; j < dog.y; ++j){
printf("%c", dog.purp[i][j]);
}
}
print(dog.x, dog.y);
return 0;
}
You need to understand the concept of operator precedence. Just like in mathematics, where an expression like 1 + 2 × 3 means 1 + (2 × 3) and not (1 + 2) × 3, programming languages have rules as to the order in which different operators in an expression are performed.
The rules for C are here: http://en.cppreference.com/w/c/language/operator_precedence
In your case, the problem is that *purp[i][j] actually means *(purp[i][j]), and not (*purp)[i][j] as you were expecting.
void createArray(char*** purp, int x, int y){
*purp[i][j] = '1';
I think they should be
void createArray(char** purp, int x, int y){
purp[i][j] = '1';
And in main
createArray(&dog.purp, dog.x, dog.y);
'&' is not needed here because you're already passing a pointer. '&' is usually used to pass the address of a variable.
Correcting these few things it compiles just fine, not sure about what you want to do.
I have a struct:
struct points{
int i;
int x;
int y;
};
And I made an array of the struct and put elements in it. The i element indicates the label of a certain point. Suppose I have 1 2 3 as an input in the array. 1 corresponds to the label of the point (2, 3). Then I tried to sort the x elements:
for (a=0; a < i; a++){
for (b = 0; b < i; b++){
if (pt[b].x > pt[b+1].x){
temp1 = pt[b].x;
pt[b].x = pt[b+1].x;
pt[b+1].x = temp1;
}
}
}
It was sorted correctly. Now when I printed the i (label), it did not correspond with the x element when sorted. In short, only the x element moved. I want to make the i and y move with the x as it is sorted. What should I do?
Instead of just swapping x you need to swap all the data so that the entire array of structures gets sorted.
You could do this with a separate function, for clarity:
void swap_points(struct points *pa, struct points *pb)
{
const struct points tmp = *pa;
*pa = *pb;
*pb = tmp;
}
Then call that instead of the three inner-most lines of code in your sort.
You really should just use qsort() to do this, it's much simpler:
static int compare_points(const void *va, const void *vb)
{
const struct points *pa = va, *pb = vb;
return pa->i < pb->i ? -1 : pa->i > pb->i;
}
qsort(pt, i, sizeof pt[0], compare_points);
You are actually sorting the array, but only the values for i, not the whole structure!
You'll want to use C's qsort here:
#include <stdlib.h>
#include <stdio.h>
struct points
{
int i;
int x;
int y;
};
int compare(const struct points *a, const struct points *b)
{
if (a->i < b->i) return -1;
if (a->i == b->i) return 0;
if (a->i > b->i) return 1;
}
int main(void)
{
int i;
struct points p[3] = { { 4, 2, 1 }, { 1, 3, 5 }, { 2, 8, 1 } };
qsort(p, 3, sizeof(struct points),
(int (*)(const void*, const void*)) compare);
printf("{ ");
for (i=0; i<3; ++i)
{
printf("{ %d, %d, %d }", p[i].i, p[i].x, p[i].y);
if (i < 2) printf(", ");
}
printf(" }\n");
}
See http://www.cplusplus.com/reference/cstdlib/qsort/
You have to copy the other elements in the struct too.
I suppose you to write a function which replace the values of an element, like this:
void copyPoints(point1* a, point2* b)
{
int temp = a->i;
a->i = b->i;
b->i = temp;
temp = a->x;
a->x = b->x;
b->x = temp;
temp = a->y;
a->y = b->y;
b->y = temp;
}
Then modify the code like this:
for (a=0; a < i; a++)
{
for (b = 0; b < i; b++)
{
if (pt[b].x > pt[b+1].x)
copyPoints(&(pt[b]),&(pt[b+1]));
}
}
I'm attempting to complete an assignment on sparse matrices in C. I have a sparse matrix held as a list of values and coordinates and am converting it to Yale format.
I have run into a strange memory allocation issue that no one seems to have seen before. My code is:
yale* convertMatrix(matrix_list* input){
int matrix_elements = input->elements;
int matrix_rows = input->m;
yale* yale = (struct y*)calloc(1, sizeof(yale));
int* A = (int*)calloc(matrix_elements, sizeof(int));
int* IA = (int*)calloc(matrix_rows + 1, sizeof(int));
int* JA = (int*)calloc(matrix_elements, sizeof(int));
printf("%d elements\n",matrix_elements);
yale->A = A; // Value
yale->IA = IA; // Row (X)
yale->JA = JA; // Column (Y)
yale->elements = matrix_elements;
yale->m = matrix_rows;
yale->n = input->n;
list* tmp_list = input->first;
for(int i = 0, j = 0, tmp_y = 0; i < matrix_elements && tmp_list!=NULL; i++){
printf("Input Value: %d \n",tmp_list->point.value);
A[i] = tmp_list->point.value;
// Initialise the first row
if(i == 0) IA[0] = tmp_list->point.x;
else{
// Add a new row index
if(tmp_y != tmp_list->point.x){
j++;
IA[j] = i;
tmp_y = tmp_list->point.x;
}
}
JA[i] = tmp_list->point.y;
tmp_list = tmp_list->next;
}
for(int i = 0; i < matrix_elements; i++)
printf("%d,",yale->A[i]);
printf("\n");
for(int i = 0; i < matrix_rows + 1; i++)
printf("%d,",yale->IA[i]);
printf("\n");
for(int i = 0; i < matrix_elements; i++)
printf("%d,",yale->JA[i]);
return yale;
}
And here is the struct for yale:
typedef struct y{
int n;
int m;
int elements;
int *IA;
int *JA;
int *A;
} yale;
But the program segfaults at the first relevant printf on the first iteration of the loop.
printf("%d,",yale->A[i]);
I'm positive:
matrix_elements is an integer (9 in my test case)
matrix_rows is an integer
A / IA / JA are all filled with correct values (if you swap yale->A for A in the printf, it works fine).
Directly callocing the array to the struct pointers doesn't affect the result.
Mallocing, callocing, not typecasting, all no effect.
Thanks to Xcode and gdb I can also see that at the point of the segfault. The structure pointers do NOT seem to point to the arrays
I suggest you run your code under Valgrind. This should report the buffer overflow error. (A buffer overflow is where you write past the end of an array).
I also recommend you write some unit tests for your code. They can be very helpful detecting bugs. In particular, I suggest you write a test with a 3x3 input matrix with a value in every position. Check that the values you get out are what you expect.
To get it compiled, I need to prepend this to the snippet:
#include <stdlib.h>
#include <stdio.h>
typedef struct y{
int n;
int m;
int elements;
int *IA;
int *JA;
int *A;
} yale;
typedef struct list {
struct list *next;
struct point { int x,y,value; } point;
} list;
typedef struct matrix_list {
int elements;
int m;
int n;
struct list *first;
int *point;
} matrix_list;
UPDATE: I transformed the program into something more readable (IMHO). I don't have the faintest idea what the IA and JA are supposed to do, but the below fragment should be equivalent to the OP.
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
struct y {
unsigned int n;
unsigned int m;
unsigned int elements;
unsigned int *IA;
unsigned int *JA;
int *A;
} ;
struct list {
struct list *next;
struct point { unsigned int x,y; int value; } point;
} ;
struct matrix_list {
unsigned int elements;
unsigned int m;
unsigned int n;
struct list *first;
} ;
struct y *convertMatrix(struct matrix_list* input)
{
unsigned int matrix_elements = input->elements;
unsigned int matrix_rows = input->m;
unsigned int ii,jj,tmp_y;
struct y *yale ;
struct list *tmp_list ;
yale = calloc(1, sizeof *yale);
assert (yale != NULL);
printf("%u elements\n",matrix_elements);
yale->A = calloc(matrix_elements, sizeof *yale->A);
assert (yale->A != NULL);
yale->IA = calloc(matrix_rows + 1, sizeof *yale->IA);
assert (yale->IA != NULL);
yale->JA = calloc(matrix_elements, sizeof *yale->JA);
assert (yale->JA != NULL);
yale->elements = matrix_elements;
yale->m = matrix_rows;
yale->n = input->n;
// Initialise the first row, set start condition
// FIXME: this ignores the empty list or size=0 cases
yale->IA[0] = tmp_y = input->first->point.x;
ii = jj = 0;
for(tmp_list = input->first ;tmp_list; tmp_list = tmp_list->next) {
printf("Input Value: %d \n",tmp_list->point.value);
yale->A[ii] = tmp_list->point.value;
// Add a new row index
if(tmp_y != tmp_list->point.x){
jj++;
yale->IA[jj] = ii;
tmp_y = tmp_list->point.x;
}
yale->JA[ii] = tmp_list->point.y;
if (++ii >= matrix_elements ) break;
}
for(int i = 0; i < matrix_elements; i++)
printf("%d,",yale->A[i]);
printf("\n");
for(int i = 0; i < matrix_rows + 1; i++)
printf("%u,",yale->IA[i]);
printf("\n");
for(int i = 0; i < matrix_elements; i++)
printf("%u,",yale->JA[i]);
return yale;
}
Note: I moved the (ii == 0) {} condition out of the loop, and replaced the one-letter indices by there two-letter equivalents. Also: all the indices are unsigned (as they should be)