Changing an array value from a function in C - c

The program crashes right in the instruction mentioned in the source code (I didn't write all the code because it's too long)
int main()
{
char screen[24][80];
//......every thing is well until this instruction
backgrounds(5,screen);
//......the program doesn't execute the rest of the code
}
//______________________________________________________
//this is a header file
void backgrounds(int choice,char **screen)
{
if(choice==5)
{
screen[18][18]='-';
screen[18][19]='-';
screen[18][20]='-';
}
}

A char [24][80] cannot be converted to a char **.
When passed to a function, an array decays into a pointer to its first element. This is simple for a 1 dimensional array, but less so for higher dimensions.
In this case, a char [24][80] is an array of char [80]. So passing a variable of this type to a function yields a char (*)[80].
Change your function definition to either this:
void backgrounds(int choice,char (*screen)[80])
Or this:
void backgrounds(int choice,char screen[24][80])
Or you can use a variable length array for maximum flexibility:
void backgrounds(int choice, int x, int y, char screen[x][y])

Related

Invalid type of arguments C

I am trying to implement a function that read lines from a file and put them into a string array. But it gives me the warning:
expected char ** But argument is of type char * (*)[(sizetype)(numberOfchar)]
It was working on Windows but when I switch into Linux it stops working.
Here is the caller and the array variable :
char *hashes[numberOfchar];
PutInArray(textName, numberOfchar, &hashes);
And here is the function (the void* is for the next part of the program, threading) :
void* PutInArray(char* k, int d, char *tab[d]) {
FILE* fp = NULL;
int i;
fp = fopen(k, "r");
if(fp != NULL) {
for (i = 0; i < d; i++) {
tab[i] = (char *)malloc((34) * sizeof(char));
fgets(tab[i], 34, fp);
}
fclose(fp);
}
}
Let's see how function calls work for other types.
You have a variable int v; and a function void foo(int x) (the variable declaration and the parameter declaration look the same). You call foo(v). You also have a function void bar(int* x) (the variable declaration has one star less than the parameter declaration). You call bar(&v).
You have a variable int* v; and a function void foo(int* x) (the variable declaration and the parameter declaration look the same). You call foo(v). You also have a function void bar(int** x) (the variable declaration has one star less than the parameter declaration). You call bar(&v).
You have a variable const struct moo ***v and a function void foo(const struct moo ***x) (the variable declaration and the parameter declaration look the same). You call foo(v). You also have a function void bar(const struct moo ****x) (the variable declaration has one star less than the parameter declaration). You call bar(&v).
You have a variable char *hashes[numberOfchar] and a function void* PutInArray(char* k, int d, char *tab[d]). The variable declaration and the parameter declaration still look the same. Why on God's green earth stick & in front of the variable?
I hear you saying "but I want to pass hashes by reference, and to pass by reference I need to use &". Nope, arrays are automatically passed by reference (or rather an array automatically gets converted to a pointer of its first element; parameters of array type are similarly adjusted so that the rule formulated above just works).
For completeness, the analogue of bar would have a parameter that looks like this:
char* (*tab)[numberOfchar]
and if you had such parameter, you would have to use &hashes. But you don't need it.
Your code is almost OK. Concerning the error/warning you get, just write PutInArray(textName, numberOfchar, hashes) instead of PutInArray(textName, numberOfchar, &hashes) for the following reason:
In function PutInArray(char* k, int d, char *tab[d]), char *tab[d] has the same meaning as char*[] and char**, i.e. it behaves as a pointer to a pointer to a char.
Then you define hashes as char *hashes[numberOfchar], which is an array of pointers to char. When using hashes as function argument, hashes decays to a pointer to the first entry of the array, i.e. to a value of type char **, which matches the type of argument tab. However, if you pass &hashes, then you'd pass a pointer to type char *[], which is one indirection to much. (BTW: passing &hashes[0] would be OK).
BTW: PutInChar should either return a value or should be declared as void PutInArray(char* k, int d, char *tab[d]) (not void*).

Use of strcmp, initialization makes pointer from integer without a cast

void check_vertical_win(char A[rows][columns]){
int i,j;
char *str1=A[i][j];
char *str2=A[i-1][j];
char *str3=A[i-2][j];
char *str4=A[i-3][j];
int elegxos1;
int elegxos2;
elegxos1=strcmp(str1,str2);
elegxos2=strcmp(str3,str4);
for(j=0;j<6;j++){
for(i=6;i>=3;i--){
if(elegxos1==0 && elegxos2==0){
printf("\nBill is the winner.\n");
}
}
}
}
I want to check if two strings in a matrix are equal,so i'm using the function strcmp. However the compiler gives warning: Initialization makes pointer from integer without a cast.
(Then when i run the programme it says: Windows are checking for a solution at my problem).
I've tried a lot to find my mistake looking other similar programmes but i can't find out.
void check_vertical_win(char A[rows][columns])
This takes a matrix of chars. If you have a matrix where each entry is a string, it should be:
void check_vertical_win(char* A[rows][columns])
Also, you're using variables i and j before they are initialized (they contain garbage):
int i,j;
char *str1=A[i][j];
char *str2=A[i-1][j];
char *str3=A[i-2][j];
char *str4=A[i-3][j];

