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.