programing

C에서 상수/문자열을 연결하려면 어떻게 해야 합니까?

procenter 2022. 8. 17. 23:02
반응형

C에서 상수/문자열을 연결하려면 어떻게 해야 합니까?

저는 C에서 일하고 있는데 몇 가지 일을 연결해야 합니다.

지금은 이렇게 하고 있어요.

message = strcat("TEXT ", var);

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

C에 대한 경험이 있다면 실행하려고 하면 세그멘테이션 장애가 발생한다는 것을 알고 있을 것입니다.그럼 어떻게 하면 좋을까요?

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어디서 명시적으로 목적지 버퍼의 크기를 지정하야 한다.수신처 버퍼의 사이즈를 명시적으로 지정할 필요가 있습니다.

참고: 문자열 리터럴은 상수이므로 버퍼로 사용할 수 없습니다.따라서 항상 버퍼에 char 배열을 할당해야 합니다.

" " "strcat단순히 무시할 수 있습니다.첫 번째 인수로 전달된 것과 동일한 포인터를 반환할 뿐입니다.이것은 편리성을 위해 준비되어 있으며, 콜을 한 줄의 코드로 연결할 수 있습니다.

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

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

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

C 코드로 사용하지 마십시오.가장 깨끗하고 가장 안전한 방법은 다음을 사용하는 것입니다.

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

일부 코멘트는 인수의 수가 포맷 문자열과 일치하지 않을 수 있으며 코드는 컴파일되지만 대부분의 컴파일러는 이미 경고를 발행하고 있습니다.

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

#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 */ 
                ;

strncpy(), strncat() 또는 snprintf()를 사용합니다.
버퍼 공간을 초과하면 메모리에 있는 다른 모든 항목이 삭제됩니다.
또, '\문자에 것을 잊지 !)

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

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

C에 대한 경험이 있는 경우 문자열은 마지막 문자가 늘 문자인 문자 배열에 불과하다는 것을 알 수 있습니다.

그래서 마지막 글자를 찾아서 붙여야 하기 때문에 불편합니다. strcat그렇게 해주실 거예요.

따라서 strcat은 첫 번째 인수를 통해 늘 문자를 검색합니다.그런 다음 두 번째 인수의 내용으로 대체합니다(그 내용이 null로 끝날 때까지).

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

message = strcat("TEXT " + var);

여기서 텍스트 "TEXT"에 포인터에 무언가를 추가합니다("TEXT"의 유형은 const char*).포인터).

그것은 보통 효과가 없습니다.또한 "TEXT" 배열은 보통 일정한 세그먼트에 배치되기 때문에 수정되지 않습니다.

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

스태틱 텍스트를 다시 수정하려고 한다는 점을 제외하면 이 방법이 더 효과적일 수 있습니다.strcat이 결과에 새 메모리를 할당하지 않았습니다.

대신 다음과 같은 일을 할 것을 제안합니다.

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

『 『 』의 매뉴얼을 .sprintf옵션을 확인합니다.

여기서 중요한 점은 다음과 같습니다.

버퍼에 텍스트와 늘 문자를 저장할 충분한 공간이 있는지 확인합니다.버퍼를 할당하는 strncat 및 printf의 특별한 버전 등 사용자에게 도움이 되는 몇 가지 기능이 있습니다.버퍼 크기를 보장하지 않으면 메모리가 손상되고 원격으로 악용 가능한 버그가 발생합니다.

사람들이 현악기 취급이 많이 좋아졌다고 지적했듯.따라서 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에서 이 작업을 수행하는 더 좋은 방법을 찾을 수 없었습니다.

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

strcat ("Hello, ", name);

시도합니다.이 경우, TACE에 붙이려고 합니다.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.

스태틱하게 할당된 주소로 문자열을 복사하려고 합니다.당신은 완충장치에 들어가야 해요.

구체적으로는:

...마지막으로...

목적지

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

여기도 예가 있어요.

다음과 같은 방법을 사용해 보십시오.

#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;
}

또한 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);
}

strcat()의 첫 번째 인수는 연결된 문자열을 위한 충분한 공간을 유지할 수 있어야 합니다.따라서 결과를 수신하기에 충분한 공간을 버퍼에 할당합니다.

char bigEnough[64] = "";

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

/* and so on */

strcat()은 두 번째 인수를 첫 번째 인수에 연결하고 결과를 첫 번째 인수에 저장합니다.반환되는 char*는 단순히 첫 번째 인수이며 사용자의 편의를 위해 사용됩니다.

첫 번째 인수와 두 번째 인수가 연결된 문자열은 새로 할당되지 않습니다. 이 문자열은 코드에 따라 예상된 것입니다.

반드시 출력 버퍼를 초기화해 주세요.strcat에 대한 첫 번째 인수는 결과 문자열에 충분한 여유 공간이 할당된 null 끝 문자열이어야 합니다.

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

하다와 같은 쓸 수도 .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니즈에 맞게.

가 아닌 charchar*를 하여 한 에 char*로 할 수 .<<cout<<like임베디드 경우 ("%s", "than", "printf style ") 및 큰 malloc도 생략할 수 .*printf family family like 등의 함수 snprintf()대해 하는 것을 방지할 수 있습니다).

#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를 사용하고 있는 경우 컴파일된 코드가 더 커지기 때문에 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;
}

이것이 나의 해결책이었다.

#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");

언급URL : https://stackoverflow.com/questions/308695/how-do-i-concatenate-const-literal-strings-in-c

반응형