C ++ 여러 줄 문자열 리터럴


415

C ++에서 la Perl로 여러 줄의 일반 텍스트 상수 상수를 사용할 수있는 방법이 있습니까? 어쩌면 #include파일을 파싱 하는 파싱 ​​트릭이 있습니까? 나는 하나 생각할 수 없지만 소년, 그것은 좋을 것입니다. 나는 그것이 C ++ 0x에있을 것이라는 것을 안다.


1
일반적으로 문자열 리터럴을 코드에 포함하고 싶지 않습니다. I18N 및 L10N의 경우 런타임시로드되는 구성 파일에 문자열 리터럴을 넣는 것이 좋습니다.
Martin York

45
문자열 리터럴을 코드에 넣는 것이 문제가되지 않는 경우가 충분합니다. 문자열을 사용자에게 표시하는 데 사용하지 않는 경우; 예 : SQL 문, 파일 이름, 레지스트리 키 이름, 실행할 명령 줄, ...
mmmmmmmm

2
@Martin : 그러나 여전히 아는 것이 유용 할 수 있습니다. 예를 들어 복잡한 정규 표현식을 분해하기 위해 수행했습니다.
Boojum

답변:


591

글쎄요 ... 가장 쉬운 방법은 인접한 문자열 리터럴이 컴파일러에 의해 연결되어 있다는 사실을 사용하는 것입니다.

const char *text =
  "This text is pretty long, but will be "
  "concatenated into just a single string. "
  "The disadvantage is that you have to quote "
  "each part, and newlines must be literal as "
  "usual.";

들여 쓰기는 따옴표 안에 없기 때문에 중요하지 않습니다.

임베드 된 개행을 피하기 위해주의를 기울이면이 작업을 수행 할 수도 있습니다. 내 첫 번째 대답처럼 그렇게하지 않으면 컴파일되지 않습니다.

const char * text2 =
  "다른 한편으로, 나는 미쳤다 \
문자 그대로 여러 줄에 걸쳐 있습니다.
각 줄을 인용하지 않아도됩니다.
함유량. 작동하지만 들여 쓰기 할 수 없습니다. ";

다시 말하지만, 각 줄의 끝에있는 백 슬래쉬는 줄 끝 바로 앞에 있어야하고 소스에서 줄 바꿈을 이스케이프해야 모든 것이 줄 바꿈이없는 것처럼 작동합니다. 백 슬래시가있는 위치의 문자열에는 줄 바꿈이 없습니다. 이 양식을 사용하면 들여 쓰기가 문자열의 일부가되어 임의의 공백으로 인해 텍스트를 들여 쓰기 할 수 있으므로 분명히 텍스트를 들여 쓸 수 없습니다.


3
과거에 첫 번째 옵션은 구현에 달려 있다고 들었지만, 그 구문을 따르지 않는 컴파일러는 아직 찾지 못했습니다.
Jason Mock

28
@Jason : C89 이전 컴파일러의 일부일 필요는 없지만 C89에 정의되어 있으므로 기본적으로 모든 곳에서 지원됩니다.
Jonathan Leffler

4
또한 c ++ 98에서 여러 줄로 문자열 형식을 지정하려면 인용 된 각 문자열 조각에서 \ n 대신 \ n을 사용하십시오. C ++ 11 원시 리터럴은 여전히 ​​내가 좋아하는 것입니다.
emsr

3
@unwind 소스 라인 끝에있는 줄 바꿈은 문자열의 일부가 아니며 그냥 건너 뜁니다. 줄 바꿈을 문자열의 일부로 사용하려면 줄 끝에 \ n \이 있어야합니다.
hyde

2
Microsoft Visual Studio에 불쾌한 버그가 있습니다. 줄 끝에 백 슬래시를 사용하면 문자열 내부의 텍스트가 자동으로 들여 쓰기됩니다.
palota

408

C ++ 11에는 원시 문자열 리터럴이 있습니다. 파이썬과 펄, 루비와 같은 쉘과 스크립트 언어로 된 여기 텍스트와 같습니다.

const char * vogon_poem = R"V0G0N(
             O freddled gruntbuggly thy micturations are to me
                 As plured gabbleblochits on a lurgid bee.
              Groop, I implore thee my foonting turlingdromes.   
           And hooptiously drangle me with crinkly bindlewurdles,
Or I will rend thee in the gobberwarts with my blurlecruncheon, see if I don't.

                (by Prostetnic Vogon Jeltz; see p. 56/57)
)V0G0N";

