C Board  

Go Back   C Board > General Programming Boards > C Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 02-25-2009, 05:04 PM   #1
Registered User
 
Join Date: Nov 2008
Posts: 36
How Do I Send a Two-Dimensional Char Array to a Function?

My compiler's griping at me when I try to compile the following code:

Code:
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <combination.h>
#include <limits.h>		/* for CHAR_BIT */

#define MAX 44
#define BITMASK(b) (1 << ((b) % CHAR_BIT))
#define BITSLOT(b) ((b) / CHAR_BIT)
#define BITSET(a, b) ((a)[BITSLOT(b)] |= BITMASK(b))
#define BITCLEAR(a, b) ((a)[BITSLOT(b)] &= ~BITMASK(b))
#define BITTEST(a, b) ((a)[BITSLOT(b)] & BITMASK(b))
#define BITNSLOTS(nb) ((nb + CHAR_BIT - 1) / CHAR_BIT)

void increment(char* bitarray, int n);
int test_all_zero(char* bitarray, int n);
void one_diag(char** bitarray, int i, int j);
void make_matrix(char** bitarray, char* U_array, int n);
void invert(char* bitarray, int n);
void display(char** bitarray, int n);

main(){
       char bitarray[MAX][BITNSLOTS(MAX)];
       int i,j;
       for (i=0; i<MAX; i++){
           memset(bitarray[i], 0, BITNSLOTS(MAX));
           }
       
       char U_array[BITNSLOTS(MAX*(MAX-1)/2)];
       memset(U_array, 0, BITNSLOTS(MAX*(MAX-1)/2));

       /* TEST CODE START */
       char test_array[BITNSLOTS(45)];
       memset(test_array, 0, BITNSLOTS(45));
       
       char test_matrix[10][BITNSLOTS(10)];
       for (i=0; i<10; i++){
           memset(test_matrix[i], 0, BITNSLOTS(10));
           }
       
       printf("Starting:\n");
       make_matrix(test_matrix, test_array, 10);
       display(test_matrix, 10);
          
       printf("Inverting:\n");
       
       while (test_all_zero(test_array, 45)){
             invert(test_array, 45);
             }
       
       make_matrix(test_matrix, test_array, 10);
       display(test_matrix, 10);
       
       /* TEST CODE END */

       getch();
}

void increment(char* bitarray, int n){
     int i = 0;
     while (i < n){
           if (!BITTEST(bitarray, i)){
              BITSET(bitarray, i);
              i = n;
              }
           else{
                BITCLEAR(bitarray, i);
                i++;
                }
           }
}
                
int test_all_zero(char* bitarray, int n){
    int i;
    int counter = 0;
    for (i=0; i<n; i++){
        if (!BITTEST(bitarray, i)){
           counter++;
           }
        }
    if (counter == n){
       return 1;
       }
    else{
         return 0;
         }
}

void one_diag(char** bitarray, int i, int j){
     if (i == j){
        BITSET(bitarray[i], j);
        }
}

void invert(char* bitarray, int n){
     int i;
     for (i=0; i<n; i++){
         if (BITTEST(bitarray, i)){
            BITCLEAR(bitarray, i);
            }
         else{
              BITSET(bitarray, i);
              }
         }
}

void make_matrix(char** bitarray, char* U_array, int n){
     int i,j,k;
     for (i=0,j=i+1,k=0; k<n; j++,k++){
         if (j > n){
            i++;
            j = i+1;
            }
         if (BITTEST(U_array, k)){
            BITSET(bitarray[i], j);
            BITSET(bitarray[j], i);
            }
         else{
              BITCLEAR(bitarray[i], j);
              BITCLEAR(bitarray[j], i);
              }
         }
}

void display(char** bitarray, int n){
     int i, j;
     for (i=0; i<n; i++){
         for (j=0; j<n; j++){
             if (BITTEST(bitarray[i], j)){
                printf("1");
                }
             else{
                  printf("0");
                  }
             }
         printf("\n");
         }
     printf("\n");
}
It's giving me:

