pass char array as argument - c

Can anyone explain to me what I don't understand here please?
I am trying to pass the argument as a "string" (i know there are no strings in c) so that I can use that string later with other functions like it's a file name that has to be passed for example.
But I don't know why it won't accept it or what type should it be
#include <stdio.h>
int main ( int argc, char *argv[] )
{
char *array= argv[0];
foo(*array);
}
void foo( char *array)
// notice the return type - it's a pointer
{
printf(array);
}
thanks alot!

You should be calling the function like this:
foo(array);
What you're doing is dereferencing the pointer, which returns a char, which is the first character in the string.
Your printf call should also look like this:
printf("%s", array);
Your entire fixed code should look like the following:
#include <stdio.h>
void foo(char *array)
{
printf("%s", array);
}
int main ( int argc, char *argv[] )
{
// TODO: make sure argv[1] exists
char *array= argv[1];
foo(array);
}

When you say foo (*array), you're decaying the array into a pointer to the first element, in order to dereference that element, giving you the first character. That's what you're trying to pass to the function. Leave out the asterisk and just pass array for it to decay into the pointer you need.
The other issue is that you're not using printf correctly. First of all, here's a reference. You need to pass a string of tokens that tell the compiler what type of argument to expect next because it has no way of telling. In your case, your string would contain "%s" to tell it to expect a char *, and then you'd pass array as that char * argument.
printf ("The string is %s", array);

argv is a array of character pointers, that means argv is going to store the address of all the strings which you passed as command line argument.
so argv[0] will gives you the address of first string which you passed as command line argument, that you are storing into the pointer variable array in main function.
Now you have to pass only the address to the function foo but you are passing the first character of that string. For example if your first command line argument is temp.txt you are passing character t to the function foo. So inside foo function you are having a char pointer variable array, in that ASCII value of the character t will be assigned. And then you are passing that to printf, which will treads that ASCII value as address, and it will tries to access that address to print which will leads to crash (unexpected behaviour).
So you have to pass only the address of the command line argument to the function foo like below.
foo(array);
printf(array) - Here printf will treads the format specifier as string(%s) and it will tries to print all the characters starting from the address array untill it meets a null character \0.
But better to add the printf like below
printf("%s", array);

Related

Why does declaring a character string parameter in a function needs a pointer in C?

