C - Call a function - c

I want to get a value from a function in other function i think i have to call a function in other function, then call it on main, but how?
void funcA(PEOPLE people[], int *total)
{
FILE *fp;
char line[100];
fp = fopen("example.txt", "r");
if (fp == NULL) {
exit(1);
}
else {
fgets(line, 100, fp); //get a number from the txt
total = atoi(line); //convert to int
}
}
void funcB(PEOPLE people[], int *total)
{
int i;
for (i = 0; i < total; i++) {
printf("%s\n", people[i].name);
}
funcA(people, &total);
}
void main()
{
PEOPLE people[100];
int *total;
funcB(people, &total);
}
What i'm doing wrong? I need the value from total to do cicle for;

First, you should call funcA from funcB like this:
funcA(people, total);
Then, if I understand you correctly, you want to return a value from your function(s). You can do it like this:
int funcA(PEOPLE people[], int *total){
int ret;
// set ret to desired value
return ret;
}
...
int value = funcA(people, total);
After sorting this out, you need to initialize your variables correctly, sort out the naming discrepancies (linha vs line, PEOPLE vs PERSON) and all other issues noted by others.

There are numerous problems here (total is a pointer, for loop on the pointer, never initialized to anything, etc etc).
To answer your question, functions have return types:
int foo(void) {
return 3;
}
int main(int argc, char**argv) {
printf("Foo returned %d\n", foo());
return 0;
}
In this case foo returns int. You return values with the return keyword.
You can also return data in pointers:
void foo(int* c) {
*c = 3;
}
int main(int argc, char**argv) {
int h;
foo(&h);
printf("Foo returned %d\n", h);
return 0;
}
This is helpful if you have multiple values to return.

Oh boy !
First what You are doing right or at least it seems so. You are drawing attention and get points for upvotes, despite the fact, that the code looks like typed in directly to the editor box on the Stackoverflow and never checked with any compiler. Good job :)
Now what's wrong. The list is long but some tips
void main()
{
PERSON person[100];
int *total;
funcB(people, &total);
}
void funcB(PEOPLE people[], int *total);
It would be nice if You showed us the definitions of (probably) structs PEOPLE and PERSON.
In the code we can see, there is no definition of people - the variable you pass to funcB.
You define a pointer to int - total and don't initialize it. Then You pass an address of that pointer to funcB which takes int* not int** as a second argument. Those types are not compatible.
void funcB(PEOPLE people[], int *total)
{
int i;
for (i = 0; i < total; i++) {
printf("%s\n", people[i].name);
}
funcA(people, &total);
}
void funcA(PEOPLE people[], int *total)
You use a pointer in the loop condition instead of the value pointed too. There is no value, because You didn't initialize the pointer in main, but here You have incompatible types in the condition. You pass an address of the pointer to funcA instead of the pointer, like in main.
void funcA(PEOPLE people[], int *total)
{
FILE *fp;
char line[100];
fp = fopen("example.txt", "r");
if (fp == NULL) {
exit(1);
}
else {
fgets(line, 100, fp); //get a number from the txt
total = atoi(linha); //convert to int
}
}
You use an undefined symbol 'linha' - I guess it's a misspelling of 'line'. Then You assign an int to a pointer instead of an int pointed to by that pointer.

Check these:
exit() function exited from your program, not only from function. You can use return; to return from the function.
total is not initialized when you use that. Use funcA(people, &total); line before the for loop in your function funcB.

Related

How do I pass an array of structures to a function?

