Domanda

Sono stato recentemente morso da un bug sottile.

char ** int2str = {
   "zero", // 0
   "one",  // 1
   "two"   // 2
   "three",// 3
   nullptr };

assert( int2str[1] == std::string("one") ); // passes
assert( int2str[2] == std::string("two") ); // fails

Se hai i poteri di recensione del codice divino noterai che ho dimenticato il , dopo "two".

Dopo il considerevole sforzo per trovare quel bug che devo chiedere Perché qualcuno dovrebbe mai desiderare questo comportamento?

Vedo come questo potrebbe essere utile per la magia macro, ma allora perché è una "caratteristica" in un linguaggio moderno come Python?

Hai mai usato la concatenazione letterale delle stringhe nel codice di produzione?

È stato utile?

Soluzione

Ne vedo diversi C e C ++ risposte ma nessuna delle risposte veramente perché O davvero qual era la logica di questa funzione? In C ++ questa è la funzione proviene da C99 E possiamo trovare la logica per questa funzione andando a Razionale per lo standard internazionale - lingue di programmazione - C sezione 6.4.5 Letterali a corda che dice (enfasi la mia):

Una stringa può essere continuata su più righe utilizzando la continuazione della linea di retro -new -line, ma ciò richiede che la continuazione della stringa inizi nella prima posizione della riga successiva. Per consentire layout più flessibile, e per risolvere alcuni problemi di preelaborazione (vedere §6.10.3), il comitato C89 ha introdotto la concatenazione letterale delle stringhe. I letterali a due corde di fila vengono incollati insieme, senza carattere nullo nel mezzo, per rendere letterale una corda combinata. Questa aggiunta alla lingua C consente a un programmatore di estendere una stringa letterale oltre la fine di una linea fisica senza dover usare il meccanismo di backslash -newlline e quindi distruggere lo schema di rientro del programma. Non è stato introdotto un operatore di concatenazione esplicito perché la concatenazione è un costrutto lessicale piuttosto che un'operazione di runtime.

Pitone che sembra avere lo stesso motivo, questo riduce la necessità di brutto \ Per continuare i letterali a corde lunghe. Che è coperto nella sezione 2.4.2 Concatenazione letterale delle corde delIl riferimento in lingua Python.

Altri suggerimenti

Certo, è il modo semplice per rendere il tuo codice buono:

char *someGlobalString = "very long "
                         "so broken "
                         "onto multiple "
                         "lines";

Il motivo migliore, tuttavia, è per strani formati di stampa, come il tipo di forza:

uint64_t num = 5;
printf("Here is a number:  %"PRIX64", what do you think of that?", num);

Ci sono un sacco di quelli definiti e possono tornare utili se hai requisiti di dimensione del tipo. Controllali tutti A questo link. Alcuni esempi:

PRIo8 PRIoLEAST16 PRIoFAST32 PRIoMAX PRIoPTR

È un'ottima caratteristica che ti consente di combinare stringhe preprocessore con le stringhe.

// Here we define the correct printf modifier for time_t
#ifdef TIME_T_LONG
    #define TIME_T_MOD "l"
#elif defined(TIME_T_LONG_LONG)
    #define TIME_T_MOD "ll"
#else
    #define TIME_T_MOD ""
#endif

// And he we merge the modifier into the rest of our format string
printf("time is %" TIME_T_MOD "u\n", time(0));

