C / Objective-C에서 문자열 리터럴을 여러 줄로 나누는 방법은 무엇입니까?


321

꽤 긴 sqlite 쿼리가 있습니다.

const char *sql_query = "SELECT statuses.word_id FROM lang1_words, statuses WHERE statuses.word_id = lang1_words.word_id ORDER BY lang1_words.word ASC";

쉽게 읽을 수 있도록 여러 줄로 나누려면 어떻게해야합니까? 내가 다음을 수행하면 :

const char *sql_query = "SELECT word_id
                        FROM table1, table2
                        WHERE table2.word_id = table1.word_id
                        ORDER BY table1.word ASC";

오류가 발생했습니다.

여러 줄로 쿼리를 작성하는 방법이 있습니까?

답변:


569

문자열을 여러 줄로 나누는 방법에는 두 가지가 있습니다.

사용하여 \

C를 사용하여 모든 줄을 \를 사용하여 여러 줄로 나눌 수 있습니다.

평야 C :

char *my_string = "Line 1 \
                   Line 2";

목표 -C :

NSString *my_string = @"Line1 \
                        Line2";

더 나은 접근

문자열에만 작동하는 더 나은 접근 방식이 있습니다.

평야 C :

char *my_string = "Line 1 "
                  "Line 2";

목표 -C :

NSString *my_string = @"Line1 "
                       "Line2";    // the second @ is optional

두 번째 방법은 공백이 많지 않기 때문에 더 좋습니다. 그러나 SQL 쿼리의 경우 둘 다 가능합니다.

참고 : #define을 사용하면 두 문자열을 연결하기 위해 추가 '\'를 추가해야합니다.

평야 C :

#define kMyString "Line 1"\
                  "Line 2"

22
둘 다 in 및 C 및 C ++와 동일합니다. 후자의 솔루션은 이전의 솔루션이 많은 쓸모없는 공백을 프로그램에 내장 하여 DB 서버로 전송 되기 때문에 선호 됩니다.
Alnitak

더 나은 Objective-C 예제에서 2 행의 시작 부분에 @가 없습니다.
Lawrence Johnston

두 번째 옵션을 설명하는 사양에 대한 링크가 @있습니까?
Heath Borders

@HeathBorders : 바로 여기에 있지는 않지만 답을 쓸 때 찾아 보았습니다.
Georg Schölly

10
더 나은 접근 방식의 또 다른 장점은 각 줄 다음에 주석을 넣을 수 있다는 것입니다.
fishinear

110

전처리기로 할 수있는 트릭이 있습니다.
그것은 공백을 무너 뜨릴 가능성이 있으며 코드를 읽는 사람들에게 혼란을 줄 수 있습니다.
그러나 인용 부호를 피할 필요가 없다는 장점이 있습니다.

#define QUOTE(...) #__VA_ARGS__
const char *sql_query = QUOTE(
    SELECT word_id
    FROM table1, table2
    WHERE table2.word_id = table1.word_id
    ORDER BY table1.word ASC
);

전처리 기는 이것을 다음으로 바꿉니다.

const char *sql_query = "SELECT word_id FROM table1, table2 WHERE table2.word_id = table1.word_id ORDER BY table1.word ASC";

JSON을 포함하는 큰 리터럴 문자열이있는 단위 테스트를 작성할 때이 트릭을 사용했습니다. 모든 따옴표 문자 \ "를 이스케이프 할 필요는 없습니다.


5
완전한! 이제 나는 단지 몇 백 달러의 공감대를주고 그것이 속한 곳에서 그것을 얻을 필요가있다.
Mike

나는 같은 방식으로 반응했지만 문제가없는 것은 아닙니다. 방금 특수 유니 코드 문자로 heredoc을 시도했지만 리터럴 외부에서 허용되지 않는 비 ASCII 문자에 대한 오류가 발생했습니다.
philipkd

+1이지만 레코드가 변경 될 때 표현식을 다시 컴파일하지 않는 컴파일러 (MSVC) 또는 편집기 (QtCreator)에 문제가 있습니다. 변경이 감지되지 않는 것과 같습니다 ... Build 대신 Rebuild를 누르면 트릭이 발생합니다.
Andreas

이 치킨 너겟 정보에 감사드립니다. 모든 여분의 쓰레기없이 내가해야 할 일을 정확하게 수행합니다.
FishGuy876

불행히도 문자열에 리터럴 따옴표가 있으면 작동하지 않습니다. 글쎄, 그것은 경고를 생성한다는 점에서 일종의 작동합니다. 그러나 내 코드베이스는 -Werror ...
AnilRedshift

24

XCode-> 환경 설정으로 이동하여 들여 쓰기 탭을 선택한 다음 줄 바꿈을 켤 수도 있습니다.

그렇게하면 추가로 입력 할 필요가 없으며 이미 쓴 내용에 적합합니다. :-)

하나의 성가신 것은 ...

if (you're long on indentation
    && short on windows) {
            then your code will
                end up squished
                     against th
                         e side
                             li
                              k
                              e

                              t
                              h
                              i
                              s
}

2
@YoYoYonnY 동의하지만 감사합니다. 이 의견이 실제로 의견으로 가능하지 않았기 때문에 답변 형식을 사용한다는 것은 나에게 충격입니다. 이것은 S / O의 한계 인 것처럼 보입니다. 특히 풍부한 의견을 쓸 수는 없습니다 (알고있는 한).
Max von Hippel

