I have a issue with passing by reference using string - c

This is the question i am working on.
"A simple encryption scheme named "rotate13" for encrypting text is to convert each letter (a…z or A...Z) to another letter by counting forward 13 letters, looping around from 'z' to 'a' or 'Z' back to 'A' if necessary.
Write a function named rotate13 which takes a single null-terminated string as a parameter
and converts it to its rotate13 equivalent. The function should modify the string directly, and it
should not return anything. Remember, only letters should change; all other characters remain
the same. You may assume that ctype.h is correctly included at the top of your program so
that you can use any functions within the library if you wish. "
And this is the error i keep getting
"error C2664: 'rotate13' : cannot convert parameter 1 from 'char (*)[10]' to 'char *[]'"
Thanks for the help. It will help me in my revisions for finals.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int rotate13(char *array[]);
int size=10;
int main()
{
char arr[10];
printf("Please enter the letters you wish to encrypt: ");
scanf("%s",&arr);
printf("%s",arr);
rotate13(&arr);
system ("pause");
return 0;
}
int rotate13(char *array[])
{
int pointer;
while(*array[pointer]!='\0')
{
if(isupper(*array[pointer])!=0)
{
if(*array[pointer]<'N')
*array[pointer]=*array[pointer]+13;
else
*array[pointer]=*array[pointer]-13;
}
else
{
if(*array[pointer]<'n')
*array[pointer]=*array[pointer]+13;
else
*array[pointer]=*array[pointer]-13;
}
pointer++;
}
printf("%s", *array);
return 0;
}

Remove & from scanf("%s",&arr);
scanf("%s",arr);
rotate13 is expecting an argument of type char ** but, by passing &arr you are passing it an argument of type int (*)[10]. Passing arr to rotate13 will solve your problem.
rotate13(arr);

You want to pass a string as the parameter of rotate13, so use either
int rotate13(char *array);
or
int rotate13(char array[]);
and pass arr like rotate13(arr). the same for scanf("%s",arr);
And inside the function rotate13, pointer is an int(bad variable name) that isn't initialized. To access the characters, use array[pointer], not *arr[pointer].
The function should look like this:
int rotate13(char array[])
{
int n;
while(array[n]!='\0')
{

Use rotate13(arr); instead of rotate13(&arr); and parameter should be char [] instead of char *[]
rotate13(&arr); sends the address of the array to the function which causes the parameter mismatch

As other answers have said, you're better of with int rotate13(char array[]). To understand the context, you should read this wonderful page: http://c-faq.com/aryptr/
Basically, passing a pointer to an array is redundant here, because in C when you pass an array to a function, what's actually passed is a pointer to its first element. Arrays are inherently passed by reference.

Some things need to be explained. "string" in C is the address of a character buffer.
Since the identifier arr in char arr[10]; degrades to a pointer to the first element of the array, So you don't need to specify a pointer (i.e &) to the string in the argument to scanf.
By passing &arr in your scanf as scanf("%s",&arr); the pointer passed to scanf is now a doubly-indirect pointer (it is a pointer to a pointer to the beginning of the buffer) and will likely cause the program to crash or other bad behaviour.
The strings in c, dont require &array as they implicitly pass address of the first element of the character array
So your two statments scanf("%s",&arr) should be simply scanf("%s",arr) and rotate13(&arr) should be rotate13(arr). notice that address of the first element are implicitly passed in the function calls.
Your function rotate13(char *array[ ]) is completely wrong way of doing it
char arr[10] -> can hold single string ( simply an array )
char *array[] -> can hold multiple strings ( also called array of pointers)
the formal parameter should be rotate13(char array[]) or rotate13(char *array).
After seeing your code I believe your not changing the contents of arr so you require a call by value instead of a call by address
char array[] - > call by value , char *array -> call by address
Your variable int pointer is not initialized before its use, Its dangerous. First initialize is to zero.
Change all the occurences of *array[pointer] to array[pointer]
If your wishing to change the contents of arr use call by address just change rotate13(char array[]) to rotate13(char *array) and Dont forget to initialize pointer variable to zero .

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

Changing an array value from a function in 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])

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

C Function implementation - with Pointer vs without Pointer

