array of pointer

i want to make array of pointer to char and assign it char
however array size is from user
for example:
user said 3
a[0]="xxxx"
a[1]="sssss"
a[2]="hhhh"
size of array is from user and size of string is also according to user
is this correct way to do this?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  #include <stdlib.h>
#include <stdio.h>
using namespace std;

int main()
{   int k=0;
    scanf("%d",&k);

    char * l[k]={new char[401]}; // how can i initialize every pointer of char?
    char arrays[401];
    char *s=arrays;

    for(int i=0;i<k;i++){
        scanf("%s",s);
        strcpy(l[i],s); // why every time i copy and change s using scanf, the value also change. is there another way?
    }
1
2
3
4
5
6
7
#include <stdio.h>
  
int main()
{
    const char* strings[] = { "one", "two", "three" };
    printf("number of elements = %d\n", (int)sizeof(strings)/sizeof(strings[0]));
}


The strings "one", "two", "three" are constants and cannot be changed. So the array is of type const char*[3] rather than char*[3].
1
2
3
4
5
6
7
8
9
10
11
12
13
    char * l[k] // this is an array of pointers. C++ does not have VLA.
    =
    { new char[401] }; // you make first pointer point to an array,
      // and set the rest to 0 (hopefully nullptr)

    char arrays[401];
    char *s=arrays; // you set pointer s to paint to arrays
    // you don't need s, you could use arrays directly

    for(int i=0;i<k;i++){
        scanf("%s",s); // you read into arrays
        strcpy(l[i],s); // all put first iteration calls strcpy( 0, s );
    }

C++ does not support VLA (but some compilers do as extension).
The "array" l should be dynamic.
For example, char* * l = new char* [k];

What does happen when strcpy copies to invalid address?
To memory that has not been allocated for array of char?
Undefined behaviour.

The new is C++. The scanf and strcpy are in C library. Usable in C++ code, but the C++ Standard Library has more convenient and much safer alternatives.

This is not exactly same as yours:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <string>
#include <vector>
#include <iostream>

int main()
{
  size_t k {};
  if ( std::cin >> k ) {
    std::vector<std::string> foo;
    foo.reserve( k );

    std::string s;
    int i = 0;
    while ( i < k && std::cin >> s ) {
      foo.emplace_back( s );
      ++i;
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main()
{
  int rows = 0;
  int cols = 81;
  char buffer[81];
  printf("Rows: ");
  scanf("%d", &rows);
  char **words = malloc(rows * cols);

  for (int i = 0; i < rows; i++)
  {
    words[i] = malloc(cols);
    sprintf(buffer, "Line %d", i+1);
    strcpy(words[i], buffer);
  }
  
  for (int i = 0; i < rows; i++)
  {
    printf("%s\n", words[i]);
  }

  /* deleting words */
    
  for (int i = 0; i < rows; i++)
  {
    free(words[i]);
  }
  free(words);
}
return 0;
@Thomas: your line 12 is too verbose and line 9 has a magic number. (Lines 33-34 have typo.)


Lines 16-18 contain a design decision that every "row" has cols characters.
If one just needs to store the input, then one can:
1. read to buffer
2. malloc just enough for the row
3. copy from buffer into row
words holds an array of char*, so the allocation on line 12 should be:
 
char** words = malloc(rows * sizeof(char*));


The allocation of each word is incorrect. You need to allocate space for the string and the trailing null, then copy the string into that buffer. So the code should be:
1
2
3
4
5
for (int i = 0; i < rows; ++i) {
    int len = snprintf(buffer, sizeof(buffer), "Line %d", i + 1);
    words[i] = malloc(len + 1);
    strncpy(words[i], buffer, len + 1);
}


There's a single standard library function that performs the last two steps:
1
2
3
4
for (int i = 0; i < rows; ++i) {
    snprintf(buffer, sizeof(buffer), "Line %d", i + 1);
    words[i] = strdup(buffer);
}
Last edited on
@keskiverto, @kbw

thanks for pointing this out. I think I shouldn't write any code before the 2. cup of coffee. :(
> size of array is from user and size of string is also according to user

This is a somewhat hard problem for a programmer just starting out with C. The difficult part is that a line of text entered by the user may be of an arbitrary length; we need to read character by character, resizing the buffer as required, till all characters in the line are placed into the buffer.

Something along these lines, perhaps:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <stdio.h>
#include <stdlib.h>

// resize buffer to new_sz bytes. return resized buffer (pointer)
// quit program if out of memory
void* resize( void* buffer, size_t new_sz )
{
    buffer = realloc( buffer, new_sz ) ;
    if( buffer == NULL )
    {
        puts( "out of memory" ) ;
        exit(1) ;
    }
    return buffer ;
}

// get a line of text of arbitrary length from stdin
char* getline()
{
    size_t capacity = 80 ;
    size_t size = 0 ;
    char* line = resize( NULL, capacity ) ;

    for( int c = getchar() ; c != '\n' && c != EOF ; c = getchar() )
    {
        line[size++] = c ;
        if( size == capacity ) line = resize( line, capacity*=2 ) ;
    }

    if( size == capacity ) line = resize( line, capacity+1 ) ;
    line[size] = 0 ; // null terminate

    return line ;
}

// get n a lines of text (of arbitrary length) from stdin
char** get_n_lines( size_t n )
{
    char** lines = resize( NULL, n * sizeof(char*) ) ;
    for( size_t i = 0 ; i < n ; ++i ) lines[i] = getline() ;
    return lines ;
}

void deallocate( char** lines, size_t n )
{
    for( size_t i = 0 ; i < n ; ++i ) free( lines[i] ) ;
    free(lines) ;
}

int main()
{
    printf( "how many lines? " ) ;
    unsigned int n ;
    scanf( "%u\n", &n ) ;

    char** lines = get_n_lines(n) ;

    puts( "\nlines are:\n----------\n" ) ;
    for( unsigned int i = 0 ; i < n ; ++i ) printf( "%2u.  %s\n", i+1, lines[i] ) ;

    deallocate( lines, n ) ;
}


This would be a C++ program with equivalent functionality:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <string>
#include <vector>

int main()
{
    std::cout << "how many lines? " ;
    std::size_t n ;
    std::cin >> n >> std::ws ;

    std::vector<std::string> lines(n) ;
    for( std::string& ln : lines ) std::getline( std::cin, ln ) ;

    puts( "\nlines are:\n----------\n" ) ;
    for( std::size_t i = 0 ; i < lines.size() ; ++i ) std::cout << i+1 << ". " << lines[i] << '\n' ;
}
Topic archived. No new replies allowed.