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 #?

È stato utile?

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.

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