[Warning] passing arg 1 of 'make_matrix' from incompatible pointer type
[Warning] passing arg 1 of 'display' from incompatible pointer type
...

And so on. I've looked all over for good examples of how to pass a two-dimensional character array to a function, and none of the methods have worked. Can anyone help me please?
DonFord81 is offline   Reply With Quote
Old 02-25-2009, 05:15 PM   #2
Frequently Quite Prolix
 
dwks's Avatar
 
Join Date: Apr 2005
Location: Canada
Posts: 7,629
If you want to pass a multi-dimensional array to a function, the simplest way is to specify all of the array sizes except the leftmost; e.g.,
Code:
int one[10];
int two[10][20];
int three[10][20][30];

void func_one(char one[]) {}
void func_two(char two[][20]) {}
void func_three(char three[][20][30]) {}

func_one(one);
func_two(two);
func_three(three);
Note that the syntax "char three[][20][30]" is equivalent to "char (*three)[20][30]". I prefer the latter, although I imagine you'd likely find the former easier to read. Note that "char *three[20][30]" is different; that indicates a two dimensional array whose elements are of type char*.
__________________
dwk

Seek and ye shall find. quaere et invenies.

"Simplicity does not precede complexity, but follows it." -- Alan Perlis
"Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
"The only real mistake is the one from which we learn nothing." -- John Powell


Other boards: DaniWeb, TPS
Unofficial Wiki FAQ: cpwiki.sf.net

My website: http://dwks.theprogrammingsite.com/
Projects: codeform, xuni, atlantis, etc.

New project: nort
dwks is offline   Reply With Quote
Old 02-25-2009, 05:16 PM   #3
Registered User
 
Join Date: Oct 2008
Location: TX
Posts: 1,262
In main() test_matrix is the first argument to both make_matrix() and display(). It's a pointer to BITNSLOTS(10) chars taken as a unit but the function defn declares it to be a char** pointer and that's why the compiler warnings.
itCbitC is offline   Reply With Quote
Old 02-25-2009, 05:26 PM   #4
Registered User
 
Join Date: Nov 2008
Posts: 36
Quote:
Originally Posted by itCbitC View Post
In main() test_matrix is the first argument to both make_matrix() and display(). It's a pointer to BITNSLOTS(10) chars taken as a unit but the function defn declares it to be a char** pointer and that's why the compiler warnings.
All right... how do I rectify this?
DonFord81 is offline   Reply With Quote
Old 02-25-2009, 05:28 PM   #5
Frequently Quite Prolix
 
dwks's Avatar
 
Join Date: Apr 2005
Location: Canada
Posts: 7,629
[edit] Here I am rambling on in general, without paying attention to your problem.

You could try passing "char [][BITNSLOTS(MAX)]" parameters to your functions instead of "char **" parameters.
[/edit]

You can't just use a char** because the compiler doesn't know how many elements are between array[0][0] and array[1][0]. It needs this information to figure out what you mean when you address the elements in the array. Hence my examples above where you tell the compiler how many elements there are in dimensions besides the leftmost one. (The compiler doesn't need to know how many elements are in the leftmost array dimension, because it doesn't do array bounds checking . . . .)

Anyway. If you want to pass a 2D array of any dimensions to a function, I suppose you could flatten the array like this.
Code:
#include <stdio.h>

void func(int *array, int x_size, int y_size);

int main() {
    int data[][3] = {
        {1, 2, 3},
        {4, 5, 6}
    };
    
    /* Now data[0][0] = 1
               [0][1] = 2
               [0][2] = 3
               [1][0] = 4
               ...
    */
    
    /* x_size: number of elements in data[x][*] */
    /* y_size: number of elements in data[*][y] */
    size_t x_size = sizeof(data) / sizeof(data[0]);  /* this will be 2 */
    size_t y_size = sizeof(data[0]) / sizeof(data[0][0]);  /* this will be 3 */
    
    func((int *)data, x_size, y_size);
    
    return 0;
}

