Come dividere una stringa letterale su più righe in C / Objective-C?


321

Ho una query sqlite piuttosto lunga:

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

Come posso spezzarlo in più righe per facilitarne la lettura? Se faccio quanto segue:

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

Sto ricevendo un errore

C'è un modo per scrivere query su più righe?

Risposte:


569

Esistono due modi per dividere le stringhe su più righe:

Utilizzando \

Tutte le righe in C possono essere divise in più righe usando \.

Pianura C:

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

Objective-C:

NSString *my_string = @"Line1 \
                        Line2";

Approccio migliore

C'è un approccio migliore che funziona solo per le stringhe.

Pianura C:

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

Objective-C:

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

Il secondo approccio è migliore, perché non c'è molto spazio bianco incluso. Per una query SQL, tuttavia, entrambi sono possibili.

NOTA: Con un #define, devi aggiungere un '\' extra per concatenare le due stringhe:

Pianura C:

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

22
Entrambi sono gli stessi di in e C e C ++. Quest'ultima soluzione è preferita perché la prima incorpora molto spazio bianco inutile nel programma che verrà anche trasmesso al server DB.
Alnitak,

Ti manca un @ all'inizio della riga 2 nell'esempio Objective-C migliore.
Lawrence Johnston,

Hai un link a una specifica che documenta l'opzione del secondo @?
Heath Borders,

@HeathBorders: Non proprio qui, ma l'ho cercato quando ho scritto la risposta.
Georg Schölly,

10
Un altro vantaggio dell'approccio migliore è che puoi inserire // commenti dopo ogni riga.
Fishinear

110

C'è un trucco che puoi fare con il pre-processore.
Ha i potenziali lati negativi che collasserà lo spazio bianco e potrebbe essere fonte di confusione per le persone che leggono il codice.
Ma ha il lato positivo che non è necessario sfuggire ai caratteri di citazione al suo interno.

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

il preprocessore lo trasforma in:

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

Ho usato questo trucco quando stavo scrivendo alcuni test unit che avevano stringhe letterali di grandi dimensioni contenenti JSON. Significava che non dovevo scappare da ogni carattere di citazione \ ".


5
Perfetto! Ora ho solo bisogno di dare questo qualche centinaio di voti e farlo arrivare dove appartiene ...
Mike,

Stavo reagendo allo stesso modo, ma questo non è senza problemi. Ho appena provato a fare un ereditario in questo modo con un carattere Unicode speciale e ho avuto un errore sui caratteri non ASCII non consentiti al di fuori dei letterali.
philipkd,

+1 ma per la cronaca sto riscontrando problemi con il compilatore (MSVC) o l'editor (QtCreator) che non (ri) compilano l'espressione come dovrebbe cambiare. È come se il cambiamento non venisse rilevato ... Colpire Rebuild invece di Build fa il trucco.
Andreas,

Grazie per questa pepita di pollo di informazioni. Fa esattamente quello che dovevo fare senza tutta la spazzatura extra.
FishGuy876,

Questo purtroppo non funziona se nella stringa sono presenti virgolette letterali. Bene, in un certo senso funziona, in quanto genera un avvertimento. Ma la mia base di codice è -Werror ...
AnilRedshift

24

Puoi anche andare in XCode -> Preferenze, selezionare la scheda Rientro e attivare il ritorno a capo.

In questo modo, non dovrai digitare nulla in più e funzionerà per le cose che hai già scritto. :-)

Una cosa fastidiosa è però ...

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 Sono d'accordo, ma lo apprezzo anche. Mi sembra che questo commento non sarebbe stato veramente possibile come commento, quindi l'uso del formato di risposta. Sembra una limitazione di S / O, che non puoi scrivere commenti particolarmente ricchi (per quanto ne so).
Max von Hippel,

24

Ho sempre questo problema, quindi ho creato un piccolo strumento per convertire il testo in una stringa Objective-C multilinea con escape:

http://multilineobjc.herokuapp.com/

Spero che questo ti faccia risparmiare un po 'di tempo.


1
ottimo strumento! domanda: perché fuggi '|'?
justadreamer,

Buon punto. L'ho cambiato per non sfuggire più a "|". Grazie per avermi fatto sapere.
Flaviu,

Ho avuto la stessa idea. Vorrei averlo visto prima. Il mio strumento è: nsstringify.nateflink.com
Nate Flink,

1
Grazie, mi hai fatto risparmiare un sacco di tempo!
djskinner,

Prova a utilizzare il formato Clang (si integra con i tuoi editor preferiti): clang.llvm.org/docs/ClangFormat.html
Ahmed Fasih

18

Estensione dell'idea di preventivo per 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__dovrebbe funzionare anche.
Nicholas Daley,

Per stringhe mutabili: #define NSStringMultiline(...) [[NSMutableString alloc] initWithCString:#__VA_ARGS__ encoding:NSUTF8StringEncoding]
rimsky

Per me, la stringa risultante non ha nuove righe.
rimsky

Le nuove righe sfuggite vengono catturate correttamente (il che non è così conveniente o piacevole).
rimsky

@rimsky, e penso che funzioni #define NSStringMultiline(...) [@#__VA_ARGS__ mutableCopy]anche con stringhe mutabili.
Iulian Onofrei,

5

Un'altra soluzione per la pila, cambia il tuo file .m in .mm in modo che diventi Objective-C ++ e usi letterali grezzi C ++, in questo modo:

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

I letterali grezzi ignorano tutto fino alla sequenza di terminazione, che nel caso predefinito è la virgoletta.

Se la sequenza tra virgolette deve apparire nella stringa da qualche parte, puoi anche specificare facilmente un delimitatore personalizzato, come questo:

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

Ho anche scoperto che GCC aggiunge C ++ stringhe letterali prime come un'estensione al linguaggio C: stackoverflow.com/questions/797318/...
Ciro Santilli郝海东冠状病六四事件法轮功

3

Puoi anche fare:

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

2

GCC aggiunge letterali di stringa grezzi multilinea C ++ come estensione C.

C ++ 11 ha valori letterali di stringa non elaborati come indicato in: https://stackoverflow.com/a/44337236/895245

Tuttavia, GCC li aggiunge anche come estensione C, devi solo usare -std=gnu99invece di -std=c99. Per esempio:

main.c

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

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

Compila ed esegui:

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

Questo può essere usato, ad esempio, per inserire un assieme in linea multilinea nel codice C: Come scrivere un codice di assieme in linea multilinea in GCC C ++?

Ora devi solo rilassarti e aspettare che sia standardizzato su C20XY.

Il C ++ è stato chiesto a: C ++ stringa multilinea letterale

Testato su Ubuntu 16.04, GCC 6.4.0, binutils 2.26.1.


0

Un'alternativa è utilizzare qualsiasi strumento per rimuovere le interruzioni di riga. Scrivi la tua stringa usando qualsiasi editor di testo, una volta terminato, incolla qui il tuo testo e copialo nuovamente in xcode.


1
Nessuna soluzione a lungo termine. E se dovessi cambiarlo di nuovo più tardi. Ottieni fastidioso veloce, meglio usare le tecniche multilinea già menzionate e formattarlo direttamente nel file.
Schwarzie2478
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.