Can anyone please explain, why there is a need to include an "asterisk" (*) in a character string parameter declaration in a function?
#include <stdio.h>
void func2(char *fName);
int main() {
char name[20];
printf("What is your name? ");
scanf("%s", name);
//some code here
}
void func2(char *fName) {
//some code here
}
An intuitive reason is that character strings can take different lengths. As it is not possible to define a "one size fits all" parameter type, you need to use a pointer to indicate the beginning of your character string in your function parameters.
First of all, note that, C language does not have native string type. In C, strings are actually one-dimensional array of characters terminated by a null character \0.
Quoting C11, 6.3.2.1p3 [emphasis added]
Except when it is the operand of the sizeof operator, the _Alignof operator, or the unary & operator, or is a string literal used to initialize an array, an expression that has type ''array of type'' is converted to an expression with type ''pointer to type'' that points to the initial element of the array object and is not an lvalue.
The declarations
void func2 (char fName[]);
void func2 (char fName[20]);
void func2 (char fName[100]);
are exactly same as
void func2 (char *fName);
This conversion of array-like declarators into pointers holds only within function formal parameter declarations, nowhere else. Check this.
In the program, when you pass array name to a function
int main (void) {
char name[20];
......
func2 (name);
......
the argument name, which is array of type char, is converted to pointer of type char that points to the initial element of the array name.
Consider this example:
#include <stdio.h>
void func2 (char *fName);
void func3 (char fName[]);
void func4 (char fName[20]);
void func5 (char fName[1]);
int main (void) {
char name[20];
printf ("What is your name? ");
scanf ("%19s", name);
func2 (name);
func3 (name);
func4 (name);
func5 (name);
return 0;
}
void func2 (char *fName) {
printf ("In func2, name: %s\n", fName);
}
void func3 (char fName[]) {
printf ("In func3, name: %s\n", fName);
}
void func4(char fName[20]) {
printf ("In func4, name: %s\n", fName);
}
void func5 (char fName[1]) {
printf ("In func5, name: %s\n", fName);
}
Compile
# gcc -Wall -Wextra prg.c
#
Execute
# ./a.out
What is your name? Gem
In func2, name: Gem
In func3, name: Gem
In func4, name: Gem
In func5, name: Gem
The answer is in several parts:
C has no built-in, first-class string type.
Type char is for holding single characters like 'c'. A variable of type char cannot hold a multi-character string like "cat" (or even, for that matter, a single-character string like "c").
In C, strings are implemented as null-terminated arrays of char.
Arrays are second-class citizens in C. You cannot assign one array to another, or pass an array to a function.
When you try to assign an array, or pass it to a function, or in fact do anything where it seems like the value of the array would be needed, what you get instead is a pointer to the array's first element.
So that's why functions that operate on strings receive arguments of type char *. The original string was an array of char, but somewhere along the way before the function received it the string got represented as a pointer to its first element.
If you're used to languages where there is a true, built-in, first-class string type, where manipulating strings (and using operators and functions to create new strings) is as straightforward as operating on integers, characters, and floating-point values, then C can be pretty confusing at first. In C, whenever you work with strings, there are always pointers involved, and you always have to think about details like where the pointers point, and whether the pointer points to enough memory for the string it's trying to reference, and whether there's a proper null terminator. Once you're used to it, this is all easy enough to do, but it is something you have to think a little extra about.
When declaring parameters to functions, declaring an array variable(one dimensional array of characters) without size is equivalent to declaring a pointer. Often this is done to emphasize the fact that the pointer variable will be used in a manner equivalent to an array.
/* two equivalent function definitions */
void func2( char *fName );
void func2( char fName[] );
Hope this will make you even more clear.
when passing a string, all that actually gets passed is a pointer to the string

How does this passing of an array to "qsort" work?

So I have the main function declared below, to which the user must pass arguments from the command line when first executing the program. Then, it takes the *argv[] array of string inputs and sorts them using the stdlib.h's qsort function, after which it finally prints out all elements, besides the file name, in the input array;
int main(int argc,char *argv[]){
qsort(argv,args,sizeof(*argv),comp_func);
for(int U=1;U<argc;U++)printf("%s\n",argv[U]);
}
The comp_func function passed to qsort is shown below:
int comp_func(char*a,char*b){
return strcmp(*(char **)a,*(char **)b);
}
What I would like to know is what is going on here? I am pretty that qsort sends each 2-length permutation of the array to the given comparator function, both of which are, in this case, strings since argv is an array of strings. However, what I don't get is what is going on here:
strcmp(*(char **)a,*(char **)b)
What is *(char **)a doing? Is it just creating an arbitrary char[] array of a pointer to an arbitrary string with a length of 1, whose first value is then assigned the a, after which it is finally dereferenced, ultimately returning the string a? If so, then why doesn't just plain old a work? Also, interestingly, if I printf just plain old a, it outputs a string of random characters that goes something like ??O_?. However, when I printf *(char **)a instead, I get the actual string input. Why is that? I am a beginner in C, so please bear with me if I ask any more questions.
qsort() expects a consecutive array of objects as first argument base. Now, argv is an array of const char * pointers, so
qsort(argv, args, sizeof(*argv), comp_func);
says, sort that array of pointers, where sizeof(*argv) is the size of a const char *.
What gets passed to comp_func(), is the address of two objects offset from the base pointer, i.e. the addresses of the char pointers in argv. To get the actual string array/pointer back that contains the argument string, we need to de-reference it. That is, the argument strings are actually at *a and *b.
The signature is still all wrong and should throw compiler warnings all over the place. comp_func() actually takes two const void *:
int
comp_func(const void *a,const void *b) {
return strcmp(*(const char **)a,*(const char **)b);
}
The casts are necessary, since *a is not a valid type with const void * and strcmp() needs const char *, too.
tldr; its a type-cast followed by a deference.
the typical form of a compare function is
int comp_func(void *a, void *b)
(char**)a casts a into pointer to char*, in this case its actually pointer to the start of the char array.
*(char**)a then dereferences it, meaning the pointer to start of array is passed to the strcmp() function.
printf takes pointer to start of array to print from that pointer onwards until the pointer points to a char '\0' in the array. the gibberish is because it was passed a pointer to pointer, so you get an memory address printed instead.
First of all the compare function should be
int comp_func(const void* a, const void* b)
Then try to analyze the code: you are passing to that function argv that is decalred as char *argv[], that can be seen as char **
So inside the function, you must cast the generic void pointer to the root type char **.
Then you have to dereference to the element of the array of pointers that you want to compare, so: *(char **)

How to find number of rows in dynamic 2D char array in C?

I have an input function like :
int func(char* s[])
{
// return number of rows in the character array s
}
where the char array s is provided randomly as for eg: {"sdadd", "dsdsd", "dsffsf", "ffsffsf"}.
Here output should be 4 for above example.
Passing string arrays requires more information...
This is similar to the input you would find in say a call to int main(int argc, char *argv[]). The exception is that when main() is called, it reads the command line and provides count information, in argc, to determine the number of arguments in argv[]. That is why the char *argv[] argument can be passed.
You have the same requirement. That is when passing an argument such as char *s[], i.e., you must also somehow provide a value telling func() how many strings. C has no way of knowing the number of strings in that variable without being told. This is because an array reference ( char *s[]; ) decays into a pointer to char ( char *s; ) pointing to the first element of that array, i.e., no array size information.
So, the answer to your question is:, with the information given, func() cannot determine the number of strings in s.
An important distinction:
The size CAN be determined for character arrays, such as
char *s[]={"this","is","an","array"}; // the assignment of values in {...}
//make this an array of strings.
But only when s is declared in the same scope of the function attempting to determine the number of elements. If that condition is met, then use:
int size = sizeof(s)/sizeof(s[0]); //only works for char arrays, not char *
//and only when declared and defined in scope of the call
In scope, in this context, simply means that char *s[]... be defined with global visibility, or within the function calculating number of elements. If passed as an argument, char *s[];, as defined above, will be simply seen as char *s, and the number of arguments cannot be determined.
Other options for retrieving count of strings in a string array include:
1) Modify your input array so that something in the last string is unique, like "%", or "\0". This will allow you to test strings with standard C string functions.
2) Include an argument in the function providing number of strings. (eg, similar to main(...) or printf(...))
Like with all array parameters in C there is no way to do that, because arrays decay to a pointer to their first element (for a discussion cf. the C FAQ, http://c-faq.com/aryptr/) when passed as function parameters.
As always in this case you have two possibilities.
Use an end marker. That works always if the element type of the array can hold a special value which does not occur "naturally" for that type. For chars that's '\0', for pointers like in your array that's NULL, the null pointer. For example argv[], the second argument to main(), is terminated by a null pointer. That makes iterating easy:
#include<stdio.h>
int main(int argc, char *argv[])
{
int i;
for(i=0; argv[i] != NULL; i++)
{
printf("%s\n", argv[i]);
}
return 0;
}
Pass a length information with the array. That's, interestingly, the information in argc which the C runtime also passes to main().
Beyond that there is no (or at least no portable) way to know how many elements an array has which is passed as a parameter to a function in C.
int size = sizeof(s)/sizeof(s[0]);
This statement will do. The variable size will be assigned the number of strings present in the *s[].

Pointer to one single char of a two dimensional array

As far as I know, an array like
int example[10]
Is nothing else than a pointer to the first element in this array.
char* argv[]
Is an array of pointers; so that should be pointers which point to other pointers.
I have following problem now:
int main(int argc, char* argv[])
{
double ptrarg2=argv[2][1];
printf("beginletter=%c\nbeginpos=%d\n",&ptrarg2, ptrarg2);
return 0;
}
I am starting the program with ./program test and expecting the output to be:
beginletter=c
beginpos=123213123
While 123213123 should be the adress where the c is actually stored.
I am actually getting:
beginletter=
beginpos=0
what am I doing wrong? Thank you in advance!
It looks like argv[0] is going to be "./program", argv[1] is going to be "test", and argv[2] is going to be undefined or NULL because you don't have three arguments. The value of argc should tell you how many items there are in argv[]. My guess in this case is that the answer will be 2, and therefore only the first two (argv[0] and argv[1]) are valid.
There are several other strange things going on here. ptrarg2 is declared as a double, not as a char; the behavior here would be to convert the character to its floating point numeric equivalent and store that. Perhaps you meant ptrarg2 to be a char?
Next up, the printf() doesn't correspond very well to its additional arguments. &ptrarg2 is a double *, but you're assigning it to a %c (character) field, not a %p (pointer) field. ptrarg2 is a double, but you're assigning it to a %d (decimal number) field, not a %lf (long float, aka double) field. printf will happily try and print out values even when your types don't match, but they will be wrong, and crashing is quite possible.
&ptrarg2 is the address of the local variable, which is not the address that you are expecting. Just use argv[1][0] and argv[1]. argv[1][0] will give you the first character of the first argument, and argv[1] will give you the pointer to the first argument.
#include <stdio.h>
int main(int argc, char* argv[])
{
printf("beginletter=%c\nbeginpos=%p\n",argv[1][0], argv[1]);
return 0;
}

printf behaving weirdly

I have a simple program which is supposed to print a string. But I am not getting the expected output. Can anyone tell me what is wrong with the program ?
Here is my code:
main()
{
char arr[] = "Test_string";
printf("%20s"+1,arr);
return 0;
}
output: 20s
Expected output is:Test_string
"Test_string" getting printed in 20 places as we are giving "%20s" as format specifier.
It is very simple if you carefully look at your printf call.
Here is the prototype of printf : int printf(const char *format, ...);.
printf expects a pointer to format string as the first argument. In your program you are passing a pointer to this string : "20s" and printf promptly prints what you are passing.
Let me explain why the pointer passed is pointing to "20s" and not "%20s".
Quoted strings in C are interpreted as character pointers.
Character arrays which, when passed to a function, decay into a pointer.
printf("%20s",arr); is equivalent to :
const char * ptr = "%20s";
printf(ptr,arr);
similarly printf("%20s"+1,arr); is equivalent to :
const char * ptr = "%20s";
printf(ptr+1,arr);
Because you are passing "%20s"+1, the actual pointer which is passed to printf is pointing to a string "20s".
Remove the +1 next to the format string
printf("%20s",arr);

Resources