void func(int *array, int x_size, int y_size) {
    int x, y;
    
    for(y = 0; y < y_size; y ++) {
        for(x = 0; x < x_size; x ++) {
            printf("%d", *(array + (x * y_size) + y));
            if(x + 1 < x_size) putchar(' ');
        }
        putchar('\n');
    }
}
That's a pretty bad way to do it, though. (And my names are horrible, but never mind that . . . .) And I'm sure you could get away with a int** pointer instead of a int* pointer with some more casting, which might be marginally more intuitive. Plus there may be other ways I'm not aware of.

Personally, if I'm passing a two-dimensional array to a function, I wrap it in a structure. This has several advantages: you're already passing the size of the array to the function, because presumably it is in the structure, and you don't have to do any casting . . . if you create a new level of structure indirection for each dimension of the array, that is. For example:
Code:
struct list_t {
    struct name_t *name;
    size_t names;
};

struct name_t {
    char *name;
    size_t length;
};
__________________
dwk

Seek and ye shall find. quaere et invenies.

"Simplicity does not precede complexity, but follows it." -- Alan Perlis
"Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
"The only real mistake is the one from which we learn nothing." -- John Powell


Other boards: DaniWeb, TPS
Unofficial Wiki FAQ: cpwiki.sf.net

My website: http://dwks.theprogrammingsite.com/
Projects: codeform, xuni, atlantis, etc.

New project: nort
dwks is offline   Reply With Quote
Old 02-25-2009, 05:36 PM   #6
Registered User
 
Join Date: Oct 2008
Location: TX
Posts: 1,262
Quote:
Originally Posted by DonFord81 View Post
All right... how do I rectify this?
There are many ways it can be written depending on what the macro BITNSLOT(10) evaluates to. If BITNSLOT(10) evaluates to 2 then:
Code:
char (*pa) [2]
char pa[][2]
Edit:: that was just an example so the parameterized decl can be written as:
Code:
char (*pa) [BITSNSLOT(10)]
char pa[][BITSNSLOT(10)]

Last edited by itCbitC; 02-25-2009 at 05:43 PM.
itCbitC is offline   Reply With Quote
Old 02-25-2009, 06:14 PM   #7
Registered User
 
Join Date: Nov 2008
Posts: 36
It worked! Thank you all so much!
DonFord81 is offline   Reply With Quote
Old 02-26-2009, 03:01 AM   #8
Mysterious C++ User
 
Join Date: Oct 2007
Posts: 14,099
It's better to merely "flatten" it to a 1D array by taking a T* instead of T** if you don't want to pass it as a 2D array since all arrays are just laid out after each other in memory.
So there you go.
__________________
Using: Microsoft Windows™ 7 Professional (x64), Microsoft Visual Studio™ 2008 Team System
I dedicated my life to helping others. This is only a small sample of what they said:
"Thanks Elysia. You're a programming master! How the hell do you know every thing?"
Quoted... at least once.
Quote:
Originally Posted by cpjust
If C++ is 2 steps forward from C, then I'd say Java is 1 step forward and 2 steps back.
Elysia is offline   Reply With Quote
Reply

Tags
array, char, function, string, two-dimension

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Code review Elysia C++ Programming 71 05-13-2008 09:42 PM
airport Log program using 3D linked List : problem reading from file gemini_shooter C Programming 3 03-04-2005 02:46 PM
pointers InvariantLoop C Programming 13 02-04-2005 09:32 AM
Unknown Memory Leak in Init() Function CodeHacker Windows Programming 3 07-09-2004 09:54 AM
qt help Unregistered Linux Programming 1 04-20-2002 09:51 AM


All times are GMT -6. The time now is 05:04 AM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.0 RC2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22