Connecting Tech Pros Worldwide Forums | Help | Site Map

Passing char[][] as argument

Newbie
 
Join Date: Oct 2008
Posts: 22
#1: Nov 17 '08
I'm trying to pass this array

Expand|Select|Wrap|Line Numbers
  1. char files[num][maxLen+8];
like this

Expand|Select|Wrap|Line Numbers
  1. if(fillFileArr(&(files[0][0]), &(buf[0]), num)==-1)
  2.     return -1;
to this function

Expand|Select|Wrap|Line Numbers
  1. int fillFileArr(char ** files, char * buf, int num) {
  2.     int word=0, wordPos=0, bufferPos=0;
  3.     while(word<num && buf[bufferPos]!='\0') {
  4.         if(word==0 && wordPos==0 && bufferPos==0)
  5.             printf("! ");
  6.         if(buf[bufferPos]=='\n') {
  7.             if(buf[bufferPos+1]!='\0')
  8.                 printf("\n! ");
  9.  
  10.  
  11.             word++;
  12.             wordPos=0;
  13.         } else {
  14.             printf("files[%d][%d] = %c\n", word, wordPos, buf[bufferPos]);
  15.             files[word][wordPos++] = buf[bufferPos];
  16.             printf("%c",buf[bufferPos]);
  17.         }
  18.         bufferPos++;
  19.     }
  20.     return 0;
  21. }
but it results in a seg fault... I guess there's a pointer mistake somewhere, but can't really find it..

Would someone please point it out?

Thanks in advance

Banfa's Avatar
AdministratorVoR
 
Join Date: Feb 2006
Location: South West UK
Posts: 6,168
#2: Nov 17 '08

re: Passing char[][] as argument


&(files[0][0]) has type char *

but

int fillFileArr(char ** files, char * buf, int num)

is a function expecting char **. Actually I am rather surprised that this doesn't actually produce any compiler warnings.

Also files[word][wordPos++] = buf[bufferPos]; is trying to pretend that files inside the function is still a char [][] but it isn't.

Is maxLen fixed? (i.e. a constant) if so you could try

int fillFileArr(char (*files)[maxLen+8], char * buf, int num)

otherwise you probably need to pass in a char * and the 2 dimensions of the array pointed to.
Needs Regular Fix
 
Join Date: Sep 2007
Location: The Netherlands
Posts: 427
#3: Nov 17 '08

re: Passing char[][] as argument


if(fillFileArr(&(files[0][0]), &(buf[0]), num)==-1) is wrong: is &(files[0][0]) of type char ** ? I suggest you read this.
EDIT: Oops, Banfa was faster.
Moderator
 
Join Date: Mar 2007
Location: North Bend Washington USA
Posts: 5,366
#4: Nov 17 '08

re: Passing char[][] as argument


It probably here:
Expand|Select|Wrap|Line Numbers
  1. if(fillFileArr(&(files[0][0]), &(buf[0]), num)==-1) 
  2.     return -1; 
  3.  
Your function needs a char** and you have provided a char*.

And I would like to know what compiler you are using as your code does not compile. My compiler complains about &files[0][0] not being a char**.

Also, your function parameter for this array is not a char**. A char** is not the address of an array. In your case the array is:
Expand|Select|Wrap|Line Numbers
  1. char files[num][maxLen+8]; 
  2.  
