Writing a function to calculate number of elemets in a c ctruct - c

Hi i am writing a program to calculate the number of elements currently in a struct but i have the following error and am not sure how to fix them, thanks in advance
I have these errors:
structponters.c:4:30: error: array type has incomplete element type
void sizeStruct(struct point coordinates[]);
^
structponters.c:4:24: warning: ‘struct point’ declared inside parameter list
void sizeStruct(struct point coordinates[]);
^
structponters.c:4:24: warning: its scope is only this definition or
declaration, which is probably not what you want
structponters.c: In function ‘main’:
structponters.c:23:19: warning: assignment makes pointer from integer without a cast
sizeCoordinates = sizeof coordinates / sizeof coordinates[0];
^
structponters.c:28:14: error: type of formal parameter 1 is incomplete
sizeStruct(coordinates);
^
structponters.c: In function ‘sizeStruct’:
structponters.c:35:26: warning: comparison between pointer and integer
while(coordinates[i].x != NULL)
^
structponters.c:28: confused by earlier errors, bailing out
This is the code:
#include <stdio.h>
#include <stdlib.h>
void sizeStruct(struct point coordinates[]);
struct point{
int x;
int y;
};
main(){
struct point *pp = malloc(sizeof(struct point));
pp->x = 4;
pp->y = 7;
struct point coordinates[] = {{3,5}, {7,9}, {9,12}, {15, 19}};
int *sizeCoordinates = malloc(sizeof(int));
sizeCoordinates = sizeof coordinates / sizeof coordinates[0];
printf("%d, %d\n", pp->x, pp->y);
printf("size of coordinates is %d \n", sizeCoordinates);
sizeStruct(coordinates);
}
void sizeStruct(struct point coordinates[]){
int i =0;
while(coordinates[i].x != NULL)
i = i +1;
printf("number of elemets in coordinates is: %d\n", i);
}

#include <stdio.h>
#include <stdlib.h>
//Required before `sizeStruct` because sizeStruct use the `struct point`
struct point{
int x;
int y;
};
void sizeStruct(struct point coordinates[]);
int main(void){
struct point *pp = malloc(sizeof(struct point));
pp->x = 4;
pp->y = 7;
struct point coordinates[] = {{3,5}, {7,9}, {9,12}, {15, 19}, { 0, 0}};//{0,0} is sentinel
int sizeCoordinates;//no need malloc, just use int
sizeCoordinates = sizeof coordinates / sizeof coordinates[0];
printf("%d, %d\n", pp->x, pp->y);
printf("size of coordinates is %d \n", sizeCoordinates);
sizeStruct(coordinates);
free(pp);
return 0;
}
void sizeStruct(struct point coordinates[]){
int i =0;
while(coordinates[i].x != 0 && coordinates[i].y != 0)//!= NULL : Comparison of the int and pointer type incorrect
i = i + 1;
printf("number of elemets in coordinates is: %d\n", i);//The number of valid data
}

Related

How can i use pointer to 2D struct array in a fonction C

