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

Jak sprawdzić drugi wyraz stringa?

Object Storage Arubacloud
0 głosów
401 wizyt
pytanie zadane 21 kwietnia 2019 w C i C++ przez Rafep Nowicjusz (170 p.)
Cześć! Mam pewne pytanie - jak w języku C++ zwrócić 2 wyraz stringa?

3 odpowiedzi

+1 głos
odpowiedź 21 kwietnia 2019 przez mokrowski Mędrzec (155,460 p.)
#include <string>
#include <iostream>
#include <sstream>

int main() {
    std::string msg = "ala ma kota";
    std::string firstWord;
    std::string secondWord;
    std::istringstream ss{msg};
    ss >> firstWord >> secondWord;
    std::cout << "Pierwszy: " << firstWord << "\tDrugi: " << secondWord << '\n';
}

 

0 głosów
odpowiedź 21 kwietnia 2019 przez Eryk Andrzejewski Mędrzec (164,260 p.)

Popatrz na to: https://stackoverflow.com/questions/12966957/is-there-an-equivalent-in-c-of-phps-explode-function

Taką funkcją explode() rozbijasz sobie string na tablicę pojedynczych wyrazów, a następnie wyciągasz drugi element tej tablicy (o indeksie 1).

Być może istnieje lepsze rozwiązanie, na razie nic sensownego nie przychodzi mi do głowy. wink

0 głosów
odpowiedź 21 kwietnia 2019 przez niezalogowany
edycja 21 kwietnia 2019

a można też tak

#include <iostream>
using namespace std;

int main()
{
   char spacja=32;
    string a {"Hello world!"};
    string drugi{""};
    char * wsk{nullptr};
    for (int i=0; i<a.size(); i++) if(a[i]==spacja) {wsk=&a[i];break;}
    while (1)
       {
         drugi+=*wsk++;
         if ((*wsk==spacja)||*wsk=='\0')break;
       }
       cout<<drugi;
    return 0;
}

jak byś miał porozdzielane przecinkami spacja=','

komentarz 21 kwietnia 2019 przez mokrowski Mędrzec (155,460 p.)

Stanowczo NIE! W którym miejscu standardu masz zapewnienie że std::string terminowany jest zerem ('\0')? Dopiero wywołanie .c_str() na std::string zwraca takie dane. Masz także szereg konwersji (i założeń) które są niebezpieczne

pr.cpp:10:41: warning: implicit conversion changes signedness: 'int' to 'std::__cxx11::basic_string<char,
      std::char_traits<char>, std::allocator<char> >::size_type' (aka 'unsigned long') [-Wsign-conversion]
    for (int i=0; i<a.size(); i++) if(a[i]==spacja) {wsk=&a[i];break;}
                                      ~ ^
pr.cpp:10:61: warning: implicit conversion changes signedness: 'int' to 'std::__cxx11::basic_string<char,
      std::char_traits<char>, std::allocator<char> >::size_type' (aka 'unsigned long') [-Wsign-conversion]
    for (int i=0; i<a.size(); i++) if(a[i]==spacja) {wsk=&a[i];break;}

 

komentarz 21 kwietnia 2019 przez niezalogowany

oczywiście zawsze trzeba zrobić obsługę sytuacji wyjątkowych. Jak nie znaleziono nawet t tym przypadku

#include <iostream>

using namespace std;

int main()
{
    //char spacja=32;

    string a {"Hello world!"};
    //string drugi{""};
    size_t poczatek=a.find(' ');
    size_t koniec=a.find(' ',poczatek+1);
    if (koniec ==string::npos) koniec=a.size();

    char *drugi = new char[koniec-poczatek+1];
    cout<<poczatek<<endl;
    cout<<koniec<<endl;
    a.copy(drugi,koniec-poczatek,poczatek);
    drugi[koniec-poczatek]='\0';
    cout<<drugi<<endl;

    delete[] drugi;
    return 0;
}

 

komentarz 21 kwietnia 2019 przez niezalogowany
edycja 21 kwietnia 2019

@mokrowski,
 miałem dopisać funkcje ale zrezygnowałem bo kod zaczął się komplikować a nie będę pisał drugiej biblioteki string

#include <iostream>
using namespace std;

