Pointers to structures and functions - c

I have a simple structure called entry defined which contains name and age. Given an array of these structures, I want to sort the array based on age.
Below is my attempt at applying this, at the moment I can't even get this to compile. I think my pointer logic is incorrect in both the if statement comparison and the subsequent swapping of the pointers. I've tried various ways to do the same thing, but I'm not getting anywhere. I'm pretty new to C, and I'm still trying to get my head around pointers, so it's probably something basic I'm misunderstanding. Can anybody please explain what I'm doing wrong below?
Any help would be greatly appreciated.
#include <stdio.h>
struct entry {
char name[15];
int age;
};
void entrySort( struct entry *dict);
void entrySort( struct entry *dict){
int i,j; // counters
int ct = 4;
struct entry *tmp; // temporary holder
for( i = 0; i < ct; i++){
for( j = 0; j < ct; j++ ){
if ((*dict[i].age) > (*dict[j].age)){
tmp = (dict + i);
(dict+i) = (dict+j);
(dict+j) = tmp;
}
}
}
int main (void){
int ct = 4, i;
struct entry reg[4] =
{{ "John", 24 },
{ "Alan", 18 },
{ "Jim", 40 },
{ "Sarah",32 }};
entrySort(reg);
for( i = 0; i < ct; i++)
printf("name: %s. Age: %d\n", reg[i].name, reg[i].age);
return 0;
}

You pass an array of struct entry objects as a pointer: struct entry *dict, but you are treating it as it would be an array of pointers to struct entry objects: (*dict[i]).age.
(dict+i) is still just a pointer pointing to the memory where i+1. element is stored, i.e. &dict[i]. To actually access this element at index i, you need to use dereference operator: *(dict + i), which is equal to dict[i].
And also note that your swapping of elements at i and j is wrong. "Temporary holder" tmp should be an object that will temporarily hold data, not just a pointer to memory, that you are going to rewrite, thus declare it as struct entry tmp;:
struct entry tmp;
for( i = 0; i < ct; i++) {
for( j = 0; j < ct; j++ ) {
if ((dict[i].age) > (dict[j].age)) {
tmp = dict[i];
dict[i] = dict[j];
dict[j] = tmp;
}
}
}
By the way in the code you have posted, the ending curly brace (}) of your if is missing.

