• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

( string+=int ) != ( string = string + int ) ????

Object Storage Arubacloud
0 głosów
718 wizyt
pytanie zadane 23 listopada 2016 w C i C++ przez String Gaduła (4,520 p.)

Cześć :)
Napisałem prosty, króciutki program:

//TEST
#include <iostream>
#include <string>
using namespace std;

int main()
{
    int n;
    string word;
    int number; // 0<=n<=9
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>number;
        word+=number+48;
    }

    cout<<word;

	return 0;
}

 

Zadaniem programu jest wypisanie liczb z przedziału <0,9> w kolejności, w której poda te liczby użytkownik, który na początku ustala ile liczb chce wpisać.
Proste? proste.

Istotne jest to, że dany ciąg ma być przedstawiony w postaci jednego wyrazu.
 

Dla n=5; number: 1, 2, 3, 4, 5;

Chcę otrzymać: "12345"

 

Program działa, jednakże zastanawia mnie dlaczego zapis zawarty w tytule jest prawdziwy.

Kiedy zamiast: 

word+=number+48;

Wpiszę: 

word=word+number+48;

Kompilator wyrzuca błąd.
Mógłby mi ktoś wytłumaczyć dlaczego tak się dzieje?? Ogólnie rzecz biorąc a+=b to to samo co, a=a+b, także nie rozumiem.

error: no match for 'operator+' (operand types are 'std::__cxx11::string(...)

3 odpowiedzi

+1 głos
odpowiedź 23 listopada 2016 przez niezalogowany
wybrane 23 listopada 2016 przez String
 
Najlepsza

Spróbuj tak:

word=word+char(number+48);

 

komentarz 23 listopada 2016 przez String Gaduła (4,520 p.)
I wszystko jasne.
Ostatecznie podczas I sposobu, rzutowanie odbywa się automatycznie po prostu, tak?
komentarz 23 listopada 2016 przez niezalogowany
Tak dokładnie.
komentarz 23 listopada 2016 przez String Gaduła (4,520 p.)
Dzięki :)
komentarz 23 listopada 2016 przez niezalogowany

Ja jak jeszcze nie znałem rzutowań miałem taki problem:
 

#include <iostream>
#include <math.h>
using namespace std;

