Warnings when passing arguments to a function - c

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) {

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 can I pass an array of structures to another function

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...

C Pointer Error

The program below is supposed to read a txt file and put the data in a struct. But it gives an pointer error. It gives an error in strcpy() about pointers. I'm new in C. Whats wrong?
#include <stdio.h>
#include <string.h>
int main()
{
struct citydata {
char city[20];
int temp;
};
struct citydata values[15];
struct citydata Avg;
struct citydata high;
struct citydata low;
FILE* inp;
int reccount = 0;
int x = 0;
char s;
int n;
inp = fopen("mydata.txt", "r");
if (!inp) {
printf("Unable ot open file\n");
}
while (fscanf(inp, "%s %d", s, &n) != EOF) {
strcpy(values[x].city, s);
values[x].temp = n;
x++;
}
fclose(inp);
}
Don't ignore compiler warnings.
When if you compile this code (say, with gcc), you get the following warnings:
test.c:27:24: warning: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘int’ [-Wformat=]
while (fscanf(inp, "%s %d", s, &n) != EOF) {
^
test.c:28:32: warning: passing argument 2 of ‘strcpy’ makes pointer from integer without a cast [-Wint-conversion]
strcpy(values[x].city, s);
^
In file included from test.c:2:0:
/usr/include/string.h:125:14: note: expected ‘const char * restrict’ but argument is of type ‘char’
extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
so, as comments suggest, you can't scan directly into the struct; you can only scan into simpler types the C standard libraries recognizes: integer, floating-point numbers, char * strings etc. Similarly, you can't perform a string copy from your structs, which are not strings.
C is a strongly-typed language with very few allowed implicit conversions. In some cases, you are able to pass integers instead of floats or vice-versa, but nothing "magically converts" into a string, or is "magically parsed" from a string.
... and there are other issues:
Note #EdHeal 's comment: If your fopen() fails, you mustn't continue running the rest of the code. Either you should exit(EXIT_FAILURE); or wrap the rest of the code in main() within an else() block.
You should printf error messages to the standard error stream, so instead of printf("error message here") it should fprintf(stderr,"error message here"). Also, the standard C library places an error code you can get as the errno variable, or you can have an error message printed to the standard error stream with the perror() function. There are a few other related related functions (like strerror(), `err() etc.) which I will not get into here.
make some mistakes with pointers=)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct citydata
{
char *city;
int temp;
} citydata;
int main()
{
char *s;
citydata *values;
values = (citydata*)malloc(sizeof(citydata) * 16);
FILE * inp;
int reccount = 0;
int x = 0;
int n;
inp = fopen("mydata.txt", "r");
if(!inp)
printf("Unable ot open file\n");
while (fscanf(inp,"%s %d",s, &n) != EOF)
{
values[x].city = (char*)malloc(sizeof(char) * 20);
strcpy(values[x].city, s);
values[x].temp = n;
x++;
}
fclose(inp);
}

Incompatible pointer types in C. When do we use * or &? Having trouble with the concept of pointers by reference

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
}

not sure what's going on in this code

I have some C code, and I'm not quite sure what's going on.
#include <stdio.h>
#include <stdlib.h>
#define DIM1 7
#define DIM2 5
#define RES_SIZE 1000
typedef double stackElementT;
typedef struct {
stackElementT *contents;
int maxSize;
int top;
int min2;
} stackT;
void StackInit(stackT *stackP, int maxSize) {
stackElementT *newContents;
newContents = (stackElementT *)malloc(sizeof(stackElementT)*maxSize);
if (newContents == NULL) {
fprintf(stderr, "Not enough memory.\n");
exit(1);
}
stackP->contents = newContents;
stackP->maxSize = maxSize;
stackP->top = -1;
}
void StackDestroy(stackT *stackP) {
free(stackP->contents);
stackP->contents = NULL;
stackP->maxSize = 0;
stackP->top = -1;
}
int StackIsEmpty(stackT *stackP) { return stackP->top < 0; }
int StackIsFull(stackT *stackP) { return stackP->top >= stackP->maxSize-1; }
void StackPush(stackT *stackP, stackElementT element) {
if(StackIsFull(stackP)) {
fprintf(stderr, "Can't push element: stack is full.\n");
exit(1);
}
stackP->contents[++stackP->top] = element;
}
stackElementT StackPop(stackT *stackP) {
if(StackIsEmpty(stackP)) {
fprintf(stderr, "Can't pop element: stack is empty.\n");
exit(1);
}
return stackP->contents[stackP->top--];
}
int shell(char* s1, int arg) {
printf("> ");
scanf("%s %d%*c", &s1, &arg);
return arg;
}
int main() {
char cmds[DIM1][DIM2] = {{"push"}, {"pop"}, {"add"}, {"ifeq"}, {"jump"}, {"print"}, {"dup"}};
char* s1; int arg;
arg = shell(s1, arg);
printf("%s\n", &s1);
}
Input: push 4. It prints J+ instead of "push" but prints 4 normally.
It also gives these warnings on compile:
stack.c: In function ‘shell’:
stack.c:60: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘char **’
stack.c: In function ‘main’:
stack.c:71: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘char **’
stack.c:65: warning: unused variable ‘cmds’
stack.c:69: warning: ‘arg’ is used uninitialized in this function
Can someone please explain?
When you use the %s format specifier, it expect a value which is a pointer to the start of a string. In C, this type is char *.
Taking your main function, your variable s1 is of type char *. Therefore, s1 is a valid parameter to printf, so this line is valid:
printf("%s\n", s1);
Note the absence of an & in front of s1. In your code, you used the &, which takes the address of s1, the result of which will be of type char **. This is the wrong type, so don't use the &.
The thing is, printf can't actually tell what type its arguments are, since it is a variadic function. It simply uses whatever arguments are there, according to the types specified in the format string.
The same thing goes for scanf, but there is a pitfall: you must make sure that enough memory is allocated to account for the user input, else you will experience a buffer overflow with unpredictable results. Aside from this, printf and scanf are perfectly complementary.
Anyhoo, this takes care of the compiler warnings, aside from the unused cmds variable (it's unnecessary in the provided code). Also, there is the part of args - it really should be a variable declared inside of shell, and not passed as a parameter, since its value is not even used inside shell.
Don't know what's up with the rest of the code. It's superfluous considering your main function only calls on shell.

Resources