Try:
#include <stdio.h>
struct entry {
char name[15];
int age;
};
void entrySort( struct entry *dict, int);
void entrySort( struct entry *dict, int ct){
int i,j; // counters
/* int ct = 4; */
struct entry tmp; // temporary holder
for( i = 0; i < ct; i++){
for( j = 0; j < ct; j++ ){
if ((dict[i].age) > (dict[j].age)){ /* no * */
tmp = *(dict + i);
*(dict+i) = *(dict+j);
*(dict+j) = tmp;
}
}
}
int main (void){
int ct = 4, i;
struct entry reg[4] =
{{ "John", 24 },
{ "Alan", 18 },
{ "Jim", 40 },
{ "Sarah",32 }};
entrySort(reg, ct);
for( i = 0; i < ct; i++)
printf("name: %s. Age: %d\n", reg[i].name, reg[i].age);
return 0;
}

For completeness, here's how you'd do it with qsort:
#include <stdlib.h>
int sort_entry(const void *va, const void *vb) {
const struct entry *a = va;
const struct entry *b = vb;
if(a->age < b->age) return -1;
else if(a->age == b->age) return 0;
return 1;
}
...
qsort(reg, ct, sizeof(struct entry), sort_entry);

Related

How to create an array of initialized pointers

I have a structure:
struct Path{
int8_t maxtopy;
};
And I want to create an array of pointers to structure Path. I've tried something like that:
int main(){
struct Path *paths[NUMBER_OF_PATHS];
init_paths(paths);
}
void init_paths(struct Path **paths){
paths[0]->maxtopy = -1;
for(int i = 1; i < NUMBER_OF_PATHS; i++)
paths[i]->maxtopy = -1;
}
It is not going to work. Value to the first path is assigned correctly. But when for loop starts I am gettting Segmentation fault. I already figured out that when I am creating array of pointers, only the first pointer is going to be assigned to some structure. So I cannot e.g. paths[1]->maxtopy = -1;, because paths[1] doesn't point to any existing structure.
I have tried something like this:
for(int i = 1; i < NUMBER_OF_PATHS; i++){
static struct Path a;
paths[i] = &a;
paths[i]->maxtopy = i;
}
It doesn't work because it initialize a only once. So every pointer in paths array points to the same structure.
My question is: How to create an array of pointers that point to initialized structures?
You've created an array of pointers, butt the pointers need to point to something. You can dynamically allocate each with malloc.
struct Path{
int8_t maxtopy;
};
int main(void) {
struct Path *paths[NUMBER_OF_PATHS];
for (size_t i = 0; i < NUMBER_OF_PATHS; i++) {
paths[i] = malloc(sizeof(struct Path));
paths[i]->maxtopy = i;
}
return 0;
}
Of course, if your array is declared in main and is not of excessive size, you may want to simply write the following.
int main(void) {
struct Path paths[NUMBER_OF_PATHS];
for (size_t i = 0; i < NUMBER_OF_PATHS; i++) {
paths[i].maxtopy = i;
}
return 0;
}
const int NUMBER_OF_PATHS = 10;
struct Path {
int8_t maxtopy;
};
void init_paths(struct Path** paths) {
for (int i = 0; i < NUMBER_OF_PATHS; i++) {
paths[i] = (Path*)malloc(sizeof(Path));
paths[i]->maxtopy = i;
}
}
int main() {
struct Path* paths[NUMBER_OF_PATHS];
init_paths(paths);
for (auto i : paths) {
printf("%d\n", i->maxtopy);
}
}

Reading of a char contained in a struct results in access violation exception

i am trying to implement a linked-list in C with the aim to do a BFS on it.
The input for the list should look like this:
a-bc
b-a
c-a
which represents a list looking like this:
a
/ \
b c
now, my problem is that I cannot read the variable name defined in my Vertex struct. My program segfaults with Access Reading Violation. While printf("%s", s) takes a char *, casting the name to a char* doesn't help. The error takes place before the char is even accessed?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Vertex Vertex;
typedef struct Vertex
{
char name;
int visited;
int distance;
Vertex* next;
} Vertex;
struct Vertex* AddVertex(Vertex* head, char newVertexName)
{
Vertex* newHead = malloc(sizeof(Vertex));
newHead->name = newVertexName;
printf("added vertex named: %s", newHead->name); // causing the error
newHead->next = head;
newHead->visited = 0;
newHead->distance = 0;
return newHead;
}
int main()
{
// BFS
char s[100];
int l = 0;
const int nNrOfVerts = 27;
Vertex* adjList[28];
// initialise array of pointers
for(int i = 0; i <= nNrOfVerts; ++i)
{
adjList[i] = NULL;
}
// fill vertices with user data
for(int i = 1; i <= nNrOfVerts; ++i)
{
printf("enter %d vert: ", i);
if(scanf("%s", &s) != 1)
{
break;
}
l = strlen(s);
if(l > 2)
{
for(int k = 0; k < l; ++k)
{
// increment to accustom for the - seperator
if(1 == k)
{
k = 2;
}
adjList[i] = AddVertex(adjList[i], s[k]);
}
}
for(int k = 0; k < 100; ++k)
{
s[k] = NULL;
}
}
bfs(adjList);
// printing the list
for(int i = 1; i <= l; ++i)
{
for(int j = 0; j <= nNrOfVerts; ++j)
{
if(adjList[j]->distance == i)
{
printf("Level: %d is: %s", i, adjList[j]->name);
}
printf("No node for dist: %d", i);
}
}
return 0;
}
How can I access the value of newHead->name or adjList[i]->name for that matter? The interesting thing is, if I try to access adjList[i]->distance the correct integer is returned...
You declared name as a char but then you try to print it as a character :
printf("added vertex named: %s", newHead->name);
Change the %s to %c :
printf("added vertex named: %c", newHead->name);
or change your name to a char *.

EXC_BAD_ACCESS on pointer in linked list for radix sort

I'm trying to come up with a rudimentary radix sort (I've never actually seen one, so I'm sorry if mine is awful), but I am getting an EXC_BAD_ACCESS error on the line link = *(link.pointer);. My C skills aren't great, so hopefully someone can teach me what I'm doing wrong.
I'm using XCode and ARC is enabled.
Here is the code:
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#define ARRAY_COUNT 10
#define MAX_VALUE 1000000
#define MODULO 10.0f
typedef enum
{
false,
true
} bool;
typedef struct linkedListStruct
{
int value;
struct linkedListStruct *pointer;
} LinkedList;
void radixSort(int *array);
bool arraySorted(int *array);
int * intArray(int minValue, int maxValue);
int main(int argc, const char * argv[])
{
int *sortingArray = intArray(0, MAX_VALUE);
radixSort(sortingArray);
printf("Array %s sorted", arraySorted(sortingArray) ? "" : "not");
return 0;
}
void radixSort(int *array)
{
int numberOfIterations = (int)ceilf(log(MAX_VALUE)/log(MODULO));
for(int n = 0; n < numberOfIterations; n++)
{
LinkedList *linkedListPointers[(int)MODULO] = {0};
int i = ARRAY_COUNT;
while(i--)
{
int location = (int)floor((array[i] % (int)powf(MODULO, n + 1))/powf(MODULO, n));
LinkedList link = { array[i], NULL };
link.pointer = linkedListPointers[location];
linkedListPointers[location] = &link;
}
int location = 0;
for(int pointerSelection = 0; pointerSelection < MODULO; pointerSelection++)
{
if(linkedListPointers[pointerSelection])
{
LinkedList link = { 0, linkedListPointers[pointerSelection] };
linkedListPointers[pointerSelection] = NULL;
while(link.pointer)
{
link = *(link.pointer);
array[location++] = link.value;
}
}
}
}
}
bool arraySorted(int *array)
{
int i = ARRAY_COUNT;
while(--i)if(array[i - 1] > array[i])break;
return !i;
}
int * intArray(int minValue, int maxValue)
{
int difference = maxValue - minValue;
int *array = (int *)malloc(sizeof(int) * ARRAY_COUNT);
int i;
for(i = 0; i < ARRAY_COUNT; i++)
{
array[i] = rand()%difference + minValue;
}
return array;
}
Also, if someone wants to suggest improvements to my sort, that would also be appreciated.
The problem came from how I was allocating the linked list. I changed
LinkedList link = { array[i], NULL };
link.pointer = linkedListPointers[location];
to
LinkedList *link = malloc(sizeof(LinkedList));
link->value = array[i];
link->pointer = linkedListPointers[location];
In the first example, the pointer to link remained the same through each loop iteration (I wasn't aware it would do that), so I needed to make the pointer point to a newly allocated memory chunk.
EDIT:
Changing that also had me change from
while(link.pointer)
{
link = *(link.pointer);
array[location++] = link.value;
}
to
while(linkPointer)
{
link = *linkPointer;
array[location++] = link.value;
linkPointer = link.pointer;
}

Dynamic array in struct calloc or pointers failing, C

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)

C and dynamic structure element access

I have this complicated structure thingie:
#include <stdlib.h>
typedef struct {
int x;
int y;
} SUB;
typedef struct {
int a;
SUB *z;
} STRUCT;
#define NUM 5
int main(void)
{
STRUCT *example;
int i;
example = malloc(sizeof(STRUCT));
example->z = malloc(NUM * sizeof(SUB));
for(i = 0; i < NUM; ++i) {
/* how do I access variable in certain struct of array of z's */
}
return 0;
}
example is dynamically allocated structure and z inside the example is dynamically allocated array of SUB structures.
How do I access certain variable in certain element of structure z?
I have been trying something like this: example->z[i].x but it doesnt seem to work.
At the moment I am using this shabby looking workaraound:
SUB *ptr = example->z;
int i;
for(i = 0; i < amount_of_z_structs; ++i) {
/* do something with 'ptr->x' and 'ptr->y' */
ptr += sizeof(SUB);
}
Your problem isn't where you say it is. Your code as posted gives a compile error:
error: request for member ā€˜zā€™ in something not a structure or union
at the line
example.z = malloc(sizeof(STRUCT));
because you meant to write example->z, since example is a pointer to STRUCT, not a STRUCT.
From there on, you can access example->z[i].x exactly as you said. That syntax has always been fine.
For example:
/* your declarations here */
example = malloc(sizeof(STRUCT));
example->z = malloc(NUM * sizeof(SUB));
for(i = 0; i < NUM; ++i) {
example->z[i].x = i;
example->z[i].y = -i;
printf("%d %d\n", example->z[i].x, example->z[i].y);
}
/* output:
0 0
1 -1
2 -2
3 -3
4 -4
*/
When you have pointers pointing to pointers you often end up running into precedence issues. I can't recall if this is one, but you might try (example->b)[i].x.
First of all, your second malloc is wrong; example is a pointer so this:
example.z = malloc(NUM * sizeof(SUB));
should be this:
example->z = malloc(NUM * sizeof(SUB));
Then in your loop you can say things like this:
example->z[i].x = i;
example->z[i].y = i;
You'll also want to have this near the top of your file:
#include <stdlib.h>
Try this:
int my_x = example[3].z[2].x;
The above code will first access the example[3] (the fourth element of the example array).
Once you get that particular element, its contents can be automatically access in the same way as you do with normal objects.
You then access z[2] from that element. Note that, example[3] is an element, so you could use a . to access its members; if its an array, you can access it as an array.
So till now, example[3].z[2] is one element of the SUB array inside one element of the example array.
Now you can simply access the member x using the way shown above.
typedef struct {
int x;
int y;
} SUB;
typedef struct {
int a;
SUB *z;
} STRUCT;
STRUCT *example;
int main() {
example = malloc(sizeof(STRUCT)*10); //array of 10;
int i=0,j=0;
for (;i<10;i++){
example[i].a = i;
example[i].z = malloc(sizeof(SUB)*5);
for (j=0; j<5; j++)
example[i].z[j].x = example[i].z[j].y = j;
}
//access example[3] and access z[2] inside it. And finally access 'x'
int my_x = example[3].z[2].x;
printf("%d",my_x);
for (i=0;i<10;i++){
printf("%d |\n",example[i].a);
//example[i].z = malloc(sizeof(SUB)*5);
for (j=0; j<5; j++)
printf("%d %d\n",example[i].z[j].x,example[i].z[j].y);
free(example[i].z);
}
free(example);
}
In the 'shabby workaround', you wrote:
SUB *ptr = example->z;
int i;
for(i = 0; i < amount_of_z_structs; ++i) {
/* do something with 'ptr->x' and 'ptr->y' */
ptr += sizeof(SUB);
}
The problem here is that C scales pointers by the size of the object pointed to, so when you add 1 to a SUB pointer, the value is advanced by sizeof(SUB). So, you simply need:
SUB *ptr = example->z;
int i;
for (i = 0; i < NUM; ++i) {
ptr->x = ptr->y = 0;
ptr++;
}
Of course, as others have said, you can also do (assuming C99):
for (int i = 0; i < NUM; ++i)
example->z[i].x = example->z[i].y = 0;
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#define NUM 5
typedef struct
{
int x;
int y;
}SUB;
typedef struct
{
int a;
SUB* z;
}STRUCT;
void main(void)
{
clrscr();
printf("Sample problem..\n\n");
STRUCT* example;
int i;
example = (STRUCT*)malloc(sizeof(STRUCT));
example->z = (SUB*)malloc(NUM * sizeof(SUB));
for(i = 0; i < NUM; i++)
{
example->z[i].x = i +1;
example->z[i].y = (example->z[i].x)+1;
printf("i = %d: x:%d y:%d\n", i, example->z[i].x, example->z[i].y);
}
}

Resources