int main()
{
    double n=200; // cos super mega skomplikowanego
    cout<<pow(n, 1/2)<<endl; // kompilator potraktowal 1 i 2 jako inty - podzielil jak inty czyli z 1/2 wyszlo 0
    cout<<pow(n, double(1/2)<<endl;
    // prawidlowy wynik:
    cout<<pow(n, double(1)/double(2))<<endl;
    cout<<pow(n, (double)(1/2)<<endl;
    cout<<pow(n, 0.5)<<endl; 

// Ten problem nie bedzie widoczny:
    double pot=0.5;
    cout<<pow(n, pot)<<endl;
    // po prostu problem polegal na tym by jasno zadeklarowac jaka zmienna czym jest :)
    return 0;
}

 

komentarz 23 listopada 2016 przez String Gaduła (4,520 p.)
Hahah, no w sumie fajne fajne :)
0 głosów
odpowiedź 23 listopada 2016 przez Knayder Nałogowiec (37,640 p.)

Spróbuj tak:
 

word = word + (number+48);

 

komentarz 23 listopada 2016 przez String Gaduła (4,520 p.)
Próbowałem, nie działa.
0 głosów
odpowiedź 27 sierpnia 2019 przez tothk2a11 Początkujący (290 p.)

Ja do zamiany zmiennej typu int na string oraz string na int używam strumienie napisowe <sstream>.

int suma=0;
stringstream ss;   // deklaracja zmiennej strumieniowej do przekazywania danych 

ss << suma;         //przekazanie zmiennej typu int do strumienia
string daneDoZapisu("D:/bazaSekwencji/sekwencje Suma = " +  ss.str() + ".txt");  //sklejanie napisu

cout << daneDoZapisu << "\n";


Przy okazji podepnę się pod temat:

Mam problem z czyszczeniem strumienia w celu wykorzystania go do dalszej pracy.

W programie który pisze potrzebuje zapisywać wyniki pracy do różnych plików. W tym celu ścieżkę do miejsca zapisu umieściłem w stringu daneDoZapisu, który modyfikuje przed zapisem danych do pliku. Modyfikatorem ścieżki jest zmienna typu int.

Mam jednak mały problem z czyszczeniem samego strumienia w trakcje wykonywania pętli, zresztą poza pętlom też mam problem.

int main()
{

    int suma=0;
    stringstream ss; // zmienna strumieniowa do przekazywania danych z wiersza do zmiennych w tablicy

    for (int i=0; i<12; i++)
    {
        ss << suma;
        string daneDoZapisu("D:/Sekwencje/Sekwencje Suma = " +  ss.str() + ".txt");

        cout << daneDoZapisu << "\n";

        suma++;
        ss.clear();
getch();
    }

 return 0;
}

W teorii pod koniec pętli (ss.clear();) powinno wyczyścić strumień przed kolejnym cyklem pętli. Jednak z tego co mi wyświetla w konsoli to chyba nie działa albo robię coś nie tak. W kolejnym cyklu pętli dostaje stringa który jest zmodyfikowany o napis z poprzednich cykli + aktualna modyfikacja.

Co w tym może być nie tak. 

Znalazłem już rozwiązanie jak to obejść. Zamiast pojedynczego strumienia deklaruje tablice strumieni [] i w każdym cyklu pentli korzystam z innego strumienia - i dział, ale to nie sprawdzi się w praktyce. Problem w tym że nie wiem dlaczego funkcja clear(); nie czyści mi strumienia przechowującego dane. 

komentarz 27 sierpnia 2019 przez tangarr Mędrzec (154,780 p.)

@tothk2a11
Wszystko masz w dokumentacji cppreference
stringstream::str(const string& new_str) wywołuje rdbuf()->str(new_str).
stringstream::rdbuf() zwraca referencję na obiekt basic_stringbuf.
dokumantację funkcji basic_stringbuf::str(const string &s) masz tutaj.
Interesujący fragment:

Deletes the entire underlying character sequence of this std::basic_stringbuf and then configures a new underlying character sequence containing a copy of the contents of s.

W implementacji prawdopodobnie wygląda tak (w uproszczeniu):

void basic_stringbuf::str(const string &new_str) {
    mBuff = new_str;
}

Do pewnego stringa wewnątrz klasy zostanie przypisana wartość new_str (zostanie zrobiona kopia).
tzk zwrócił uwagę, że lepiej jest użyć

ss.str(string());

niż

ss.str("");

Z tego powodu, że w pierwszej sytuacji wywoływany jest (tani) konstruktor domyślny stringa, natomiast mój przykład powoduje wywołanie konstruktora string(const char *napis) który wykonuje (niepotrzebną w tej sytuację) kopię łańcucha napis.
Taki konstruktor musi wykonać przynajmniej 3 akcje:
1. Obliczenie długości napisu
2. Zaalokowanie pamięci (w przypadku krótkich napisów może zostać użyty statyczny bufor wewnątrz stringa - short string optimalization)
3. Przekopiowanie napisu do nowego bufora.

komentarz 27 sierpnia 2019 przez tkz Nałogowiec (42,000 p.)

Przypisanie, z angieskeigo assignment of statements o ile dobrze kojarze 

variable = expression;

variable = constant

Replace, zamiana/podmiana, chociaż to drugie jest bardziej poprawne, mówiąc o stringach jest możliwe 7 wariantów. 

(1) string

Copies str.

(2) substring

Copies the portion of str that begins at the character position subpos and spans sublen characters (or until the end of str, if either str is too short or if sublen is string::npos).

(3) c-string

Copies the null-terminated character sequence (C-string) pointed by s.

(4) buffer

Copies the first n characters from the array of characters pointed by s.

(5) fill

Replaces the portion of the string by n consecutive copies of character c.

(6) range

Copies the sequence of characters in the range [first,last), in the same order.

(7) initializer list

Copies each of the characters in il, in the same order.

 http://www.cplusplus.com/reference/string/string/replace/

komentarz 27 sierpnia 2019 przez tangarr Mędrzec (154,780 p.)
Chyba trochę zbyt dosłownie wziąłeś ten "replace". Funkcje string::replace( ... ) służą do podmiay części napisu. stringstream::str(const string &) wymienia cały napis w buforze. Więc raczej w implementacji zostanie użyty operator przypisania (takie rozwiązanie wydaje się prostsze).
komentarz 27 sierpnia 2019 przez tangarr Mędrzec (154,780 p.)

Z ciekawości zajrzałem do kodu biblioteki i znalazłem coś ciekawego:
 

/**
*  @brief  Setting a new buffer.
*  @param  __s  The string to use as a new sequence.
*
*  Deallocates any previous stored sequence, then copies @a s to
*  use as a new one.
*/
void
str(const __string_type& __s)
{
   // Cannot use _M_string = __s, since v3 strings are COW
   // (not always true now but assign() always works).
    _M_string.assign(__s.data(), __s.size());
    _M_stringbuf_init(_M_mode);
}

Implementacja (MinGW 7.3) używa funkcji assign aby wykonać pełną kopię.

komentarz 27 sierpnia 2019 przez tkz Nałogowiec (42,000 p.)

I działa na konstruktorze 

(4) buffer

Copies the first n characters from the array of characters pointed by s.

buffer (4)
string& assign (const char* s, size_t n);

Nie ma nic o przypisaniu. Przypisanie w stringu http://www.cplusplus.com/reference/string/string/operator=/

Mniejsza o to, i tak w sumie nic się nie zmieni podczas tej wymiany zdań. Obojętnie czy nazwiesz to  przypisaniem, czy podmiana, czy czymkolwiek innym. 

Podobne pytania

+1 głos
1 odpowiedź 898 wizyt
pytanie zadane 27 grudnia 2016 w C i C++ przez breeg Początkujący (390 p.)
0 głosów
1 odpowiedź 195 wizyt
0 głosów
1 odpowiedź 812 wizyt
pytanie zadane 16 listopada 2018 w C i C++ przez robertwe Gaduła (4,620 p.)

92,555 zapytań

141,402 odpowiedzi

319,540 komentarzy

61,938 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...