문제

나는 C에서 일하고 있으며 몇 가지를 연결해야합니다.

지금 나는 이것을 가지고있다 :

message = strcat("TEXT ", var);

message2 = strcat(strcat("TEXT ", foo), strcat(" TEXT ", bar));

이제 C에 대한 경험이 있다면, 당신이 그것을 실행하려고 할 때 이것이 세분화 결함을 줄임을 알고 있습니다. 그래서 어떻게해야합니까?

도움이 되었습니까?

해결책

C에서 "줄"은 단지 평범합니다 char 배열. 따라서 다른 "줄"과 직접 연결할 수는 없습니다.

당신은 사용할 수 있습니다 strcat 함수는 문자열을 가리키는 문자열을 추가합니다 src 문자열의 끝까지 dest:

char *strcat(char *dest, const char *src);

여기에 있습니다 cplusplus.com의 예:

char str[80];
strcpy(str, "these ");
strcat(str, "strings ");
strcat(str, "are ");
strcat(str, "concatenated.");

첫 번째 매개 변수의 경우 대상 버퍼 자체를 제공해야합니다. 대상 버퍼는 숯 어레이 버퍼 여야합니다. 예 : char buffer[1024];

확실하게 하다 첫 번째 매개 변수에는 복사하려는 내용을 저장할 수있는 충분한 공간이 있습니다. 당신이 이용할 수 있다면 : 다음과 같은 기능을 사용하는 것이 더 안전합니다. strcpy_s 그리고 strcat_s 대상 버퍼의 크기를 명시 적으로 지정 해야하는 경우.

메모: 문자열 리터럴은 일정하기 때문에 버퍼로 사용할 수 없습니다. 따라서 항상 버퍼에 숯 배열을 할당해야합니다.

반환 값 strcat 단순히 무시할 수 있습니다. 단지 첫 번째 인수와 동일한 포인터를 반환합니다. 편의를 위해 존재하며 통화를 한 줄의 코드로 묶을 수 있습니다.

strcat(strcat(str, foo), bar);

따라서 문제를 다음과 같이 해결할 수 있습니다.

char *foo = "foo";
char *bar = "bar";
char str[80];
strcpy(str, "TEXT ");
strcat(str, foo);
strcat(str, bar);

다른 팁

사용하지 마십시오 strcat C 코드에서. 가장 깨끗하고 가장 중요한 것은 가장 안전한 방법은 사용하는 것입니다. snprintf:

char buf[256];
snprintf(buf, sizeof buf, "%s%s%s%s", str1, str2, str3, str4);

일부 의견 제시자는 인수 횟수가 형식 문자열과 일치하지 않을 수 있으며 코드가 여전히 컴파일 될 것이라는 문제를 제기했지만 대부분의 컴파일러는이 경우에 이미 경고를 발행합니다.

여러분, str를 사용하십시오Ncpy (), strNcat () 또는 sNprintf ().
버퍼 공간을 초과하면 메모리에서 따르는 다른 것을 버립니다!
(그리고 후행 Null ' 0'문자를위한 공간을 허용하는 것을 잊지 마십시오!)

또한 malloc과 realloc은 얼마나 많은 문자열이 연결되고 있는지 미리 모르는 경우 유용합니다.

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

void example(const char *header, const char **words, size_t num_words)
{
    size_t message_len = strlen(header) + 1; /* + 1 for terminating NULL */
    char *message = (char*) malloc(message_len);
    strncat(message, header, message_len);

    for(int i = 0; i < num_words; ++i)
    {
       message_len += 1 + strlen(words[i]); /* 1 + for separator ';' */
       message = (char*) realloc(message, message_len);
       strncat(strncat(message, ";", message_len), words[i], message_len);
    }

    puts(message);

    free(message);
}

문자열은 컴파일 시간에도 연결 될 수 있습니다.

#define SCHEMA "test"
#define TABLE  "data"

const char *table = SCHEMA "." TABLE ; // note no + or . or anything
const char *qry =               // include comments in a string
    " SELECT * "                // get all fields
    " FROM " SCHEMA "." TABLE   /* the table */
    " WHERE x = 1 "             /* the filter */ 
                ;

출력 버퍼를 초기화하는 것을 잊지 마십시오. strcat에 대한 첫 번째 인수는 결과 문자열에 충분한 여분의 공간을 할당 한 널 종단 된 문자열이어야합니다.

char out[1024] = ""; // must be initialized
strcat( out, null_terminated_string ); 
// null_terminated_string has less than 1023 chars

strcat ()의 첫 번째 인수는 연결된 문자열을위한 충분한 공간을 잡을 수 있어야합니다. 따라서 결과를받을 수있는 충분한 공간이있는 버퍼를 할당하십시오.

char bigEnough[64] = "";

strcat(bigEnough, "TEXT");
strcat(bigEnough, foo);

/* and so on */

strcat ()는 첫 번째 인수와 두 번째 인수를 연결하고 결과를 첫 번째 인수에 저장할 것입니다. 반환 된 숯*은 단순히이 첫 번째 논쟁이며 편의를 위해서만 저장합니다.

