Jak dołączyć znak do std :: string?


175

Następujący błąd kończy się niepowodzeniem prog.cpp:5:13: error: invalid conversion from ‘char’ to ‘const char*’

int main()
{
  char d = 'd';
  std::string y("Hello worl");
  y.append(d); // Line 5 - this fails
  std::cout << y;
  return 0;
}

Spróbowałem również poniższego, który kompiluje się, ale zachowuje się losowo w czasie wykonywania:

int main()
{
  char d[1] = { 'd' };
  std::string y("Hello worl");
  y.append(d);
  std::cout << y;
  return 0;
}

Przepraszam za to głupie pytanie, ale przeszukałem google, zobaczyłem tylko „tablica znaków do tablicy znaków ptr”, „tablica znaków do tablicy znaków” itp.


błąd kompilatora tak ... Zapomniałem o błędzie, ale jest rozsądny.
drowneath

3
Poniżej masz lepsze odpowiedzi, ale możesz sprawić, że drugi przykład będzie działał jak ten char d [2] = {'d', 0}; lub po prostu char d [2] = "d"; Zasadniczo potrzebujesz 0, aby zakończyć ciąg w stylu c, który przekazujesz, aby dołączyć
sbk

Odpowiedzi:


225
y += d;

Użyłbym +=operatora zamiast nazwanych funkcji.


2
dlaczego uważasz, że + = lepsze niż push_back? Czy to po prostu mniej pisania, czy masz inny powód?
Glen,

4
To mniej pisania. W gcc, basic_string::operator+=to tylko wezwanie push_back.
Eduffy

2
Jest to bardziej naturalne IMO dla strun. push_back to funkcja kontenera, a ciąg znaków jest wyspecjalizowany w STL :)
AraK

6
Odwróćmy to pytanie: dlaczego uważasz, że push_back jest lepsze niż + =? Moim zdaniem + = jest jasne i zwięzłe.
Jesper

34
Chcesz być ostrożny, ponieważ jeśli nabędziesz przyzwyczajenia, kompilacja będzie dobrze, jeśli yjest to char*zamiast std::string. Dodałby dznaki do wskaźnika y.
Zan Lynx,


19

Aby dodać znak do zmiennej std :: string przy użyciu metody append, musisz użyć tego przeciążenia:

std::string::append(size_type _Count, char _Ch)

Edycja: Masz rację Źle zrozumiałem parametr size_type, wyświetlany w pomocy kontekstowej. To jest liczba znaków do dodania. Więc prawidłowe połączenie to

s.append(1, d);

nie

s.append(sizeof(char), d);

Lub najprościej:

s += d;

Myślę, że użycie sizeof nie jest tutaj semantycznie poprawne (chociaż zdarza się, że działa, ponieważ sizeof (char) jest zawsze jeden). Metoda dołączania jest oczywiście bardziej użyteczna, jeśli chcesz dołączyć więcej kopii tego samego znaku !!!!!!!!!!
UncleBens

1
Dlaczego używasz sizeof(char)zamiast 1? Chcesz dodać dokładnie jedno powtórzenie d, więc powiedz to. Używanie sizeoftutaj jest mylące, ponieważ sugeruje, że należy podać appendrozmiar bajtu używanego typu danych (co nie ma miejsca).
Ferdinand Beyer

Jak powiedział Unclebens, metoda dołączania jest naprawdę bardziej użyteczna przy wielokrotnym dodawaniu tego samego znaku.
Patrice Bernassola

10

Oprócz innych wymienionych konstruktorów, jeden z konstruktorów łańcuchów przyjmuje znak i liczbę powtórzeń tego znaku. Możesz więc użyć tego do dołączenia pojedynczego znaku.

std::string s = "hell";
s += std::string(1, 'o');

7

Testuję kilka propozycji, uruchamiając je w dużej pętli. Użyłem Microsoft Visual Studio 2015 jako kompilatora, a mój procesor to i7, 8Hz, 2GHz.

    long start = clock();
    int a = 0;
    //100000000
    std::string ret;
    for (int i = 0; i < 60000000; i++)
    {
        ret.append(1, ' ');
        //ret += ' ';
        //ret.push_back(' ');
        //ret.insert(ret.end(), 1, ' ');
        //ret.resize(ret.size() + 1, ' ');
    }
    long stop = clock();
    long test = stop - start;
    return 0;

Zgodnie z tym testem wyniki są następujące:

     operation             time(ms)            note
------------------------------------------------------------------------
append                     66015
+=                         67328      1.02 time slower than 'append'
resize                     83867      1.27 time slower than 'append'
push_back & insert         90000      more than 1.36 time slower than 'append'

