webentwicklung-frage-antwort-db.com.de

Wie teilt man ein String-Literal in C/Objective-C auf mehrere Zeilen auf?

Ich habe eine ziemlich lange SQLite-Abfrage:

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";

Wie kann ich es in mehrere Zeilen aufteilen, um das Lesen zu erleichtern?

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

Ich bekomme einen Fehler.

Gibt es eine Möglichkeit, Abfragen in mehreren Zeilen zu schreiben?

297

Es gibt zwei Möglichkeiten, Strings über mehrere Zeilen aufzuteilen:

Verwenden von \

Alle Zeilen in C können mit\in mehrere Zeilen aufgeteilt werden.

Einfaches C:

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

Ziel c:

NSString *my_string = @"Line1 \
                        Line2";

Besserer Ansatz

Es gibt einen besseren Ansatz, der nur für Saiten funktioniert.

Einfaches C:

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

Ziel c:

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

Der zweite Ansatz ist besser, weil nicht viel Leerraum enthalten ist. Bei einer SQL-Abfrage sind jedoch beide möglich.

HINWEIS: Mit einem #define müssen Sie ein zusätzliches '\' hinzufügen, um die beiden Zeichenfolgen zu verketten:

Einfaches C:

#define kMyString "Line 1"\
                  "Line 2"
532
Georg Schölly

Es gibt einen Trick, den Sie mit dem Pre-Prozessor machen können.
.__ Es hat die Nachteile, dass es Leerzeichen zusammenbricht und für Leute, die den Code lesen, verwirrend sein könnte.
Aber es hat den Vorteil, dass Sie keine Anführungszeichen mit Escapezeichen versehen müssen.

#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
);

der Präprozessor macht dies zu:

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

Ich habe diesen Trick verwendet, als ich einige Komponententests mit großen literalen Strings mit JSON geschrieben habe. Das bedeutete, dass ich nicht jedem Anführungszeichen\"entgehen musste.".

98
Nicholas Daley

Sie können auch in XCode -> Voreinstellungen wechseln, die Registerkarte Einzug auswählen und Zeilenumbruch aktivieren.

Auf diese Weise müssen Sie nichts extra eingeben, und es funktioniert für das, was Sie bereits geschrieben haben. :-)

Eine nervige Sache ist jedoch ...

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
}
25
DenverCoder9

Ich habe dieses Problem die ganze Zeit, also habe ich ein winziges Werkzeug zum Konvertieren von Text in einen mehrzeiligen Objective-C-String erstellt:

http://multilineobjc.herokuapp.com/

Ich hoffe, das erspart Ihnen etwas Zeit.

19
Flaviu

Erweiterung der Quote Idee für Objective-C:

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

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

Eine weitere Lösung für den Stapel, ändern Sie Ihre .m-Datei in .mm, sodass sie zu Objective-C++ wird, und verwenden Sie C++ - Rohliterale wie folgt:

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

Rohliterale ignorieren alles bis zur Beendigungssequenz, die im Standardfall in Klammern steht.

Wenn die Klammer-Anführungszeichenfolge irgendwo in der Zeichenfolge erscheinen muss, können Sie problemlos auch ein benutzerdefiniertes Trennzeichen angeben:

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";
5
John Stephen

Sie können auch tun:

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

GCC fügt mehrzeilige C++ - Rohzeichenfolgenliterale als C-Erweiterung hinzu

C++ 11 enthält rohe String-Literale, wie unter: https://stackoverflow.com/a/44337236/895245 beschrieben.

GCC fügt sie jedoch auch als C-Erweiterung hinzu. Sie müssen lediglich -std=gnu99 anstelle von -std=c99 verwenden. Z.B.:

haupt c

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

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

Kompilieren und ausführen:

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

Dies kann zum Beispiel verwendet werden, um Multiline-Inline-Assembly in C-Code einzufügen: Wie schreibe ich Multiline-Inline-Assembly-Code in GCC C++?

Jetzt müssen Sie sich nur zurücklehnen und warten, bis C20XY standardisiert ist.

C++ wurde gefragt: Multiline-Stringliteral für C++

Getestet auf Ubuntu 16.04, GCC 6.4.0, binutils 2.26.1.