Here is my code:
#include <stdio.h>
#include <stdlib.h>
#define X 5
#define Y 7
struct mystruct {
char name[10];
int id[1];
int status[1];
};
void show_struct(struct mystruct* table, int X_selected, int Y_selected);
void main(void)
{
struct mystruct* table[X][Y];
int X_selected = 3;
int Y_selected = 4;
table[X_selected][Y_selected] = (struct mystruct*)malloc(sizeof(struct mystruct));
strcpy(table[X_selected][Y_selected]->name, "NAME");
*table[X_selected][Y_selected]->id = 0;
*table[X_selected][Y_selected]->status = 1;
show_struct(table, X_selected, Y_selected);
}
void show_struct(struct mystruct* table, int X_selected, int Y_selected)
{
if (**CONDITION**) {
printf("OK , STATUS IS 1");
}
else {
printf("ERROR , STATUS IS NOT 1");
}
}
I need help to find the CONDITION in my code to check if status = 1
When i debug at line show_struct(table, X_selected, Y_selected); before going in fonction, i can see status=1 is successfully placed on table:
Memory Table
OK, now that you specified what you are trying to do, let's simply start with your code. Let's use the godbolt compiler explorer. I'll only link to versions of your code so that I don't have to copy so much code into this answer.
If we run your original code (with 0 instead of your condition marker) through a recent gcc (12.2.) on godbolt we get a number of warnings and, of course, the error where the condition should be (version 0). Let's fix the first warnings because they are simple:
<source>:16:6: warning: return type of 'main' is not 'int' [-Wmain]
16 | void main(void)
| ^~~~
<source>: In function 'main':
<source>:25:5: warning: implicit declaration of function 'strcpy' [-Wimplicit-function-declaration]
25 | strcpy(table[X_selected][Y_selected]->name, "NAME");
| ^~~~~~
<source>:3:1: note: include '<string.h>' or provide a declaration of 'strcpy'
2 | #include <stdlib.h>
+++ |+#include <string.h>
3 |
<source>:25:5: warning: incompatible implicit declaration of built-in function 'strcpy' [-Wbuiltin-declaration-mismatch]
25 | strcpy(table[X_selected][Y_selected]->name, "NAME");
| ^~~~~~
<source>:25:5: note: include '<string.h>' or provide a declaration of 'strcpy'
OK, main should return an int. Googling that points us to an SO answer pointing out that int main(void) is OK, and not having a return statement is OK, too. Got it.
strcpy must be declared. gcc already suggests to include the header string.h. Got it.
The next warning is harder:
<source>: In function 'main':
<source>:30:17: warning: passing argument 1 of 'show_struct' from incompatible pointer type [-Wincompatible-pointer-types]
30 | show_struct(table, X_selected, Y_selected);
| ^~~~~
| |
| struct mystruct * (*)[7]
<source>:14:35: note: expected 'struct mystruct *' but argument is of type 'struct mystruct * (*)[7]'
14 | void show_struct(struct mystruct* table, int X_selected, int Y_selected);
| ~~~~~~~~~~~~~~~~~^~~~~
In particular, what is struct mystruct * (*)[7], and why is the compiler thinking we are passing that when in fact we pass a 2-dimensional array? Before I suggest a solution that is simpler and avoids complicated types, I'll give short explanation.
A 2-dimensional array in C is, in fact, an array of (1-dimensional) arrays. It's easy to understand a 1-dimensional array for a type T (T may be struct mystruct * like in your program, but the argument is universal). T table[7]; defines an array of 7 Ts. Now I can define an array of 5 of those arrays; because square brackets are evaluated left-to-right, I have to write the new dimension to the left of the old one (think "I first index the 2-dimensional array, obtaining an element — which is a 1-dimensional array, which I index again to obtain the j-th T" — left to right): T table[5][7]. 5 one-dimensional arrays with 7 Ts each.
The crucial point is to remember what happens when you pass an array to a function: It is "adjusted" to a pointer to its first element. The elements of a T table[5][7] are arrays of 7 T, or T [7], a pointer to that is a T (*)[7]. We must put the * in parentheses because otherwise, per operator precedence, the index operation would come first, resulting in a pointer to T, which is something different: We don't have an array of seven pointers to T — we have a pointer to an array of seven T. The order of "pointer" and "array" in these two sentences reflects the order of evaluation, which is enforced by the parentheses in the second case. Now, in our case T is struct mystruct *, so that the argument actually passed to the function is what gcc reports: struct mystruct * (*)[7]. It is a pointer to an array of seven pointers to mystruct. That is not the same as a pointer to mystruct.
The easiest way to implement a function that prints one mystruct object would actually be to define the function to simply take a pointer to that mystruct object. The caller is responsible for providing the right pointer. This makes the function more general: Perhaps we want to print mystructs which are not in the table?
Pointers have a nice reserved value to show that they don't point to anything, which is NULL in C. We'll test whether the pointer is NULL to check whether it was initialized. Note that we cannot test e.g. `if(myStructPtr->id == 0) because if myStructPtr is not initialized the program will be faulty and likely crash. But we can and often must examine the actual pointer value.
void show_struct(struct mystruct* myStructPtr)
{
if (myStructPtr != NULL) {
printf("OK , initialized");
}
else {
printf("ERROR, uninitialized");
}
}
Passing such a pointer is relatively straightforward: You index the table properly! The obtained element is a pointer, after all:
show_struct(table[X_selected][Y_selected]);
Now we must make sure that the pointers stored in the table are actually null. We can do that with brace initialization. We don't actually need to initialize all elements, missing ones will be filled with zeroes by default:
struct mystruct* table[X][Y] = {{0}};
Now we have everything together for a working program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define X 2
#define Y 3
struct mystruct {
char name[10];
int id[1];
int status[1];
};
void show_struct(struct mystruct* myStructPtr)
{
if (myStructPtr != NULL) {
printf("OK , initialized\n");
printf("Status: %d\n", *myStructPtr->status);
}
else {
printf("ERROR, uninitialized\n");
}
}
int main(void)
{
struct mystruct* table[X][Y] = {{0}};
int X_selected = 1;
int Y_selected = 1;
table[X_selected][Y_selected] = (struct mystruct*)malloc(sizeof(struct mystruct));
strcpy(table[X_selected][Y_selected]->name, "NAME");
*table[X_selected][Y_selected]->id = 0;
*table[X_selected][Y_selected]->status = 1;
printf("Selected: ");
show_struct(table[X_selected][Y_selected]);
printf("\n");
for(int xInd = 0; xInd < X; xInd++)
{
for(int yInd = 0; yInd < Y; yInd++)
{
printf("%d, %d:\n", xInd, yInd);
show_struct(table[xInd][yInd]);
printf("****************************************\n");
}
}
}
Here is a solution that is probably a little more than you asked for. I created a new structure for the array of structures which carries the size information with it, and a few functions that operate on that "array structure" instead on raw pointers.
My solution assumes that you eventually want to enter array sizes at run time (your prototype has defines for the array sizes; in that case you could simply define proper arrays of sizes known at compile time).
The "array structure", myTable, holds only a pointer to the actual data. This makes it so small that it can be passed around by value. That copying is shallow: A copy points to the same data as the original. (This way we can fill a table with a function that gets it by value, as in fill_tbl(struct myTable tbl).
The program has a header file myStructArray.h with the structure definitions and function declarations, an implementation file myStructArray.c with the function implementations, and a main.c file.
myStructArray.h
#ifndef MY_STRUCT_ARRAY_H
#define MY_STRUCT_ARRAY_H
#include <stdint.h> // size_t
struct mystruct {
char name[10];
int id;
int status;
};
struct myTable
{
size_t mXSz;
size_t mYSz;
struct mystruct* mStructs;
};
/// <summary>
/// return a table with a pointer to the dynamically allocated array
/// </summary>
struct myTable createTable(size_t szX, size_t szY);
/// <summary>
/// get a pointer to an element in the given table
/// </summary>
struct mystruct* getStructPtr(struct myTable tbl, size_t x, size_t y);
/// <summary>
/// print single struct
/// </summary>
/// <param name="s"></param>
void show_struct(struct mystruct* s);
/// <summary>
/// print the entire table
/// </summary>
/// <param name="tbl"></param>
void show_table(struct myTable tbl);
void destroy_table(struct myTable tbl);
#endif
myStructArray.c
#include <stdint.h> // size_t
#include <stdio.h> // printf
#include <string.h> // memset
#include <stdlib.h> // malloc
#include "myStructArray.h"
#include <assert.h>
void show_struct(struct mystruct *s)
{
if (s->id) {
printf("OK, STATUS IS 1\n");
printf("name: ->%s<-\n", s->name? s->name : "Null");
printf("status: %i\n", s->status);
}
else {
printf("ERROR, STATUS IS NOT 1");
}
}
struct mystruct* getStructPtr(struct myTable tbl, size_t x, size_t y)
{
assert(x < tbl.mXSz&& y < tbl.mYSz);
return &tbl.mStructs[y * tbl.mXSz + x];
}
void show_table(struct myTable tbl)
{
for (size_t y = 0; y < tbl.mYSz; y++)
{
for (size_t x = 0; x < tbl.mXSz; x++)
{
printf("*************** x: %zu, y: %zu******\n", x, y);
show_struct(getStructPtr(tbl, x, y));
}
printf("\n");
}
}
struct myTable createTable(size_t szX, size_t szY)
{
struct myTable newTbl = {szX, szY, 0};
size_t byteSz = szX * szY * sizeof(struct mystruct);
newTbl.mStructs = (struct mystruct *) malloc(byteSz);
memset(newTbl.mStructs, 0, byteSz); // make sure all ids are 0
return newTbl; // yes, by value (two numbers and a pointer)
}
void destroy_table(struct myTable tbl)
{
free(tbl.mStructs); // ok if null
}
main.c
#define _CRT_SECURE_NO_WARNINGS // for visual C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "myStructArray.h"
void fill_tbl(struct myTable tbl)
{
for (size_t y = 0; y < tbl.mYSz; y++)
{
for (size_t x = 0; x < tbl.mXSz; x++)
{
struct mystruct* sp = getStructPtr(tbl, x, y);
sprintf(sp->name, "%zu/%zu", x, y);
sp->id = 1+ y*tbl.mXSz + x;
sp->status = 1;
}
}
}
void main(void)
{
int size_x, size_y;
printf("size_x size_y: ");
scanf("%i %i", &size_x, &size_y);
struct myTable tbl = createTable(size_x, size_y);
fill_tbl(tbl);
int x_selected, y_selected;
printf("x_selected y_selected: ");
scanf("%i %i", &x_selected, &y_selected);
struct mystruct *sPtr = getStructPtr(tbl, x_selected, y_selected);
strcpy(sPtr->name, "NAME");
sPtr->id = 1234;
sPtr->status = 1;
show_struct(getStructPtr(tbl, x_selected, y_selected));
show_table(tbl);
}
Sample session
"3 2" and "0 1" in the first two lines is user input for the sizes and indexes. The rest is output.
size_x size_y: 3 2
x_selected y_selected: 0 1
OK, STATUS IS 1
name: ->NAME<-
status: 1
*************** x: 0, y: 0******
OK, STATUS IS 1
name: ->0/0<-
status: 1
*************** x: 1, y: 0******
OK, STATUS IS 1
name: ->1/0<-
status: 1
*************** x: 2, y: 0******
OK, STATUS IS 1
name: ->2/0<-
status: 1
*************** x: 0, y: 1******
OK, STATUS IS 1
name: ->NAME<-
status: 1
*************** x: 1, y: 1******
OK, STATUS IS 1
name: ->1/1<-
status: 1
*************** x: 2, y: 1******
OK, STATUS IS 1
name: ->2/1<-
status: 1

Setting array of pointers

i'm doing a small exercise to load an array of pointers (double pointer) to a struct. I have the following definition in the header file:
#include <stdio.h>
#define LEN (5)
typedef struct sample_s {
int num;
char *name;
}sample_t;
typedef struct new_sample_s {
char *string;
sample_t **sample_arr;
}new_sample_t;
sample_t table[LEN] = {
{0, "eel"},
{1, "salmon"},
{2, "cod"},
{3, "tuna"},
{4, "catfish"}
};
and using the definitions int this .c file:
#include "test.h"
void print_new_sample_array(sample_t **sample_arr) {
int len = sizeof(table)/sizeof(new_sample_t);
for(int i = 0; i < len; i++){
printf("The array element is: %s\n", sample_arr[i]->name);
}
}
int main() {
new_sample_t new_sample;
new_sample.sample_arr = table;
print_new_sample_array(new_sample.sample_arr);
return 0;
}
I have two questions:
First I'm not sure how to correctly load the table to the new_sample.sample_arr
Error message here:
test.c: In function ‘main’:
test.c:13:27: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
new_sample.sample_arr = table;
^
Second, I'm not sure how I can refer to the properties of each element in the sample_arr. For example, when I do the following, the program errored out:
for(int i = 0; i < LEN; i++){
printf("This is the elem in the array: %s", new_sample[i]->name);
}
I'm trying to learn more about the double pointer concept and why I did it wrong. I would really appreciate the answer keeps the sample_arr as double pointer
Thank you!
In this assignment statement
new_sample.sample_arr = table;
the right operand (after implicit conversion of the array to pointer to its first element) has the type sample_t * while the left operand has the type sample_t ** due to the declaration of the data member
sample_t **sample_arr;
There is no implicit conversion from the type sample_t * to the type sample_t **. So the compiler issued a message.
You should declare the data member like
sample_t *sample_arr;
and correspondingly the function declaration will look like
void print_new_sample_array(sample_t *sample_arr);
And within the function the call of printf will look like
printf("The array element is: %s\n", sample_arr[i].name);

incompatible types when assigning to type struct * from struct

I can't understand why i get this error : The error is : "incompatible types when assigning to type 'PERSOANA * {aka struct *}' from type 'PERSOANA {aka struct }' "
Can you please explain me where is the mistake ?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char name[20];
char name2[20];
char cnp[15];
} PERSON;
PERSON read_array(int n);
int main()
{
int n;
printf("n = ");
scanf("%d", &n);
PERSON *v;
v = read_array(n); //here i get the error
return 0;
}
PERSON read_array(int n) {
PERSON *v;
v = malloc(n * sizeof(PERSON));
for(int i = 0; i < n; i++) {
printf("name=");
gets(v[i].name);
//more instr
}
return v; // and also here
}
Return a pointer to PERSON, not the object PERSON.
// PERSON read_array(int n);
PERSON *read_array(int n);
// ^
// PERSON read_array(int n) {
// v
PERSON *read_array(int n) {
I can't understand why i get this error : Incompatible types when assigning to type PERSON from type PERSON.
I am reasonably confident that you do not get that error, but if you actually do then you should switch to a better compiler. I speculate that the error you get is instead
Incompatible types when assigning to type PERSON * from type PERSON
, because that's in fact what you are trying to do, given your declaration of function read_array().
From implementation and use, it appears that you want that function to return a pointer to a structure rather than a copy of the structure. That would be
PERSON *read_array(int n);
... and the same in the function definition.

Access struct member by an argument of function in C

int f(){
struct NUMBER {
int A;
int B;
};
struct NUMBER *num = malloc(sizeof(struct NUMBER));
num->A = 1;
num->B = 2;
int x = num->B;
return x;
}
int main(){
int z = f();
printf("%d\n", z);
}
Obviously, ./a.out will show 2.
My question: Can I access struct member by an argument of function? i.e. f(A) return 1, and f(B) return 2. Thanks a lot.
Not at all elegant, but I think it shows you what you need to do/know.
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
struct NUMBER {
int A;
int B;
};
struct NUMBER extNumber = {1, 2};
int f(int offset) {
int iRet = -1;
if (offset == offsetof(struct NUMBER, A)) {
iRet = extNumber.A;
} else if (offset == offsetof(struct NUMBER, B)) {
iRet = extNumber.B;
}
return iRet;
}
int main (int argc, char **argv) {
struct NUMBER number;
int iVal;
iVal = f(offsetof(struct NUMBER, A));
printf ("A : %d\n", iVal);
iVal = f(offsetof(struct NUMBER, B));
printf ("B : %d\n", iVal);
}
Can I access struct member by an argument of function?
I think you are also assuming struct is not visible outside the function. Now if the person who wrote main does not have visibility into the function (say it is part of a library), then the answer is NO.
Otherwise if author of main can see internals of the function, then: Can someone come up with a fancy way to access struct member inside the function via function argument? Towards that lets think what does f(A) mean? Here, A is a name of struct member, so do you mean passing char A to f and translating that to struct member inside f [e.g. result = *(int *)num+(inchar-'A') where inchar is aninput parameter to the function of type char]. Similarly, one can imagine other ways.
As far as I understand your problem, the cleanest and most "C-like" solution is to pass a pointer to your struct to f(), where you populate it:
typedef struct _NUMBER
{
int A;
int B;
}
NUMBER;
void f (NUMBER* pvNumber)
{
pvNumber->A = 1;
pvNumber->B = 2;
return;
}
Call it like this:
int main ()
{
NUMBER vNumber;
int z;
f (&vNumber);
z = vNumber.A; // or vNumber.B
return 0;
}
So you don't select the desired member inside f(), but outside of it.
Yes. you need to define some way to access to member desired, this is usually done with constants, or an enum. As an aside, you should always check the pointer returned by malloc() before using it.
#define GET_A (0)
#define GET_B (1)
int f(int selector){
struct NUMBER {
int A;
int B;
};
int result;
struct NUMBER *num = malloc(sizeof(struct NUMBER));
if (!num)
return -1; // or some other error code...
num -> A = 1;
num -> B = 2;
switch(selector)
{
case GET_A: result = num->A; break;
case GET_B: result = num->B; break;
// etc... if you have more members in your struct.
default: result = -1; break; // some error code.
}
free(num)
return result;
}
int main(){
int z = f(GET_B);
printf( "%d\n" , f(GET_B));
}

C dynamic memory allocation for table of structs

Hi here is my code. I want to dynamincly change no of elemnts in table with structs __state:
typedef struct __state{
long int timestamp;
int val;
int prev_value;
}*state_p, state_t;
int main(int argc, char **argv){
int zm;
int previous_state = 0;
int state = 0;
int i = 0;
int j;
state_p st;
//here i want to have 20 structs st.
st = (state_p) malloc(sizeof(state_t) * 20);
while(1){
previous_state = state;
scanf("%d", &state);
printf("%d, %d\n", state, previous_state);
if (previous_state != state){
printf("state changed %d %d\n", previous_state, state);
// here i got compile error:
main.c: In function ‘main’:
main.c:30: error: incompatible type for argument 1 of ‘save_state’
main.c:34: error: invalid type argument of ‘->’
main.c:34: error: invalid type argument of ‘->’
save_state(st[i],previous_state, state);
}
i++;
}
return 0;
}
I suppose i have to change that st[i] to smth like st+ptr ? where pointer is incermeting in each loop iteration ? Or am I wrong ? When i change code: initialization into state_p st[20] and in each loop iteration i put st[i] = (state_p)malloc(sizeof(state_t)) everything works fine, but i want to dynammicly change number of elemets in that table.
Thx in advance for any help
You don't show the prototype for save_state. I'm assuming the first parameter should be a pointer to a state. If that's the case, then you need:
save_state(st + i, previous_state, state);
or
save_state(&(st[i]), previous_state, state);

Resources