如何在C / Objective-C中的多行中分割字符串文字?


319

我有一个很长的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";

我收到一个错误。

有没有办法在多行中编写查询?

Answers:


568

有两种将字符串拆分为多行的方法:

使用\

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行的开头缺少@。
劳伦斯·约翰斯顿

您是否有链接到规范的文档,该规范记录了第二个规范的可选性@
Heath Borders'6年

@HeathBorders:不在这里,但是我在写答案时一直在查询。
GeorgSchölly2012年

10
更好的方法的另一个优点是,您可以在每行之后加上//注释。
fishinear 2013年

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

我的反应也一样,但这并非没有问题。我只是尝试用特殊的Unicode字符用这种方式做一个Heredoc,但遇到了一个错误,即不允许在文字范围之外使用非ASCII字符。
philipkd

+1,但为记录起见,我在编译器(MSVC)或编辑器(QtCreator)遇到问题时,没有(重新)编译表达式,因为表达式应该更改。就像没有检测到更改一样。
安德烈亚斯(Andreas)

感谢您提供的鸡块信息。它完全可以执行我需要做的所有工作,而没有所有额外的垃圾。
FishGuy876 '19

不幸的是,如果字符串中有文字引号,则此操作将无效。嗯,这是可行的,因为它会产生警告。但是我的代码库是-Werror ...
AnilRedshift,

24

您也可以进入XCode-> Preferences,选择Indentation标签,然后打开Line Wrapping。

这样,您无需键入任何其他内容,它将对您已经编写的内容起作用。:-)

一件令人讨厌的事情是...

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 2012年

好点子。我将其更改为不再转义“ |”。谢谢你让我知道。
Flaviu 2012年

我有同样的想法。希望我能先看到这一点。我的工具是:nsstringify.nateflink.com
Nate Flink

1
谢谢,为我节省了很多时间!
djskinner 2013年

尝试使用Clang格式(与您喜欢的编辑器集成):clang.llvm.org/docs/ClangFormat.html
Ahmed 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__应该也可以。
尼古拉斯·戴利

对于可变字符串: #define NSStringMultiline(...) [[NSMutableString alloc] initWithCString:#__VA_ARGS__ encoding:NSUTF8StringEncoding]
rimsky 2015年

对我来说,结果字符串没有新行。
2015年

转义的换行符被正确捕获(这不太方便或不错)。
rimsky 2015年

@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 ++多行字符串文字

在Ubuntu 16.04,GCC 6.4.0,binutils 2.26.1上进行了测试。


0

一种替代方法是使用任何工具删除换行符。使用任何文本编辑器编写字符串,完成后,将文本粘贴到此处,然后再次将其复制到xcode中。


1
没有真正的长期解决方案。如果以后必须再次更改该怎么办。快速获取烦恼,最好使用已经提到的多行技术,并将其直接格式化为文件格式。
Schwarzie2478
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.