Конкатенация строк C - странные символы - PullRequest
1 голос
/ 14 октября 2010

Я пишу программу на C, которая принимает n строки и объединяет их с помощью strcat.Сначала я выделил целевую строку на sizeof(char)* strlen каждой строки + 1 (для нулевого символа).Затем с помощью for я использую strncat для создания финальной строки.В и я добавляю нулевой символ.

Все идет хорошо, но иногда в начале строки назначения появляются странные символы (например, «?»).Это происходит, когда во время выполнения программы конечная строка короче, чем раньше (во время того же выполнения).

Что-то мне не хватает?

Это код:

size = 0;
for(i = 0; i < n; i++) {
    size += sizeof(char)*(strlen(strings[i]));
}

size++;

target = malloc(size);

if(!target) { /** Error handling... */ }

for(i = 0; i < n; i++) {
    target = strncat(target, strings[i], strlen(strings[i]));
}

target[size] = '\0';

Спасибо,

—Донован

Ответы [ 4 ]

7 голосов
/ 14 октября 2010

Вы должны сначала инициализировать целевую строку пустой строкой сразу после ее выделения.

target[0] = '\0';

При первом вызове strncat первая строка будет добавлена ​​к цели.Если ваша цель не инициализирована, она может быть не пустой, что приводит к появлению мусорных символов, которые вы видите.

(Другое решение - скопировать первую из ваших строк с strncpy в цель и затем добавитьследующие строки к нему.)

2 голосов
/ 14 октября 2010
target[size] = '\0';

Массив размером n имеет действительные индексы 0 до n - 1.Возможно, вы захотите изменить это значение на:

target[size-1] = '\0';

(хотя это не приводит к запуску мусорных символов. Для этого см. ответ Дидье Троссе .)

Некоторыебольше подсказок для вашего кода:

  • sizeof (char) == 1 по определению, поэтому его можно пропустить.
  • Поскольку вы точно знаете, что строки подойдут, вы можете использовать обычный strcatВот.Это сэкономит вам n звонков на strlen.
  • Окончательный target[size-1] = '\0' фактически не нужен, потому что str(n)cat всегда завершает нулем свою цель.
1 голос
/ 14 октября 2010

Между прочим, каждый вызов strncat() должен будет проходить по строке, чтобы просто найти место, где он будет вставлен. Это делает вашу функцию O (n 2 ). Это довольно просто сделать лучше (изменения в вашем коде выделены жирным шрифтом ):

size = 0;
for(i = 0; i < n; i++) {
    size += strlen(strings[i]);
}

size++;

target = malloc(size);

if(!target) { /** Error handling... */ }

<b>char *current_ptr = target;</b>

for(i = 0; i < n; i++) {
<b>    size_t len = strlen(strings[i]);
    memcpy(current_ptr, strings[i], len);
    current_ptr += len;</b>
}

<b>*current_ptr = 0;</b>
0 голосов
/ 14 октября 2010

Также вам не нужно собирать возвращаемое значение strncat обратно в цель.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...