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?
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];
}
You can use an empty string "":
#include <stdio.h>
int main(void)
{
char arr[][3] = {"ab", "cd", ""};
char (*p)[3] = arr;
while (**p) { /* while not an empty string */
printf("%s\n", *p);
p++;
}
return 0;
}
If arr can contain an empty string, you can use a non printable character, like ETX (end of text):
#include <stdio.h>
int main(void)
{
char arr[][3] = {"ab", "", "\x03"};
char (*p)[3] = arr;
while (**p != '\x03') {
printf("%s\n", *p);
p++;
}
return 0;
}
For a a non modifiable array you can use NULL:
#include <stdio.h>
int main(void)
{
char *arr[] = {"ab", "cd", NULL}; /* Read only */
char **p = arr;
while (*p) { /* while not NULL */
printf("%s\n", *p);
p++;
}
return 0;
}
You need to define a sentinel value.
As sentinel for linear and scattered arrays this can be any valid C-"string", which is known to not be used as play-load value during operation for any of the array's elements.
For scattered arrays also NULL can be used as sentinel.
Example for linear array
Define the sentinel value:
#define END_OF_ARRAY "__EOA__"
or just the empty "string":
#define END_OF_ARRAY ""
Note that the sentinel has to be a C-"string" when used with a linear array!
char array [][8] = {
"1st",
"2nd",
END_OF_ARRAY
}
To detect the array's size you then might use a function like this:
ssize_t get_array_size(const char (*parray)[][8])
{
ssize_t s = -1;
if (NULL == parray)
{
errno = EINVAL;
}
else
{
s = 0;
while (strcmp((*parray)[s], END_OF_ARRAY))
{
++s;
}
}
return s;
}
Example for scattered array
Define the sentinel value:
#define END_OF_ARRAY NULL
or also possible
#define END_OF_ARRAY "__EOA__"
Note that commonly NULL is used.
char * array[] = {
"1st",
"2nd",
END_OF_ARRAY
}
To detect the array's size you then might use a function like this:
ssize_t get_array_size(const char *** parray)
{
ssize_t s = -1;
if (NULL == parray || NULL == *parray)
{
errno = EINVAL;
}
else
{
s = 0;
while ((*parray)[s] != END_OF_ARRAY)
{
++s;
}
}
return s;
}
Usage
For both examples call it like this:
int main(void)
{
ssize_t result = get_array_size(&array);
if (-1 == result)
{
perror("get_array_size() failed");
}
else
{
size_t size = result;
printf("number of elements: %zu\n", size)
}
return 0;
}
Simpler approach for scattered arrays
Define the sentinel value:
#define END_OF_ARRAY NULL
or also possible
#define END_OF_ARRAY "__EOA__"
Note that commonly NULL is used.
char * array[] = {
"1st",
"2nd",
END_OF_ARRAY
}
To detect the array's size you then might use a function like this:
ssize_t get_array_size(const char ** parray)
{
ssize_t s = -1;
if (NULL == parray)
{
errno = EINVAL;
}
else
{
s = 0;
while (parray[s] != END_OF_ARRAY)
{
++s;
}
}
return s;
}
Usage
Note when calling this simpler implementation the array is passed directly and not its address is being passed:
int main(void)
{
ssize_t result = get_array_size(array);
if (-1 == result)
{
perror("get_array_size() failed");
}
else
{
size_t size = result;
printf("number of elements: %zu\n", size)
}
return 0;
}
You can assign like this.
char ar[3][20];
ar[2][0]='\0';
You can place the null at which position you need. Consider you need to place the null in 1th line 10th column you can do like this.
ar[1][10]='\0';
Like this where you need to place the null you can place the null.
ar[1][10] = 0;
char a[3][5]to what do you want to assign theNULL?