당신은 첫 번째와 두 번째 인수가 연결된 새로 할당 된 문자열을 얻지 못합니다.

사람들이 문자열 처리를 많이 지적했듯이 많이 향상되었습니다. 따라서 C 스타일 문자열 대신 C ++ 문자열 라이브러리를 사용하는 방법을 배우고 싶을 수도 있습니다. 그러나 여기에 순수한 c.의 해결책이 있습니다

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

void appendToHello(const char *s) {
    const char *const hello = "hello ";

    const size_t sLength     = strlen(s);
    const size_t helloLength = strlen(hello);
    const size_t totalLength = sLength + helloLength;

    char *const strBuf = malloc(totalLength + 1);
    if (strBuf == NULL) {
        fprintf(stderr, "malloc failed\n");
        exit(EXIT_FAILURE);
    }

    strcpy(strBuf, hello);
    strcpy(strBuf + helloLength, s);

    puts(strBuf);

    free(strBuf);

}

int main (void) {
    appendToHello("blah blah");
    return 0;
}

그것이 올바른/안전한지 확실하지 않지만 지금은 ANSI C에서 더 나은 방법을 찾을 수 없었습니다.

버퍼 크기가 제한되지 않고 수행하는 가장 좋은 방법은 asprintf ()를 사용하는 것입니다.

char* concat(const char* str1, const char* str2)
{
    char* result;
    asprintf(&result, "%s%s", str1, str2);
    return result;
}

문자열 리터럴을 수정하려고 시도하는 것은 정의되지 않은 동작입니다. 이것은 다음과 같은 것입니다.

strcat ("Hello, ", name);

시도 할 것입니다. 그것은 태클을 시도 할 것입니다 name 문자열 문자 문자 문자 그대로 문자열 "Hello, ", 잘 정의되지 않았습니다.

이것을 시도하십시오. 그것은 당신이하려는 것처럼 보이는 것을 달성합니다.

char message[1000];
strcpy (message, "TEXT ");
strcat (message, var);

이것은 버퍼 영역을 만듭니다 ~이다 수정 된 다음 문자열 리터럴과 다른 텍스트를 모두 복사 할 수 있습니다. 버퍼 오버 플로우에주의하십시오. 입력 데이터를 제어하거나 미리 확인하는 경우 나와 같이 고정 길이 버퍼를 사용하는 것이 좋습니다.

그렇지 않으면 힙에서 충분한 메모리를 할당하여 처리 할 수있는 완화 전략을 사용해야합니다. 다시 말해, 다음과 같습니다.

const static char TEXT[] = "TEXT ";

// Make *sure* you have enough space.

char *message = malloc (sizeof(TEXT) + strlen(var) + 1);
if (message == NULL)
     handleOutOfMemoryIntelligently();
strcpy (message, TEXT);
strcat (message, var);

// Need to free message at some point after you're done with it.

당신은 같은 일을하는 자신의 기능을 쓸 수 있습니다. strcat() 그러나 그것은 아무것도 바꾸지 않습니다.

#define MAX_STRING_LENGTH 1000
char *strcat_const(const char *str1,const char *str2){
    static char buffer[MAX_STRING_LENGTH];
    strncpy(buffer,str1,MAX_STRING_LENGTH);
    if(strlen(str1) < MAX_STRING_LENGTH){
        strncat(buffer,str2,MAX_STRING_LENGTH - strlen(buffer));
    }
    buffer[MAX_STRING_LENGTH - 1] = '\0';
    return buffer;
}

int main(int argc,char *argv[]){
    printf("%s",strcat_const("Hello ","world"));    //Prints "Hello world"
    return 0;
}

두 문자열이 모두 1000 자 이상이면 문자열을 1000 자로 자릅니다. 값을 변경할 수 있습니다 MAX_STRING_LENGTH 당신의 필요에 맞게.

char*대신 char [고정 _size]가 있다고 가정하면, 당신은 단일 크리에이티브 매크로를 사용하여 한 번에 모든 것을 할 수 있습니다. <<cout<<like 주문 ( "Distanted %s n", "보다", "printf style 형식"). 임베디드 시스템으로 작업하는 경우이 방법은 Malloc 및 대형을 제거 할 수 있습니다. *printf 기능의 가족 snprintf() (이것은 dietlibc가 *printf에 대해서도 불평하지 않도록합니다)

#include <unistd.h> //for the write example
//note: you should check if offset==sizeof(buf) after use
#define strcpyALL(buf, offset, ...) do{ \
    char *bp=(char*)(buf+offset); /*so we can add to the end of a string*/ \
    const char *s, \
    *a[] = { __VA_ARGS__,NULL}, \
    **ss=a; \
    while((s=*ss++)) \
         while((*s)&&(++offset<(int)sizeof(buf))) \
            *bp++=*s++; \
    if (offset!=sizeof(buf))*bp=0; \
}while(0)