Use typedef for passing parameters by reference

I have this part in instructions of my school project:
In hw_numbers.h define type hw_number_array (for passing arguments to functions by reference). To store numbers in that array, use array of unsigned long.
My friend gave me hint, that it should look like this:
typedef unsigned long hw_number_array[];
Can someone explain me, why should I use this for passing an array to function?
And how can this type even exist without defining actual size of array?
If the size of the array is omitted, this is called an array of unknown bound. There are only certain places where this can be used, but a function parameter is one of them. There is a special rule that says even if a bound is given for an array, the bound is ignored and the parameter is equivalent to a pointer:
void f(int []) // this means void f(int *)
C++ inherited this rule from C. Some programmers consider it helpful for documenting that it is intended that an array is passed for the parameter as opposed to a pointer to a single value.
When calling such a function, it appears that you can pass an array by reference:
{
int a[5];
f(a); // actually passes an int pointer
}
But this is actually an illusion. The array decays to a pointer, and then a pointer is passed instead.
Here's some code you can try:
typedef unsigned long hw_number_array[];
int main()
{
unsigned long myArray[100];
setValue(myArray, 5, 10);
unsigned long value = getValue(myArray, 5);
return 0;
}
unsigned long setValue(hw_number_array a, int index, unsigned long value)
{
a[index] = value;
}
unsigned long getValue(hw_number_array a, int index)
{
return a[index];
}

Regarding array of pointer to char

I understand why this does not work:
int main(int argc, char *argv[]) {
char *names[] = {"name1", "name2", "name3", "name4"};
int i = 0;
while (i++ <= 3) {
printf("%s\n", *names++);
}
}
Error:
a.c: In function 'main':
a.c:16: error: wrong type argument to increment
shell returned 1
It's because I am trying to increment an array variable (and NOT a pointer). Please don't mind the line number in the error message, I have lot's of commented code above and below what I have put up here.
However, I do not understand why this piece of code works:
void myfunc(char *names[]) {
int i = 0;
while (i++ <= 3) {
printf("%s\n", *names++);
}
}
int main(int argc, char *argv[]) {
char *names[] = {"name1", "name2", "name3", "name4"};
myfunc(names);
}
How can we increment names in myfunc()? It's still a local array variable in myfunc().
Could someone please help?
Thanks.
In the 1st example names is an array. Arrays cannot be incremented.
In the 2nd example names is a pointer. Pointers can be incremented.
Background to why the 2nd example compiles:
A [] in a variable definition in a function declaration is the same as (another) *.
So this
void myfunc(char * names[]);
is equivalent to
void myfunc(char ** names);
The latter makes it obvious that here names is not an array but a pointer.
When you pass an array as a function argument, it turns it into a pointer to the first element in the array. This means that when you declare an array and attempt to increment it directly, you are trying to increment an array. When you pass the array as an argument, on the other hand, it is passed as a pointer, so you can increment it.
If you wish to pass the array as an array, and not as a pointer, you might consider using std::array, which is a fixed size container.
EDIT: I apologise. std::array is only available in C++.
When you pass array to a function it decays into pointer.
Refer here to know about array-decaying

Handing array over to function. Correct use of pointers?

I have an array/pointer related problem.
I created an int array myArray of size 3. Using a function I want to fill this array.
So I'm calling this function giving her the adress &myArray of the array.
Is the syntax correct for the function declaration`? I'm handing over the pointer to the array, so the function can fill the array elements one by one.
But somehow my array is not filled with the correct values.
In Java I could just give an array to a method and have an array returned.
Any help is appreciated! Thanks!
#include <stdio.h>
int myArray[3];
void getSmth(int *anArray[]);
int main(void)
{
getSmth(&myArray);
}
void getSmth(int *anArray[])
{
for(i=0...)
{
*anArray[i] = tmpVal[i];
}
}
Remove one level of indirection:
#include <stdio.h>
int myArray[3];
void getSmth(int anArray[]);
int main(void)
{
getSmth(myArray);
}
void getSmth(int anArray[])
{
for(i=0...)
{
anArray[i] = tmpVal[i];
}
}
Also, as others have suggested, it would be a good idea to pass the size of the array into getSmth().
No, the syntax is not correct. You have an extra *, making the argument into an array of pointers.
In general, it's better to use:
void getSmth(int *array, size_t length);
since then the function can work on data from more sources, and the length becomes available which is very handy for iterating over the data as you seem to want to be doing.
You'd then call it like so:
int main(void)
{
int a[12], b[53];
getSmth(a, sizeof a / sizeof a[0]);
getSmth(b, sizeof b / sizeof b[0]);
}
Note the use of sizeof to compute (at compile-time) the number of elements. This is better than repeating the numbers from the definitions of the variables.
Right now, your function accepts an int *anArray[] parameter, which is an array of pointers to int. Remove the unneccessary * and your function signature should look simply like this:
void getSmth(int anArray[]); // array of int
or
void getSmth(int *anArray); // pointer to first array element of type int
You should use either int anArray[] or int *anArray (which is effectively the same, because array decays to pointer). You should also make sure that the function knows how big your array is either by agreement or passing it as a parameter for it can not use sizeof for the purpose.

Resources