очистка массива символов c

104

Я думал, что установка первого элемента на null очистит все содержимое массива char.

char my_custom_data[40] = "Hello!";
my_custom_data[0] = '\0';

Однако это устанавливает значение null только для первого элемента.

или

my_custom_data[0] = 0; 

memsetя думал, что два приведенных выше примера должны очистить все данные, а не использовать .

ant2009
источник
1
Джаред, почему ты установил тег c ++? он говорил о "C" и не добавил никаких тегов, связанных с C ++.
Йоханнес Шауб - лит,
1
Это одинаково хорошо применимо к массивам символов в C ++, даже если он не указал.
Адам Хоуз,
4
Я удалил тег C ++, чтобы избежать того, что мы уже видели у людей, предлагающих специальные решения для C ++
Alnitak

Ответы:

113

Это зависит от того, как вы хотите просматривать массив. Если вы просматриваете массив как серию символов, то единственный способ очистить данные - прикоснуться к каждой записи. memsetвероятно, самый эффективный способ добиться этого.

С другой стороны, если вы решили рассматривать это как строку C / C ++ с завершающим нулем, установка первого байта в 0 эффективно очистит строку.

ДжаредПар
источник
4
Ключевое слово в ответе - «эффективно». Только первый элемент имеет значение begin, равное 0, а остальные все еще имеют неопределенные значения, но если вы обрабатываете массив как строку с завершающим нулем, а первый элемент имеет значение NULL, то строка считается пустой.
Арнольд Спенс,
действительно, это ответ, ребята.
Йоханнес Шауб - лит,
@caparcode, точно. Вот почему очень важно понимать, как используется массив.
JaredPar,
Да, именно это я должен был сказать в своем первом посте. Символ - это строка с завершением. так что либо они сделают то же самое. char [0] = '\ 0'; или char [0] = 0. Я не уверен, но слышал, что использование '\ 0' лучше для использования строк с завершающим нулем.
ant2009,
@robUK, да ты прав. Технически '\ 0' равно 0 (в ascii), но вы должны использовать '\ 0', потому что это проясняет ваше намерение
Марк Теста
70

Массив в C - это просто место в памяти, поэтому ваше my_custom_data[0] = '\0';назначение просто устанавливает первый элемент в ноль и оставляет остальные элементы нетронутыми.

Если вы хотите очистить все элементы массива, вам придется посетить каждый элемент. Вот для чего memset:

memset(&arr[0], 0, sizeof(arr));

Как правило, это самый быстрый способ решить эту проблему. Если вы можете использовать C ++, рассмотрите вместо этого std :: fill:

char *begin = &arr;
char *end = begin + sizeof(arr);
std::fill(begin, end, 0);
Джон Феминелла
источник
1
Я считаю, что вторая версия должна быть: std :: fill (arr, arr + sizeof (arr) / sizeof (arr [0]), 0);
Дэвид Родригес - дрибес,
Уточнение: не используйте sizeof с fill, потому что позже у вас возникнут проблемы с массивами int, long, double или что у вас есть.
Zan Lynx,
Я предпочитаю: std :: fill (& arr [0], & arr [arr_len], 0);
Zan Lynx,
Зан Линкс, это неопределенное поведение. вы не можете делать & arr [arr_len]. но вам нужно сделать std :: fill (arr, arr + sizeof arr, 0); или если у вас есть длина где-то std :: fill (arr, arr + arr_len, 0); Предполагая массив символов
Йоханнес Шауб - litb
Действует только в Си. хотя вопрос явно был нацелен на C (другой парень добавил тег C ++, я не знаю почему), std :: fill показывает сходство с C ++ :)
Johannes Schaub - litb
25

Почему вы думаете, что установка одного элемента очистит весь массив? В C особенно мало что происходит без явного программирования программистом. Если вы установите для первого элемента ноль (или любое другое значение), то вы сделали именно это, и не более того.

При инициализации вы можете установить массив в ноль:

char mcd[40] = {0}; /* sets the whole array */

В остальном я не знаю никакой другой техники, кроме memset или чего-то подобного.

абеленки
источник
Думаю, это зависит от используемого вами компилятора
cocoafan
1
@cocoafan: Нет, это не зависит от компилятора. Это часть спецификации языка. Любой компилятор, который ведет себя иначе, не следует языку C.
abelenky
Я этого не знал, спасибо. Я не нашел ни одного ресурса, где можно было бы прочитать этот особый случай. Было бы неплохо иметь это как закладку.
cocoafan,
1
Это называется частичной инициализацией. У меня нет спецификации C99, но вот два источника: bit.ly/enBC2m «Вам не нужно инициализировать все элементы в массиве. Если массив частично инициализирован, элементы, которые не инициализированы, получают значение 0 из соответствующий тип ". bit.ly/f9asHH «Если инициализаторов меньше, чем элементов в массиве, остальные элементы автоматически инициализируются на 0»
abelenky
Это не относится к массиву, который уже был объявлен и которому присвоены значения?
skinnedKnuckles
10

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

