tags:

views:

304

answers:

8

Hi, I have a doubt in my program

#include<stdio.h>

int myFunc(char **);
main()
{
    char *a[2]={"Do","While"};
    myFunc(a);
}

int myFunc(char **P)
{
    /* Here I want to print the strings passed but I'm unable to
       print the strings I just tried the below statement which
       printed just the first letter which is 'D'*/
       printf("%c",**P);
}

when i tried

printf("%s",**P);

I am getting run time error. so can anyone please help me out?

Thanks Madhu

+5  A: 
for( int i = 0; i < 2; i++ ) {
    char* string = P[i];
    printf( "%s", string );
}

And you shoud use some way of passing size of array into the function - either pass it as an int parameter,

int myFunc(char **P, int size)
{
    for( int i = 0; i < size; i++ ) {
        //whatever here
    }
}

or always append a zero value to the array and only loop until you find that zero value.

char* array[] = { "String1", "String2", 0 };

Otherwise you will have hard to maintain code.

sharptooth
+1. This is also how argv is terminated. Pretty "quasi standard"
Johannes Schaub - litb
+8  A: 

Too many stars - try

printf("%s",*P);

And you need %s format specifier - %c is just for single character.

If you want to print all strings, you need to pass number of strings in array and then print these strings from the loop.

Check the code suggested by Cătălin Pitiș. To pass the number of strings, you call function like this:

myFunc(a, sizeof(a)/sizeof(a[0]));
qrdl
well if you are calling function like this you don't need to pass the size parameter since it always can be calculated.
Artem Barger
@Artem What? It's C, not Java or anything. There is no way to find array dimension at runtime, only at compile time. Uchite matchast'.
qrdl
printf("%s", *P) will print just the first string
n-alexander
@n-alexander It would be nice if you read the post before commenting and down-voting, starting from "If you want to print all strings ..."
qrdl
+11  A: 

Put size as parameter to allow the function to know how many strings you have in your array. Then, you should iterate the array and print each one.

int myFunc( char** p, int size)
{
  for( int i = 0; i < size; ++i)
  {
     printf("%s", p[i]);
  }
}

Later edit (as requested :-) )

int main( int, char**)
{
   char *a[2]={"Do","While"};
   myFunc( a, 2); // Could be myFunc( a, sizeof(a)/sizeof(char*));
   // ...
   return 0; 
}
Cătălin Pitiș
+1, and one thing I would mention also is that by simply using printf("%s", *p) we would only get "Do" printed, because each string constant in {"Do","While"} gets a null-terminator appended automatically.
Groo
Show the revised call in main() too.
Jonathan Leffler
A: 

Wrong Answer: I think you may have to dereference P when you print it, although I could be wrong.

EDIT: I'm tired, it's 3 am here but I don't feel like sleeping so I'm here trying to answer questions. After reading the criticism, I reread the question and noticed that he does dereference P, but as is stated in another answer, it's dereferenced too much. When one wants to print a char string, one wants to pass a pointer as the char string is really an array.

Another EDIT: I would also like to point out that the person who asked the question made an edit after I answered and that when I first answered it didn't read "printf("%s",**P);" it read "printf("%s", P);" and the last part was bold.

indyK1ng
-1. He *does* dereference P...
DevSolar
@indyK1ng: edited questions are a nuisance - they can make your accurate answer seem inaccurate and wrong. They're also a fact of life on SO. If you find your answer is not relevant and not repairable, delete it (self-protection - there is even a hair-shirt badge available 'Peer Pressure' for some answers). Or revise it, noting the original material you answered (if you click on the edit information, you can see what was changed when), and document what you answered, and what you'd answer with the revised question. Good luck.
Jonathan Leffler
+1  A: 

First, the good news: the type of a is equivalent to char **, so you are passing a valid parameter to myFunc().

The first problem is that %c is a format specifier that means print a single character. Since **P is an expression that evaluates to a single character, your first version does exactly what you told it to do. That isn't what you want.

The second version is close to syntactically correct. It should read printf("%s", *P), where *P is an expression that evaluates to a pointer to a nul-terminated ASCII string. In this case, it evaluates to "Do". This version won't print both strings.

Although it is true that the name of an array is the same as a pointer to its first element, that is a kind of "lie to students". Passing an array to a function does not and cannot convey the length of the array. To do that, you need either a second argument containing the length, or a convention like the nul-terminator on a string to indicate the end of the array. With that change, you can modify myFunc() to use a loop over the elements passed and print each one.

RBerteig
+4  A: 

I like objective-c style nil (0) terminated arrays:

void myFunc(char **P)
{
    while (*P)                   // loop to iterate over all strings until 0
       printf("%s\n",*P++);      // print and move to next element in array
}

int main()
{
    char *a[]={"Do","While",0};  // added 0 to null terminate array,
    myFunc(a);                   // kind of like string
}

Output:

Do
While
stefanB
+1  A: 

The problem in your code is that you want to print a string (char*) but you're giving it a char. Remember that P is an array of char*. When you de-reference it once, you get a char*; when you do it a second time, you just get the char at the beginning of the char*.

When you try to use the char value with the %s specifier, it treats the value as a pointer, and tries to dereference that value. Hence, it will try to print the "string" at the memory location X, where X is the value of the char (i.e. a value from 0 to 255). This gives you an access violation/segmentation fault (the error you see at runtime).

The best workarounds for this, as noted by Cătălin Pitiș and RBerteig, are to either:

  • pass another parameter to specify the length of the array
  • add an additional null at the end of the array.
Jimmy
Hi jimmy,Thanks a lot for the input.Infact my doubt goes over one thing i.e when u hav an array of pointers amd then wen u pass the address of the 1st element of the array to a function which has a parameter which is a double pointer and so in that functuon when u dereference the 1st time,we get it the contents of the array which is the adddress of the string and then when we do the second dereferencing in fact we get the whole string printed right?I m a bit confused in this usage as how are we able to print the string with just *p instead of **p..Please explain??
+1  A: 

if you don't want to keep and pass around array size::

int myFunc(char **);
main()
{
    char *a[2]={"Do","While", NULL};
    myFunc(a);
}

int myFunc(char **P)
{
    if( !P )
        return 0;
    while(*P != NULL)
    {
        printf("%s",*P);
        P++;
    }
}
n-alexander