int main()
{
   char spacja=',';
    string a {"Hello world!"};
    string drugi{""};
    char * wsk{nullptr};
    for (int i=0; i<a.size(); i++) if(a[i]==spacja) {wsk=&a[i];break;}
    while (wsk)
       {
         drugi+=*wsk++;
         if ((*wsk==spacja)||*wsk=='\0')break;
       }
       drugi+='\0';
       cout<<drugi;
    return 0;
}

tu mi się nie wywala, chyba że coś przegapiłem

...
 while (wsk)  //taka kosmetyka
....

drugi+='\0'; 

Mógłbyś wyjaśnić o jakie inne niebezpieczeństwa chodzi, bo ja często jak zaponę nazwy funkcji to lubię ja napisać sam jak jest prosta tak dla zabawy.

 

komentarz 21 kwietnia 2019 przez mokrowski Mędrzec (155,460 p.)
Cytowałem ostrzeżenia kompilatora. Jeśli miałbym się czepiać, to ani to dla Ciebie nie będzie pożytkiem ani ja nie będę zadowolony.

Zwrócę tylko Twoją uwagę na odpowiedź na 2 pytania:

1. typ char jest signed czy unsigned?

2. jaki typ zwraca dla string'a .size() ? signed czy unsigned? I jest to int czy może coś innego?

Reszta to kwestia stylu i konsekwencji danego zapisu. Tu zawsze można dyskutować nawet gorąco.
komentarz 21 kwietnia 2019 przez niezalogowany
edycja 21 kwietnia 2019
No własne tu masz rację zwraca typ size_t czyli podobno unsigned int, ale kiedyś próbowałem coś porównać size_t i unsigned int i były problemy ze typy niezgodne. Ale to było dawno. Ale chętnie bym się dowiedział na czym polega ta różnica, skoro już zostałem wywołany.

No wiadomo ze stringi są bardzo długie i można przekroczyć zakres, ale chodziło o drugi wyraz i odpowiedzi wcześniejsze, są dobre. Ale czasami własna funkcja nie jest niczym złym. Szczególnie, że w stringu chyba też wszystko oparte jest na wskaźnikach.

Ja nawet nie jestem programistą więc się za bardzo nie obrażę jak czegoś nie będę wiedział.

A tak dopiszę uruchomiłem kompilator i pisałem char a=-1 i nic mi nie wyświetlił a -300 wyświetlił jakąś literę. Dla mnie char zawsze zaczynał się od 0. To jak byś rozwinął temat to był bym wdzięczny.
komentarz 21 kwietnia 2019 przez mokrowski Mędrzec (155,460 p.)

https://en.cppreference.com/w/cpp/types/size_t

2 i 3 akapit...

std::size_t is commonly used for array indexing and loop counting. Programs that use other types, such as unsigned int, for array indexing may fail on, e.g. 64-bit systems when the index exceeds UINT_MAX or if it relies on 32-bit modular arithmetic.

When indexing C++ containers, such as std::string, std::vector, etc, the appropriate type is the member typedef size_type provided by such containers. It is usually defined as a synonym for std::size_t. 

No wiadomo ze stringi są bardzo długie i można przekroczyć zakres, ale chodziło o drugi wyraz i odpowiedzi wcześniejsze, są dobre.

Właśnie z tego powodu który cytuję, nie są dobre. Skąd wiesz jak długi jest 1 wyraz? A co jak ma powyżej 70 000 znaków (bo przecież może mieć)? Wtedy int (który w świetle standardu ma najmniej 16 bitów), nie pomieści indeksu.

Szczególnie, że w stringu chyba też wszystko oparte jest na wskaźnikach.

Standard języka nie mówi "na czym chyba jest to oparte". Mówi tylko że jeśli zakładasz terminację zerem, to od tego jest c_str().

Reszty informacji możesz poszukać na forum. Także w moich wypowiedziach.  Wtedy dowiesz się że operacje dodawania typu unsigned i signed mają zachowaienie niezdefiniowane. Masz więc (nie)szczęście że działają.

komentarz 21 kwietnia 2019 przez niezalogowany
edycja 21 kwietnia 2019

No i każdego dnia można dowiedzieć się czegoś ciekawego. Dzięki. Ale czy dobrze rozumuję ze size_t jest nieograniczone to by była bardzo dobra informacja. Size_t waży tyle samo co int.

unsigned 
 aa=999999999999999999999999999999999999999999999999999;
size_t a=999999999999999999999999999999999999999999999;

   // size_t a=1000000000000000000000000000000000000000000000;
    cout << a << endl;
    cout << aa << endl;