I'm trying to pass an array of structs to a function which fills them with data.
When I try to compile the code I am told that there is an error:
In function 'main':
error: expected expression before 'Robot_t'
loading_Profiles (Robot_t RobotInfo[]);
I am not sure what I am missing?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <string.h>
typedef struct {
int Robot_Number;
char Robot_Name[30];
int Year_Manufacturer;
float Top_Speed;
float Mass;
float Best_Score;
} Robot_t;
void loading_Profiles();
int main()
{
Robot_t RobotInfo[5];
loading_Profiles (Robot_t RobotInfo[]);
int i;
for (i = 0; i < 50; i++) {
printf("%d\t\t%s\t\t%d\t\t\t%.2f\t\t%.2f\t\t%.2f\n",
RobotInfo[i].Robot_Number, RobotInfo[i].Robot_Name,
RobotInfo[i].Year_Manufacturer, RobotInfo[i].Top_Speed,
RobotInfo[i].Mass, RobotInfo[i].Best_Score);
}
return 0;
}
void loading_Profiles()
{
int Counter = 0;
int i;
Robot_t RobotInfo[5];
FILE *ROBOTtxt = fopen("Robot.txt", "r");
if (ROBOTtxt == NULL) {
perror("an error occured during the loading of the file\n");
exit(-1);
}
for (i = 0; i < 50; i++) {
char LineNumber[100] = "";
fgets(LineNumber, 100, ROBOTtxt);
sscanf(LineNumber, "%d %s %d %f %f %f",
&RobotInfo[i].Robot_Number,
RobotInfo[i].Robot_Name,
&RobotInfo[i].Year_Manufacturer,
&RobotInfo[i].Top_Speed,
&RobotInfo[i].Mass,
&RobotInfo[i].Best_Score);
Counter++;
if (feof(ROBOTtxt)) {
break;
}
}
if (ferror(ROBOTtxt)) {
perror("an error has occured");
exit(-1);
}
fclose(ROBOTtxt);
}
There are several issues with your program. The obvious one is that your function prototypes do not match:
void loading_Profiles()
should be
void loading_Profiles(Robot_t *robots)
in both the declaration and definition.
The array Robot_t RobotInfo[5] in main, and the Robot_t RobotInfo[5] in loading_Profiles do not refer to the same array. They are separate arrays, local to each function. You need to pass the array from main to the loading_Profiles function, which should then modify the array.
Your code also contains various size errors. You are defining an array of 5 elements, and then trying to read and write up to 50 elements. Beyond the mismatch, you need to think about what happens if your file contains less lines than expected.
Counter is unused. As are the return values of some functions that can indicate status / errors:
fgets already partially indicates if it has reached EOF by returning NULL.
sscanf returns the numbers of conversions that took place, which can be used to make sure a partial set of data wasn't stored.
Here is a rewritten example that showcases how to pass arrays around, fill them to a maximum, and utilize the return values of stdio functions. Notice how the type signature of load_robot_profiles matches exactly between the declaration, definition, and invocation of the function.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int number;
char name[32];
int year_manufactured;
float top_speed;
float mass;
float best_score;
} Robot;
size_t load_robot_profiles(Robot *, size_t, const char *);
int main(void) {
Robot robots[5];
size_t length = load_robot_profiles(robots, 5, "robots.txt");
for (size_t i = 0; i < length; i++) {
Robot *r = &robots[i];
printf("%d\t%s\t%d\t\t%.2f\t%.2f\t%.2f\n",
r->number, r->name, r->year_manufactured,
r->top_speed, r->mass, r->best_score);
}
}
size_t load_robot_profiles(Robot *robots, size_t size, const char *fname) {
size_t i = 0;
FILE *file = fopen(fname, "r");
char input[128];
if (!file)
return 0;
while (i < size && fgets(input, sizeof input, file)) {
Robot *r = &robots[i];
if (6 == sscanf(input, "%d %s %d %f %f %f",
&r->number, r->name, &r->year_manufactured,
&r->top_speed, &r->mass, &r->best_score))
i++;
}
fclose(file);
return i;
}
Also note: Defining a type with a _t suffix is ill-advised, as eventually you will brush up against a conflict with an existing POSIX type, or other standard.
Your definition and declaration of the function void loading_Profiles() don't include any arguments, but you're calling it with an argument: loading_Profiles (Robot_t RobotInfo[]);.
You need to change the function to accept Robot_t RobotInfo[] as an argument and then modify the RobotInfo[] array.
The function signature should be like that:
void loading_Profiles(Robot_t* RobotInfo);
Also, there is no need to redeclare the Robot_t RobotInfo[5] inside your loading_Profiles function, since it is already passed by the function call.

