-2

I want to make an (2d) array of names using dynamic allocation of memory, where length of each name is 1<=name<=1000000.

I have tried this but this is wrong could you help me

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
    int n,i;
    char *Names;

    scanf("%d",n);
    *Names=(char **)malloc(sizeof(char **)*n);

    for( i=0;i<n;i++)
        (*Names+i)=(char*)malloc(sizeof(char *)*100000);

    for(int i=0;i<n;i++)
        scanf("%s",Names[i]);
}
return 0;
}

Sample output:

/*
  kirito
  asuna
  pranav
*/
gsamaras
  • 71,951
  • 46
  • 188
  • 305
Pranav Choudhary
  • 2,726
  • 3
  • 18
  • 38
  • 1
    Your braces don't match. – Paul Ogilvie Nov 28 '18 at 12:03
  • `for( i=0;i<2..` should be `for( i=0;i – Paul Ogilvie Nov 28 '18 at 12:04
  • 1
    `char *Names;` is a pointer to a character which might be the first of an array of characters. It is not suitable to hold an array of pointers to strings. – Gerhardh Nov 28 '18 at 12:05
  • As @Gerhardh says, change to `char **Names;` – Paul Ogilvie Nov 28 '18 at 12:06
  • And don't dereference Names when assigning to it. Use Names= not *Names = – Garr Godfrey Nov 28 '18 at 12:07
  • `char (*Names)[100000] = malloc(n * sizeof *Names);` should do the whole job. – mch Nov 28 '18 at 12:08
  • 1
    To get useful help, please be a bit more precise about "I have tried this but this is wrong". – Gerhardh Nov 28 '18 at 12:08
  • Look up the definition of scanf (eg on https://linux.die.net/man/3/scanf ) - it is wise to consider the return value of such functions, especially when learning about them. You will also see that the first call to scanf in your program should use &n rather than n . Rather than allocating a fixed number of fixed-size string locations, it might be preferable to read each string first into a single local string array, find its length, then use malloc() to assign a Names item that is just big enough (eg Names[i] = malloc(strlen(input_name) + 1) - but also check for NULL return !). – MikeW Nov 28 '18 at 12:11
  • 1
    Possible duplicate of [Correctly allocating multi-dimensional arrays](https://stackoverflow.com/questions/42094465/correctly-allocating-multi-dimensional-arrays) – Andrew Henle Nov 28 '18 at 12:35
  • 1
    Note that what you are allocating is **not** a "two-dimensional array". It's an array of pointers to a bunch of separately-allocated one-dimensional arrays. It's about the most inefficient way to dynamically allocate such data structures as possible. It's almost trivial to replace the multiple `malloc()` calls in the `for` loop with a single call to `malloc()` and then fill in the pointers in the array of pointers used to access the actual data elements. – Andrew Henle Nov 28 '18 at 12:36
  • The correct way to allocate a 2D array is: `char (*Names)[100000] = malloc(n * sizeof *Names);` – Support Ukraine Nov 28 '18 at 12:39
  • 1
    The real question here is what you need. If you need a 2d array, this method is wrong. If you need string table with strings of variable length, it can be the correct method. – Lundin Nov 28 '18 at 12:39

3 Answers3

2

This should correct most of the errors you had, most of which were pointed out in the comments.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
    int n,i;
    /* Declare as char** */
    char **Names;

    /* Use &n to read into the address of n, otherwise you crash here */
    scanf("%d",&n);
    /* don't deference during the assignment, and you are allocating n char*, so use sizeof(char*)  */
    Names=(char **)malloc(sizeof(char *)*n);

    /* Use sizeof(char) not sizeof(char *), since here we want to store 100000 chars not 100000 pointers to char */
    for( i=0;i<n;i++)
        Names[i]=(char*)malloc(sizeof(char)*100000);

    for( i=0;i<n;i++)
        scanf("%s",Names[i]);

    /* remove extra } that was here */
    return 0;
}
Garr Godfrey
  • 8,257
  • 2
  • 25
  • 23
  • 1
    Hey Garr, thank for helping, but casting `malloc()`, really doesn't help. Check the link in the post note of my answer, if you are not sure why! :) – gsamaras Nov 28 '18 at 12:15
  • 1
    And in any case, it's good practice to check the return value from malloc() in case it's NULL. – MikeW Nov 28 '18 at 12:20
  • I know many people have that opinion, but it doesn't really hurt either and it was in OP code so I left it. – Garr Godfrey Nov 28 '18 at 12:20
  • BTW, `sizeof(char) == 1`, by definition. – Bob__ Nov 28 '18 at 12:23
  • Casting the return from malloc where ISO C pointer is not in use, avoids a compiler warning and helps static checkers like Lint and so on. – MikeW Nov 28 '18 at 12:24
  • @Bob__ yeah, but then when you decide to port it to use wide characters you make it especially hard to do. I usually keep sizeof(char) in place, it gets optimized out. – Garr Godfrey Nov 28 '18 at 12:27
  • @GarrGodfrey [casting malloc can hide an error in some cases](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). – gsamaras Nov 28 '18 at 12:27
  • Fair enough, although I'd use `sizeof **Names` to be safe. – Bob__ Nov 28 '18 at 14:41
1

You want to dynamically allocate a 2D array, but you use a single pointer. With your approach, you need to use a double pointer.

This method allocates dynamically a matrix of characters, with dimensions N x M:

char **get(int N, int M)
{
    /* TODO: Check if allocation succeeded. (check for NULL pointer) */
    char **table;
    table = malloc(N*sizeof(char *));
    for(int i = 0 ; i < N ; i++)
        table[i] = malloc( M*sizeof(char) );
    return table;
}

You would call it like this:

scanf("%d", &n);
char **names = get(n, 100000);

Notice how I used &n instead of n, since scanf() expects a pointer as its parameter.

Note: Do not forget to free the memory when are done with it. I had an example in 2D dynamic array, if you are not sure how to.


PS: Do I cast the result of malloc? No!

gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • But was this a homework question ? – MikeW Nov 28 '18 at 12:13
  • 1
    @MikeW I don't know. The professor should be able to see if the student copied, in case it's HW. Moreover, if it's HW, then the OP should be inspired by the answer, rather than copy paste it. – gsamaras Nov 28 '18 at 12:16
0

Strictly speaking, you are not creating an array, but just a pointer to some allocated memory that you can access with the array syntax. However, it is not an array. The difference within what you attempt to do might seem superficial, but it is not.

a) a true array cannot be reseated. b) were it an array, you would not have to free() the memory later. (Applies to both fixed size arrays and VLAs.) c) You cannot get the size of the whole array by sizeof when using dynamic allocation.

GermanNerd
  • 643
  • 5
  • 12