C function signature problems - c

I'm working on a C assignment for school and the assignment asks us to use this specific function signature that is causing errors for my compiler.
I'm getting an error from line 38 (the smallest function signature) in vector_test.c, the error reads ""," expected (got "*")". This is my first time working in C so I think I must be doing something wrong in regards to how I have setup the typedef in types.h or something along those lines, just not exactly sure and thought I'd get some extra opinions. Anything you could point out that I'm doing wrong here would be helpful, thank you!
Here's the code:
vector_test.c
#include "types.h"
int smallest(const Vector3t, int);
void main (int argc, char *argv[]) {
unsigned int N = 0;
printf ("Number of elements ===>");
scanf ("%u", &N);
struct Vector3t points[N];
for (int i = 0; i < N; i++)
{
scanf("%d,%d,%d", &points[i].x, &points[i].y, &points[i].z);
}
for (int p = 0; p < N; p++)
{
printf("%i", points[p].x);
printf("%i", points[p].y);
printf("%i\n\n", points[p].z);
}
int result = smallest(points, N);
printf("%s", "The point closest to the origin is (");
printf("%i", points[result].x);
printf("%s", ", ");
printf("%i", points[result].y);
printf("%s", ", ");
printf("%i", points[result].z);
printf("%s", ")");
}
int smallest(const Vector3t* pts, int n)
{
int shortest = 99999999;
int shortIndex = -1;
for (int i = 0; i < n; i++)
{
int distance = pts[i].x + pts[i].y + pts[i].z;
if (distance < shortest)
{
shortest = distance;
shortIndex = i;
}
}
return shortIndex;
}
types.h
#ifndef types_H
#define types_H
struct vec3 {
int x;
int y;
int z;
};
typedef struct Vector3t {
int x;
int y;
int z;
} vec3;
#endif
Here's the assignment instructions for this specific part so you can see what I'm trying to do:
1. Create a header file called “types.h” (with a macro guard)
a. In this header file, create a struct type called vec3 with int types: x, y, and z
b. Create a typedef to the struct vec3 above and call it Vector3t
2. Create a C source file called “vector_test.c”
a. This file should include “types.h” and any other C system includes you may need
b. Create a main function that does the following:
i. Prompts the user “Number of elements ===> “
ii. Read an unsigned int from the user – this variable will be referred to as N
iii. Create an array of Vector3t of size N and call it points
iv. Read in triples of int (comma separated) from the user to populate the entire array
v. Using the function signature: int smallest(const Vector3t* pts, int n), implement a
function that returns the index of the point that is the closest to the point (0, 0, 0)
vi. Call this function and store the index into an int called result
vii. Print out to the user “The point closest to the origin is (<x>, <y>, <z>)” where <x>, <y>, and <z>
correspond to the values of points[result]
viii. Free all allocated data

Your function forward declaration is:
int smallest(const Vector3t, int);
While your function definition says:
int smallest(const Vector3t* pts, int n)
In your forward declaration you're saying that you're passing in the struct as a parameter, while in your definition you're saying that it's taking a pointer to the struct. These are incompatible signatures.

You get it wrong in the first steps:
Create a header file called "types.h" (with a macro guard)
In this header file, create a struct type called vec3 with int types: x, y, and z
Create a typedef to the struct vec3 above and call it Vector3t
For first,
struct vec3 {
int x;
int y;
int z;
};
is correct. Then to define the typedef, you first give the the actual type, then the type alias:
typedef struct vec3 Vector3t;
Alternatively, these 2 can be combined into one typedef:
typedef struct vec3 {
int x;
int y;
int z;
} Vector3t;
Also the declaration of smallest doesn't match the definition (shouldn't they look alike?) and the return type of main must be int.

Related

Changing the value of an element in a struct

