I am trying to pass an array of structs as pointer in another function. But the compiler just refuses.
I build up this code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Values{
char timestamp[21];
char temperature[2];
int tmp;
};
char *readString(char out[], FILE *fp){// Reading and storing the input values, out = the string that this func returns
int ch, i;
while(EOF!=(ch=fgetc(fp)))
if(ch == '"') break;
for(i=0;EOF!=(ch=fgetc(fp));++i){
if(ch == '"') break;
out[i] = ch;
}
out[i]='\0';
return out;
}
void printValues(struct Values * v, int i){ //just a printing method, for printing the values, i = the amount of values I have
int j;
for(j=0; j<i; j++){
printf("%s \t : \t %s \t :\t %d \n\n", v[j]->timestamp, v[j]->temperature, v[j]->tmp);
}
}
void makeTmpIntegers(struct Values values[], int i){ //making temperatures integers so I can use them in sorts, i = the amount of values I have
int j;
for(j=0; j<i;j++){
values[j].tmp = atoi(values[j].temperature);
}
}
int main(void){ //The beginning of the programm, what did you expect?
struct Values values[8223];
FILE *file = fopen("hum.txt", "r" );
int i=0; //the number of every stored value (for the timestamps)
int k=0; //the number of every stored value (for the temperatures)
if (file != NULL ){
char tempString [21];
int flag = 1;
while(*readString(tempString, file)){ //if the readStrinf outputs "/0" == "" (end of FILE)
if(flag == 1){strcpy(values[i].timestamp, tempString); flag++; i++;}
else if(flag == 2){strcpy(values[k].temperature, tempString); flag--; k++;}
}
fclose(file);
}
makeTmpIntegers(values, i);
printValues(&values, i);
return 0;
}
I know for a fact that I can pass the struct from a function to another (it works fine that way), but I want to pass pointers (memory reasons).
I have been trying to do it at the function called printValues()
In this case the compiler does not compile. This is the message I get:
In function 'printValues':
24 46 [Error] invalid type argument of '->' (have 'struct Values')
24 63 [Error] invalid type argument of '->' (have 'struct Values')
24 82 [Error] invalid type argument of '->' (have 'struct Values')
In function 'main':
53 17 [Warning] passing argument 1 of 'printValues' from incompatible pointer type
21 6 [Note] expected 'struct Values *' but argument is of type 'struct Values (*)[8223]'
Plus if I initialize the function like this: void printValues(struct Values * v[], int i)
It does compile but it does not prints the values at all
I know that the correct way to read an integer from a txt file, is not like this but I couldn't figure something else out
This is OK:
struct Values{
char timestamp[21];
char temperature[2];
int tmp; };
So are these two function signatures:
void printValues(struct Values * v, int i) { ... }
void makeTmpIntegers(struct Values values[], int i) { ... }
This is WRONG:
v[j]->timestamp, v[j]->temperature, ...
Substitute:
v[j].timestamp, v[j].temperature, ...
ALSO:
Change printValues(&values, i); to printValues(values, i);
I haven't checked carefully for any other errors, but this should get you moving in the right direction...
ADDENDUM:
In both of the examples above, printValues(struct Values * v, int i) and makeTmpIntegers(struct Values values[], int i), you're ALREADY "passing by pointer". You just need to fix your syntax, as in my examples.
As Oppen said below:
Also, note that passing an array argument in C is functionally
equivalent to passing a pointer, no copy is involved, so I'm not sure
what memory reasons stop you from just passing the array of structs
directly...
Related
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.
So I have a code that works how it has to work, but I am getting the "warning: passing argument 2 of 'outsideBettingHistory' from incompatible pointer type", why is that?
My project is huge so I will only rewrite parts that play the role in the warning, so you can paste it yourself and get the same errors.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct Bet {
char* bets[3][2];
} Bet;
void outsideBettingHistory(int x, char betChosen[0][10], bool won, int result) {
//You can ignore what is inside this function
FILE *f;
f = fopen("bettingHistory.txt", "a");
if(!f) {
printf("\nThe bettingHistory.txt not found or unable to open");
exit(0);
}
if(won) {
fprintf(f, "%s %s", "Bet type: ", betChosen[0]);
fprintf(f, ". Won %d credits\n", result);
}
if(!won) {
fprintf(f, "%s %s", "Bet type: ", betChosen[0]);
fprintf(f, ". Lost %d credits\n", result);
}
fclose(f);
}
int betColours(int balance, Bet* betTypes) {
//A lot of stuff that have nothing to do with the warning
int typeOfBet = 0; //This is the example of 3 variables that this function would give to the outsideBettingHistory(); function
bool won = false;
int resultAmount = 8;
outsideBettingHistory(typeOfBet, betTypes->bets[0][typeOfBet], won, resultAmount);
return balance;
}
int main() {
int balance = 100;
Bet betTypes = { .bets={{"Red", "Black"}, {"Even", "Odd"}, {"1 to 18", "19 to 36"}}};
betColours(balance, &betTypes);
}
Also, for void outsideBettingHistory(int x, char betChosen[0][10], bool won, int result) I am getting "note: expected 'char (*)[10]' but argument is of type 'char *'" How do I get rid of these warnings?
In this call
outsideBettingHistory(typeOfBet, betTypes->bets[0][typeOfBet], won, resultAmount);
the second argument has the type char * because the data member bets is a two-dimensional array of pointers of the type char * and you selected the element of the array bets[0][typeOfBet] that is the same as bets[0][0] because typeOfBet was initialized by 0. That is you passed to the function a pointer to the first character of the string literal "Red".
But the second parameter of the function outsideBettingHistory
void outsideBettingHistory(int x, char betChosen[0][10], bool won, int result) {
has the type char ( * )[10].
And the types are not compatible. So the compiler issues an error.
You should decide for yourself what you are trying to pass to the function and what the function shall do.
If it is supposed that the function outsideBettingHistory must deal with a string literal (an element of the two-dimensional array) then declare the function like
void outsideBettingHistory(int x, const char *betChosen, bool won, int result) {
I am writing a program to read a file of records, extract some fields into a VLA’s, sort them using insertion sort, search for a user-specified target using binary search, and print out the result.
Bud I keep getting these errors:
search.c: In function âmainâ:
search.c:57: warning: passing argument 1 of âgetGradesFromFileâ makes integer from pointer without a cast
search.c:19: note: expected âintâ but argument is of type âchar *â
search.c:57: warning: passing argument 2 of âgetGradesFromFileâ makes pointer from integer without a cast
search.c:19: note: expected âchar *â but argument is of type âintâ
search.c:57: warning: passing argument 3 of âgetGradesFromFileâ from incompatible pointer type
search.c:19: note: expected âint *â but argument is of type âchar *â
search.c:57: warning: passing argument 4 of âgetGradesFromFileâ makes integer from pointer without a cast
search.c:19: note: expected âintâ but argument is of type âint *â
search.c:57: warning: passing argument 7 of âgetGradesFromFileâ makes pointer from integer without a cast
search.c:19: note: expected âchar *â but argument is of type âintâ
search.c:57: error: too many arguments to function âgetGradesFromFileâ
search.c:59: warning: passing argument 1 of âprintArrayâ makes integer from pointer without a cast
search.c:38: note: expected âintâ but argument is of type âchar *â
search.c:59: warning: passing argument 2 of âprintArrayâ makes pointer from integer without a cast
search.c:38: note: expected âchar *â but argument is of type âintâ
search.c:62: error: expected expression before âintâ
search.c:62: error: too few arguments to function âinsertionSortâ
search.c:67: warning: comparison between pointer and integer
search.c:68: warning: comparison between pointer and integer
search.c:68: warning: comparison between pointer and integer
search.c:69: warning: passing argument 3 of âbinarySearchâ makes integer from pointer without a cast
search.c:33: note: expected âintâ but argument is of type âint (*)[60]â
search.c:69: error: too few arguments to function âbinarySearchâ
search.c:73: error: expected â(â before â{â token
Any help with these errors is appreciated!!
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
void getGradesFromFile(int size,
char line[],
int studentI_D[],
int test1,
int test2,
int test3,
char grades[]);
void insertionSort(char list[],
int last);
void binarySearch(int size,
int studentID[],
int target,
char* locn);
void printArray(int size,
char list[*],
int studentI_D[*],
int test1,
int test2,
int test3,
char grades[*]);
int main(void)
{
char grades[60];
char str[60];
int size = sizeof(str) / sizeof(str[60]);;
int studentID [60];
char letter;
int exam1, exam2, exam3;
getGradesFromFile("grades.csv", size, str, studentID, exam1, exam2, exam3, grades);// function call
printf("The original numbers are:");
printArray(str, size, studentID, exam1, exam2, exam3, grades);
printf("\n\n");
printf("The sorted numbers are:");
insertionSort(int size, studentID, grades);// inscertion sort function call
printf("\n\n");
printf("Enter student ID and -1 to quit");
scanf("%d", studentID);
while (studentID != -1){
if (studentID > 99999 && studentID < 1000000){
binarySearch(size, studentID, &studentID);
}
else if {
printf ("Error and enter again [100000, 999999] and -1 to quit");
}
exit;
}
return 0;
} // end of main
void getGradesFromFile(int size,
char line[],
int studentI_D[],
int test1,
int test2,
int test3,
char grades[])
{
FILE* pData;
int i = 0;
if ((pData == NULL) {// opens file grades.csv
fprintf(stderr, "Error opening file %s.\n");// error handling statement
exit(1);
}
while (fgets(line,sizeof(line), pData) != NULL){
sscanf(line, "%25s, %d, %d, %d, %c", studentID[i], &test1, &test2, &test3,
grades[i]);
i++;
}
}
if fclose(pData) {
fprintf(stderr, "Error closing file %s.\n", filename);// close file
exit(2);
}
}
void insertionSort(int length, int studentID[], char grades[])
{
int i, key, key1, j;
for (i = 1; i < n; i++)
{
key = studentID[i];
key1= grades[i];
j = i-1;
while (j >= 0 && studentID[j] > key)
{
studentID[j+1] = studentID[j];
grades[j+1] = grades[j];
j = j-1;
}
studentID[j+1] = key;
grades[i+j] = key1;
}
}
void binarySearch(int size, int student[], int target, char *locn)
{
int first = 0;
int last = size - 1;
int mid;
bool found = false;
while (first <= last) {
mid = (first + last) / 2;
if (target > list[mid]) {
first = mid + 1;
} else if (target < list[mid]) {
last = mid - 1;
} else {
*locn = mid;
found = true;
break;
}
}
return found;
}
void printArray(int size,
char A[size],
int studentI_D[size],
int test1,
int test2,
int test3,
char grades[size])
{
for (int i=0; i<size; i+=4) {// prints the array in four lines
printf("\n");
for (int j=0; j<4; j++) {
printf("%10.2f ", A[i+j]);
}
}
}
void flushScanf(void)
{
char c;
while((c = getchar() != '\n' && c != EOF)
;
}
void getGradesFromFile(int size,
char line[],
int studentI_D[],
int test1,
int test2,
int test3,
char grades[]);
size is int type but you are passing "grades.csv" which is a string hence its address will be paased and hence it becomes pointer.
line[] is an array hence a pointer, You are passing size of type int
studentI_D[] is an array of type int. you are passing str of type char and so on....
Your function declaration and definition got 7 parameters but you are passing 8 parameters and hence resulting in error.
You need to check rest yourself. These are silly errors.
I'm having trouble with pointers. I know I should have gone to office hours, but I'm in desperate need of help. The biggest problem right now is trying to debug this program. From my understanding, I'm supposed to declare an address in my void functions. After, I have to use & for readfile(%testarray). What am I doing wrong? The objective of my program is to read a file of numbers and store them in an array. Then, I would print all of the numbers in my array. Any help would be greatly appreciated.
sort.c:11:3: warning: passing argument 1 of 'read_file' makes pointer from integer without a cast [enabled by default]
sort.c:3:6: note: expected 'int **' but argument is of type 'int'
sort.c: In function 'read_file':
sort.c:27:3: warning: format '%d' expects argument of type 'int *', but argument 3 has type 'int' [-Wformat]
Code:
#include <stdio.h>
#include <stdlib.h>
void read_file(int* myList[]);
int main()
{
int testarray[20];
read_file(&testarray[20]);
return 0;
}
void read_file(int* myList[])
{
FILE* inFile;
int i;
inFile = fopen("data.txt","r");
if (inFile == NULL)
{
printf("Unable to open file");
exit(1);
}
i = 0;
while (fscanf(inFile,"%d", *myList[i]) != EOF)
{
printf("%d ", *myList[i]);
i = i+1;
}
printf("\n");
printf("%d\n", i );
} //void
When you use square brackets [] after a name in a function header, you tell the compiler that you are passing an array.
int testarray[] means an array of integers
int *testarray[] means an array of integer pointers
Since you pass an array of integers, the function signature should be either
void read_file(int myList[]);
or its equivalent
void read_file(int *myList);
The call should look like this:
read_file(testarray);
Next, on the subject of & vs. *: ampersand makes a pointer from an value expression that has an address, while an asterisk makes a value from a pointer expression. scanf takes a pointer, so you need to call it with either
fscanf(inFile,"%d", &myList[i])
or an equivalent
fscanf(inFile,"%d", myList+i)
You should be using:
read_file(&testarray);
As you try to pass a pointer to the whole array. What you have done simply takes the address of the 20-th element in the array(which is out of bounds btw).
Here is your fixed code.
#include <stdio.h>
#include <stdlib.h>
void read_file(int myList[20]);
int main()
{
int testarray[20];
read_file(testarray);
return 0;
}
void read_file(int myList[20])
{
FILE* inFile;
int i;
inFile = fopen("data.txt","r");
if (inFile == NULL)
{
printf("Unable to open file");
exit(1);
}
i = 0;
while (fscanf(inFile,"%d", &myList[i]) != EOF)
{
printf("%d ", myList[i]);
i = i+1;
}
printf("\n");
printf("%d\n", i );
}
The expression &testarray[20] is a pointer to one beyond the last entry in the array (i.e. the same as int *), which is not the same as a pointer to an array. And besides, you now declare the argument to be an array of pointers, not a pointer to an array. (difference between int *arr[] and int (*arr)[]).
Also, you don't need to pass a pointer to the array to the function, instead just let the function have a normal array (or pointer) argument, and pass the array as-is:
void read_file(int myList[]);
int main(void)
{
int testarray[20];
read_file(testarray);
/* .... */
}
Inside the read_file you don't need the dereference operator * when using the array. You can use it as a normal array.
Assuiming 10 numbers in the text file, refer the following code :
#include <stdio.h>
#include <stdlib.h>
void read_file(int *);
int main()
{
int *List=(int *)malloc(10*sizeof(int));// Allocate memory for 10 integers
read_file(List);
return 0;
}
/* Passing a pointer to the contiguous locations, just the starting location is enough*/
void read_file(int *ptr)
{
FILE *inFile;
inFile=fopen("Numbers.txt","r");
int i=0;
if(inFile!=NULL)
while(fscanf(inFile,"%d",ptr)!=EOF)
{
printf("%d ",*(ptr));
i++;
}
free(ptr);// Free the memory Locations
}
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);