wyjście już sobie  odpowiedziałem nie, nie jest

4294967295
4294967295

a dla a=1000000000000000000000000000000000000000;  wyjście 0 bardzo interesujące

a tak w ogóle to przekraczanie typów podobno jest bardo niebezpiecznie i zawsze trzeba postawić jakiś warunek ograniczający.

komentarz 22 kwietnia 2019 przez niezalogowany

@mokrowski, nurtuje mnie jeszcze jedno pytanie? bo żaden problem zamiast pętli for dać pętle 

  wsk=&a[0];
     while (1)
    {
        if (*wsk==string::npos) {wsk=nullptr; break;}
        if((*wsk)==spacja) break;
        wsk++;
    }

ale nadal jetem ograniczony rozmiarem size_t dobrze rozumuję. A co z dłuższymi stringami.

komentarz 22 kwietnia 2019 przez mokrowski Mędrzec (155,460 p.)

W źródłach k†óre podałem, masz wyraźnie zaznaczone że std::size_t jest typem danych do przechowywania indeksów największych możliwych na danej platformie systemowej kontenerów danych i do tego ten typ jest przeznaczony. Ograniczenie to jest więc ograniczeniem platformy systemowej. Upraszczając (by nie robić wykładu np. o rozszerzeniach PAE dla x86) nie wyjdziesz poza nie bo ... nie możesz w danym systemie. Dla 32-bitowych platform, będzie to typ danych przechowujący najmniej ~4GB (w praktyce 1GB w systemach głównego nurtu zabiera jądro systemu). Dla 64-bit odpowiednio więcej (tu już granicą są inne powody). Inaczej jest co do zasady dla danych np. typu plik. Plik w systemach 32-bit, może dziś mieć więcej niż 4GB danych. Ale to już zupełnie inna historia.

Zupełnie inną historią jest także alokowanie na stosie lub stercie. Stos z zasady ma ograniczoną wielkość (~2-4MB dla Windows/Linux) i tu jest ograniczenie wcześniej występujące. Jeszcze innym ograniczeniem jest występowanie na niektórych platformach wskaźników bliskich (ang. near) i dalekich (ang. far/huge). One nawet mają różny sizeof(...). Ogólnie operując na wskaźnikach pokujesz się właśnie w takie rozważania. A po co? Przecież to jest coś co ma rozwiązać biblioteka standardowa? Masz (złudną) nadzieję że "będzie szybciej bo wskaźnik"? W praktyce ani szybciej ani czytelniej.

komentarz 22 kwietnia 2019 przez niezalogowany
edycja 22 kwietnia 2019
Jeszcze raz dzięki.

Będę mógł pogrzebać w temacie tak dla relaksu.

Przeglądałem QStringi i są dużo łatwiejsza obsługa niż te z biblioteki std. Ale obawiam się że coś za coś. Bo napisałem kiedyś programik do rozkrojów stała tablica 400 elementów i mogłem 400 razy puścić pętlę zaczynając z każdego elementu i komputer nawet tego nie odczuł (czyli żaden problem mieć 160 000 elementów). Trochę przy sortowaniu myślał ale to było zwykłe nie bąbelkowe więc miał prawo. Kontenery są super ale nie wiem czy to tak naprawdę nie obciąża programu i za wygodę obsługi nie płaci się czasem wykonania.

Dodam jeszcze dlaczego wskaźniki są takie fajne, to był jeden z pierwszych moich programików i zrobiony iteracyjne trzeba było różne fikołki robić by wrócić na początek tablicy miałem chyba z trzy poziomy pętli w funkcji a dzięki wskaźnikowi wystarczyła by jedna docieram do 400 elementu i ustawiam wskaźnik na pierwszy element i tak aż się nie wyzeruje tablica, czyli mam taką okrągłą tablicę.

Podobne pytania

0 głosów
3 odpowiedzi 511 wizyt
pytanie zadane 12 lipca 2018 w PHP przez Q7V Gaduła (4,250 p.)
0 głosów
2 odpowiedzi 13,418 wizyt
–1 głos
1 odpowiedź 184 wizyt
pytanie zadane 19 sierpnia 2019 w C i C++ przez magda_19 Gaduła (3,080 p.)

92,570 zapytań

141,422 odpowiedzi

319,643 komentarzy

61,958 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!

...