È possibile concatenare una stringa letterale e una letterale di carattere?
Domanda
Perché name
si comporta in modo errato nel seguente codice C ++?
string name = "ab"+'c';
Come si comporterebbe il codice equivalente in Java / C #?
Soluzione
Prova
std::string name = "ab" "c";
o
std::string name = std::string("ab") + c;
In C ++, " ab " non è un std::string
, ma piuttosto un puntatore a una stringa di caratteri. Quando aggiungi un valore integrale a un puntatore, ottieni un nuovo puntatore che punta più in basso nella stringa:
char *foo = "012345678910121416182022242628303234";
std::string name = foo + ' ';
name
viene impostato su " 3234 " ;, poiché il valore intero di '' è 32 e 32 caratteri oltre l'inizio di foo è di quattro caratteri prima della fine della stringa. Se la stringa fosse più corta, proveresti ad accedere a qualcosa in un territorio di memoria indefinito.
La soluzione a questo è di creare una stringa std: dall'array di caratteri. std: le stringhe ti consentono di aggiungere caratteri come previsto:
std::string foo = "012345678910121416182022242628303234";
std::string name = foo + ' ';
<=> viene impostato su " 012345678910121416182022242628303234 "
Altri suggerimenti
Il problema è che " ab " non è un C ++ std::string
, ma un const char[3]
.
Quindi l'operatore + che sta cercando è operator+ (const char[3], char)
. Non esiste, quindi il compilatore prova a far decadere l'array in un puntatore, quindi cerca operator+ (const char*, char)
. Questo esiste, quindi il compilatore lo sceglie, ma fa la cosa sbagliata. L'aggiunta di un valore integrale (il carattere) a un puntatore (il carattere const *) è un'operazione abbastanza comune e, ovviamente, è ciò che fa questo operatore +. La chiave per comprenderlo è rendersi conto che il primo argomento è 1) una matrice e 2) un puntatore ogni volta che la matrice non ha senso. Era usato anche come stringa in C, sì, ma non è una stringa. È un puntatore (o occasionalmente, un array).
C'è un operator+ (const std::string&, char)
che concatena, ma il compilatore non lo cercherà nemmeno, perché il primo argomento non è uno std :: string.
Quindi una soluzione è creare manualmente la stringa:
string name = std::string("ab")+'c';
Ora il compilatore può capire l'operatore corretto + da chiamare.
In C ++, il compilatore sta cercando una funzione con questo prototipo:
T operator+ (const char*, char);
Dato che non ce n'è uno, non riesce a capire cosa sia T e non può risolvere la chiamata operator<<
, quindi ricade sull'unica soluzione rimasta: l'aggiunta del puntatore. Non vi è alcun problema con la catenizzazione di una stringa come nella risposta di Josh, perché esiste una funzione per essa.
Dato il codice C ++:
std::string name = "ab"+'c';
L'equivalente in Java è:
String name = "ab".substring('c');
Entrambi promuovono il carattere a int. Ovviamente in Java viene controllato il range e quindi genera un'eccezione. In C ++ ottieni un comportamento indefinito (o qualcosa del genere).
Java:
public class Main
{
public static void main(String[] args)
{
System.out.println("AB" + 'c');
}
}
L'output è:
ABC
Modifica:
In realtà il compilatore codifica in modo rigido String ABc ...
Se si fa " AB " + argv [0] .charAt (0); per farlo usare una variabile, allora il compilatore lo fa (sostanzialmente):
StringBuilder b = new StringBuilder;
b.append("AB");
b.append(argv[0].charAt(0));
System.out.println(b.toString());
Puoi concatenare stringhe e caratteri in C # - non è rigoroso come C ++ immagino.
Funziona bene in C #:
string test = "foo" + 'b';
Un compilatore C ++ non concatena automaticamente i letterali di stringa con i letterali di carattere. Ma concatenerà letteralmente stringhe tra loro. La sintassi è così:
const char * cs = "ab" "c"; // append string-literals
Come altri hanno già detto, string
non è un tipo di linguaggio C ++ incorporato . Ma esiste un tipo <=> nella libreria standard C ++. Ecco alcuni esempi di utilizzo:
#include <string>
const char * cs = "ab" "c";
std::string s1( cs );
std::string s2( "ab" "c" );
std::string s3 = "ab" "c";
Bene, quello che di solito farei in C ++ è
string name = string (" ab ") + 'c';
Ricorda che il letterale " ab " è non di tipo stringa. Quello che stavi facendo era sperare che non ci fosse & Quot; + & Quot; che funziona tra array di caratteri e caratteri e quindi sperando che il compilatore possa in qualche modo notare che si desidera davvero che il risultato sia uno std :: string, quindi analizzare la propria espressione sul lato destro per una combinazione di conversioni implicite che potrebbero combinare con l'operatore / i per produrre un risultato di quel tipo. Mi sembra un ordine piuttosto alto.
Indipendentemente da ciò, non importa. Vedete, in C l'unica differenza tra un array e un puntatore è come viene allocata la loro memoria. Una volta che ne hai uno, essenzialmente hai una & Quot; matrice / puntatore cosa & Quot ;. Pertanto & Quot; + & Quot; è un operatore definito su tutti gli array e i puntatori, che accetta un altro argomento di qualsiasi tipo intero e esegue la matematica del puntatore, restituendo un puntatore a molti elementi oltre quel punto. Inoltre, in C & Quot; char & Quot; è davvero solo un altro tipo di tipo intero. Queste decisioni di progettazione in C sono state entrambe utili hack , ma come spesso accade con gli hack, si combinano con risultati intuitivamente inaspettati. Quindi tutti & Quot; ab & Quot; + 'c' fa per te è restituire un indirizzo di 99 byte oltre ovunque " ab " letterale sembra essere archiviato in memoria.
A volte puoi fare affidamento su conversioni implicite, ma devi essere davvero pronto ad aiutare il tuo compilatore un po 'altre volte.