char buf[256];
int len=0;

strcpyALL(buf,len,
    "The config file is in:\n\t",getenv("HOME"),"/.config/",argv[0],"/config.rc\n"
);
if (len<sizeof(buf))
    write(1,buf,len); //outputs our message to stdout
else
    write(2,"error\n",6);

//but we can keep adding on because we kept track of the length
//this allows printf-like buffering to minimize number of syscalls to write
//set len back to 0 if you don't want this behavior
strcpyALL(buf,len,"Thanks for using ",argv[0],"!\n");
if (len<sizeof(buf))
    write(1,buf,len); //outputs both messages
else
    write(2,"error\n",6);
  • 참고 1, 당신은 일반적으로 이와 같이 argv [0]를 사용하지 않습니다 - 예제입니다.
  • 참고 2, 정수를 문자열 유형으로 변환하기 위해 itoa ()와 같은 비표준 함수를 포함하여 char*를 출력하는 모든 함수를 사용할 수 있습니다.
  • 참고 3, 당신이 당신의 프로그램의 어느 곳에서나 이미 printf를 사용하고 있다면 compiled 코드가 더 크기 때문에 snprintf ()를 사용하지 않을 이유가 없습니다.
int main()
{
    char input[100];
    gets(input);

    char str[101];
    strcpy(str, " ");
    strcat(str, input);

    char *p = str;

    while(*p) {
       if(*p == ' ' && isalpha(*(p+1)) != 0)
           printf("%c",*(p+1));
       p++;
    }

    return 0;
}

정적으로 할당 된 주소로 문자열을 복사하려고합니다. 버퍼에 고양이가 필요합니다.

구체적으로:

...한조각...

목적지

Pointer to the destination array, which should contain a C string, and be large enough to contain the concatenated resulting string.

...한조각...

http://www.cplusplus.com/reference/clibrary/cstring/strcat.html

여기에도 예가 있습니다.

C에서 경험이있는 경우 문자열은 마지막 문자가 널 캐릭터 인 숯 배열 일뿐입니다.

이제 무언가를 추가하기 위해 마지막 캐릭터를 찾아야하기 때문에 그것은 매우 불편합니다. strcat 당신을 위해 그렇게 할 것입니다.

그래서 strcat은 널 캐릭터에 대한 첫 번째 주장을 검색합니다. 그런 다음 이것을 두 번째 인수의 내용으로 바꿀 것입니다 (널로 끝날 때까지).

이제 코드를 살펴 보겠습니다.

message = strcat("TEXT " + var);

여기에서 텍스트 "텍스트"에 대한 포인터에 무언가를 추가하고 있습니다 ( "텍스트"의 유형은 const char*입니다. 포인터).

일반적으로 작동하지 않습니다. 또한 "텍스트"배열을 수정하면 일반적으로 일정한 세그먼트에 배치되므로 작동하지 않습니다.

message2 = strcat(strcat("TEXT ", foo), strcat(" TEXT ", bar));

정적 텍스트를 다시 수정하려고한다는 점을 제외하고는 더 잘 작동 할 수 있습니다. STRCAT는 결과를 위해 새로운 메모리를 할당하지 않습니다.

대신 이런 일을 할 것을 제안합니다.

sprintf(message2, "TEXT %s TEXT %s", foo, bar);

문서를 읽으십시오 sprintf 옵션을 확인합니다.

그리고 이제 중요한 요점 :

버퍼에 텍스트와 널 문자를 담을 수있는 충분한 공간이 있는지 확인하십시오. 당신을 위해 버퍼를 할당하는 당신을 도울 수있는 몇 가지 기능이 있습니다. 버퍼 크기를 보장하지 않으면 메모리 손상과 원격으로 이용 가능한 버그가 발생합니다.

이것은 내 해결책이었습니다

#include <stdlib.h>
#include <stdarg.h>

char *strconcat(int num_args, ...) {
    int strsize = 0;
    va_list ap;
    va_start(ap, num_args);
    for (int i = 0; i < num_args; i++) 
        strsize += strlen(va_arg(ap, char*));

    char *res = malloc(strsize+1);
    strsize = 0;
    va_start(ap, num_args);
    for (int i = 0; i < num_args; i++) {
        char *s = va_arg(ap, char*);
        strcpy(res+strsize, s);
        strsize += strlen(s);
    }
    va_end(ap);
    res[strsize] = '\0';

    return res;
}

그러나 당신은 당신이 연결할 문자열의 수를 지정해야합니다.

char *str = strconcat(3, "testing ", "this ", "thing");

이와 유사한 것을 시도하십시오.

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

int main(int argc, const char * argv[])
{
  // Insert code here...
  char firstname[100], secondname[100];
  printf("Enter First Name: ");
  fgets(firstname, 100, stdin);
  printf("Enter Second Name: ");
  fgets(secondname,100,stdin);
  firstname[strlen(firstname)-1]= '\0';
  printf("fullname is %s %s", firstname, secondname);

  return 0;
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top