2010-08-20 4 views
5

문자열 ToLiteral (문자열 입력)부터 this post까지와 같은 기능이 필요합니다.C 문자열의 문자를 이스케이프 시퀀스로 변환

char *literal = to_literal("asdf\r\n"); 

항복 싶은되도록 리터럴 ==> "\\ 자위대 R \\ N".

나는 인터넷 검색을했으나 아무것도 찾을 수 없었습니다 (틀린 용어를 사용해야 함). 그러나이 기능을 갖춘 라이브러리는 어딘가에 있어야한다고 가정합니다.

interresting 해줘서 고맙습니다. "c 문자열 탈출 함수"를 검색하는 것은 더 많은 예제를 얻는 열쇠가되는 것 같으며 GLIB는 내가 필요한 것처럼 보이는 g_strescape()를 제공합니다.

+0

"문자열 리터럴"은 여기에서 사용할 올바른 문구가 아닙니다. 원하는 것은 C 이스케이프 시퀀스를 갖는 문자가 해당 시퀀스로 대체되도록 문자열을 변환하는 함수입니다. –

+0

'literal == "asdf \ r \ n"'절대로 사실이 아닙니다. 나는 당신이'strcmp (literal, "asdf \\ r \\ n") == 0'을 의미한다고 생각합니다. – jamesdlin

+0

No. Literal == "asdf \\ r \\ n"왜냐하면 to_literal은 "asdf \ r \ n"을 "asdf \\ r \\ n"으로 변환해야하기 때문입니다. 그러나 대답을 통해 나는 더 나은 함수 이름 (C에서)이 ** char * escape (char *) **라는 것을 알게되었습니다. –

답변

8

같은 것을 할 수 있지만, 당신은 할 수 ... 이스케이프 시퀀스에 대한 실제 16 진수 코드를 비교 테이블을 업 K와 적절한 코드를 표시 채찍 일까지 :이 C에서 표준화되지 않기 때문에 내가 (일부 컴파일러 \e를 사용하고 다른 사람이 \x 사용)은 "탈출"문자에 대한 이스케이프 시퀀스의 번역을 남겨 두었다

/* Expands escape sequences within a C-string 
* 
* src must be a C-string with a NUL terminator 
* 
* dest should be long enough to store the resulting expanded 
* string. A string of size 2 * strlen(src) + 1 will always be sufficient 
* 
* NUL characters are not expanded to \0 (otherwise how would we know when 
* the input string ends?) 
*/ 

void expand_escapes(char* dest, const char* src) 
{ 
    char c; 

    while (c = *(src++)) { 
    switch(c) { 
     case '\a': 
     *(dest++) = '\\'; 
     *(dest++) = 'a'; 
     break; 
     case '\b': 
     *(dest++) = '\\'; 
     *(dest++) = 'b'; 
     break; 
     case '\t': 
     *(dest++) = '\\'; 
     *(dest++) = 't'; 
     break; 
     case '\n': 
     *(dest++) = '\\'; 
     *(dest++) = 'n'; 
     break; 
     case '\v': 
     *(dest++) = '\\'; 
     *(dest++) = 'v'; 
     break; 
     case '\f': 
     *(dest++) = '\\'; 
     *(dest++) = 'f'; 
     break; 
     case '\r': 
     *(dest++) = '\\'; 
     *(dest++) = 'r'; 
     break; 
     case '\\': 
     *(dest++) = '\\'; 
     *(dest++) = '\\'; 
     break; 
     case '\"': 
     *(dest++) = '\\'; 
     *(dest++) = '\"'; 
     break; 
     default: 
     *(dest++) = c; 
    } 
    } 

    *dest = '\0'; /* Ensure nul terminator */ 
} 

참고. 자신에게 적용 할 수있는 것을 추가 할 수 있습니다. 당신은 당신을 위해 대상 버퍼를 할당하는 기능을 원하는 경우

는 :

// warning: untested code. 
void make_literal(char const *input, char *output) { 
    // the following two arrays must be maintained in matching order: 
    static char inputs[] = "\a\b\f\n\r\t\v\\\"\'"; 
    static char outputs[] = "abfnrtv\\\"\'"; 

    char *p, *pos; 

    for (;*input;input++) { 
     if (NULL!= (pos=strchr(inputs, *input))) { 
      *output++ = '\\'; 
      *output++ = outputs[pos-inputs]; 
     } 
     else 
      *output++ = *input; 
    } 
    *output = '\0'; 
} 

이론적으로, 이것은 수 :