so the function argument has to be a pointer to an array of maxLen+8:
Expand|Select|Wrap|Line Numbers
  1. int fillFileArr(char (* files)[maxLen+8], char * buf, int num) { 
  2. etc...
  3.  
Read this: http://bytes.com/forum/thread772412.html.
Newbie
 
Join Date: Oct 2008
Posts: 22
#5: Nov 17 '08

re: Passing char[][] as argument


Quote:

Originally Posted by weaknessforcats

It probably here:

Expand|Select|Wrap|Line Numbers
  1. if(fillFileArr(&(files[0][0]), &(buf[0]), num)==-1) 
  2.     return -1; 
  3.  
Your function needs a char** and you have provided a char*.

Ok

Quote:
And I would like to know what compiler you are using as your code does not compile. My compiler complains about &files[0][0] not being a char**.
gcc/cc in Xcode for OSX Leopard

Quote:
Also, your function parameter for this array is not a char**. A char** is not the address of an array. In your case the array is:
Expand|Select|Wrap|Line Numbers
  1. char files[num][maxLen+8]; 
  2.  
so the function argument has to be a pointer to an array of maxLen+8:
Expand|Select|Wrap|Line Numbers
  1. int fillFileArr(char (* files)[maxLen+8], char * buf, int num) { 
  2. etc...
  3.  
Read this: http://bytes.com/forum/thread772412.html.
I'll check it out and look to it if I have the time - sort of in a hurry on this project, and this particular piece is not that critical...

Thanks for all the help - I'll look into this again when I have the time :)
Newbie
 
Join Date: Oct 2008
Posts: 22
#6: Nov 19 '08

re: Passing char[][] as argument


Ok... I have made another atempt on the previously mentioned function - this time I hope it might work with some tweaking - different from the last code, which seemed impossible to implement :)

What I want to do is:
Take a pointer to a string and and some numbers giving the dimensions of the text (longest words and number of words) which is needed to allocate enogh memory for all the data. Then I will allocate memory, fill the pointers with data and return the char **.

Expand|Select|Wrap|Line Numbers
  1. char ** fillFileArr(char * buf, int num, int maxLen) {
  2.     char ** arr = (char *) malloc(num);
  3.     int y;
  4.  
  5.     for(y=0; y<num; y++) {
  6.         arr[y] = (char *) malloc(maxLen+1);
  7.     }
  8.  
  9.     int word=0, wordPos=0, bufferPos=0;
  10.     while(word<num && buf[bufferPos]!='\0') {
  11.         if(word==0 && wordPos==0 && bufferPos==0)
  12.             printf("! ");
  13.         if(buf[bufferPos]=='\n') {
  14.             arr[word][wordPos] = '\0';
  15.  
  16.             if(buf[bufferPos+1]!='\0')
  17.                 printf("\n! ");
  18.  
  19.             word++;
  20.             wordPos=0;
  21.         } else {
  22.             arr[word][wordPos++] = buf[bufferPos];
  23.             printf("%c", buf[bufferPos]);
  24.         }
  25.         bufferPos++;
  26.     }
  27.  
  28.     return arr;
  29. }
According to this article [http://stackoverflow.com/questions/4...arguments-in-c] (which my code is to a certain degree based upon) it should be possible to later on do a

Expand|Select|Wrap|Line Numbers
  1. arr[y][x];
on this data - right?

Yours sincerely
Needs Regular Fix
 
Join Date: Sep 2007
Location: The Netherlands
Posts: 427
#7: Nov 19 '08

re: Passing char[][] as argument


Check your types: is (char *) malloc(num) of type char** on line 2? Did you try to compile this code?
Newbie
 
Join Date: Oct 2008
Posts: 22
#8: Nov 19 '08

re: Passing char[][] as argument


Quote:

Originally Posted by arnaudk

Check your types: is (char *) malloc(num) of type char** on line 2? Did you try to compile this code?

I tried both casting the malloc to (char **), (char *) and nothing - same result...
Expert
 
Join Date: Mar 2008
Location: Naperville, Illinois U.S.
Posts: 831
#9: Nov 19 '08

re: Passing char[][] as argument


Quote:

Originally Posted by krreks

I tried both casting the malloc to (char **), (char *) and nothing - same result...

And what result was that?

By the way, I suggest you turn on all of the compiler warning options. Line 6 of post #6 should have provoked a compiler warning. You should resolve all compiler warnings before you try to execute your program.
Needs Regular Fix
 
Join Date: Sep 2007
Location: The Netherlands
Posts: 427
#10: Nov 19 '08

re: Passing char[][] as argument


Quote:

Originally Posted by krreks

I tried both casting the malloc to (char **), (char *) and nothing - same result...

But one of those is wrong. You'll probably save yourself some time if you read that article on arrays mentioned above. The correct form should be
char ** arr = (char **) malloc(num*(maxLen+1)); now you have an array big enough to hold num strings of maxLen characters (plus '\0'), and drop the malloc() on line 6.
Newbie
 
Join Date: Oct 2008
Posts: 22
#11: Nov 19 '08

re: Passing char[][] as argument


Quote:

Originally Posted by donbock

And what result was that?

By the way, I suggest you turn on all of the compiler warning options. Line 6 of post #6 should have provoked a compiler warning. You should resolve all compiler warnings before you try to execute your program.

It was late last night but as far as I remember i got seg faults in all three cases. I'm compiling with

Expand|Select|Wrap|Line Numbers
  1. gcc -o server server.c helpers.o protocol.o -I. -DDEBUG -g -Wall
Banfa's Avatar
AdministratorVoR
 
Join Date: Feb 2006
Location: South West UK
Posts: 6,168
#12: Nov 19 '08

re: Passing char[][] as argument


Quote:

Originally Posted by arnaudk

The correct form should be
char ** arr = (char **) malloc(num*(maxLen+1));

Actually in C the correct form avoiding unrequired casts is

char ** arr = malloc(num*(maxLen+1));

and in C++ the correct form is

char ** arr = new char *[num*(maxLen+1)];

assuming you want num*(maxLen+1) pointers although I would have thought that num pointers would be enough.
Needs Regular Fix
 
Join Date: Sep 2007
Location: The Netherlands
Posts: 427
#13: Nov 19 '08

re: Passing char[][] as argument


Quote:

Originally Posted by Banfa

Actually in C the correct form avoiding unrequired casts is
char ** arr = malloc(num*(maxLen+1));

Casting still silently takes place here since malloc always returns void*. Writing (char**) makes it more explicit but is indeed not required; some compilers may warn that implicit casting is taking place if on a 'paranoid' warning level, although probably not when casting from void, come to think of it.
Quote:

Originally Posted by Banfa

assuming you want num*(maxLen+1) pointers although I would have thought that num pointers would be enough.

Right, assuming krreks wants to store num strings, each of length maxLen+1, then he'll need num pointers to char[maxLen+1] arrays;
Expand|Select|Wrap|Line Numbers
  1. char (*array)[num] = malloc(num*(maxLen+1)); // C
  2. char (*array)[num] = new char[num][maxLen+1]; // C++
Banfa's Avatar
AdministratorVoR
 
Join Date: Feb 2006
Location: South West UK
Posts: 6,168
#14: Nov 19 '08

re: Passing char[][] as argument


Quote:

Originally Posted by arnaudk

Casting still silently takes place here since malloc always returns void*. Writing (char**) makes it more explicit but is indeed not required; some compilers may warn that implicit casting is taking place if on a 'paranoid' warning level.

True but I have see too many programmers silence implicit casting between types warnings with a cast when they had an actual error that needed fixing thus hiding the error.

The programmer should not put in casts by default, then if they get warnings they should be asking can I alter my code to remove with warning without a cast and only then if the answer is no should they put in a cast.

Explicit casting basically switches off all the compilers checks that things are being done correctly.
Needs Regular Fix
 
Join Date: Sep 2007
Location: The Netherlands
Posts: 427
#15: Nov 19 '08

re: Passing char[][] as argument


Ah, OK, I see your point.
Newbie
 
Join Date: Oct 2008
Posts: 22
#16: Nov 19 '08

re: Passing char[][] as argument


I ended up solving my problem with the following piece of code.

Expand|Select|Wrap|Line Numbers
  1. char * fillFileArr(char * buf, int num, int maxLen) {
  2.     char * arr = (char *)malloc(num*(maxLen+1));
  3.  
  4.     int word=0, wordPos=0, bufferPos=0;
  5.     while(word<num && buf[bufferPos]!='\0') {
  6.         if(buf[bufferPos]=='\n') {
  7.             arr[(word*(maxLen+1))+wordPos] = '\0';
  8.  
  9.             word++;
  10.             wordPos=0;
  11.         } else {
  12.             arr[(word*(maxLen+1))+wordPos++] = buf[bufferPos];
  13.         }
  14.         bufferPos++;
  15.     }
  16.  
  17.     return arr;
  18. }
  19.  
  20. void printFileArr(char * files, int num, int maxLen, int withIndex, int indexStart) {
  21.     int i, index=indexStart;
  22.     for(i=0; i<num; i++) {
  23.         if(withIndex==1)
  24.             printf("! [%2d] ", index++);
  25.         else
  26.             printf("! ");
  27.         printf("%s\n", files+((maxLen+1)*i));
  28.     }
  29. }
  30.  
  31. char * getFromFileArr(char * arr, int maxLen, int wantedIndex) {
  32.     return (arr+((maxLen+1)*wantedIndex));
  33. }
Moderator
 
Join Date: Mar 2007
Location: North Bend Washington USA
Posts: 5,366
#17: Nov 19 '08

re: Passing char[][] as argument


The correct code for allocating a 2D array is:

Expand|Select|Wrap|Line Numbers
  1. char (* arr)[maxLen+8] = malloc(num*(maxLen+1)); 
  2.  
Your function should have had a char (*)[maxLen+8] argument plus one argument for the number of maxLen+8 arrays.

Read this: http://bytes.com/forum/thread772412.html.
Reply