I'm new to structs. I am trying to write a program that has a struct, and the struct is supposed to store a character array and its length. I want to be able change the length's value as I would be creating functions like trimming/concatenating the array. Here is a code I wrote:
#include <stdio.h>
#include <stdlib.h>
struct strstruct{
unsigned int length;
char string[20];
};
typedef struct strstruct stru;
int strleng(stru A){
int i=0;
while(A.string[i]!='\0'){
i++;
}
A.length =i;
return i;
}
int main(){
stru A = {1,
{'a','b','c','d','e','f'}
};
printf("%d %d\n",strleng(A),A.length);
return 0;
}
The value of A.length is not changing inspite of calling strleng.
(i)Why?
(ii) Is there another way to do it?
For starters the order of evaluation of arguments in a function call is unspecified.
So in this call
printf("%d %d\n",strleng(A),A.length);
the evaluation of the argument expression A.length can occur before calling the function strleng or vice versa.
Secondly the function strleng declared like
int strleng(stru A);
deals with a copy of the original object A declared in main and used as an argument. So changing the copy does not influence on the original object.
You need to pass the object by reference through a pointer to it.
unsigned int strleng( stru *A){
unsigned int i=0;
while(A->string[i]!='\0'){
i++;
}
A->length =i;
return i;
}
and in main you should write for example
unsigned int n = strleng( &A );
printf("%u %u\n", n, A.length );
Pay attention to that on one hand, the data member length is declared as having the type unsigned int
unsigned int length;
On the other hand, within your original function strleng you are using an object of the signed type int and the function return type is also int. The function should use at least the same type unsigned int instead of the type int.
Try the code below:
#include <stdio.h>
#include <stdlib.h>
struct strstruct{
unsigned int length;
char string[20];
};
typedef struct strstruct stru;
int strleng(stru* A){
int i=0;
while(A->string[i]!='\0'){
i++;
}
A->length =i;
return i;
}
int main(){
stru A = {1,
{'a','b','c','d','e','f'}
};
printf("%d %d %d\n",A.length, strleng(&A),A.length);
printf("%d \n",A.length);
return 0;
}
You will get output: 6 6 1. I should get the answer now.
At first, you need to use pointer as a parameter if you want to modify struture's value inner a fucntion.
For your question:
To most of the c compiler, the functions inner a printf function is prcessed from right to left. I think the compiler in your case is this one.
For some c compiler, it do process functions in one line from left to right.
I hope it can help you, c online compiler: https://www.onlinegdb.com/online_c_compiler.
printf("%d %d\n",strleng(A),A.length);
Firstly, Here you are passing the argument to the strleng function as a value means strleng function' parameter is a copy of A. In other words, variable A in the main function and structure variable inside the strleng function are two independent variables. So changing A.length in the strleng function will not be visible to your variable A in the main function. (There are many good online resources available about Pass by value vs. Pass by reference. You can check those for better understanding)
Most of the compilers takes each parameter of printf() from right to left. So here A.length execute first then strleng(A). So even you pass the argument by reference, it will still output 6 1.
Updated Code
#include <stdio.h>
#include <stdlib.h>
struct strstruct {
unsigned int length;
char string[20];
};
typedef struct strstruct stru;
int strleng(stru* A) {
int i = 0;
while(A->string[i] != '\0'){
i++;
}
A->length = i;
return i;
}
int main() {
stru A = {1, {'a','b','c','d','e','f'}};
printf("%d %d %d\n", A.length, strleng(&A), A.length);//6 6 1
return 0;
}

Multidimensional arrays in functions in c