I've just started to work with C, and never had to deal with pointers in previous languages I used, so I was wondering what method is better if just modifying a string.
pointerstring vs normal.
Also if you want to provide more information about when to use pointers that would be great. I was shocked when I found out that the function "normal" would even modify the string passed, and update in the main function without a return value.
#include <stdio.h>
void pointerstring(char *s);
void normal(char s[]);
int main() {
char string[20];
pointerstring(string);
printf("\nPointer: %s\n",string);
normal(string);
printf("Normal: %s\n",string);
}
void pointerstring(char *s) {
sprintf(s,"Hello");
}
void normal(char s[]) {
sprintf(s,"World");
}
Output:
Pointer: Hello
Normal: World
In a function declaration, char [] and char * are equivalent. Function parameters with outer-level array type are transformed to the equivalent pointer type; this affects calling code and the function body itself.
Because of this, it's better to use the char * syntax as otherwise you could be confused and attempt e.g. to take the sizeof of an outer-level fixed-length array type parameter:
void foo(char s[10]) {
printf("%z\n", sizeof(s)); // prints 4 (or 8), not 10
}
When you pass a parameter declared as a pointer to a function (and the pointer parameter is not declared const), you are explicitly giving the function permission to modify the object or array the pointer points to.
One of the problems in C is that arrays are second-class citizens. In almost all useful circumstances, among them when passing them to a function, arrays decay to pointers (thereby losing their size information).
Therefore, it makes no difference whether you take an array as T* arg or T arg[] — the latter is a mere synonym for the former. Both are pointers to the first character of the string variable defined in main(), so both have access to the original data and can modify it.
Note: C always passes arguments per copy. This is also true in this case. However, when you pass a pointer (or an array decaying to a pointer), what is copied is the address, so that the object referred to is accessible through two different copies of its address.
With pointer Vs Without pointer
1) We can directly pass a local variable reference(address) to the new function to process and update the values, instead of sending the values to the function and returning the values from the function.
With pointers
...
int a = 10;
func(&a);
...
void func(int *x);
{
//do something with the value *x(10)
*x = 5;
}
Without pointers
...
int a = 10;
a = func(a);
...
int func(int x);
{
//do something with the value x(10)
x = 5;
return x;
}
2) Global or static variable has life time scope and local variable has scope only to a function. If we want to create a user defined scope variable means pointer is requried. That means if we want to create a variable which should have scope in some n number of functions means, create a dynamic memory for that variable in first function and pass it to all the function, finally free the memory in nth function.
3) If we want to keep member function also in sturucture along with member variables then we can go for function pointers.
struct data;
struct data
{
int no1, no2, ans;
void (*pfAdd)(struct data*);
void (*pfSub)(struct data*);
void (*pfMul)(struct data*);
void (*pfDiv)(struct data*);
};
void add(struct data* x)
{
x.ans = x.no1, x.no2;
}
...
struct data a;
a.no1 = 10;
a.no1 = 5;
a.pfAdd = add;
...
a.pfAdd(&a);
printf("Addition is %d\n", a.ans);
...
4) Consider a structure data which size s is very big. If we want to send a variable of this structure to another function better to send as reference. Because this will reduce the activation record(in stack) size created for the new function.
With Pointers - It will requires only 4bytes (in 32 bit m/c) or 8 bytes (in 64 bit m/c) in activation record(in stack) of function func
...
struct data a;
func(&a);
...
Without Pointers - It will requires s bytes in activation record(in stack) of function func. Conside the s is sizeof(struct data) which is very big value.
...
struct data a;
func(a);
...
5) We can change a value of a constant variable with pointers.
...
const int a = 10;
int *p = NULL;
p = (int *)&a;
*p = 5;
printf("%d", a); //This will print 5
...
in addition to the other answers, my comment about "string"-manipulating functions (string = zero terminated char array): always return the string parameter as a return value.
So you can use the function procedural or functional, like in printf("Dear %s, ", normal(buf));

Pointer to array of structures in C

Please let me know how can I pass a pointer to the array of structures in C as a function argument.
Below is my code.
#include <stdio.h>
#include<strings.h>
typedef struct _Alert
{
char MerchantNo[21];
time_t last_update;
} Alert;
typedef Alert *PALERT;
int set(PALERT palertMerch[5], int *merchnoIndex, char * txnMerchant)
{
strcpy(palertMerch[*merchnoIndex]->MerchantNo, txnMerchant);
*(merchnoIndex) = *(merchnoIndex) + 1 ;
return 0;
}
int main()
{
Alert alert[5];
for(int i =0; i<5;i++)
{
memset(alert[i].MerchantNo, 0x00, 21);
alert[i].last_update = (time_t)0;
}
char *p = "SACHIN";
int index = 0;
set(alert[5], index, p);
}
Error message
"3.c", line 34: argument #1 is incompatible with prototype:
prototype: pointer to pointer to struct _Alert {array[21] of char MerchantNo, long last_update} : "3.c", line 14
argument : struct _Alert {array[21] of char MerchantNo, long last_update}
"3.c", line 34: warning: improper pointer/integer combination: arg #2
cc: acomp failed for 3.c
You just pass the array, it'll get decayed to the pointer to the first array element:
set( alert, &index, p );
Note that I also corrected your second error of passing integer as a pointer for the second argument.
Edit 0:
I missed the declaration of PALERT - your function definition is wrong, it should be something like:
int set( PALERT palertMerch, int* merchnoIndex, const char* txnMerchant )
{
assert( *merchnoIndex >= 0 && *merchnoIndex < 5 );
strcpy( palertMerch[*merchnoIndex].MerchantNo, txnMerchant );
...
}
I know, arrays and pointers are a bit confusing in C, and you were trying to jump to arrays of pointers already :)
You actually cannot pass an array to a function. What happens when you do, is that a pointer to the first element in an array is passed in instead. (That proccess is often described as "an array decays into a pointer").
That is,
set(alert, index, p);
Is just the same as:
set(&alert[0], index, p);
(Note that you called it as set(alert[5], index, p); , this just passes in the 6. element of your array , which btw is invalid, as your array only have room for 5 elements.)
So, what you do when you want to pass an array to a function is you
Pass a pointer to the first element in the array (which can be done by just writing name_of_array or &name_of_array[0]
Add another argument that is the length of the array. You might need this as if your array can have different sizes, and you cannot know how many elements an array have, if all you got is a pointer to its first element:
Let's skip item 2. above for now, you can just do:
//PALERT is already a pointer, otherwise specify the first argument as:
//ALERT *palertMerch
int set(PALERT palertMerch, int *merchnoIndex, char * txnMerchant)
{
strcpy(palertMerch[*merchnoIndex]->MerchantNo, txnMerchant);
*(merchnoIndex) = *(merchnoIndex) + 1 ;
return 0;
}
And call it like:
char *p = "SACHIN";
int index = 0;
set(alert, index, p);
btw, unless you have a good reason, try not to hide a pointer in a typedef as you do in typedef Alert *PALERT; doing so often gets confusing.
remove the array brackets and it should work.
The reason for this is that array notation is an easier way to represent sequences of items in memory. For example, in an array a[5], you can access the third element as a[3] or *(a+3).
Your function takes type PALERT *[5]. You are passing in Alert[5] instead. There are other problems with your code that need fixing before it will successfully run.

Resources