Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help with inputting multidimensional string arrays....
#11
Okay. Everything works, but now it wont let me make an array
age[number]; because it needs a constant expression can't allocate an array of size 0 and unknown size. I want to have an array to store numbers in much like DIM age(0 to number). (MSVC++)
am: "Where should I put this thing so that it doesn't hurt anyone we know or care about?"
Max:"Out the window, Sam. There's nobody but strangers out there."
Reply
#12
If you want to use a variable to define a new array, that array is de facto a dynamic array. Use malloc for such purposes.

Code:
age = (int *) malloc (number * sizeof(int));

That way you are allocating space for # number integers (not that number * sizeof(int) returns how many bytes take number elements that measure the size of an int, 'cause we are making an integer array).
SCUMM (the band) on Myspace!
ComputerEmuzone Games Studio
underBASIC, homegrown musicians
[img]http://www.ojodepez-fanzine.net/almacen/yoghourtslover.png[/i
Reply
#13
mmm I don't understand C syntax.. is that something like this in C++?

Code:
int *age = new int[number]
In a world without walls and doors, who needs Windows and Gates?
Reply
#14
everything works, but I get an error: Debug error! Damage after normal block (#44) at 0x00430060
this happens when I try to free names and age:

Code:
char **names;
   int *age;
   age = (int *) malloc(number * sizeof(int));
   names = (char **) malloc(number);
  
   free(age);
   /*for (i = 0; i < number; i++) {
         free(names[i]);
   }
   */
   free(names);
   return 0;

how do you free them?
am: "Where should I put this thing so that it doesn't hurt anyone we know or care about?"
Max:"Out the window, Sam. There's nobody but strangers out there."
Reply
#15
I found a really great c tutorial at http://computer.howstuffworks.com/c.htm I think I have it right and it ran with no errors (sorry, I wrote a lot of things down here, but now I am just trying to fully understand what is happening).

to deallocate *age from the heap, you are putting the pointer *age back to it's unitialised state and freeing the block of memory used by it back to the heap. So when you free() a pointer like *age you leave off the '*' but when you free a pointer to a pointer (which I still don't understand why you would use a pointer to a pointer) you would leave off one of the '*'s like so: free(*names);
that worked for the compiler, but if there are two pointers (**names) what happens to the other pointer that I think I didn't deallocate?

also, someone tell me if I'm right and please elaborate:
Code:
age = (int *) malloc(number * sizeof(int));
names = (char **) malloc(number);

in the code above age is a pointer that points to an address somewhere in the heap (found by using malloc) that is 4 bytes long (because you are finding the sizeof(int) which is 4 bytes.
but what is the (int *) part, and what exactly is happening when you allocate age (like a translation from C to English).

names is a pointer to a pointer of some characters. I loosely understand that any string is an array which makes it automatically a pointer, so a pointer to a string would be a pointer to a pointer? You then allocate number. But again I don't understand the parameters. What is malloc(number) doing? Is it allocating number ammounts of pointers to a char? Also what is (char**)?
am: "Where should I put this thing so that it doesn't hurt anyone we know or care about?"
Max:"Out the window, Sam. There's nobody but strangers out there."
Reply
#16
Sorry, I pointed (groan) you wrong on some of the code, shame on you Na_th_an for not picking me up on it ;-). Firstly, you need to specify sizes when mallocing memory, so you should have:
Code:
char **names;

/*
* Allocate the first level pointers
* We need #number of pointers, which are pointing to strings
* Strings are represented in C as pointers to char so we
* malloc number times the size of a pointer to char.
*/
names = malloc(number * sizeof(char *));

/*
* Allocate each of our hundred character strings.
* Each character in the string is one char long so:
*/
for(i = 0; i < number; i++) {
  names[i] = malloc(100 * sizeof(char));
}

And when you free things, you need to free everything you malloced in the reversed order that it was malloced, so for the above you would need:
Code:
for(i = 0; i < number; i++) {
  free(names[i]);
}
free(names);

Hope that makes sense.

Quote:to deallocate *age from the heap, you are putting the pointer *age back to it's unitialised state and freeing the block of memory used by it back to the heap. So when you free() a pointer like *age you leave off the '*' but when you free a pointer to a pointer (which I still don't understand why you would use a pointer to a pointer) you would leave off one of the '*'s like so: free(*names);

Looking at the declaration of free we see:
Code:
void free(void *ptr);
So free takes a ptr of any kind (void pointers are a special kind which can be used for pointers of any type). So if you have a poi
nter variable like int *age; then you call free(age) because age is a pointer.

A pointer can act as an array because the pointer just points to its first element. e.g
Code:
/* Declare an array with a pointer */
int *array;
/* Malloc it to work like int array[10]; */
array = malloc(10 * sizeof(int));

/* Place values in each pos */
for(i = 0; i < 10; i++) {
  /* We are accessing the pointer here */
  array[i] = i;
}

/* Free the array */
free(array);
A pointer to pointer works like a two dimensional array, kinda like an array of arrays. Do a google search on pointers, arrays, pointer arithmetic and malloc to learn more, sorry I dont know of any good sites off hand, Ive got a really good text book which is unbeatable for learning.

Piptol, I dont know C++ well enough to answer fully, however is that code actually valid? You should be able to use new to instantiate objects, but int is a value type so it should be created like a normal array or pointer variable, of course C++ may have some hacks under the hood to make this transparent to the programmer. Malloc and free are still available (AFAIK) in C++, but its object instantiation is prefered. Object creation is slightly different to mallocing, because malloc just allocates flat space in memory, whereas object instantiation creates an object reference in some internal look up tables, which has much more overhead.
esus saves.... Passes to Moses, shoots, he scores!
Reply
#17
I kept getring conversion errors, but this seems right:

