Failing to pass variable of struct-array as function parameter - c

I am fairly new to the concept of structs in C, and have run into a problem. I have looked for any similar problems posted here, but cannot find any. What I am trying to do is pass a variable in an array of structs as a parameter in a function, as so:
struct Student
{
float average;
int ID;
int grades[5];
char firstName[20], lastName[20];
};
void main(void)
{
struct Student sTable[10];
float maxAverage(float sTable[].average)
{
int i;
float max = 0;
for(i = 0;i < 10; ++i)
{
if(sTable[i].value > max)
{
max += sTable[i].value;
}
}
return max;
}
printf("%f",maxAverage(sTable[].average));
}

There are a few problems here.
You cannot nest functions inside other functions like you can in languages like Java, C#, Python.
You are passing the struct array incorrectly.
Your main declaration is incorrect.
You want code something like this:
struct Student
{
float average;
int ID;
int grades[5];
char firstName[20], lastName[20];
};
float maxAverage(struct Student sTable[])
{
int i;
float max = 0;
for(i = 0;i < 10; ++i)
{
if(sTable[i].value > max)
{
max += sTable[i].average;
}
}
return max;
}
int main(void)
{
struct Student sTable[10];
//initialize sTable
printf("%f", maxAverage(sTable));
return 0;
}
Note that you are missing initialization of sTable.
What's more you really ought to pass the length of the array as a parameter to maxAverage. That will then allow you more flexibility to use arrays of any length.

First of all, you can't declare or define a function inside another function, so move maxAverage outside of main (which, incidentally, should return int, not void). Secondly, given an array of structs, you can't just automatically create an array of the values from a certain field of the structs; if you want to, you would have to manually declare a separate array of (in this case) floats and then copy over the average fields one by one. A simpler way would be to simply pass sTable itself to maxAverage and have maxAverage only operate on the average fields of the structs in the array.

Related

Understanding part of an algorithm

Below is a part of an algorithm i was given to use for a project, but as it's my first time to use an algorithm i don't understand the following lines. Please will need your help.
For i=1 to n do
t[i] .mark <-- 0
t[i] .num <-- -1
End
This pseudo code can be translated to C
Use struct
struct cm{
int mark;
int num;
};
#define N 10
int main(void)
{
struct cm t[N];
for (int i=0;i<N;i++){
t[i].mark = 0;
t[i].num = -1;
}
//print your struct elements field
for (int i=0;i<N;i++){
printf("%d: %d, %d\n",i ,t[i].mark, t[i].num);
}
}
We have an array of struct because of we need each element of it have two field of data (i.e. mark,num).
struct cm t[N]; define a N length array of structure cm.
In loop we assign to each field of array elements proper values.
For more readability you can use typedef instead of using struct to define your desire data structure in this case.
typedef vs struct
Use typedef
typedef struct typecm{
int mark;
int num;
}typecm;
#define N 10
int main(void)
{
typecm s[N];
for (int i=0;i<N;i++){
s[i].mark = 0;
s[i].num = -1;
}
//print values
for (int i=0;i<N;i++){
printf("%d: %d, %d\n",i ,s[i].mark, s[i].num);
}
}
The "t" seems to be an array of objects, and "mark" and "num" are properties of the object.
This may help you:
From an array of objects, extract value of a property as array

Structs and passing values to them