I have this exercise to make a transpose of a matrix in C. I made a function to check for type n*n but when I'm trying to ask the user for the matrix I don't know how I should declare the array. And I'm getting this compile error "type of formal parameter 1 is incomplete" in the function on the [n2] part.
The parameters of the functions for multi dimensional arrays shouldn't be like this -> int matrix[][n2]. or is cause i'm using a variable and not a constant or a pre defined size. ?
#include <stdio.h>
#define prompt "Dimenção da matriz (nxn) >>"
#define prompt_1 "Introduza os valores : "
void getType( int *n1, int *n2 );
void getMatrix( int matrix[][n2], int lim1, int lim2);
//void trans(int matrix[][n2]);
int main(int argc, char const *argv[]) {
int n1, n2;
getType(&n1, &n2);
int matrix[n1][n2];
//printf("%dx%d\n", n1, n2);
getMatrix(matrix, n1, n2);
//trans(matrix);
return 0;
}
void getType(int *n1, int *n2){
printf("%s", prompt );
scanf("%dx%d", &(*n1), &(*n2));
}
void getMatrix( int matrix[][n2], int lim1, int lim2){
printf("%s\n", prompt_1 );
for(int line = 0; line < lim1; line++ ){
for(int column = 0; column < lim2; column++){
printf("Linha %d coluna %d ->", line, column );
scanf("%d", &matrix[line][column]);
}
}
}
The signature should be:
void getMatrix( int lim1, int lim2, int matrix[lim1][lim2] )
You are allowed omit the lim1 inside square brackets but it is good documentation to include it.
The main point is that the variable inside the square brackets must either be a parameter from earlier in the parameter list, or some other variable in scope (which can only be a global variable, but that's usually a bad idea).
Also it would be good to check scanf return value otherwise you may create matrix with garbage dimension.

Cannot access memory

I'm getting a segfault, and when I debug it I get the following message:
Cannot access memory at 0x806d128
I attempted to set a watchpoint there to monitor the address, but the response gdb gave me was:
Cannot watch constant value '0x806d128'
However when I print the pointer containing the address it recognises the struct that I've got stored there:
(body *) 0x806d128
According to gdb the error occurs in addForce(), which is a bit odd since that address is accessed earlier in init()
Here's the relevant code:
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define prec float
prec gdt = 0.0001;
typedef struct {
float Fx, Fy, vx, vy, mass;
int posX, posY;
} body;
void addForce(body* a, body* b){
int xa=(*a).posX, ya=(*a).posY;
int xb=(*b).posX, yb=(*b).posY;
float F=(*a).mass * (*b).mass * gdt /(pow(xa-xb, 2)+pow(ya-yb, 2));
float v=atan((ya-yb)/(xa-xb));
float Fx=cos(v)/F, Fy=sin(v)/F;
(*a).Fx+=Fx;
(*a).Fy+=Fy;
(*b).Fx-=Fx;
(*b).Fy-=Fy;
}
int newRandInt(int bot, int top){
return bot + (rand() % (top++));
}
prec newRand()
{
prec r = (prec)((double)rand()/(double)RAND_MAX);
return r;
}
void init(int N, body* star){
for(int i=0; i<N;i++){
star[i].posX = newRandInt(0, 800);
star[i].posY = newRandInt(0, 800);
star[i].Fx = newRand();
star[i].Fy = newRand();
star[i].vx = newRand();
star[i].vy = newRand();
star[i].mass = newRand();
}
}
int main(int argc, char* argv[]) {
int N = 200;
body* stars = malloc(sizeof(body)*N);
init(N, stars);
for(int j1=0; j1<N; j1++){
for(int j2=0; j2<N-1; j2++){
if(j1!=j2){
addForce(stars+sizeof(body)*j1, stars+sizeof(body)*j2);
}
}
}
return 0;
}
This call to addForce is not what you want:
addForce(stars+sizeof(body)*j1, stars+sizeof(body)*j2);
You don't want the sizeof(body) expression in this call to addForce. The call you probably want is:
addForce(stars+j1, stars+j2);
stars is an array of body so you can reference individual stars with
body *p = &stars[i]
or just
body *p = stars + i
Both of these have the type body*
In this line:
addForce(stars+sizeof(body)*j1, stars+sizeof(body)*j2);
when you do sizeof(body) it evaluates to size of structure in bytes, then it is multiplied by j1. So you have some_nr*j1.
That value is added to stars, which is pointer to body.
Pointer arithmetics evaluate some_nr*j1*sizeof(pointer to body).
What you want to do is stars+j1 alone, which will be correctly evaluated as pointer to body and added to arrays.
The same happends in the second part of addForce.
What you missed is that with pointers arithmetics the second operand of '+' operator is recalculated to match size of pointee.

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;
}

Dev-C++ gives '&' reference syntax error

What's the matter with Dev-C++, or are there errors in my code about using reference variable?
#include <stdio.h>
struct P {
int x;
};
int main(int argc, char **argv){
struct P Point[5];
struct P & rPoint;
int i;
for(i=0;i<=4;i++) {
rPoint = Point[i]; // I know. I can use Point[i].x = i. But...
rPoint.x = i;
}
for(i=0;i<=4;i++) {
rPoint = Point[i];
printf("%d\n", rPoint.x);
}
system("pause");
return 0;
}
Error: 9 C:***\main.c syntax error before '&' token
C++ does not allow unassigned references, so this is your error:
struct P & rPoint;
If you want reassignment, use a pointer.
int main(int argc, char **argv){
struct P points[5];
struct P* point;
int i;
for(i=0;i<=4;i++) {
point = points + i; // or &points[i]
point->x = i;
}
// ...
C++ references don't work like that. You have to initialize the reference when you define it. So something like:
int x = 5;
int &r = x; // Initialise r to refer to x
Also, you can't "re-seat" a reference; it will always refer to the same variable. So continuing the above example:
int x = 5;
int y = 10;
int &r = x;
r = y; // This will not re-seat y; it's equivalent to x = y
Error: 9 C:*\main.c syntax error before '&' token
Besides what the others said, you are compiling it as a C file, and in C references do not exist. Give it a .cpp extension if you want to compile it as C++, or make point a pointer instead of a reference (actually, you'll have to make it a pointer anyway, since you can't reseat a reference).

Resources