문자열의 모든 공백과 들여 쓰기 및 줄 바꿈이 유지됩니다.

이들은 또한 utf-8 | 16 | 32 또는 wchar_t 일 수 있습니다 (일반적인 접두사 포함).

여기서는 이스케이프 시퀀스 V0G0N이 실제로 필요하지 않다는 점을 지적해야합니다. 그 존재는) "를 문자열 안에 넣을 수 있습니다. 다시 말하면,

                "(by Prostetnic Vogon Jeltz; see p. 56/57)"

(추가 인용 부호 참고)와 위의 문자열은 여전히 ​​정확합니다. 그렇지 않으면 나는뿐만 아니라 사용할 수 있었다

const char * vogon_poem = R"( ... )";

따옴표 안에있는 파렌은 여전히 ​​필요합니다.


24
이것은 실제로 내가 원하는 것, 따옴표를 피할 수있는 기능, 백 슬래시-N, 이스케이프 및 실제 문자열에 줄 바꿈이 여전히 표시됩니다. 내장 코드 (예 : 셰이더 또는 Lua)에 유용합니다. 불행히도, 우리는 아직 C ++-0x를 사용하지는 않습니다. :-(
mlepage

2
임베디드 SQL 및 Python 스크립트에 대해 이것을 고려하고있었습니다. gcc가 C ++ 98 모드에서 미끄러지게 할 수 있기를 바랍니다. 아아, 아니오.
emsr

3
나는 clang과 gcc에 더 익숙합니다. 이 컴파일러에서는 C ++ 0x 또는 c ++ 11에 플래그를 설정해야합니다. MS 웹 사이트를 보면 아직 원시 리터럴이없는 것 같습니다. C ++ 기능이 구현됨에 따라 MS가 새로운 컴파일러 업데이트를 더 빨리 릴리스한다는 것을 알고 있습니다. Visual C ++ Compiler 2012 년 11 월 CTP [ microsoft.com/en-us/download/details.aspx?id=35515] 에서 최신 기술을 찾으십시오 .
emsr

5
@rsethc 코드 블록을 주석 처리 하려면 #if 0#endif를 사용하십시오 . 둥지도.
bobbogo

1
보곤시에서 영감을!
Thane Plummer

27

#define MULTILINE(...) #__VA_ARGS__
괄호 안에있는 모든 것을 소비합니다.
연속 된 공백 문자를 단일 공백으로 바꿉니다.


1
\n바꿈이 필요한 경우 추가 할 수 있습니다
Simon

참고 ` (and hence \ n을 ) is copied literally, but ''로 변환 \"그래서의. MULTILINE(1, "2" \3)금리 "1, \"2\" \3".
안드레아스 스핀들러

@AndreasSpindler 따옴표와 백 슬래시는 모두 문자열이나 문자 리터럴 토큰 안에있는 한 (추가) 백 슬래시로 이스케이프됩니다. 당신의 요점이 무엇인지 잘 모르겠습니다. 일치하지 않는 인용 부호 (이중 또는 단일)를 갖는 것은 불법이므로 수축이 작동하지 않거나 어쨌든 그 수가 홀수입니다. 아마도 가장 큰 단점 일 것입니다. 어쨌든 +1. "실제 프로그래머"는 항상 줄 바꿈이없는 쌍으로 수축을 사용하므로 작은 따옴표가 균형을 이룹니다.
Potatoswatter

요점은 그가 "괄호 안에있는 모든 것을 소비한다"고 썼다는 것입니다.
Andreas Spindler

25

여러 줄 문자열을 입력하는 가장 편리한 방법은 매크로를 사용하는 것입니다. 따옴표와 괄호가 균형을 이루고 '최상위'쉼표를 포함하지 않는 경우에만 작동합니다.

#define MULTI_LINE_STRING(a) #a
const char *text = MULTI_LINE_STRING(
  Using this trick(,) you don't need to use quotes.
  Though newlines and     multiple     white   spaces
  will be replaced by a single whitespace.
);
printf("[[%s]]\n",text);

gcc 4.6 또는 g ++ 4.6으로 컴파일하면 다음이 생성됩니다. [[Using this trick(,) you don't need to use quotes. Though newlines and multiple white spaces will be replaced by a single whitespace.]]

참고 , 그것을 괄호 나 따옴표 안에 포함 된 경우를 제외하고, 문자열에있을 수 없습니다. 작은 따옴표는 가능하지만 컴파일러 경고를 생성합니다.

편집 : 의견에서 언급했듯이 #define MULTI_LINE_STRING(...) #__VA_ARGS__의 사용을 허용합니다 ,.


c ++에 루아 코드 스 니펫을 포함시키려는 프로젝트의 경우, 작은 파이썬 스크립트를 작성하여 여러 줄 문자열을 입력하고 c ++ 소스 파일을 생성했습니다.
bcmpinc

단위 테스트를 위해 collada 파일에서 거대한 멀티 라인 float-list 문자열을 추가하면 나에게 완벽합니다. 나는 어디에나 따옴표를 넣는 것을 좋아하지 않았고, 복사 및 붙여 넣기 솔루션이 필요했습니다.
Soylent Graham

7
#define MULTILINE(...) #__VA_ARGS__문자열에 쉼표를 포함 시키려면 사용할 수 있습니다 .
Simon

2
이것은 대부분의 여분의 whitesapce (모두 \n\r)를 제거하여 일부 경우에는 유용하고 다른 경우에는 치명적입니다.
BCS


15

당신은 이것을 할 수 있습니다 :

const char *text = "This is my string it is "
     "very long";

@unwind의 답변과 다른 점은 무엇입니까?
Sisir

1
@Sisir 나는 풀기 2 분 전에 게시했습니다.
에릭

해당 부분이 누락되어 죄송합니다. 나의 +1
Sisir

10

1 온스의 경험은 많은 이론의 가치가 있기 때문에 다음과 같은 테스트 프로그램을 시도했습니다 MULTILINE.

#define MULTILINE(...) #__VA_ARGS__

const char *mstr[] =
{
    MULTILINE(1, 2, 3),       // "1, 2, 3"
    MULTILINE(1,2,3),         // "1,2,3"
    MULTILINE(1 , 2 , 3),     // "1 , 2 , 3"
    MULTILINE( 1 , 2 , 3 ),   // "1 , 2 , 3"
    MULTILINE((1,  2,  3)),   // "(1,  2,  3)"
    MULTILINE(1
              2
              3),             // "1 2 3"
    MULTILINE(1\n2\n3\n),     // "1\n2\n3\n"
    MULTILINE(1\n
              2\n
              3\n),           // "1\n 2\n 3\n"
    MULTILINE(1, "2" \3)      // "1, \"2\" \3"
};

이 조각을 컴파일 cpp -P -std=c++11 filename하여 재현하십시오.

트릭의 뒤에은 #__VA_ARGS____VA_ARGS__쉼표 구분 기호를 처리하지 않습니다. 따라서 문자열 화 연산자로 전달할 수 있습니다. 선행 및 후행 공백이 잘리고 단어 사이의 공백 (개행 포함)이 단일 공백으로 압축됩니다. 괄호는 균형을 이루어야합니다. 이러한 단점은 C ++ 11의 디자이너가에도 불구하고 #__VA_ARGS__원시 문자열 리터럴이 필요한 이유를 설명한다고 생각합니다 .


9

C ++ 11 컴파일러 (GCC 4.2.1)를 가질만큼 운이 좋지 않고 문자열에 개행을 포함시키려는 경우 @unwind의 답변에서 @emsr의 의견에 대해 조금 설명하기 만하면됩니다 (char * 또는 클래스 문자열), 다음과 같이 작성할 수 있습니다.

const char *text =
  "This text is pretty long, but will be\n"
  "concatenated into just a single string.\n"
  "The disadvantage is that you have to quote\n"
  "each part, and newlines must be literal as\n"
  "usual.";

매우 명백하고 사실이지만, 처음 읽었을 때 @emsr의 짧은 의견이 나에게 튀어 나오지 않았으므로 직접 발견해야했습니다. 잘만되면, 나는 몇 분 동안 다른 사람을 구했습니다.


-1
// C++11. 
std::string index_html=R"html(
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>VIPSDK MONITOR</title>
    <meta http-equiv="refresh" content="10">
</head>
<style type="text/css">
</style>
</html>
)html";

코드 스 니펫이 아니라 답변에 설명을 추가하십시오
Geordie

-1

옵션 1. 부스트 라이브러리를 사용하여 아래와 같이 문자열을 선언 할 수 있습니다

const boost::string_view helpText = "This is very long help text.\n"
      "Also more text is here\n"
      "And here\n"

// Pass help text here
setHelpText(helpText);

옵션 2. 프로젝트에서 부스트를 사용할 수없는 경우 최신 C ++에서 std :: string_view ()를 사용할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.