/* Returned buffer may be up to twice as large as necessary */ 
char* expand_escapes_alloc(const char* src) 
{ 
    char* dest = malloc(2 * strlen(src) + 1); 
    expand_escapes(dest, src); 
    return dest; 
} 
+0

호출자가 쉽게 잘못 호출 할 수있는 모든 - 결과를 malloc 및 반환 할 – pm100

+2

그것은 그것을 작성하는 또 다른 방법이지만 거의 모든 C 표준 라이브러리 문자열 함수는이 방법으로 작성됩니다. –

+2

'expand_escapes()'가 다른 비 인쇄 문자를 8 진수 이스케이프로 인코딩하는 것은 아마도 친숙 할 것입니다. 이 명령은 일반적인 ASCII ESC 문자를 '\ 033'으로 처리합니다. 물론 출력 버퍼는 입력 크기의 최대 4 배까지 될 수 있으므로 반환하기 전에 realloc을 많이 할당하는 것이 좋습니다. 또한 길이 매개 변수가있는 임베드 된 NUL 문자를 처리 할 수 ​​있습니다. 여기서 음수 길이는 첫 번째 NUL에서 중지를 의미합니다. – RBerteig

0

나는 당신이, 당신이 이런 식으로 (acter)는 char에 대한 포인터를 초기화 할 수있는 용어를 혼동 생각 :

char *literal = "asdf\r\n" 

개정 : 그러나, C 문자열 예를 들어 이스케이프 따옴표를 사용할 수 있습니다 :

<backspace>asdf<escape-character><carriage-return><linefeed><vertical-tab><tab> 
char *literal = "\basdf\x1b\r\n\v\t"; 

을 인쇄 할 것이다

이러한 문자는 콘솔 기능에 따라 표시되지 않으며 이스케이프에 대한 화살표와 탭 간격이 표시 될 수 있습니다 ... 간단한 논리를 사용하여이 문제를 해결할 수 있습니다. \마다 다른 \ 포인터가 실제 \n\r 그래서 수도를 잡고되면서

void ToLiteral(const char *pStr){ 
    char *p = (char*)pStr; 
    while (*p){ 
     /* if (*p == '\\') putchar('\\'); */ 
     /* PERFORM THE LOOK UP */ 
     putchar(*p++); 
    } 
} 

그러나 그것을보고, 그것은 바로 생각하지 않았다 : 그것은 충분해야 다음 코드와 같은

asdf\\r\\n 

뭔가를 표시하도록 화장실을 더 쉽게 사용할 수있다. 조회 테이블이에 대한 내장 함수가 없습니다이

struct LookUp{ 
    int codeLiteral; 
    char *equivCodeLiteral; 
}; 

struct LookUp look[] = { { 0xa, "\\r"}, { 0xd, "\\n" }, { 0x9, "\\t" } }; 
+1

참조 된 게시물을 보면, 나는 그의 질문에 대답하지 않는다고 생각합니다. 그는 "asdf \ r \ n"과 같은 문자열을 "asdf \\ r \\ n"문자열에서 예상되는 결과를 생성하는 문자열로 변환하려고합니다. – kbrimington

+0

예, 그렇습니다. 참조하는 게시물을 봅니다. 그는 분명히 탭과 개행 문자가 각각의 이스케이프 시퀀스로 좋아 지도록하고 싶습니다. "Hello \ nworld"=> "Hello \\ nworld" – Brian

+0

주의 사항 Emptor : 코드는 내가 인정하는 바보가 아닙니다. - 이건 내 머리 꼭대기에 ... 조심해! :) – t0mm13b

1

을 나는이 같은 변환 뭔가를 할 거라고 생각 (예를 들어) Tyler McHenry의 코드보다 약간 느립니다.특히 switch 문을 사용하면 올바른 경로의 일정 시간을 선택할 수 있습니다 (그러나 요구하지는 않음). 실제로, 관련된 값의 희소성을 고려할 때, 당신은 아마 일정한 시간 선택을 얻지 못할 것이고, 관련된 문자열은 너무 짧아 어떤 경우에도 그 차이는 보통 아주 작을 것입니다. 다른 방향으로는 더 쉽게 유지할 수 있기를 기대합니다 (예 : 더 많은 이스케이프 시퀀스를 지원하려는 경우 양식이 인 경우 일정 시간 유지해야합니다).

+1

"다음 두 배열은 일치하는 순서로 유지되어야합니다"- 그래서 그것들을'{}'구문으로 초기화하고 해당 항목을 세로로 정렬하십시오 ;-) –

+0

@ 스티브 : 확실히 합리적인 가능성이 있습니다 ... –

관련 문제