C Code: Pass string from one function to another function - c

The main problem is: as soon as I send a string from one function to another, this second function doesn't really get the string as a parameter.
In detailled:
I have a function void myfunc() contains a word. This word should be send to another function, so it can count the length of it. That's what I've written so far:
void myfunc(int (*countlength)(char ch)){
char word[10] = "Hello\n";
int result = countlength(&word);
printf("Length of word: %d\n", result);
}
The word is being send to this function countlength(char* word):
int countlength(char* word) {
int length = strlen(word);
return length;
}
However the function countlength() can't count it's length and I don't know why...
The thing is, it works when the word is in the main function. Does anybody know why my Code doesn't work?

Two mistakes:
void myfunc(int (*countlength)(char ch)){
should be
void myfunc(int (*countlength)(char* ch)){
instead, as the function accepts char pointers.
Secondly,
int result = countlength(&word);
should be
int result = countlength(word);
as word is already a char*.

What you're passing to the function doesn't match what it's expecting.
&word has type char (*)[10], i.e. a pointer to an array of size 10. The function expects a char *, so just pass word. Arrays are converted to a pointer to their first element when passed to a function, so the types will match.

This parameter declaration of a function pointer
int (*countlength)(char ch)
does not correspond to the function declaration used as an argument for this parameter
int countlength(char* word)
So you need to declare the parameter like
int (*countlength)(char *ch)
In fact the identifier ch is redundant. You could just write
int (*countlength)(char *)
That is the declaration of the function myfunc will look like
void myfunc(int (*countlength)(char *));
You declared a character array within the function like
char word[10] = "Hello\n";
So the expression used as an argument in this call
countlength(&word)
has the type char ( * )[10] instead of the expected type char *.
There is no need to use the address of operator. The array designator used as an argument in this call
countlength( word )
is implicitly converted to a pointer to the first element of the array and has the type char *.
This function
int countlength(char* word) {
int length = strlen(word);
return length;
}
does not change its argument. So it should be declared at least like
int countlength( const char* word) {
int length = strlen(word);
return length;
}
The used standard C string function strlen has the return type size_t. In general an object of the type int can be not enough large to store possible lengths of strings.
So the function should be declared like
size_t countlength( const char* word) {
return strlen(word);
}
Thus returning to the function myfunc it should look like
void myfunc( size_t ( *countlength )( const char * ) )
{
char word[10] = "Hello\n";
size_t result = countlength( word );
printf( "Length of word: %zu\n", result );
}

Well; if you use the code like this, it's working just fine
When you declare an array, its name has a type of a pointer so here word has a type of char* and it's the pointer of the array's first element
#include <stdio.h>
#include <string.h>
int countlength(char* word) {
int length = strlen(word);
return length;
}
void myfunc(){
char word[10] = "Hello\n";
int result = countlength(word);
printf("Length of word: %d\n", result);
}
main(){
myfunc();
}
Length of word: 6

Related

strstr not working with needles shorter than 3 char

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* findSequence(char s[], char ch, int n){
int i;
char*ptr;
char needle[n];
char*npdr=&needle;
for(i=0;i<n;i++){needle[i]=ch;}
ptr = strstr(s,ndpr);
printf("%s",ptr);
return ptr;
}
int main()
{
char stringa[]={"ciccciopasticcio"};
char carattere='c';
char*ptr;
int n=3;
ptr=findSequence(stringa, carattere,n);
return 0;
}
This quick code, should search for a matching between a string and a needle of non set lenght, it works just fine with any n>=3 the problem is with 1 and 2 as n values.
watching the debug i noticed that the pointer npdr adds a second and third value to the sequence on his own example: n=2 needle="cc" npdr=address of needle[0] "cc#"
Do you have any ideas of why this is happening?
The standard function strstr expects two pointers to strings. But you are calling the function passing an array as the second argument that does not contain a string - a sequence of characters terminated by the zero character '\0'
char needle[n];
char*npdr=&needle;
for(i=0;i<n;i++){needle[i]=ch;}
ptr = strstr(s,ndpr);
So the code invokes undefined behavior.
Also this initialization
char*npdr=&needle;
is incorrect. The initialized pointer has the type char * while the initializing expression has the type char ( * )[n]. At least you need to write
char*npdr=needle;
You could declare the array like
char needle[n + 1];
and
needle[n] = '\0';
Pay attention to that the function should not output any message. It is the caller of the function will decide whether to output a message. Moreover this call of printf
printf("%s",ptr);
will invoke undefined behavior if the pointer ptr is equal to NULL.
The function itself should be declared the following way
char* findSequence(const char s[], char ch, size_t n);
That is the first parameter should be declared with the qualifier const because passed strings are not changed within the function. And the second parameter should have unsigned integer type size_t instead of the signed integer type int.
Also using a variable length array within the function makes the function unsafe.
The function can be defined using standard C string function strchr instead of the function strstr.
Here is a demonstration program.
#include <stdio.h>
#include <string.h>
char * findSequence( const char s[], char ch, size_t n )
{
const char *p = NULL;
if (n != 0 && ch != '\0')
{
size_t count = 0;
do
{
count = 0;
p = strchr( s, ch );
if (p)
{
s = p;
do
{
++count;
} while (*++s == ch);
}
} while (p != NULL && count != n);
}
return ( char * )p;
}
int main( void )
{
char stringa[] = { "ciccciopasticcio" };
char carattere = 'c';
size_t n = 3;
char *ptr = findSequence( stringa, carattere, n );
if (ptr != NULL)
{
puts( ptr );
}
}
The program output is
ccciopasticcio

Understanding parameters of strlen in C

I am a bit confused on why my code is not iterating a string in C programming.
Essentially.
I have this function here
int atoi(const char *s[]){
printf(" The length is %d",strlen(s));
int length = strlen(s);
for(int i = 0; i< length; ++i){
printf("This is %s",*(s+i));
}
return 0;
}
My first question
When doing strlen(s) why does it work, but when doing strlen(*s) it does not work, isn't strlen supposed to be taking in the value not the pointer so the latter should work?
How would I go about looping through the pointer that points to the string in memory?
Cheers
Do not use standard function names
strlen takes a pointer to char and returns size_t (not int)
Your print format is wrong.
Your function takes an array of pointers not a pointer to char
int myfunc(const char *s)
{
size_t length = strlen(s);
printf(" The length is %zu", length);
for(size_t i = 0; i< length; ++i){
printf("This is '%c'\n",*(s+i));
}
return 0;
}
For starters you should not name your user-defined functions the same ways as standard C functions.
There is already standard C function with the name atoi declared in header <stdlib.h>. Using the same name can result in compiler or linker errors.
Your function atoi declared like
int atoi(const char *s[]){
that is the same as
int atoi(const char **s){
due to adjusting by the compiler a parameter having an array type to pointer to the array element type accepts a "double" pointer. So using the function strlen with the double pointer invokes undefined behavior
printf(" The length is %d",strlen(s));
The function strlen expects an argument of the type char * or const char * but not an argument of the type const char **.
Moreover the return value of the function strlen has the type size_t. And using the conversion specifier %d in a call of printf with a corresponding argument expression of the type size_t again invokes undefined behavior. You have to use the conversion specifier %zu instead of %d.
This for loop
for(int i = 0; i< length; ++i){
printf("This is %s",*(s+i));
}
does not make sense because the variable length actually does not contain the number of elements in the passed array.
You need either explicitly to pass the number of elements in the array or the array should have a sentinel value.
And the return type of the function int also does not make sense because the returned value 0 reports nothing useful to the caller of the function.
If the function is designed only to traverse a string in a for loop then it should be declared like for example
char * func( const char *s )
{
for ( const char *p = s; *p != '\0'; ++p )
{
putchar( *p );
}
return ( char * )s;
}
If you want to pass to the function an array of strings then the function can be implemented for example the following way as shown in the demonstration program below provided that the array contains a sentinel value
#include <stdio.h>
void func( const char **s )
{
for ( ; *s != NULL; ++s )
{
printf( "%s ", *s );
}
}
int main( void )
{
const char * s[] = { "Hello", "World!", NULL );
func( s );
putchar( '\n' );
}
The program output is
Hello World!
Question:
when doing strlen(s) why does it work, but when doing strlen(*s) it
does not work?
Answer:
strlen() expects an argument of type const char *, not a const char **. You passed an array of pointers to char to the function, which decayed to a char **. From the man page:
The strlen() function calculates the length of the string pointed
to by s, excluding the terminating null byte ('\0').
Question:
How would I go about looping through the pointer that points to the
string in memory?
printf("This is %s",*(s+i));
Answer:
Assuming you wanted to pass a string (an array of null-terminated bytes) to the function and print it char by char, change the function declaration to take a const char *, and use the correct format specifier in the call to printf() (The %s format specifier expects a pointer to char, not a char itself). Change the call to:
printf ("%c", *(s + i));
Note that *(s + i) is equivalent to s[i], which is more readable. So the above call to printf() can be rewritten as:
printf ("%c", s[i]);
Aside: strlen() returns size_t, not an int. Do not mismatch numeric types.

How can I change the value of a char using a pointer?

So I am quite new to using pointers and wanted to know how I could do the following but for a string value.
int number(int, int *);
int main()
{
int a = 15;
int b =0;
number(a,&b);
fprintf(stdout,"Number b is %d\n",b);
return 0;
}
int number(int a, int *b) {
*b = a;
}
It seems you mean something like the following
#include <stdio.h>
char * assign( char **s1, char *s2 )
{
return *s1 = s2;
}
int main(void)
{
char *s1 = "Hello World!";
char *s2;
puts( assign( &s2, s1 ) );
return 0;
}
The program output is
Hello World!
That is to assign a value to the pointer s2 (that has the type char *) within the function you need to pass it to the function by reference as you are doing in your program with an object of the type int. Otherwise the function will deal with a copy of its argument and changes the copy will not influence on the argument.
Passing an object by reference in C means passing an object indirectly through a pointer to it.
If you have character arrays that store strings then to copy a string to a character array you can use the standard string function strcpy declared in the header <string.h>.

Pointer to function Prototype

i am trying to figure out what those prototypes mean
1.int* (*fpData)(int (*paIndex)[3] , int (* fpMsg) (const char *),
int (*fpCalculation[3]) (const char *));
2.int* (*fpData[2])(int (*paIndex)[3] , int (* fpMsg) (const char *),
int (* fpCalculation[3]) (const char *));
3.int* (*(*fpData)(const char *))(int (*paIndex)[3] ,
int (* fpMsg) (const char *),
int (* fpCalculation[3]) (const char *));
First you should find actual variable which is being declared. In all 3 examples this is fpData. Then you should start to read declaration staring from this variable moving from inside to outside.
So, let us begin with first example. We see fpData, so we say "fpData is...", then we see "*" before "fpData", so we say "fpData is pointer to...", then we see function type declaration outside of *fpData, so we say "fpData is pointer to function...". Then we should read types of arguments and result of this function.
Well, you can read types for all 3 arguments without problems. They are:
"paIndex is pointer to array of length 3 of ints"
"fpMsg is pointer to function from const char * to int"
"fpCalculation is array of length 3 of pointers to function from const char * to int"
In the last argument you should note that [3] has the higher priority than "*". I mean that while reading declaration from inside to outside you should read first array and then pointer. I. e. int *a[3] is "a is array of length 3 of pointers of int" and not "pointer to array".
Assuming all this I think you can read 2nd declaration without problems.
Now you should learn this: type of function result is written outside (i. e. BEFORE AND AFTER) of everything else.
Let us consider this:
char (*(*fp)(int))(double)
What this means? Well let's start reading, "fp is pointer to function which takes int and returns... what?" Well, we already have read (*fp)(int) part. Now we want to read everything else. And we want to understand what is result type of function we already read. And now we should note that result of function is the thing which is written OUTSIDE (i. e. BEFORE and AFTER) of everything else, i. e. outside of what we already read.
So, we have read (*fp)(int). Everything else, i. e. char (*XXX)(double) is return type for function we already read. So, well, let's continue reading. Finally we will get this:
"fp is pointer to function which gets int and returns pointer to function which gets double and returns char".
Now you can read 3rd declaration without problems
The C gibberish ↔ English link that chux posted still looks like gibberish to
me. So I'll try to sound more human:
int* (*fpData)(int (*paIndex)[3] , int (* fpMsg) (const char *),
int (*fpCalculation[3]) (const char *));
This declares a function pointer fpData that returns a pointer to int. The
function takes 3 variables of the following types:
paIndex is a pointer to an int array of dimension 3. This can be used for
example when you have this:
void bar(int (*paIndex)[3])
{
}
void foo(void)
{
int fields[5][3] = { {1,1,1}, ... };
bar(fields);
}
fpMsg is a function pointer that returns an int. The function takes one
arguments only, a const char* (a string basically).
fpCalculation is an array of dimension 3 of function pointers that return
int. The functions take on argument only: a const char*.
This is a beast of a function pointer, it works in an evironment like this:
#include <stdio.h>
int msg(const char *name)
{
printf("msg: %s\n", name);
return 0;
}
int abc1(const char *name)
{
printf("abc1: %s\n", name);
return 0;
}
int abc2(const char *name)
{
printf("abc2: %s\n", name);
return 0;
}
int *scary_function(int (*paIndex)[3] , int (* fpMsg) (const char *),
int (*fpCalculation[3]) (const char *))
{
fpMsg("fpMsg");
fpCalculation[0]("fpCalculation0");
fpCalculation[1]("fpCalculation1");
fpCalculation[2]("fpCalculation2");
for(int i = 0; i < 4; ++i)
{
for(int j = 0; j < 3; ++j)
{
printf("%-3d ", paIndex[i][j]);
}
puts("");
}
return NULL;
}
void foo(void)
{
int matrix[4][3] = { {1,2,3}, {4,5,6}, {7,8,9}, {10,11,12} };
int (*fpcalcs[3])(const char*) = { msg, abc1, abc2 };
int* (*fpData)(int (*paIndex)[3] , int (* fpMsg) (const char *),
int (*fpCalculation[3]) (const char *));
fpData = scary_function;
// calling the function through the function pointer
fpData(matrix, msg, fpcalcs);
}
int main(void)
{
foo();
return 0;
}
The output of this is
msg: fpMsg
msg: fpCalculation0
abc1: fpCalculation1
abc2: fpCalculation2
1 2 3
4 5 6
7 8 9
10 11 12
So I've explained in detail how to parse the declaration of these function
pointers. Now try understanding the other 2 yourself, if you still have problems,
post a comment.
1.int* (*fpData)(int (*paIndex)[3] , int (* fpMsg) (const char *), int (*fpCalculation[3]) (const char *));
Here, fpdata is pointer to a function which takes three arguments and returns a pointer to an integer. The arguments are as follows:
pointer to 3 elements integer array,
pointer to a function which takes const char pointer as an argument and return type int,
array of 3 function pointers and each function takes const char pointer as an argument and return type is int
2.int* (*fpData[2])(int (*paIndex)[3] , int (* fpMsg) (const char *), int (* fpCalculation[3]) (const char *));
In this case, fpdata is array of 2 function pointers, and each function takes three arguments -
pointer to 3 elements integer array,
pointer to a function which takes const char pointer as an argument and return type int,
array of 3 function pointers and each function takes const char pointer as an argument and return type is int
The return type is a pointer to an integer
3.int* (*(*fpData)(const char *))(int (*paIndex)[3] , int (* fpMsg) (const char *), int (* fpCalculation[3]) (const char *));
Finally, fpdata is a pointer to a function which takes three arguments -
pointer to 3 elements integer array,
pointer to a function which takes const char pointer as an argument and return type int,
array of 3 function pointers and each function takes const char pointer as an argument and return type is int
The return type is a function pointer which takes const char pointer as argument and return type is pointer to an integer.
int* (*fpData)(int (*paIndex)[3] , int (* fpMsg) (const char *),
int (*fpCalculation[3]) (const char *));
it is function prototype declaration.
Where fpData is a function name, function that takes three arguments:
int (*paIndex)[3]
int (* fpMsg) (const char *)
int (*fpCalculation[3]) (const char *)
…and returns a function pointer [pointer to a function that take no argument but returns pointer to an integer].
Details :: Given function can be written as below
typedef int* (*ret_func_ptr) ();
ret_func_ptr (*fpData)(int (*paIndex)[3] , int (* fpMsg) (const char *),
int (*fpCalculation[3]) (const char *));

How do I pass an array as an argument to a function?

I have read the post here on the same subject, but it doesn't seem to have the solution to my problem.
If I need to write a function str_reverse() which reverses any string passed to it, how can I go about it? Just as the person who asked the question I linked above, the following code
#include <stdio.h>
#include <string.h> //for strlen
#define maxL 300 //Max String Length
void str_reverse(char);
int main(){
//Variables
char x[maxL];
//User Prompt
printf("Enter a string no longer than %d characters: ", maxL);
gets(x);
str_reverse(x);
//Return Statement
return 0;
}
void str_reverse(char x){
int i, l;
l = strlen(x);
printf("In reverse: ");
for(i=l-1; i>=0; i--)
printf("%c",x[i]);
}
gives me an error. How can I create a program which allows me to reverse the string?
You are passing fine but the function isn't receiving properly. Change it to:
void str_reverse(char *x){
..
}
and the prototype to:
void str_reverse(char*);
Also, gets() is dangerous and should never be used. Use fgets() instead:
if( fgets(x, sizeof x, stdin) == NULL) { /* failure */ }
x[strcspn(x,"\n")] = 0; // to remove the trailing newline, if any.
Your can pass array as type arr[] or as type * pointer. you will have to pass length as an argument to your string reverse function. New declaration of string reverse will look like this:
void str_reverse(char *x,int length)
or
void str_reverse(char x[],int length)
for more information you can follow Length of array in function argument
A function parameter declared as an array is adjusted to pointer to array element.
Thus these function declarations are equivalent and declare the same one function
#define maxL 300
void str_reverse(char[maxL]);
or
void str_reverse(char[10]);
or
void str_reverse(char[1000]);
or
void str_reverse(char[]);
or
void str_reverse( char *);
And on the other hand when an array is passed as an argument to a function it is implicitly converted to pointer to its first element.
So this function call
char x[maxL];
//...
str_reverse(x);
can be imagine like
char x[maxL];
//...
char *tmp = x;
str_reverse(tmp);
Take into account that function gets is unsafe and is not supported by the C Standard any more.
Use instead standard function fgets
Also it is better if the function returned pointer to its first character.
Your function does not try to reverse a string. It tries to output a string in the reverse order.
So the function that indeed reverses a string can be written like
char * str_reverse( char *s )
{
size_t n = strlen( s );
for ( size_t i = 0; i < n / 2; i++ )
{
char c = s[i];
s[i] = s[n- i-1];
s[n-i-1] = c;
}
return s;
}
Here is a demonstrative program
#include <stdio.h>
#include <string.h>
#define maxL 300 //Max String Length
char * str_reverse( char *s )
{
size_t n = strlen( s );
for ( size_t i = 0; i < n / 2; i++ )
{
char c = s[i];
s[i] = s[n- i-1];
s[n-i-1] = c;
}
return s;
}
int main( void )
{
//Variables
char s[maxL];
//User Prompt
printf("Enter a string no longer than %zu characters: ", maxL);
fgets( s, maxL, stdin );
s[strcspn( s, "\n" )] = '\0';
puts( str_reverse( s ) );
return 0;
}
Its output might look like
Enter a string no longer than 300 characters: Hello, World!
!dlroW ,olleH
You can achieve this by many different ways:
Option-1
Formal parameters as a pointer −
void myFunction(char *param) {
.
.
.
}
Option-2
Formal parameters as a sized array −
void myFunction(char param[10]) {
.
.
.
}
Option-3
Formal parameters as an unsized array −
void myFunction(char param[]) {
.
.
.
}

Resources