2014-09-02 5 views
1

Я пытаюсь объединить две строки в программировании на языке C. Вот мой код:strncat() снова копирует в ту же строку

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int main(int argc, char const *argv[]) 
{ 
    /* code */ 
     char s1[3],s2[34]; 

     strncat(s1,"mv ",3); 
     strncat(s2," /home/xxxxxxx/.local/share/Trash/",34); 

     printf("%s \n",s1); 

     return 0; 

} 

, когда я пытаюсь напечатать значение в s1 он печатает mv /home/xxxxxxx/.local/share/Trash как выход. Почему значение, которое я добавляю для s2, добавляется со строкой s1? Если вопрос уже задан, поставьте ссылку.

+2

Использование 'strncat()' действительно сложно! Какой номер вы предоставляете в качестве длины? Это не общая длина, доступная в 's2' (в вашем примере); это длина, оставшаяся после текущего содержимого 's2', или' sizeof (s2) - strlen (s2) - 1' (если вы исправите проблему, что ни 's1', ни' s2' не является нулевым, конец строки). Непонятно, почему вы хотите использовать команду 's1' и аргумент в' s2'. Вероятно, вам лучше работать с 'snprintf (s2, sizeof (s2),"% s% s "," mv ","/home/... ");'. –

+1

Избегайте использования 'strncat (a, b, sizeof (a));'. После застрахования 'a' имеет в себе законную строку, лучше использовать' strncat (a, b, sizeof (a) -1); a [sizeof (a) -1] = '\ 0'; '. Это гарантирует, что не слишком много символов 'char' были объединены, а массив' '\ 0'' завершен. – chux

ответ

2

s1 определяется как

char s1[3], 

, который она состоит из трех элементов (символов). Когда strncat был выполнен

strncat(s1," mv",3); 

это три элемента были заполнены { «», «т», «Y»}

После того, что этот массив не имеет завершающий нуль.

Спецификатор формата %s в функции printf выводит массив символов до тех пор, пока не будет встречен нулевой контакт. Поскольку массив s1 не имеет оканчивающегося нуля, printf продолжает выводить все байты, которые находятся за пределами массива. потому что после массива s1 существует массив s2

char s1[3],s2[34]; 

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

Учтите, что функция strncat требует, чтобы целевая строка была нулевой. Однако вы не инициализировали s1. Таким образом, поведение программы не определено.

Если вы хотите, что программа будет работать правильно, вы должны определить массив s1 как имеющий четыре символа

char s1[4] = { '\0' },s2[34]; 

strncat(s1,"mv ",4); 

Или было бы проще написать

char s1[4] = { '\0' },s2[34]; 

strcat(s1, "mv "); 

или даже следующим образом

char s1[4],s2[34]; 

strcpy(s1, "mv "); 

, что было бы лучше использовать функцию strcpy от strncpy

2

Когда я пытаюсь напечатать значение в s1, он печатает mv /home/ashwini/.local/share/Trash как выход.

Это неопределенное поведение: s1 не оканчивается нулем, поскольку она имеет строку три символа в пространстве трех символов; для нулевого терминатора нет места.

Ваш буферный буфер s2 находится в соседней области памяти, поэтому он также печатается до тех пор, пока printf не запустит нулевой ограничитель s2.

Выделяя больше памяти для s1 и учет нулевого прекращения бы решить эту проблему:

char s1[4],s2[36]; 
s1[0] = '\0'; 
strncat(s1," mv", 4); 
s2[0] = '\0'; 
strncat(s2," /home/xxxxxxx/.local/share/Trash/", 36); 

Однако strncat не является собственной функцией для работы с регулярными строками: она предназначена для использования со строками фиксированной длиной , которые больше не используются повсеместно. К сожалению, стандартная библиотека C не включает strlcat, которая имеет правильную семантику для «обычных» строк C. Тем не менее, он доступен для многих систем как расширение библиотеки.

Demo.

+0

Спасибо. Но теперь я получаю это: '*** обнаружено разбиение стека ***: ./a.out завершено Aborted (core dumped) ' – goodbytes

+0

@bhargav У вашей другой строки тоже проблемы. Взгляните на редактирование ([demo] (http://ideone.com/BngEAH)). – dasblinkenlight

3

Вы undefined behavior в вашем коде, так как ни s1, ни s2 инициализируются. Неинициализированные (нестатические) локальные переменные имеют неопределенные значения, и маловероятно, что они имеют ограничитель строки, который strncat должен найти конец строки, чтобы узнать, где append исходная строка.

После того, как вы исправили выше, у вас также есть другой случай неопределенного поведения, когда strncat пытается записать ограничитель строки за пределы массивов.

Кроме того, вы не конкатенации двух строк, а s1 и s2 являются два несвязанных массивы, вы просто добавить буквенные строки в конце двух массивов, но не вместе.


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

Или не использовать, например. snprintf (или _snprintf использует библиотеку времени выполнения Microsoft Windows) для построения строки.

char s[100]; 
snprintf(s, sizeof(s), "mv %s %s", somepath, someotherpath); 
Смежные вопросы