Results 1 to 14 of 14

Thread: two-dimensional dynamical array of char

  1. #1

    Thread Starter
    Lively Member
    Join Date
    Sep 2002
    Location
    São Paulo, SP, Brasil
    Posts
    118

    two-dimensional dynamical array of char

    Simple like that, is what i want.

    On VB, it would be something like (dunno if it really works):

    VB Code:
    1. Dim i, j As Integer
    2. Dim arr As String
    3.  
    4. i = 5
    5. j = 10
    6. arr = New Array(i, j)

    On C, I'm trying to do similar by the following:

    Code:
    int i, j;
    char **arr;
    
    char = (char**) malloc(sizeof(char) * i * j);
    But it isn't working! I must be doing something wrong, I'm not used to C pointers / array stuff... It's really confusing. :P
    --
    Cauê Cavalheiro Machado Rego

  2. #2
    Monday Morning Lunatic parksie's Avatar
    Join Date
    Mar 2000
    Location
    Mashin' on the motorway
    Posts
    8,169
    Did you set the sizes of i and j first?
    I refuse to tie my hands behind my back and hear somebody say "Bend Over, Boy, Because You Have It Coming To You".
    -- Linus Torvalds

  3. #3

    Thread Starter
    Lively Member
    Join Date
    Sep 2002
    Location
    São Paulo, SP, Brasil
    Posts
    118
    Ya, I forgot to mention on my code above, but I did.

    I did even try this way:

    Code:
    char **arr;
    
    arr = (char**) malloc(sizeof(char) * 40 * 40);
    --
    Cauê Cavalheiro Machado Rego

  4. #4

    Thread Starter
    Lively Member
    Join Date
    Sep 2002
    Location
    São Paulo, SP, Brasil
    Posts
    118
    Oh, yeah, the erro I got isn't on compiling.

    It builds the EXE file, with my BCC5, free command line compiler from Borland.

    But when I try to run the EXE on my Windows 2k, it crashes. I get 2 memmory fail and one fatal error message, in sequence, at the same second I run it.
    --
    Cauê Cavalheiro Machado Rego

  5. #5
    Monday Morning Lunatic parksie's Avatar
    Join Date
    Mar 2000
    Location
    Mashin' on the motorway
    Posts
    8,169
    I think something's seriously broken there. Are you creating the proper executable type?

    Just out of interest, what happens if you try and allocate a 3x3 block?
    I refuse to tie my hands behind my back and hear somebody say "Bend Over, Boy, Because You Have It Coming To You".
    -- Linus Torvalds

  6. #6

    Thread Starter
    Lively Member
    Join Date
    Sep 2002
    Location
    São Paulo, SP, Brasil
    Posts
    118
    Here.

    I just wrote a whole file just to test it alone:

    Code:
    #include <stdio.h>
    #include <alloc.h>
    
    int main() {
    	char **arr;
    	int i, j;
    
    	// Dynamicaly setting the array
    	arr = (char**) malloc(sizeof(char) * 10 * 10);
    
    	// Filling the array
    	for (i = 0; i < 10; i++) {
    		for (j = 0; j < 10; j++) {
    			if (i == 0 || j == 0 || i == 9 || j == 9) {
    				arr[i][j] = '#';
    			} else {
    				arr[i][j] = ' ';
    			}
    		}
    	}
    
    	// Showing the array
    	for (i = 0; i < 10; i++) {
    		for (j = 0; j < 10; j++) {
    			printf("%c", arr[i][j]);
    		}
    	}
    
    	return(0);
    }
    It compiles and doesnt works.
    I called it "arrtest.c".

    I can compile other Cs, if I don't try to use this kind of declaration.
    --
    Cauê Cavalheiro Machado Rego

  7. #7
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    This has never worked and never will...

    The problem is that indexing into an array is resolved at compile-time, but in two-dimensional dynamic arrays one dimension has no precisely defined size:
    int ar[10][10];
    -->
    ar[0] has the size sizeof(int)*10 (because it's type is int[10]), so the compiler knows how much to increment the pointer if you say
    ar[1].

    But when you do
    int **ar = (int**)malloc(sizeof(int)*10*10);
    and you want to use this as a two-dimensional array, ar[0] has the size sizof(int)*??? because the compiler has no way of knowing how large you want this dimension to be. Actually you are allocating an array of 100 int* here, but those pointers have random values. And if int happens not to match the size of void* (as is the case on 64-bit systems), you have no idea how many pointers were allocated in the first place.

    There are some possibilities:
    a) Do:
    Code:
    int ** ar = (int**)malloc(sizeof(int*)*10);
    for(int i=0; i < 10; i++)
      ar[i] = (int*)malloc(sizeof(int)*10);
    which is extremly tedious at removal because you have to call free for every call to malloc.

    b) Have the inner dimension fixed:
    int (*ar)[10] = (int (*)[10])malloc(sizeof(int[10])*10);
    which has a damn confusing syntax.

    c) The VB array approach. A VB array internally is a structure of type SAFEARRAY, which works like this (not exactly can't remember now)
    Code:
    typedef struct tagDIMENSION {
      DWORD dwSize;
    } DIMENSION, *LPDIMENSION;
    
    typedef struct tagSAFEARRAY {
      void *pData;
      DWORD dwDimensions;
      DWORD dwDataSize;
      DIMENSION dims[1];
    } SAFEARRAY, *LPSAFEARRAY;
    Gotta go now, I'll explain the workings of this tomorrow. A SAFEARRAY is ALWAYS part of a VARIANT...
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  8. #8

    Thread Starter
    Lively Member
    Join Date
    Sep 2002
    Location
    São Paulo, SP, Brasil
    Posts
    118
    I just improved the arrtest.c

    Code:
    #include <stdio.h>
    #include <alloc.h>
    
    // Dynamic set, not working
    void test1 (void) {
    	char **arr;
    	int i, j;
    
    	// Dynamicaly setting the array
    	arr = (char**) malloc(sizeof(char) * 10 * 10);
    
    	// Filling the array
    	for (i = 0; i < 10; i++) {
    		for (j = 0; j < 10; j++) {
    			if (i == 0 || j == 0 || i == 9 || j == 9) {
    				arr[i][j] = '#';
    			} else {
    				arr[i][j] = ' ';
    			}
    		}
    	}
    
    	// Showing the array
    	for (i = 0; i < 10; i++) {
    		for (j = 0; j < 10; j++) {
    			printf("%c", arr[i][j]);
    		}
    	}
    }
    
    // Non dynamic set, working
    void test2 (void) {
    	char arr[10][10];
    	int i, j;
    
    	// Filling the array
    	for (i = 0; i < 10; i++) {
    		for (j = 0; j < 10; j++) {
    			if (i == 0 || j == 0 || i == 9 || j == 9) {
    				arr[i][j] = '#';
    			} else {
    				arr[i][j] = ' ';
    			}
    		}
    	}
    
    	// Showing the array
    	for (i = 0; i < 10; i++) {
    		for (j = 0; j < 10; j++) {
    			printf("%c", arr[i][j]);
    		}
    	}
    }
    
    int main() {
    	int op;
    
    	printf("Choose the test by the number\n");
    	scanf("%d", &op);
    
    	if (op == 1) {
    		printf("Test 1 selected");
    		test1();
    	}
    
    	if (op == 2) {
    		printf("Test 2 selected");
    		test2();
    	}
    
    	return(0);
    }
    --
    Cauê Cavalheiro Machado Rego

  9. #9

    Thread Starter
    Lively Member
    Join Date
    Sep 2002
    Location
    São Paulo, SP, Brasil
    Posts
    118
    This is wonderfull Bee.

    I'll try first option, I liked it.

    I didn't even see the third yet, but I will read and re-read everysingle word as soon as I make the first option work here.
    --
    Cauê Cavalheiro Machado Rego

  10. #10

    Thread Starter
    Lively Member
    Join Date
    Sep 2002
    Location
    São Paulo, SP, Brasil
    Posts
    118
    One more, before I erase the file arrtest.c


    Code:
    // Dynamic set, WORKING! Thanks CornedBee
    void test3 (void) {
    	char **arr;
    	int i, j;
    
    	// Dynamicaly setting the array
    	arr = (char**) malloc(sizeof(char*) * 10);
    	if (arr == NULL) {
    		free(arr);
    		return;
    	}
    
    	for (i = 0; i < 10; i++) {
    		arr[i] = (char*) malloc(sizeof(char) * 10);
    		if (arr == NULL) {
    			for (j = 0; j < 10; j++)
    				free(arr[j]);
    			return;
    		}
    	}
    
    	// Filling the array
    	for (i = 0; i < 10; i++) {
    		for (j = 0; j < 10; j++) {
    			if (i == 0 || j == 0 || i == 9 || j == 9) {
    				arr[i][j] = '#';
    			} else {
    				arr[i][j] = ' ';
    			}
    		}
    	}
    
    	// Showing the array
    	for (i = 0; i < 10; i++) {
    		for (j = 0; j < 10; j++) {
    			printf("%c", arr[i][j]);
    		}
    	}
    }
    
    int main() {
    	int op;
    
    	printf("Choose the test by the number\n");
    	scanf("%d", &op);
    
    	if (op == 1) {
    		printf("Test 1 selected");
    		test1();
    	}
    
    	if (op == 2) {
    		printf("Test 2 selected");
    		test2();
    	}
    
    	if (op == 3) {
    		printf("Test 2 selected");
    		test3();
    	}
    
    	return(0);
    }
    --
    Cauê Cavalheiro Machado Rego

  11. #11
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    3rd option renewed. Forget everything I wrote above about the third option.

    Here is how you implement an array similar to the one that you use in VB, but rewritten by me.
    Using these two data structures, you can make a dynamically sized dynamically dimensionized arbitrary indexed array:
    In plain C, if I got nothing better to do I might write a nice C++ class that does the same thing. Here's the API:
    Code:
    #define SA_PTR 0x80000000
    #define SA_I16 1
    #define SA_I32 2
    #define SA_CHAR 3
    #define SA_SINGLE 4
    #define SA_DOUBLE 5
    #define SA_ARRAY 0x80000006
    #define SA_BOOL 7
    
    typedef struct tagDIMENSION
    {
      long lIndexStart;
      unsigned long ulSize;
    } DIMENSION;
    
    typedef struct tagSTRANGEARRAY
    {
      unsigned long ulDims;
      unsigned long ulSize;
      unsigned long ulType;
      void *pvData;
      DIMENSION dims[1];
    } STRANGEARRAY;
    
    STRANGEARRAY *CreateStrangeArray(unsigned long type,
        unsigned long ulDims, ...);
    
    void *ElemAt(const STRANGEARRAY *ar, ...);
    
    void DestroyStrangeArray(STRANGEARRAY *ar);
    I'll implement the function and get back to you...
    Last edited by CornedBee; Sep 17th, 2002 at 01:47 PM.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  12. #12

    Thread Starter
    Lively Member
    Join Date
    Sep 2002
    Location
    São Paulo, SP, Brasil
    Posts
    118
    Ah, good I didn't read it then.

    Is the thir option, even now, for C++ only?

    I'm using C plain only, for now, cause of class on college.

    After finishing the whole class, I'll head to C++.
    --
    Cauê Cavalheiro Machado Rego

  13. #13
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    No, I'm currently writing the third option in plain C.
    But it's hard to manage in C, C++ would make it easier.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  14. #14
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    Here's the implementation:

    Code:
    // starting from here in a source file
    
    size_t getitemsize(unsigned long type)
    {
    	if(type & SA_PTR)
    	{
    		return sizeof(void*);
    	}
    	else
    	{
    		switch(type)
    		{
    		case SA_CHAR:
    			return sizeof(char);
    		case SA_I16:
    			return sizeof(short);
    		case SA_BOOL:
    		case SA_I32:
    			return sizeof(long);
    		case SA_SINGLE:
    			return sizeof(float);
    		case SA_DOUBLE:
    			return sizeof(double);
    		}
    	}
    	return 0;
    }
    
    // This function allocates memory for a strange array
    STRANGEARRAY *CreateStrangeArray(unsigned long type,
    								 unsigned long ulDims, ...)
    {
    	va_list l;
    	int i;
    	unsigned long size = 1;
    	// may not be zero dimensions
    	if(ulDims <= 0)
    		return NULL;
    	STRANGEARRAY *ptr = (STRANGEARRAY *)malloc(
    		sizeof(STRANGEARRAY) + (ulDims-1)*sizeof(DIMENSION));
    	if(ptr == NULL)
    		return NULL;
    	ptr->ulDims = ulDims;
    	// got the mem, now find out about dimension info
    	va_start(l, ulDims);
    	for(i=0; i<ulDims; ++i) {
    		ptr->dims[i].ulSize = va_arg(l, unsigned long);
    		size *= ptr->dims[i].ulSize;
    		ptr->dims[i].lIndexStart = va_arg(l, long);
    	}
    	ptr->ulSize = size;
    	// now get the type
    	ptr->ulType = type;
    	size *= getitemsize(type);
    	ptr->pvData = malloc(size);
    	if(ptr->pvData == NULL)
    	{
    		free(ptr);
    		return NULL;
    	}
    	// array is now ready
    	return ptr;
    }
    
    void *ElemAt(const STRANGEARRAY *ar, ...)
    {
    	// find the element following the info in the structure
    	int i, j;
    	unsigned long off = 0;
    	va_list l;
    	va_start(l, ar);
    
    	for(i = 0; i < ar->ulDims; ++i)
    	{
    		unsigned long dimsize = 1;
    		long index = va_arg(l, long);
    		index -= ar->dims[i].lIndexStart;
    		if(index >= ar->dims[i].ulSize || index < 0)
    			return NULL;	// out of bounds
    		for(j = i-1; j >= 0; --j)
    		{
    			dimsize *= ar->dims[j].ulSize;
    		}
    		off += (index*dimsize);
    	}
    	off *= getitemsize(ar->ulType);
    	
    	return (void*)(((char*)ar->pvData) + (offset-1));
    }
    
    void DestroyStrangeArray(STRANGEARRAY *ar)
    {
    	free(ar->pvData);
    	free(ar);
    }
    It's quite complicated. I will not explain it until you ask me to do so.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width