Code:
names = (char **) malloc(number * sizeof(char *));
for(i = 0; i < number; i++) {
      names[i] = (char *) malloc(100 * sizeof(char));
{

in the example you gave me:
Code:
[quote]/* Declare an array with a pointer */
int *array;
/* Malloc it to work like int array[10]; */
array = malloc(10 * sizeof(int));

/* Place values in each pos */
for(i = 0; i < 10; i++) {
  /* We are accessing the pointer here */
  array[i] = i;
}

/* Free the array */
free(array); [/quote]

wouldn't you instead want to declare that the pointer array is a pointer to an integer by saying
Code:
array = (int *) malloc(10 * sizeof(int));

and here's my understanding of how a pointer to a pointer can act as a two dimensional array: a pointer points to a block of memory in the heap somewhere with any size (specified by the malloc). So a pointer to a pointer is like a two dimensional pointer array because you have to go through both pointers to get to the base point eg(**p, would mean you have to go through address of *p to get to p, so you could essentially say p[first pointer val][second pointer val]. But isn't "p" the address and not the value at the address? like *a; *a=5; do why don't you have to attach the pointer symbol * when you access a pointer array?
am: "Where should I put this thing so that it doesn't hurt anyone we know or care about?"
Max:"Out the window, Sam. There's nobody but strangers out there."
Reply
#18
One thing though: Declares should be before executable code. Yes, it will work whereever you put them, but the code gets damn messy. Don't make me visit you with my new ... with my new... scary... ... oh nevermind, just do it.
Reply
#19
Quote:wouldn't you instead want to declare that the pointer array is a pointer to an integer by saying
Code:
array = (int *) malloc(10 * sizeof(int));

You shouldn't need to if your compiler is Standard ANSI C complaint.
Edit: You can check if your compiler is by running the following small program.
Code:
#include <stdio.h>

int main() {
#ifdef __STDC__
  printf("Compiler is Standard ANSI C complaint\n");
#else
  printf("Compiler is not Standard ANSI C complaint\n");
#endif
}
The C Standard states that pointers to void (which is what malloc returns) do not need to be explicitly cast because the correct cast will be done internally. Notice that you dont need to cast the types of pointer variables when you free them either. However, if casting the value makes it easier for you to understand then there is no harm using an explicit cast.

Quote:But isn't "p" the address and not the value at the address? like *a; *a=5; do why don't you have to attach the pointer symbol * when you access a pointer array?
Yes p is the address. For example with a 2-d array using a pointer to pointer, accessing the value of **p is the same as acessing p[0][0]. The reason you dont need the *'s when using the array notation is because arrays are a special type of pointer, for example:
Code:
#include <stdio.h>
#include <stdlib.h>

int main() {

  int *p, a[10], i;

  /* Make p point to the start of array a */
  p = a;
  
  for(i = 0; i < 10; i++) {
    /* Accessing the real array */
    a[i] = i;
    
    /* Print the value for the array */
    printf("a[%d] = %d\n", i, a[i]);
    
    /* Print the value using the pointer, with array indexing */
    printf("a[%d] = %d\n", i, p[i]);
    
    /* Print the value using the pointer and manual indexing */
    printf("a[%d] = %d\n", i, *p + i);
  }
}
From this you can see that p[i] is equivalent to *p + i, the former is simply a more convienient notation.

Quote:One thing though: Declares should be before executable code.
Correct, In Standard C variable declarations can only be placed at the beginning of a block of code (after an open curly brace) before any actual code statements. I think C++ and some C compilers provide extensions for placing declarations everywhere, but you should stick them at the top.
esus saves.... Passes to Moses, shoots, he scores!
Reply
#20
okay, I think I understand. I am now trying to make each entry a struct with a pointer for the name entry inside the struct. The struct has to be an array, and it seems to run right. BTW, the program to test if my compiler is ansi-c compatable doesn't work, but I am using MSVC++6.0.

Code:
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>

void wait_for_key(void);

typedef struct {
    int   age;
    char *name;
} entry;

int main()
{  
    
    int number, i;
    char tname[100];
    
    printf("How many names do you want to enter: ");
    scanf("%d", &number);
    if (!number) return 0;

    // sets up the structure of entry to that of a one-d array info
    entry *info;
   info = (entry *) malloc(number * sizeof(entry));
        
    // inputs all the data
    for(i=0;i<number;i++) {
        printf("\nName %d: ", i + 1);
       gets(tname, 99);
      info[i]->name = (char *) malloc(sizeof(char[strlen(tname)+1]));
      strcpy(info[i]->name, tname);        
        while(kbhit());
        printf("AGE: ");
        scanf("%d", info[i]->age);
        while(kbhit());
    }
        
    system("cls");
    printf("Here are the %d people you entered:\n\n", number);
    for(i = 0; i < number; i++) {
        printf("%d) %s AGE: %d\n", i + 1, info->name, info[i]->age);
    }
   wait_for_key();         
        
    free(info);
    return 0;
}

void wait_for_key(void)
{
   while(kbhit());
    while(!(kbhit()));
}
am: "Where should I put this thing so that it doesn't hurt anyone we know or care about?"
Max:"Out the window, Sam. There's nobody but strangers out there."
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)