How to return an array from function to main [duplicate]

This question already has answers here:
Returning an array using C
(8 answers)
Closed 6 years ago.
I have to use the function to open a file, read it, save the first value as the number of following elements (dimension) and the other values in the seq[] array.
I don't know how to return both dimension and seq[] in the main; I need it because I have to use these values in other functions. As the code shows, the function returns the dimension (dim), but I don't know how to return the array.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
int leggiSequenza(char *nomeFile, int *seq) {
FILE *in;
int i;
int dim;
if((in = fopen(nomeFile, "r"))==NULL) {
printf("Error.\n");
return -1;
}
fscanf(in, "%d", &(dim));
printf("Find %d values.\n", dim);
if(dim < 0) {
printf("Errore: negative value.\n");
return -1;
}
seq = (int*) malloc(dim*sizeof(int));
i=0;
while(!feof(in) && i<(dim)) {
fscanf(in, "%d", &seq[i]);
i++;
}
for(i=0; i<(dim); i++) {
printf("Value in position number %d: %d.\n", i+1, seq[i]);
}
free(seq);
fclose(in);
return dim;
}
int main(int argc, char* argv[]) {
int letturaFile;
char nomeFile[200];
int *dimensione;
printf("Insert file name:\n");
scanf("%s", nomeFile);
printf("\n");
letturaFile = leggiSequenza(nomeFile, dimensione);
dimensione = &letturaFile;
printf("dimension = %d\n", *dimensione);
return 0;
}
I think the focus of the problem is *seq; I have to return two values (dimension and array). Moreover, I can't edit the parameters of the function.
I think my question is different from this because in my function there is a parameter with a pointer, and the function hasn't got a pointer...
Change the function to take the array pointer by pointer:
int leggiSequenza(char *nomeFile, int **seq);
// ^^^^^^^^^
Then call it with the address of your variable:
leggiSequenza(nomeFile, &dimensione);
// ^^^^^^^^^^^
Inside the function definition, change the details around like so:
int leggiSequenza(char *nomeFile, int **seq) {
// ...
int *local_seq = malloc(dim*sizeof(int));
// use local_seq in place of seq
// free(local_seq); // delete ...
*seq = localsec; // ... and replace with this
return dim;
}
Finally, the caller needs to free the array:
free(dimensione);
Update: Since you've re-asked your question: Pre-allocate the memory at the call site:
int * p = malloc(200 * sizeof(int));
int dim = leggiSequenza(filename, p);
// ...
free(p);
Simply your function should have this signature
int leggiSequenza(char *nomeFile, int **seq)
and when passing the parameter to it you should do
letturaFile = leggiSequenza(nomeFile, &dimensione);
that way, you'll have both things.
Also, everywhere in your function where you have just seq , you need to add *seq so you can dereference the pointer.
Hope this helps!
Do the alloction of the array in the main function
int *dimensione; = (int*) malloc(200*sizeof(int));
then delete this line
free(seq);
and you should have the data in the array in the main function.

Why am I not able to access values that were stored in another function?

