2015-03-14 2 views
4

способ окончание char массива, прежде чем он становится полным, чтобы положить '\0' в конце концов, как-Как определить конец массива строк

single_str[5] ='\0'; 

Тогда как закончить 2D char массив в таким образом ?

+2

2D массив символов == вектор строк == массив полукокса [] указателей. Тогда последний указатель должен быть NULL – tutankhamun

+0

@tutankhamun: Это работает только для «рассеянных» массивов. Для линейного массива типа 'char a [3] [5]' для чего вы хотите назначить 'NULL'? – alk

+0

@tutankhamun наверное .. но как это работает .. как там NULL? это назначено компилятором? – user4647543

ответ

1

Вы можете назначить подобное.

char ar[3][20]; 
    ar[2][0]='\0'; 

Вы можете поместить нуль в нужное вам положение. Считайте, что вам нужно поместить нуль в строку 1th10th, которую вы можете сделать следующим образом.

ar[1][10]='\0'; 

Нравится программа? Поделись с друзьями!

+0

более короткий путь: 'ar [1] [10] = 0;' – dbndhjefj

2

Вы можете использовать пустую строку "":

#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; 
} 

Если arr может содержать пустую строку, вы можете использовать не печатаемый символ, как ETX (конец текста):

#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; 
} 

Для не изменяемого массива вы можете использовать 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; 
} 
2

Вам необходимо определить значение часового.

В сторожевого для линейного и разбросаны массивов это может быть любой действительный C- «строка», которая, как известно, не используется в качестве значения плей-нагрузки во время работы для любого из элементов массива.

Для разбросанных массивов также NULL может использоваться как дозорный.

Пример для линейного массива

Определить значение дозорного:

#define END_OF_ARRAY "__EOA__" 

или просто пустой "строку":

#define END_OF_ARRAY "" 

Обратите внимание, что сторожевого должен быть С - «строка» при использовании с линейным массивом!

char array [][8] = { 
    "1st", 
    "2nd", 
    END_OF_ARRAY 
} 

Чтобы определить размер массива вы затем можете использовать такую ​​функцию:

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; 
} 

Пример для рассеянного массива

Определить значение дозорного:

#define END_OF_ARRAY NULL 

или также возможно

#define END_OF_ARRAY "__EOA__" 

Следует отметить, что обычно используется NULL.

char * array[] = { 
    "1st", 
    "2nd", 
    END_OF_ARRAY 
} 

Чтобы определить размер массива вы затем можете использовать такую ​​функцию:

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; 
} 

Использование

Для обоих примеров называют это так:

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; 
} 

Упрощенный подход к рассеянию лучей

Определить значение дозорного:

#define END_OF_ARRAY NULL 

или также возможно

#define END_OF_ARRAY "__EOA__" 

Обратите внимание, что обычно используется NULL.

char * array[] = { 
    "1st", 
    "2nd", 
    END_OF_ARRAY 
} 

Чтобы определить размер массива вы затем можете использовать такую ​​функцию:

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; 
} 

Использование

Примечание при вызове этой простой реализации массив передается напрямую, а не его адрес :

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; 
} 
+2

Я бы предложил использовать пустую строку как EOA, если не известно, что пустые строки будет разрешено в списке –

4

На практике вы должны в C избегать думать о 2D-массивах. Stricto sensu, язык C не знает о двумерных массивах, только о массивах массивов (фиксированная длина, все одинакового размера) или о массивах указателей (или массиве агрегатов или скаляров).

Вы можете использовать массив указателей строк. C строк условно закончился нулевым байтом. Ниже приведен пример массива постоянной (постоянных строк, т.е. const char* указателей) закончилась с помощью NULL строки

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

На моей машине, sizeof(const char*) равно 8, так sizeof(arrstr) 32; и sizeof("Nice") - 5.

Вы можете напечатать все элементы массива с

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

Вы могли бы использовать в C99 структуру, заканчивающийся с flexible array member, например,

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

, то вы можете иметь функцию конструктора, которые строят такие строки массива с пустым содержимым, как

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; } 

вы будете тогда решить (это ваш конвенции следовать), что каждая строка внутри heap-alloc с strdup - поэтому у вас нет двух внутренних указателей внутри. Вот функция, чтобы задать строку (и отпустить предыдущую, если это необходимо)

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; 
} 

(напомним, что вам разрешено free(3) в NULL указатель, она является не-ор) и вот деструктор функция, освобождая все внутренние строки.

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); 
} 

Конечно, здесь есть функция сбруя:

const char* nth_string_array(struct my_string_array_st*p, unsigned ix) 
{ 
    if (!p || ix>=p->len) return NULL; 
    return p->arr[ix]; 
}