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

Usuwanie spacji obok siebie

VPS Starter Arubacloud
0 głosów
439 wizyt
pytanie zadane 7 grudnia 2018 w C i C++ przez Michał_Warmuz Mądrala (5,830 p.)

Czesc pisze zadanie z C++ 0x

i musze podmienic oraz usunac spacje ktore wystepuja obok siebie. Podmienianie działa ale nie usuwanie spacji znaczy usuwa ale tylko czesc tych spacji 

#include <iostream>
#include <string>

using namespace std;

string konwertuj( string & sTekst )
{
    string sWynik;

    for(int i=0; i<=sTekst.size(); i++) {

        if(sTekst[i] == '<') {

            sTekst.erase(i, 1);
            sTekst.insert(i, "[");
        }
        if(sTekst[i] == '>') {

            sTekst.erase(i, 1);
            sTekst.insert(i, "]");
        }
        if(sTekst[i] == ' ' && sTekst[i+1] == ' ') {
            sTekst.erase(i, 1);
        }
    }
    sWynik = sTekst;
    return sWynik;
}
int main()
{
    string tekst = "<b>to jest </b> testowy       napis     <b>:)";
    cout << tekst<<endl;
    cout << konwertuj( tekst)<<endl;

    return 0;
}

 

2 odpowiedzi

+1 głos
odpowiedź 7 grudnia 2018 przez RafalS VIP (122,820 p.)
wybrane 7 grudnia 2018 przez Michał_Warmuz
 
Najlepsza

Ten kod jest strasznie przekombinowany.

  1. std::string w C++ nie jest immutable, więc zamiast:
    sTekst.erase(i, 1);
    sTekst.insert(i, "[");

    które tak na marginesie sprawia, że cały string(lub tylko czesc z prawej strony) jest przepisywany dwa razy :D zrob po prostu tak:

    sTekst[i]='[';
  2. 	sWynik = sTekst;
    	return sWynik;

    możesz po prostu:

    return sTekst;
  3. Po co ten przedrostek przed nazwą zmiennych. Czyżby od typu? Takie praktyki to przestarzałość. Dzisiaj mamy IDE i wystarczy najechać na nazwe zmiennej zeby sprawdzic jej typ.

  4. for (int i = 0; i <= sTekst.size(); i++) {
    ...
    sTekst[i + 1]

    Wychodzisz poza zakres tablicy. i maksymalnie jest rowne size, wiec odwolujesz sie do sTekst[size+1]. O 2 indeksy za stringiem. Technicznie rzecz biorąc o 1, bo s[s.size()] jest zawsze znakiem null '\n'.

A teraz do rzeczy:

		if (sTekst[i] == ' ' && sTekst[i + 1] == ' ') {
			sTekst.erase(i, 1);
		}

usuwasz jedną spacje. Usuwanie ze stringa w petli nie jest najlepszym pomyslem, bo po pierwsze trzeba modyfikować iterator i ręcznie, co jest nieintuicyjne i tak jak wspomnialem przy kazdym usunieciu elementy po prawej są przepisywane o 1 miejsce w lewo, więc lepiej już wpisywać do nowego stringa elementy, które zostają zamiast usuwać ze starego w miejscu.

Normalnie użyłbym idiomu remove-erase, ktory wydajnie usuwa wiele elementow ze srodka kontenera bez ciaglego przepisywania elementow, ale tutaj chodzi o usuniecie roznych podstringow - zlozonych z roznej ilosci spacji obok siebie. Co od razu narzuca regexy:

regex_replace(tekst, regex{ "\\s{2,}" }, " ");

EDIT: jesli nie znasz regexow i na razie nie chcesz poznwac to mozna to zrobic np tak:

string konwertuj(string & sTekst)
{
	string sWynik;
	bool wasSpace = false;
	for (char c : sTekst) {
		if (c != ' ') {
			wasSpace = false;
			sWynik += c;
		}
		else if (!wasSpace) {
			sWynik += c;
			wasSpace = true;
		}
	}
	return sWynik;
}

lub tak:

string konwertuj(string & sTekst)
{
    string sWynik;
    if (sTekst.size() > 0) {
        sWynik += sTekst[0];
    }
    for (size_t i = 1; i < sTekst.size(); i++)
    {
        if (sTekst[i] != ' ' || sTekst[i - 1] != ' ') {
            sWynik+=sTekst[i];
        }
    }
    return sWynik;
}

 

komentarz 7 grudnia 2018 przez niezalogowany
Do usuwania nadmiaru spacji można użyć std::unique.
+1 głos
odpowiedź 7 grudnia 2018 przez kamerek Obywatel (1,260 p.)

Cześć,

Fajnie napisany kod.

Brakuje jedynie jednej linii: i--; w warunku, który usuwa wielokrotne spacje.

if(sTekst[i] == ' ' && sTekst[i+1] == ' ') {
            sTekst.erase(i, 1);
            i--;
        }

Po usunięciu znaku z Tekstu trzeba zmniejszyć iterator pętli, żeby kolejny raz poprawnie przeszukać tekst.

pozdrawiam

komentarz 7 grudnia 2018 przez mokrowski Mędrzec (155,460 p.)
Masz tu UB. Czytasz indeks poza zakresem string'a.
komentarz 7 grudnia 2018 przez kamerek Obywatel (1,260 p.)

Możesz trochę jaśniej ? Czy masz na myśli przypadek gdy pierwsze dwa znaki to spacje?

Można to rozwiązać:

if(sTekst[i] == ' ' && sTekst[i+1] == ' ') {
            sTekst.erase(i, 1);
            if(i) i--;
        }

 

komentarz 7 grudnia 2018 przez mokrowski Mędrzec (155,460 p.)

Co się stanie jeśli indeks i będzie ostatnim znakiem w string'u? Dostęp do i + 1 nastąpi już "za ostatnim znakiem" string'a. Przez to zachowanie będzie niezdefiniowane.

Poza tym to...

for(int i = 0; i <= sTekst.size(); i++)

.. także jest błędne. Nierówność powinna być "ostra".

Podobne pytania

+1 głos
2 odpowiedzi 393 wizyt
pytanie zadane 3 października 2022 w JavaScript przez Piotrek2713 Mądrala (5,320 p.)
0 głosów
1 odpowiedź 1,236 wizyt
pytanie zadane 29 października 2020 w C i C++ przez Billy Użytkownik (680 p.)
0 głosów
1 odpowiedź 387 wizyt
pytanie zadane 27 kwietnia 2020 w C i C++ przez ResCrove Obywatel (1,700 p.)

92,451 zapytań

141,261 odpowiedzi

319,073 komentarzy

61,854 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

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 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!

...