Basically, why does it not just print the integers that are entered. Right now it just prints garbage value, but I do not know why it cannot access the values stored after it leaves the function. It only seems to get messed up after leaving the getIntegersFromUser function. If I run the for loop in the getIntegers function it does it properly, but why not in the main function?
Thanks in advance for your help.
#include <stdio.h>
#include <stdlib.h>
void getIntegersFromUser(int N, int *userAnswers)
{
int i;
userAnswers =(int *)malloc(N*sizeof(int));
if (userAnswers)
{ printf("Please enter %d integers\n", N);
for (i=0;i<N; i++)
scanf("%d", (userAnswers+i));
}
}
int main()
{
int i, M=5;
int *p;
getIntegersFromUser(M, p);
for (i=0;i<5;i++)
printf ("%d\n", p[i]);
return 0;
}
Also, this is a homework question, but it's a "Bonus Question", so I'm not trying to "cheat" I just want to make sure I understand all the course material, but if you could still try to give a fairly thorough explanation so that I can actually learn the stuff that would be awesome.
Pointers are passed by value. The function is using a copy of your pointer, which is discarded when the function ends. The caller never sees this copy.
To fix it, you could return the pointer.
int *getIntegersFromUser(int N)
{
int *userAnswers = malloc(...);
...
return userAnswers;
}
/* caller: */
int *p = getIntegersFromUser(M);
Or you could pass your pointer by reference so the function is acting on the same pointer, not a copy.
void getIntegersFromUser(int N, int **userAnswers)
{
*userAnswers = (int *) malloc(N*sizeof(int));
...
}
/* caller: */
int *p;
getIntegersFromUser(N, &p);

How to pass struct array into a function and correctly store value in it?

