2014-09-02 4 views
1

C 프로그래밍에서 두 개의 문자열을 연결하려고합니다. 나는 그것이 출력으로 mv /home/xxxxxxx/.local/share/Trash를 인쇄 s1의 값을 인쇄하려고하면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; 

} 

: 여기 내 코드입니다. s2가 s1 문자열로 추가되는 이유는 무엇입니까? 질문이 이미 나오면 링크를하십시오.

+2

'strncat() 사용은 정말 어렵습니다! 길이로 제공 한 번호는 무엇입니까? 's2'에서 사용할 수있는 총 길이가 아닙니다 (예제에서). 's2'의 현재 내용 뒤에 남겨진 길이입니다.'sizeof (s2) - strlen (s2) - 1' ('s1'과's2'도 null- 종료 된 문자열). 왜'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'가 연결되지 않았 음을 보장하고 배열은'\\ '종료됩니다. – chux

답변

2

S1은 세 개의 요소 (문자)를 갖는다

char s1[3], 

로 정의된다. strncat

strncat(s1," mv",3); 

실행될 때 세 가지 요소가 { ','M ','Y '} 그 후

충전 하였다 이는이 어레이는 종단 제로 없다.

printf 함수의 형식 지정자 %s은 종료 문자가 0이 될 때까지 문자 배열을 출력합니다. 배열 s1은 종료 0을 가지지 않기 때문에 printf는 배열을 넘어서는 모든 바이트를 계속해서 출력합니다. 배열 s1 이후에 배열 s2가 있기 때문에

char s1[3],s2[34]; 

이기 때문에 0으로 끝날 때까지 출력됩니다.

함수 strncat은 함수의 대상 문자열이 0으로 끝나야한다는 것을 고려해야합니다. 그러나 s1을 초기화하지 않았습니다. 따라서 프로그램의 동작은 정의되지 않습니다.

이 프로그램은 네 문자

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

strncat(s1,"mv ",4); 

아니면이

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

strcat(s1, "mv "); 

심지어 다음과 같은 방법을 작성하는 간단한 것을 가진 당신이 S1 배열을 정의 할 필요가 제대로 작동한다고합니다

char s1[4],s2[34]; 

strcpy(s1, "mv "); 

대신 strcpy 기능을 사용하는 것이 좋습니다. strncpy

2

s1에서 값을 인쇄하려고하면 출력으로 mv /home/ashwini/.local/share/Trash가 인쇄됩니다.

은 정의되지 않은 동작이다 : 그것은 세 문자의 공간에서 세 문자로 된 문자열을 가지고 있기 때문에 s1는 null로 끝나는 아니다; 널 종결자를위한 공간이 없습니다.

귀하의 s2 문자열 버퍼 메모리의 인접 지역에 위치 할 일이, 그래서는 s2의 널 (NULL) 종료에 printf이 실행될 때까지,뿐만 아니라 인쇄됩니다.

s1에 더 많은 메모리를 할당하고이 문제를 해결하는 것 널 (null) 종료를 차지한다 :

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 표준 라이브러리는 "regular"C 문자열에 대해 적절한 의미를 갖는 strlcat을 포함하지 않습니다. 그러나 라이브러리 확장으로 많은 시스템에서 사용할 수 있습니다. s1s2이 모두 초기화로

Demo.

+0

감사합니다. 그러나 지금 나는 이것을 얻고있다 : *** 스택 스매싱 감지 *** : ./a.out 종료 중단 (코어 덤프) – goodbytes

+0

@bhargav 다른 문자열에도 같은 문제가있다. edit ([demo] (http://ideone.com/BngEAH))를 살펴보십시오. – dasblinkenlight

3

당신은 당신의 코드에서 undefined behavior 있습니다. 초기화되지 않은 (비 정적) 지역 변수는 불확실한 값을 가지며 strncat이 소스 문자열에을 추가하는 위치를 알기 위해 문자열의 끝을 찾는 문자열 종료자를 가질 가능성이 없습니다.

위의 문제를 해결 한 후에 strncat 문자열 끝에 배열 끝을 쓰려고하면 정의되지 않은 동작이 발생할 수도 있습니다.

또한 s1s2은 두 개의 관련이없는 배열이므로 두 개의 문자열의 끝에는 리터럴 문자열을 추가하기 만하면됩니다. 당신이 무엇을 할 수 있는지


는 두 문자열을 포함하기에 충분한 어레이 및 문자열 종료를 할당하는 것입니다, 다음 는 배열에 첫 번째 문자열을 복사 한 다음 두 번째 문자열을 추가합니다.

예 : snprintf (또는 _snprintf은 Microsoft Windows 런타임 라이브러리를 사용함) 문자열을 생성합니다.

char s[100]; 
snprintf(s, sizeof(s), "mv %s %s", somepath, someotherpath);