web-dev-qa-db-fra.com

Comment diviser un littéral de chaîne sur plusieurs lignes en C/Objective-C?

J'ai une assez longue requête 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";

Comment puis-je le séparer en plusieurs lignes pour en faciliter la lecture?

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

Je reçois une erreur.

Est-il possible d'écrire des requêtes sur plusieurs lignes?

297
Ilya Suzdalnitski

Il existe deux manières de fractionner des chaînes sur plusieurs lignes:

En utilisant \

Toutes les lignes en C peuvent être divisées en plusieurs lignes en utilisant \.

Plaine C:

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

Objectif c:

NSString *my_string = @"Line1 \
                        Line2";

Meilleure approche

Il existe une meilleure approche qui fonctionne uniquement pour les chaînes.

Plaine C:

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

Objectif c:

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

La deuxième approche est préférable, car les espaces ne sont pas nombreux. Cependant, pour une requête SQL, les deux sont possibles.

Remarque: avec un #define, vous devez ajouter un '\' supplémentaire pour concaténer les deux chaînes:

Plaine C:

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

Il y a une astuce que vous pouvez faire avec le pré-processeur.
Il a le potentiel d'être effondré et peut être source de confusion pour les lecteurs du code.
Mais, il a le côté positif que vous n'avez pas besoin d'échapper aux caractères de citation à l'intérieur.

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

le préprocesseur transforme cela en:

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

J'ai utilisé cette astuce lorsque j'écrivais des tests unitaires comportant de grandes chaînes littérales contenant du JSON. Cela signifiait que je n'avais pas à échapper à chaque caractère de citation\".

98
Nicholas Daley

Vous pouvez également aller dans XCode -> Préférences, sélectionner l’onglet Indentation et activer le retour à la ligne.

De cette façon, vous n'aurez plus besoin de taper quoi que ce soit, et cela fonctionnera pour ce que vous avez déjà écrit. :-)

Une chose ennuyante est cependant ...

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

J'ai ce problème tout le temps, alors j'ai créé un outil minuscule pour convertir du texte en chaîne Objective-C échappée multiligne:

http://multilineobjc.herokuapp.com/

J'espère que cela vous fait gagner du temps.

19
Flaviu

Extension du Citation idée pour Objective-C:

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

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

Une autre solution pour la pile, changez votre fichier .m en .mm afin qu'il devienne Objective-C++ et utilisez les littéraux bruts C++, comme ceci:

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

Les littéraux bruts ignorent tout jusqu'à la séquence de terminaison, qui dans le cas par défaut est parenthesis-quote.

Si la séquence de guillemets doit apparaître quelque part dans la chaîne, vous pouvez également spécifier un délimiteur personnalisé, comme ceci:

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

Vous pouvez aussi faire:

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

GCC ajoute des littéraux de chaîne brute multilignes C++ en tant qu'extension C

C++ 11 comporte des littéraux de chaîne bruts, comme indiqué à l'adresse: https://stackoverflow.com/a/44337236/895245

Cependant, GCC les ajoute également en tant qu’extension C, il suffit d’utiliser -std=gnu99 au lieu de -std=c99. Par exemple.:

principal c

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

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

Compiler et exécuter:

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

Cela peut être utilisé, par exemple, pour insérer un assemblage multiligne multiligne dans du code C: Comment écrire un code d'assemblage multiligne en ligne dans GCC C++?

Il ne vous reste plus qu'à vous allonger et attendre qu'il soit normalisé sur C20XY.

C++ a été interrogé à l'adresse: Littéral de chaîne multiligne C++

Testé sur Ubuntu 16.04, GCC 6.4.0, binutils 2.26.1.