-1

Let's say I have an array that looks like:

char arr[MAX_ARR_LENGTH][30] = {"Tom", "and", "Jerry" };

Now, how do I append a new string that the end of the array? Let's say I want to add "Jack" as a new element so the array shoud look like:

char arr[MAX_ARR_LENGTH][30] = {"Tom", "and", "Jerry", "Jack" };

How do you achieve this in C?

I tried using for loops but because it is a 2D array, I wasn't able to figure out the right technique.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
GoodBoyNeon
  • 103
  • 7
  • `if(MAX_ARR_LENGTH > 3) strncpy(arr[3], "Jack", sizeof arr[0]);` – Weather Vane Jan 19 '23 at 11:50
  • 2
    @WeatherVane Rather `sizeof(arr[0])-1` if you insist on using the dangerous `strncpy`function. – Lundin Jan 19 '23 at 11:55
  • @Lundin it still won't add the terminator if that size. It's no more dangerous than `strcpy()`. A fuller example would be to follow with `arr[3][sizeof(arr[0])-1] = 0;` – Weather Vane Jan 19 '23 at 11:58
  • @WeatherVane: as initialized, arr[3] is all bits zero – chqrlie Jan 19 '23 at 12:08
  • @WeatherVane But if that area is zero-initialized you'll get one implicitly. It is much more dangerous than strcpy since strcpy would simply write out of bounds instead, hopefully resulting in a crash discovered during development. – Lundin Jan 19 '23 at 12:09
  • Should not make such assumptions and zero-terminate the final element after using `strncpy` anyway. – Weather Vane Jan 19 '23 at 12:11
  • 2
    @WeatherVane Except 50 years of experience using `strncpy` shows that people don't actually do that. The function is simply a bug factory by design. Or rather, by getting used for other purposes than it was originally designed for. I wrote a lengthy post regarding it here: [Is strcpy dangerous and what should be used instead?](https://software.codidact.com/posts/281518) – Lundin Jan 19 '23 at 12:16

3 Answers3

0

To copy data into your existing array if there is sufficient space (MAX_ARR_LENGTH > 3):

strcpy(arr[3], "Jack");

If you are copying a variable check it's size is < 30 with strlen() first.

You cannot expand an automatic array. Instead you want to allocate it using dynamic memory:

// alternatively use calloc() or malloc()
char **arr = realloc(NULL, 30 * MAX_ARR_LENGTH);
if(!arr) {
  // handle error
}

char **tmp = realloc(arr, 31 * MAX_ARR_LENGTH);
if(!tmp) {
  // handle error
}
arr = tmp;

You can also use use an array syntax for allocation:

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

int main() {
    char (*arr)[30] = malloc(sizeof(char[3][30]));
    strcpy(arr[0], "Tom");
    strcpy(arr[1], "and");
    strcpy(arr[2], "Jerry");
    char (*tmp)[30] = realloc(arr, sizeof(char[4][30]));
    if(!tmp) {
        // handle error
    }
    arr = tmp;
    strcpy(arr[3], "Jack");
}
Allan Wind
  • 23,068
  • 5
  • 28
  • 38
  • In this specific case there seems to be sufficient space already allocated for it, however. Also, 3 star programming is rarely ever the correct solution for any problem. In this case you would simply drop the left-most dimension of the 2D array when rewriting it as a pointer table. – Lundin Jan 19 '23 at 11:53
  • @Lundin How do you know there is space? Fixed typo. – Allan Wind Jan 19 '23 at 11:55
0

In this declaration

char arr[MAX_ARR_LENGTH][30] = {"Tom", "and", "Jerry" };

you declared an array of MAX_ARR_LENGTH elements of the type char[30] and initialized it with three string literals.

I suppose that the value of MAX_ARR_LENGTH is greater than 3.

In this case all other elements of the array that were not explicitly initialized by the string literals are implicitly initialized by zero. It means that all other elements are initialized as empty strings.

So to append a new string to the array you can write for example

#include <string.h>

//...

size_t i = 0;

while ( i < MAX_ARR_LENGTH && arr[i][0] != '\0' ) ++i;

if ( i < MAX_ARR_LENGTH ) strcpy( arr[i], "Jack" );

Here is a demonstration program.

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

#define MAX_ARR_LENGTH 10

int main( void )
{
    char arr[MAX_ARR_LENGTH][30] = { "Tom", "and", "Jerry" };

    for (size_t i = 0; i < MAX_ARR_LENGTH && arr[i][0] != '\0'; i++)
    {
        printf( "%s ", arr[i] );
    }
    putchar( '\n' );

    size_t i = 0;

    while (i < MAX_ARR_LENGTH && arr[i][0] != '\0') ++i;

    if (i < MAX_ARR_LENGTH) strcpy( arr[i], "Jack" );

    for (size_t i = 0; i < MAX_ARR_LENGTH && arr[i][0] != '\0'; i++)
    {
        printf( "%s ", arr[i] );
    }
    putchar( '\n' );
}

The program output is

Tom and Jerry
Tom and Jerry Jack

On the other hand, it will be better to track the number of actually initialized elements from the very beginning.

Here is another demonstration program.

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

#define MAX_ARR_LENGTH 10

int main( void )
{
    char arr[MAX_ARR_LENGTH][30] = { "Tom", "and", "Jerry" };

    size_t n = 0;

    while (n < MAX_ARR_LENGTH && arr[n][0] != '\0') ++n;

    for (size_t i = 0; i < n; i++)
    {
        printf( "%s ", arr[i] );
    }
    putchar( '\n' );

    if (n < MAX_ARR_LENGTH) strcpy( arr[n], "Jack" );
    ++n;

    for (size_t i = 0; i < n; i++)
    {
        printf( "%s ", arr[i] );
    }
    putchar( '\n' );
}

The program output is the same as shown above

Tom and Jerry
Tom and Jerry Jack
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

The other answers are good and correct, but to be as simple as possible:

#define MAX_ARR_LENGTH 10
#define MAX_STR_LENGTH 30

char * arr[MAX_ARR_LENGTH][MAX_STR_LENGTH];
size_t arr_size = 0;  // number of elements in use

To add an element:

if (arr_size < MAX_ARR_LENGTH)
  strcpy(arr[arr_size++], "Jill");
Dúthomhas
  • 8,200
  • 2
  • 17
  • 39