I would like to read a file that has the sample number, values and status(1.1, 23,0). I used a Struct to hold that information. I will pass the function struct array and the file location.
#include <stdio.h>
struct Data_point
{
long sampleNumber;
double value;
int status;
};
int filldata(struct Data_point *a, const char *filelocation)
{
FILE *f;
if((f=fopen(filelocation,"r"))==NULL)
{
printf("You cannot open");
}
fscanf(f, "%ld%lf%d", a.sampleNumber, a.value, a.status);
}
int main(void)
{
struct Data_point data[10];
filldata(data, "/home/alexchan/IntrotoC/rec11/dataPoints.txt");
return 0;
}
But, I got an error saying, "request for member not a structure"...
One problem is that the filldata() is taking a pointer argument. So you use -> to address members not ".". So a.sampleNumber should be a->sampleNumber for example.
Another issue is that filldata() is reading in a single struct, but you are passing it the pointer to the top of the array, which is synonymous with &(data[0]). So this function will just overwrite that first element if you call it repeatedly (which you didn't). If you call it in a loop you will need to pass it in pointers to the individual array members:
for(int i = 0; i < 10; ++i){
filldata(&(data[i]), "/home/alexchan/IntrotoC/rec11/dataPoints.txt");
}
You could actually use data + i as the first arg instead of &(data[i]) but I like the latter as I find it more readable.
struct Data_point *a is your function arugument and you are passing data which is a array. So basically you are trying to acess members from a array which is not a struct.
May be
for( int i=0; i<10;++i)
filldata(data[i],.....)
and
int filldata( struct Data_point a,...) //as you are using a.
fscanf requires a pointer-to-data for each passed argument. Use the AddressOf operator & to get a reference to each struct member:
int filldata(const char *filelocation, struct Data_point *a, int nElements)
{
int n = 0;
FILE *f = fopen(filelocation, "r");
if(f)
{
while (fscanf(f, "(%ld,%lf,%d)", &(a[n].sampleNumber), &(a[n].value), &(a[n].status)) == 3 && n < nElements)
n++;
fclose(f);
}
else { printf("Unable to open '%s'\n", filelocation); }
return n;
}
Now, this function is slightly different to yours. You need to tell it how long the array you're passing in as the "a" parameter is. It will return the number of successfully filled entries.
i.e
int main(int argc, char **argv)
{
struct Data_point data[10];
int n = filldata("C:\\Users\\254288b\\temp.txt", data, sizeof(data) / sizeof(struct Data_point));
printf("%d Data_point's were filled successfully.\n\n", n);
for(int i = 0; i < n; i++)
{
printf("Sample Number: %ld\n", data[i].sampleNumber);
printf("Value: %lf\n", data[i].value);
printf("Status: %d\n", data[i].status);
printf("----------------------------\n");
}
return 0;
}
Do note, my pattern for fscanf expects your file to be like:
(100,1.1,10)(200,2.2,20)(300,3.3,30)(400,4.4,40)
Each set is enclosed in parenthesis.

Passing Variables in C

I have a C program where I'm reading in from a file and then trying to print it to test it at the moment. The thing i'm having issues is that my const in MAX = 40 and its printing that amount of times. I've tried passing a reference to jobcount in the function but I get an error when I add * after int and an & before jobcount when passing it. I appreciate the help, its always quality input on all issues!
#include <stdio.h>
struct record{
char name[1];
int arrival_time;
int job_length;
int job_priority;
};
const int MAX = 40;
void fileinput(struct record jobs[MAX], int jobcount);
void output(struct record jobs[MAX], int jobcount);
int main(void)
{
struct record jobs[MAX];
int jobcount;
fileinput(jobs,jobcount);
output(jobs,jobcount);
return(0);
}
void fileinput(struct record jobs[MAX], int jobcount){
jobcount = 0;
FILE *f = fopen("data.dat","r");
while(fscanf(f, "%s %d %d %d", jobs[jobcount].name, &jobs[jobcount].arrival_time, &jobs[jobcount].job_length, &jobs[jobcount].job_priority) != EOF)
{
jobcount++;
printf("READ IN TEST \n");
}
}
void output(struct record jobs[MAX], int jobcount){
int j = 0;
for(j = 0;j < jobcount; j++)
{
printf("%s %d %d %d\n", jobs[j].name, jobs[j].arrival_time, jobs[j].job_length, jobs[j].job_priority);
printf("FOR LOOP TEST \n");
}
}
data.dat looks like this
A1 3 3 3
B1 4 4 4
C1 5 5 5
You should not get an error. Probably you might have changed in the forward declaration alone and forgot to change at the definition.
void fileinput(struct record jobs[MAX], int* jobcount);
fileinput(jobs,&jobcount);
And definition -
void fileinput(struct record jobs[MAX], int* jobcount) {
// ....
}
Since jobcount is a pointer, you need to dereference first to modify/access the value it is pointing at. You need to post the exact error message for further help though.
You would probably do best to revise fileinput() to return the job count:
int fileinput(struct record jobs[MAX])
{
int jobcount = 0;
...
return jobcount;
}
And then, in main():
int main(void)
{
struct record jobs[MAX];
int jobcount = fileinput(jobs);
...
return 0;
}
The main alternative is to pass a pointer to jobcount to the fileinput() function. This would perhaps be better if you also returned a status (all OK, too many entries in the data, bogus data, etc). Your function would still return a value, but it would be the error indication, and the job count would be returned via the pointer.
A third (gruesome and not recommended) alternative is to use a global variable (or file static variable) for jobcount.
For a generalized input function, you should pass the size of the array explicitly, rather than assuming it is MAX:
int fileinput(struct record jobs[], size_t maxjobs);
int jobcount = fileinput(jobs, MAX);
You'd write the code to ensure that you do not exceed the specified number of job records.
You CAN get "jobcount" from fileinput() withing a "return", if you want to. You just need "&", passing in a pointer to "jobcount":
...
const int MAX = 40;
void fileinput(struct record jobs[MAX], int * jobcount);
...
int main(void)
{
struct record jobs[MAX];
int jobcount=-1;
fileinput(jobs,&jobcount);
output(jobs,jobcount);
return(0);
}
void fileinput(struct record jobs[MAX], int * jobcount){
*jobcount = 0;
FILE *f = fopen("data.dat","r");
while(
(fscanf(f, "%s %d %d %d", jobs[jobcount].name, &jobs[jobcount].arrival_time,
&jobs[jobcount].job_length, &jobs[jobcount].job_priority) != EOF) &&
(*jobcount < MAX) )
{
*jobcount++;
printf("READ IN TEST \n");
}
...

Resources