memset(my_custom_data, 0, sizeof(my_custom_data));

Или:

memset(my_custom_data, 0, strlen(my_custom_data));
Джейк1164
источник
1
Второй вариант ( memset(my_custom_data, 0, strlen(my_custom_data));) очистит только первый '\ 0', который может находиться за пределами конца массива. Это может быть нормально, а может и нет.
brewmanz
9

Попробуйте следующий код:

void clean(char *var) {
    int i = 0;
    while(var[i] != '\0') {
        var[i] = '\0';
        i++;
    }
}
Кристиан Альтамирано
источник
2
К вашему сведению - отступите от кода на 4 пробела или выберите его и нажмите кнопку «Код», которая выглядит как две строки двоичного кода.
meagar
Отличное решение, если вы не хотите включать string.h для memset ().
Akash Agarwal
7

Почему бы не использовать memset()? Вот как это сделать.

Установка первого элемента оставляет остальную память нетронутой, но функции str будут обрабатывать данные как пустые.

Джон Фрикер
источник
1
Не используйте memset из-за удобочитаемости: stackoverflow.com/questions/453432/…
Иоганн Герелл,
1
и каков тогда ваш ответ?
mkb
6

Пожалуйста, найдите ниже, где я объяснил данные в массиве после случаев 1 и 2.

char sc_ArrData[ 100 ];
strcpy(sc_ArrData,"Hai" );

Случай 1:

sc_ArrData[0] = '\0';

Результат:

-   "sc_ArrData"
[0] 0 ''
[1] 97 'a'
[2] 105 'i'
[3] 0 ''

Случай 2:

memset(&sc_ArrData[0], 0, sizeof(sc_ArrData));

Результат:

-   "sc_ArrData"
[0] 0 ''
[1] 0 ''
[2] 0 ''
[3] 0 ''

Хотя установка первого аргумента в NULL поможет, рекомендуется использовать memset.

Акаантан Кодер
источник
4

Нет. Все, что вы делаете, это устанавливаете первое значение на '\ 0' или 0.

Если вы работаете со строками с завершающим нулем, то в первом примере вы получите поведение, имитирующее то, что вы ожидаете, однако память все еще установлена.

Если вы хотите очистить память без использования memset, используйте цикл for.

Алан
источник
Я говорю нет в цикле for. Старайтесь не писать свои собственные «улучшенные» (и обычно не) библиотечные функции. Фактически, memset и memcpy довольно специфичны и часто встраиваются в специальный машинный код для ЦП на основе того, что известно о выравнивании и длине данных.
Zan Lynx
@Zan OP не хочет использовать memset (возможно, он встроен и недоступен). Но да, memset обычно очень оптимален и, вероятно, быстрее, чем цикл for.
Адам Хоуз,
Верно, однако он не хотел использовать memset, поэтому я предложил цикл for.
Алан
3

Вам следует использовать memset. Установка только первого элемента не сработает, вам нужно установить все элементы - если нет, как вы могли установить только первый элемент в 0?

Майкл
источник
memset не следует использовать из-за удобочитаемости: stackoverflow.com/questions/453432/…
Иоганн Герелл,
2

Запись нулевого символа в первый символ делает именно это. Если вы обрабатываете его как строку, код, подчиняющийся нулевому символу завершения, будет рассматривать ее как пустую строку, но это не то же самое, что очистка данных. Если вы действительно хотите очистить данные, вам нужно использовать memset.

tvanfosson
источник
2

Обычно я делаю так:

memset(bufferar, '\0', sizeof(bufferar));
Евгений Кононов
источник
1

Я думал, что установка первого элемента на null очистит все содержимое массива char.

Это неправильно, как вы обнаружили

Однако это устанавливает значение null только для первого элемента.

Именно!

Вам нужно использовать memset для очистки всех данных, недостаточно установить для одной из записей значение null.

Однако, если установка для элемента массива значения NULL означает что-то особенное (например, при использовании завершающей нулевой строки в), может быть достаточно установить для первого элемента значение NULL. Таким образом, любой пользователь массива поймет, что он пуст, даже если массив все еще включает в себя старые символы в памяти.

хафез
источник
Не используйте «memset» из-за удобочитаемости: stackoverflow.com/questions/453432/…
Иоганн Герелл,
1

установите первый элемент в NULL. печать массива символов ничего не вернет.


источник
1

Как насчет следующего:

bzero(my_custom_data,40);
codeconnundrum
источник
-3
void clearArray (char *input[]){
    *input = ' '; 
}
волк
источник
1
Это не ОЧИСТКА, это просто установка первого символа на ""! Я думаю, вы хотели написать * input = '\ 0'
stviper
-4

Попробуйте следующее:

strcpy(my_custom_data,"");
Грег Грейди
источник