Casi in cui ciò può essere utile:

  • Generare stringhe tra cui componenti definiti dal preprocessore (questo è forse il più grande caso d'uso in C, ed è quello che vedo molto, molto frequentemente).
  • Costanti di stringa di suddivisione su più righe

Per fornire un esempio più concreto per il primo:

// in version.h
#define MYPROG_NAME "FOO"
#define MYPROG_VERSION "0.1.2"

// in main.c
puts("Welcome to " MYPROG_NAME " version " MYPROG_VERSION ".");

Dal riferimento di analisi lessicale di Python, Sezione 2.4.2:

Questa funzione può essere utilizzata per ridurre il numero di backsheshes necessarie, per dividere le stringhe lunghe comodamente su linee lunghe o persino per aggiungere commenti a parti di corde

http://docs.python.org/reference/lexical_analysis.html

Non sono sicuro di altri linguaggi di programmazione, ma ad esempio C# non ti consente di farlo (e penso che questa sia una buona cosa). Per quanto ne so, la maggior parte degli esempi che mostrano perché questo è utile in C ++ funzionerebbe comunque se si potesse usare un operatore speciale per la concatenazione delle stringhe:

string someGlobalString = "very long " +
                          "so broken " +
                          "onto multiple " +
                          "lines"; 

Questo potrebbe non essere così comodo, ma è certamente più sicuro. Nel tuo esempio motivante, il codice non sarebbe valido a meno che tu non abbia aggiunto , a separare elementi o + per concatenare le corde ...

In modo che tu possa dividere i letterali a corda lunga attraverso le righe.

E sì, l'ho visto nel codice di produzione.

Per la logica, espandere e semplificare la risposta di Shafik Yaghmour: la concatena letterale della stringa ha avuto origine in C (quindi ereditata da C ++), come ha fatto il termine, per due motivi (i riferimenti provengono da Razionale per il linguaggio di programmazione Ansi C):

  • Per la formattazione: per consentire ai letterali a corde lunghe di abbracciare più linee con un corretto rientro - in contrasto con la continuazione della linea, che distrugge lo schema di rientro (3.1.4 LETTERALI SGRICHE); e
  • Per macro magia: consentire la costruzione di letterali di stringa da macro (tramite Stringizing) (3.8.3.2 l'operatore #).

È incluso nelle lingue moderne Python e D perché lo hanno copiato da C, sebbene in entrambi questi sia stato proposto per la deprecazione, in quanto è soggetto a bug (come noti) e inutili (dal momento che si può solo avere una concatenazione operatore e piegatura costante per la valutazione a tempo di compilazione; Non puoi farlo in C perché le corde sono puntatori e quindi non puoi aggiungerli).

Non è semplice da rimuovere perché interrompe la compatibilità e devi stare attento alla precedenza (la concatenazione implicita si verifica durante lexing, prima degli operatori, ma sostituirlo con un operatore significa che devi fare attenzione alla precedenza), quindi perché è ancora presente .

Sì, è nel codice di produzione usato. Guida in stile Google Python: Lunghezza della linea Specifica:

Quando una stringa letterale non si adatta a una singola riga, usa parentesi per unione implicita della linea.

x = ('This will build a very long long '
     'long long long long long long string')

Vedere "String Concatenazione letterale"A Wikipedia per maggiori dettagli e riferimenti.

Ho certamente in C e C ++. Non vedo, non vedo molte relazioni tra la sua utilità e quanto sia "moderna" la lingua.

Mentre le persone hanno tolto le parole dalla bocca sugli usi pratici della funzione, nessuno ha finora cercato di difendere la scelta della sintassi.

Per quanto ne so, l'errore di battitura che può scivolare attraverso di conseguenza è stato probabilmente solo trascurato. Dopotutto, sembra che la robustezza contro gli errori di battitura non fosse davanti alla mente di Dennis, come mostrato ulteriormente da:

if (a = b);
{
    printf("%d", a);
}

Inoltre, c'è la possibile visione che non valesse la pena usare un simbolo extra per la concatenazione dei letterali a stringa - dopo tutto, non c'è molto altro che può essere fatto con due di essi e avere un simbolo potrebbe creare tentazioni a Prova a usarlo per la concatenazione delle stringhe di runtime, che è al di sopra del livello delle funzionalità integrate di C.

Alcune lingue moderne e di livello superiore basate sulla sintassi C hanno scartato questa notazione presumibilmente perché è non propensione. Ma queste lingue hanno un operatore per la concatenazione delle stringhe, come + (JS, C#), . (Perl, PHP), ~ (D, sebbene ciò abbia anche mantenuto la sintassi della giustapposizione di C) e una piegatura costante (nei linguaggi compilati, comunque) significa che non esiste un sovraccarico di prestazioni di runtime.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top