Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define end to an array of strings

A way of ending a char array before it becomes full is to put '\0' at end, like-

single_str[5] ='\0';

Then how to end a 2D char array in that way?

like image 851
user4647543 Avatar asked Jan 09 '23 17:01

user4647543


1 Answers

In practice, you should in C avoid thinking of 2D arrays. Stricto sensu, the C language don't know about 2D arrays, only about arrays of arrays (fixed length, all of the same size) or about arrays of pointers (or array of aggregates or scalars).

You might use an array of string pointers. C strings are conventionally ended by a zero byte. Here is an example of constant array (of constant strings, i.e. const char* pointers) ended by a NULL string

const char*const arrstr[] = {
   "Hello",
   "Nice",
   "World",
   NULL
};

On my machine, sizeof(const char*) is 8, so sizeof(arrstr) is 32; and sizeof("Nice") is 5.

You could print all the array members with

for (const char*const* p = arrstr; *p; p++) printf("%s\n", *p);

You could use in C99 a structure ending with a flexible array member, e.g.

struct my_string_array_st {
   unsigned len;
   char* arr[]; // array of len pointers */
};

then you might have a constructor function which build such string arrays with empty content like

struct my_string_array_st* make_string_array(unsigned ln) {
  struct my_string_array_st*p
     = malloc(sizeof(struct my_string_array_st) + len*sizeof(char*));
  if (!p) { perror("malloc"); exit(EXIT_FAILURE); };
  p->len = ln;
  for (unsigned ix=0; ix<ln; ix+) p->arr[ix] = NULL;
  return p; }

you'll then decide (this is your convention to follow) that each string inside is heap-allocated with strdup - so you don't have two aliased pointers inside. Here is the function to set a string (and release the previous one, if needed)

void 
set_string_array(struct my_string_array_st*p, unsigned ix, const char*str) {
  if (!p || ix>=p->len) return;
  free(p->arr[ix]);
  char* s = NULL;
  if (str) {
     s = strdup(str);
     if (!s) { perror("strdup"); exit(EXIT_FAILURE); };
  };
  p->arr[ix] = s;
}

(recall that you are allowed to free(3) a NULL pointer; it is a no-op) and here is a destructor function, releasing all the internal strings.

void destroy_string_array(struct my_string_array_st*p) {
  if (!p) return;
  unsigned l = p->len;
  for (unsigned ix=0; ix<l; ix++) free(p->arr[ix]);
  free (p);
}

Of course, here is an accessor function:

const char* nth_string_array(struct my_string_array_st*p, unsigned ix)
{
  if (!p || ix>=p->len) return NULL;
  return p->arr[ix];
}
like image 154
Basile Starynkevitch Avatar answered Jan 15 '23 15:01

Basile Starynkevitch