Wniosek

+= wydaje się bardziej zrozumiałe, ale jeśli myślisz o szybkości, użyj dołączania


Aby taka odpowiedź miała znaczenie, powinieneś przynajmniej powiedzieć, jakiego kompilatora używasz, ponieważ takie rzeczy mogą się bardzo różnić. Opowiadanie o procesorze też może być świetne, aby uzyskać przybliżone oszacowanie rzeczywistego wpływu, jaki może to mieć.
akaltar

Użyłem Visual Studio 2015. Poszukam gcc, żeby zrobić kilka innych testów. Mój procesor to i7, 8 serc, 2,20 GHz ... Ale niezależnie od tego, jaki jest mój procesor, nie będzie to miało wpływu na implementację std :: string ... chyba że niektóre z tych metod są wielowątkowe, a inne nie.
Hugo Zevetel

Czasami ma to wpływ, zwłaszcza jeśli wyświetlasz czasy w milisekundach. Zamiast tego możesz pokazać w procentach w stosunku do najszybszej metody (więc rzeczywista prędkość procesora nie ma znaczenia) Przenieś również te dane z komentarza do odpowiedzi, to tylko ogólna etykieta StackExchange. W przeciwnym razie miła odpowiedź.
akaltar


2

problem z:

std::string y("Hello worl");
y.push_back('d')
std::cout << y;

polega na tym, że musisz mieć „d”, a nie nazwę znaku, jak char d = „d”; A może się mylę?


Po prostu spróbowałem i zadziałało dobrze. Mam char c = 'd'i mogę obejść się y.push_back(c)bez problemu. Nie ma więc problemu z std::string::push_back()(poza tym, że jest dłuższy niż +=).
Franklin Yu

1
int main()
{
  char d = 'd';
  std::string y("Hello worl");

  y += d;
  y.push_back(d);
  y.append(1, d); //appending the character 1 time
  y.insert(y.end(), 1, d); //appending the character 1 time
  y.resize(y.size()+1, d); //appending the character 1 time
  y += std::string(1, d); //appending the character 1 time
}

Należy zauważyć, że we wszystkich tych przykładach mogłeś stosować znak literalny bezpośrednio: y += 'd';.

Twój drugi przykład prawie by zadziałał z niepowiązanych powodów. char d[1] = { 'd'};nie działa, ale char d[2] = { 'd'};(uwaga tablica jest rozmiar dwa) byłby pracował w przybliżeniu taka sama jak const char* d = "d";i ciągiem znaków mogą być dołączone: y.append(d);.


1

Spróbuj użyć d jako wskaźnika y.append (* d)


Jest to niebezpieczne, ponieważ pojedynczy charnie jest łańcuchem i nie ma terminatora zerowego. Takie postępowanie powoduje niezdefiniowane zachowanie.
Simon Kraemer

To jest po prostu złe. *doznacza wskaźnik usuwania referencji, dktóry jest błędem składniowym, ponieważ dnie jest wskaźnikiem.
Franklin Yu

0
str.append(10u,'d'); //appends character d 10 times

Zauważ, że napisałem 10u, a nie 10, ile razy chciałbym dodać znak; zastąp 10 dowolną liczbą.


0

Znalazłem prosty sposób ... Musiałem założyć charsznur, który był budowany w locie. Potrzebowałem, char list;ponieważ dawałem użytkownikowi wybór i użyłem tego wyboru w switch()oświadczeniu.

Po prostu dodałem kolejny std::string Slist;i ustawiłem nowy ciąg na równy znakowi, "liście" - a, b, c lub cokolwiek wybierze użytkownik końcowy, w ten sposób:

char list;
std::string cmd, state[], Slist;
Slist = list; //set this string to the chosen char;
cmd = Slist + state[x] + "whatever";
system(cmd.c_str());

Złożoność może być fajna, ale prostota jest fajniejsza. moim zdaniem


0

Dodanie również opcji wstawiania, o czym jeszcze nie wspomniano.

std::string str("Hello World");
char ch;

str.push_back(ch);  //ch is the character to be added
OR
str.append(sizeof(ch),ch);
OR
str.insert(str.length(),sizeof(ch),ch) //not mentioned above

-1

Jeśli używasz push_back, nie ma wywołania konstruktora ciągu. W przeciwnym razie utworzy obiekt łańcuchowy poprzez rzutowanie, a następnie doda znak w tym ciągu do innego ciągu. Za dużo kłopotu dla malutkiej postaci;)


1
operator + = (char c); jest przeciążony dla ciągów. W rzeczywistości konstruktor napisów nie akceptuje jednego znaku, patrz odpowiedź Briana;)
AraK
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.