24

나는 항상이 문제를 겪고 있으므로 텍스트를 이스케이프 된 여러 줄 Objective-C 문자열로 변환하는 작은 도구를 만들었습니다.

http://multilineobjc.herokuapp.com/

이것이 시간을 절약하기를 바랍니다.


1
훌륭한 도구! 질문 : 왜 '|'을 탈출합니까?
justadreamer

좋은 지적. 더 이상 "|"을 (를) 이스케이프하지 않도록 변경했습니다. 알려 줘서 고마워.
Flaviu

나는 같은 생각을 가지고 있었다. 이걸 먼저 보았 으면 좋겠다. 내 도구는 : nsstringify.nateflink.com
네이트 플 링크

1
고마워 시간을 많이 절약했습니다!
djskinner

(좋아하는 에디터와 통합) 연타 형식을 사용해보십시오 : clang.llvm.org/docs/ClangFormat.html
아메드 Fasih

18

Objective-C에 대한 견적 아이디어 확장 :

#define NSStringMultiline(...) [[NSString alloc] initWithCString:#__VA_ARGS__ encoding:NSUTF8StringEncoding]

NSString *sql = NSStringMultiline(
    SELECT name, age
    FROM users
    WHERE loggedin = true
);

3
#define NSStringMultiline(...) @#__VA_ARGS__작동해야합니다.
Nicholas Daley

변경 가능한 문자열의 경우 : #define NSStringMultiline(...) [[NSMutableString alloc] initWithCString:#__VA_ARGS__ encoding:NSUTF8StringEncoding]
rimsky

나에게 결과 문자열에는 줄 바꿈이 없습니다.
rimsky

이스케이프 된 줄 바꿈이 올바르게 캡처됩니다 (거의 편리하지 않거나 좋지 않습니다).
rimsky

@rimsky, 그리고 그것은 #define NSStringMultiline(...) [@#__VA_ARGS__ mutableCopy]가변 문자열에서도 작동 한다고 생각합니다 .
Iulian Onofrei

5

파일에 대한 또 하나의 해결책은 .m 파일을 .mm로 변경하여 Objective-C ++가되고 다음과 같이 C ++ 원시 리터럴을 사용하는 것입니다.

const char *sql_query = R"(SELECT word_id
                           FROM table1, table2
                           WHERE table2.word_id = table1.word_id
                           ORDER BY table1.word ASC)";

원시 리터럴은 종료 시퀀스 (기본 경우 괄호 인용)까지 모든 것을 무시합니다.

문자열에 괄호 인용 시퀀스가 ​​나타나야하는 경우 다음과 같이 사용자 지정 구분 기호를 쉽게 지정할 수 있습니다.

const char *sql_query = R"T3RM!N8(
                                  SELECT word_id
                                  FROM table1, table2
                                  WHERE table2.word_id = table1.word_id
                                  ORDER BY table1.word ASC
                         )T3RM!N8";

또한 GCC는 C 언어의 확장으로 C ++ 원시 문자열 리터럴을 추가하는 것으로 나타났습니다 : stackoverflow.com/questions/797318/...
치로 틸리郝海东冠状病六四事件法轮功

3

당신은 또한 할 수 있습니다 :

NSString * query = @"SELECT * FROM foo "
                   @"WHERE "
                     @"bar = 42 "
                     @"AND baz = datetime() "
                   @"ORDER BY fizbit ASC";

2

GCC, C ++ 다중 행 원시 문자열 리터럴을 C 확장으로 추가

C ++ 11에는 https://stackoverflow.com/a/44337236/895245에 언급 된대로 원시 문자열 리터럴이 있습니다.

그러나 GCC는 이들을 C 확장으로 추가하기 때문에 -std=gnu99대신에 사용해야 합니다 -std=c99. 예 :

main.c

#include <assert.h>
#include <string.h>

int main(void) {
    assert(strcmp(R"(
a
b
)", "\na\nb\n") == 0);
}

컴파일하고 실행하십시오.

gcc -o main -pedantic -std=gnu99 -Wall -Wextra main.c
./main

예를 들어 C 코드에 여러 줄 인라인 어셈블리를 삽입하는 데 사용할 수 있습니다. GCC C ++에서 여러 줄 인라인 어셈블리 코드를 작성하는 방법은 무엇입니까?

이제 C20XY에서 표준화 될 때까지 기다려야합니다.

C ++은 다음과 같은 질문을 받았습니다 : C ++ multiline string literal

Ubuntu 16.04, GCC 6.4.0, binutils 2.26.1에서 테스트되었습니다.


0

대안은 줄 바꿈을 제거하기 위해 모든 도구를 사용하는 것입니다. 텍스트 편집기를 사용하여 문자열을 작성하고 완료되면 여기에 텍스트를 붙여넣고 xcode로 다시 복사하십시오.


1
실제로 장기적인 해결책은 없습니다. 나중에 다시 변경해야하는 경우 이미 언급 한 멀티 라인 기술을 사용하여 파일에서 직접 형식을 지정하는 것이 더 빠르고 성가시다.
Schwarzie2478
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.