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

如何在C/Objective-C中跨多行拆分字符串文字?,c,objective-c,C,Objective C,我有一个很长的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

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


有没有一种方法可以在多行中写入查询?

有两种方法可以在多行中拆分字符串:

使用\ 使用\,可以将C中的所有行拆分为多行

普通C:

char *my_string = "Line 1 \
                   Line 2";
char *my_string = "Line 1 "
                  "Line 2";
#define kMyString "Line 1"\
                  "Line 2"
目标C:

NSString *my_string = @"Line1 \
                        Line2";
NSString *my_string = @"Line1 "
                       "Line2";    // the second @ is optional
#define NSStringMultiline(...) [[NSString alloc] initWithCString:#__VA_ARGS__ encoding:NSUTF8StringEncoding]

NSString *sql = NSStringMultiline(
    SELECT name, age
    FROM users
    WHERE loggedin = true
);
更好的方法 有一种更好的方法只适用于字符串

普通C:

char *my_string = "Line 1 \
                   Line 2";
char *my_string = "Line 1 "
                  "Line 2";
#define kMyString "Line 1"\
                  "Line 2"
目标C:

NSString *my_string = @"Line1 \
                        Line2";
NSString *my_string = @"Line1 "
                       "Line2";    // the second @ is optional
#define NSStringMultiline(...) [[NSString alloc] initWithCString:#__VA_ARGS__ encoding:NSUTF8StringEncoding]

NSString *sql = NSStringMultiline(
    SELECT name, age
    FROM users
    WHERE loggedin = true
);
第二种方法更好,因为没有太多的空格。但是,对于SQL查询,两者都是可能的

注意:使用#define,您必须添加额外的“\”来连接两个字符串:

普通C:

char *my_string = "Line 1 \
                   Line 2";
char *my_string = "Line 1 "
                  "Line 2";
#define kMyString "Line 1"\
                  "Line 2"
您还可以执行以下操作:

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

您还可以进入XCode->Preferences,选择缩进选项卡,然后打开换行

这样,您就不必键入任何额外的内容,而且它将适用于您已经编写的内容。:-)

但有一件恼人的事是

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
}

我一直都有这个问题,所以我制作了一个小工具,将文本转换为转义的多行Objective-C字符串:


希望这能为您节省一些时间。

您可以使用预处理器完成一个技巧。
它有潜在的负面影响,它会压缩空白,并且可能会让阅读代码的人感到困惑。
但是,它有一个优点,即不需要在其中转义引号字符

#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的大型文本字符串的单元测试时使用了这个技巧。这意味着我不必转义每个引号字符\“

扩展Objective-C的概念:

NSString *my_string = @"Line1 \
                        Line2";
NSString *my_string = @"Line1 "
                       "Line2";    // the second @ is optional
#define NSStringMultiline(...) [[NSString alloc] initWithCString:#__VA_ARGS__ encoding:NSUTF8StringEncoding]

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

一个解决方案,将.m文件改为.mm,使其成为Objto-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";
原始文本忽略所有内容,直到终止序列(默认情况下为括号引号)结束

如果括号引号序列必须出现在字符串的某个位置,也可以轻松指定自定义分隔符,如下所示:

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扩展<强/> /P> C++11具有原始字符串文字,如下所述:

但是,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);
}
例如,这可用于在C代码中插入多行内联程序集:

现在你只需要放松,等待它在C20XY上标准化

C++被问及:



在Ubuntu 16.04、GCC 4.4.0、BiUTILLS 2.21.1./P>> P>上进行测试,使用任何工具来消除断线。使用任何文本编辑器编写字符串,完成后,粘贴文本并在XCODE中再次复制。< / P>这两个都与IN和C和C++相同。后者的解决方案是首选的,因为前者嵌入了大量的使用。程序中的空白更少,也将传输到DB服务器。在better Objective-C示例中,第2行的开头缺少@。是否有一个指向规范的链接,该规范记录了第二个

@
的可选性?更好方法的另一个优点是,您可以在每行后面添加//注释。second方法在两行之间插入
\n
\r\n
?很棒的工具!问题:为什么要转义“|”?很好。我将它改为不再转义“|”。谢谢你让我知道。我有同样的想法。希望我能先看到这个。我的工具是:谢谢,为我节省了很多时间!尝试使用叮当格式(与您喜爱的编辑器集成):太好了!现在我只需要再给它几百次投票,然后把它放在它应该放的地方…我的反应是一样的,但这不是没有问题的。我只是用一个特殊的Unicode字符用这种方式做了一个heredoc,但得到了一个错误,非ASCII字符不允许在文本之外。+1但对于记录,我有tr与编译器(MSVC)或编辑器(QtCreator)不兼容(re)在发生更改时按原样编译表达式。这就像未检测到更改一样…点击“重建”而不是“生成”就可以了。感谢您提供的这些宝贵信息。它完全符合我需要的操作,没有所有额外的垃圾。不幸的是,如果字符串中有文字引号,则此操作不起作用。嗯,它有点f可以工作,因为它会生成一个警告。但是我的代码库是-Werror…
#define NSStringMultiline(…)@#uu VA_uargs uu
应该也可以工作。对于可变字符串:
#define NSStringMultiline(…)[[NSMutableString alloc]initWithCString:#uu VA_uargs u编码:NSUTF8StringEncoding]
对我来说,生成的字符串没有新行。转义的新行被正确捕获(这几乎不是那么方便或好)。@rimsky,我认为
#定义NSStringMultiline(…)[@#
也适用于可变字符串。@YoYoYonnY我同意,但我也很感激。我觉得这个注释不可能真正成为注释,因此使用了应答格式。这似乎是S/O的一个限制,你不能写特别丰富的注释(据我所知)还发现GCC将C++原始字符串文字添加到C语言的扩展:没有一个长期的解决方案。如果你必须在以后再修改它。如果快得多,最好使用已经提到的多行技术,并直接在文件中格式化。