If i had an array such as int numbers[5] i could assign values to it with numbers[0] = 1 or numbers[3] = 4. Then if i had a struct such as
struct structName
{
int number0;
int number1;
int number2;
};
is there any way to do something like the following (note this is not working code)
int main(void)
{
struct structName name; //how could i declare this to do the following
for(int i = 0; i < 2; i++)
{
name[i] = i; //maybe name.[i]
}
}
so is there a way to write name[ variable ] = someNumber to assign someNumber to say number0 (if variable was 0) or number2 (if variable was 2). ive been looking for days and cant find anything that does this. (maybe i just don't know what to look for)
is there any way to do something like the following
No, there's no way to access the fields of the structure by index. You use the names of the fields instead:
struct structName name;
name.number0 = someNumber;
name.number1 = someOtherNumber;
If you want to access the values by index, use an array instead, even if it's embedded in the structure:
struct structName
{
int numbers[3];
// other fields here
};
Then you can say:
struct structName name;
for (int i = 0; i <= 2, i++) {
name.numbers[i] = i;
}
You could write a function which uses a switch statement that allows you to access fields by index. Something like:
#include<stdio.h>
struct structName{
int number0;
int number1;
int number2;
};
void assign(struct structName * name, int i, int j){
switch(i){
case 0:
name->number0 = j;
break;
case 1:
name->number1 = j;
break;
case 2:
name->number2 = j;
break;
}
}
int main(void){
int i;
struct structName name;
for(i = 0; i <= 2; i++){
assign(&name,i,i);
}
//test:
printf("%d\n",name.number0);
printf("%d\n",name.number1);
printf("%d\n",name.number2);
return 0;
}
(which prints 0,1,2 as expected).
Needless to say, there isn't much point in doing this (as opposed to just having a field which is an array) unless the struct in question is already defined as part of an API or already part of a code base which isn't easily refactored.
Yes, with some weird and inadvisable memory manipulation. You're much better off using an array.
struct structName
{
int numbers[3];
};
int main(void)
{
struct structName name;
for(int i = 0; i <= 2; i++)
{
name.numbers[i] = i;
}
}
Also note that you had some syntax errors in your for loop and an off-by-one error.
Macros with arguments should work
#define name(x) x
So name(1) would become 1. name(2) would become 2 and so on.
In C, there is no spoon.
struct structName name;
int *idx = &name; // First we need a memory address to the struct
for (int i = 0; i < sizeof(name) / sizeof(*idx); ++i) {
// idx[i] == name.numberX
idx[i] = i;
}
Now, if you check the values of name.number0, name.number1, name.number2 you will see they contain the correct values.
This is not a very good way of doing things with structs, but I felt compelled to answer after the top response claims it is impossible.

array initialization for one of the elements in the structure

I have initialized the array for one of the element in the structure, there were some errors in printing the output, please point the errors and guide in solving it . Thanks!
#include<stdio.h>
typedef struct person
{
int row[3];
int age;
}PERSON;
int main()
{
int i;
PERSON p;
PERSON *pptr=&p;
pptr->row[3] = {4,5,6};
for (i = 0; i < 3; i++) {
printf (" %d\n", pptr->row[i]);
}
return 0;
}
Array objects in C language are not assignable. You cannot set the values in the entire array by using assignment. So, to do what you are trying to do using assignment syntax is impossible.
You had a chance to initialize your array at the point of declaration, i.e. when you defined object p
PERSON p = { { 4, 5, 6 } };
but you did not use that chance. After that it is too late to do it using pure core language features.
To set the values in the entire array after the point of declaration you can use a library function, like memcpy, in combination with a compound literal
memcpy(pptr->row, (int []) {4, 5, 6}, sizeof pptr->row);
You can't assign values to array like this: pptr->row[3] = {4,5,6};. Such syntax is valid only at initialization. You need to set each value manually or initialize your array with the values you want, something like this: PERSON p = {{4,5,6}, 0};.
#include<stdio.h>
typedef struct person
{
int row[3];
int age;
}PERSON;
int main()
{
int i;
PERSON p;
PERSON *pptr=&p;
pptr->row[0] = 4;
pptr->row[1] = 5;
pptr->row[2] = 6;
for (i = 0; i < 3; i++) {
printf (" %d\n", pptr->row[i]);
}
return 0;
}
You can't initialize array like this pptr->row[3] = {4,5,6};, You can use the above method or use for loop to initialize array..
When you have done PERSON p;. object p is created containing indeterminate values.
It means all the data members are already initialized with garbage since it's on stack.
So, pptr->row[3] = {4,5,6}; is not the initialization of the array an not allowed in this case. The for loop method is the best in this case.
for (i = 0; i < 3; i++)
scanf("%d",&(pptr->row[i])); // prenthrsis is for human readability

Manipulating dynamic array through functions in C

I am learning how to use dynamic arrays in C. What I want to do is to create a dynamic array data, and put "1" into the first entry using the function test().
void test(void)
{
data[0] = 1;
}
int main(void)
{
int *data = malloc(4 * sizeof *data);
test();
return 0;
}
This compiles in Visual Studio 2010 but the program crashes when run. Instead of using test(), using data[0] = 1 works.
My (newbie) guess is that I need to pass a pointer to data to function test(). How should I write this?
Attempt
void test(int *data)
{
data[0] = 1;
}
Then, in main use test(data) instead of just test().
Edit
The attempt works. However, is this a "proper" way of doing it?
When you use a local variable in C, (dynamic or static, array or not), you need to pass it to the function that will be using it. That's what's wrong with your initial code, test() doesn't know anything about data.
When you declare an array, (dynamic or static) you can pass it to the function in the same ways. The following code is pretty pointless, but it illustrates that using a dynamic array is really no different than a static array.
void assign_function(int arr[], int len_of_arr, int *arr2, int len_of_arr2);
void print_function(int *arr, int len_of_arr, int arr2[], int len_of_arr2);
int main()
{
int data[2] = {0}; // static array of 2 ints
int *data2 = malloc(3 * sizeof(int)); // dynamic array of 3 ints
assign_function(data, 2, data2, 3);
print_function(data2, 3, data, 2);
free(data2); // One difference is you have to free the memory when you're done
return 0;
}
So we can pass the arrays, be they dynamic or static, via array[] or as a pointer, but we need to pass an int along as well so we know how big the array is.
void assign_function(int arr[], int len_of_arr, int *arr2, int len_of_arr2)
{
int count;
for(count = 0; count < len_of_arr; count++) //This is the static array
arr[count] = count;
for(count = 0; count < len_of_arr2; count++) //This is the dynamic array
arr2[count] = count;
}
Then just for fun I reverse which array is pass in arr and arr2 here, and also how they're accessed:
void print_function(int *arr, int len_of_arr, int arr2[], int len_of_arr2)
{
int count;
for(count = 0; count < len_of_arr; count++) //This is the dynamic array now
printf("arr[%d] = %d\n", count, *(arr+count));
for(count = 0; count < len_of_arr2; count++) //And this is the static array
printf("arr2[%d] = %d\n", count, *(arr2+count));
}
Point being, passing via [] or as a pointer, and accessing via [] or a deferenced pointer is up to you, both are fine, both work. I try to avoid pointers when I can as they tend to be hard to read and more error prone when writing.
You can pass arrays dynamically in two ways :
Using a simple pointer and then using pointer arithmetic to manipulate
void test (int * data, int i)
{
*(data + i) = 1; //This sets data[i] = 1
}
Or this way :
void test(int data[], int i)
{
data[i] = 1; //This is the more familiar notation
}
Either of these ways is the 'proper' way to go about this.
The variable 'data' in test is locally scoped. It's not the same 'data' that is in main. You should pass a pointer to 'data' through the parameters of test().

How do you make an array of structs in C?

I'm trying to make an array of structs where each struct represents a celestial body.
I don't have that much experience with structs, which is why I decided to try to use them instead of a whole bunch of arrays. However, I keep on running into numerous different errors. I've tried to implement the techniques that I've seen on various threads and on StackOverflow (such as Array of structs in C and C - initialize array of structs), however not all of them were applicable.
Further information for those who have read this far: I don't need any of this to be dynamic, I know/define the size of everything beforehand. I also need this to be a global array as I'm accessing this in several different methods which have defined arguments (i.e. GLUT methods).
This is how I'm defining the struct in my header:
struct body
{
double p[3];//position
double v[3];//velocity
double a[3];//acceleration
double radius;
double mass;
};
I have a list of other global variables that I'm defining before I define the interior of the struct, and one of those is the array of this struct (basically, if I'm being too unclear in my fogged speak, the line below is above the stuff above):
struct body bodies[n];
Just so you know, n is something that I've legitimately defined (i.e. #define n 1).
I use this array in several different methods, but the easiest and least space consuming one is a simplified form of my main. Here I initialize all of the variables in each of the structs, just to set the variables for certain before I modify them in some way:
int a, b;
for(a = 0; a < n; a++)
{
for(b = 0; b < 3; b++)
{
bodies[a].p[b] = 0;
bodies[a].v[b] = 0;
bodies[a].a[b] = 0;
}
bodies[a].mass = 0;
bodies[a].radius = 1.0;
}
The current error that I'm facing is nbody.c:32:13: error: array type has incomplete element type where line 32 is where I'm making the array of the structs.
One last clarification, by header I mean the space above int main(void) but in the same *.c file.
#include<stdio.h>
#define n 3
struct body
{
double p[3];//position
double v[3];//velocity
double a[3];//acceleration
double radius;
double mass;
};
struct body bodies[n];
int main()
{
int a, b;
for(a = 0; a < n; a++)
{
for(b = 0; b < 3; b++)
{
bodies[a].p[b] = 0;
bodies[a].v[b] = 0;
bodies[a].a[b] = 0;
}
bodies[a].mass = 0;
bodies[a].radius = 1.0;
}
return 0;
}
this works fine. your question was not very clear by the way, so match the layout of your source code with the above.
Another way of initializing an array of structs is to initialize the array members explicitly. This approach is useful and simple if there aren't too many struct and array members.
Use the typedef specifier to avoid re-using the struct statement everytime you declare a struct variable:
typedef struct
{
double p[3];//position
double v[3];//velocity
double a[3];//acceleration
double radius;
double mass;
}Body;
Then declare your array of structs. Initialization of each element goes along with the declaration:
Body bodies[n] = {{{0,0,0}, {0,0,0}, {0,0,0}, 0, 1.0},
{{0,0,0}, {0,0,0}, {0,0,0}, 0, 1.0},
{{0,0,0}, {0,0,0}, {0,0,0}, 0, 1.0}};
To repeat, this is a rather simple and straightforward solution if you don't have too many array elements and large struct members and if you, as you stated, are not interested in a more dynamic approach. This approach can also be useful if the struct members are initialized with named enum-variables (and not just numbers like the example above) whereby it gives the code-reader a better overview of the purpose and function of a structure and its members in certain applications.
So to put it all together by using malloc():
int main(int argc, char** argv) {
typedef struct{
char* firstName;
char* lastName;
int day;
int month;
int year;
}STUDENT;
int numStudents=3;
int x;
STUDENT* students = malloc(numStudents * sizeof *students);
for (x = 0; x < numStudents; x++){
students[x].firstName=(char*)malloc(sizeof(char*));
scanf("%s",students[x].firstName);
students[x].lastName=(char*)malloc(sizeof(char*));
scanf("%s",students[x].lastName);
scanf("%d",&students[x].day);
scanf("%d",&students[x].month);
scanf("%d",&students[x].year);
}
for (x = 0; x < numStudents; x++)
printf("first name: %s, surname: %s, day: %d, month: %d, year: %d\n",students[x].firstName,students[x].lastName,students[x].day,students[x].month,students[x].year);
return (EXIT_SUCCESS);
}
I think you could write it that way too. I am also a student so I understand your struggle. A bit late response but ok .
#include<stdio.h>
#define n 3
struct {
double p[3];//position
double v[3];//velocity
double a[3];//acceleration
double radius;
double mass;
}bodies[n];
move
struct body bodies[n];
to after
struct body
{
double p[3];//position
double v[3];//velocity
double a[3];//acceleration
double radius;
double mass;
};
Rest all looks fine.
Solution using pointers:
#include<stdio.h>
#include<stdlib.h>
#define n 3
struct body
{
double p[3];//position
double v[3];//velocity
double a[3];//acceleration
double radius;
double *mass;
};
int main()
{
struct body *bodies = (struct body*)malloc(n*sizeof(struct body));
int a, b;
for(a = 0; a < n; a++)
{
for(b = 0; b < 3; b++)
{
bodies[a].p[b] = 0;
bodies[a].v[b] = 0;
bodies[a].a[b] = 0;
}
bodies[a].mass = 0;
bodies[a].radius = 1.0;
}
return 0;
}
That error means that the compiler is not able to find the definition of the type of your struct before the declaration of the array of structs, since you're saying you have the definition of the struct in a header file and the error is in nbody.c then you should check if you're including correctly the header file.
Check your #include's and make sure the definition of the struct is done before declaring any variable of that type.
You can do it in a same manner as you create the array of numbers but wrap the element's values in braces like this ->
struct Wrestler studs[count] = {
{"John", "Cena"},
{"The", "Undertaker"},
{"The", "Big Show"},
{"The", "Rock"},
{"Triple", "H"},
{"Scott", "Hall"},
{"Roman", "Reings"},
{"Dean", "Ambrose"}};
Here is full code
#include <stdio.h>
struct Wrestler
{
char firstName[20];
char secondName[20];
};
void pIntro(struct Wrestler *s)
{
printf("Hi, I am %s %s.\n", s->firstName, s->secondName);
};
int main(int argc, char const *argv[])
{
#define count 8
struct Wrestler studs[count] = {
{"John", "Cena"},
{"The", "Undertaker"},
{"The", "Big Show"},
{"The", "Rock"},
{"Triple", "H"},
{"Scott", "Hall"},
{"Roman", "Reings"},
{"Dean", "Ambrose"}};
for (int i = 0; i < count; i++)
{
pIntro(&(studs[i]));
}
return 0;
}

Resources