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

c++ problem z usuwaniem ostatniego znaku w stringu, jeśli jest to spacja

Object Storage Arubacloud
0 głosów
951 wizyt
pytanie zadane 16 grudnia 2015 w C i C++ przez Lexander Nowicjusz (210 p.)

Witajcie.

Mam na uczelnię do zrobienia prosty projekt z podstaw programowania w języku cpp.

Wczytuje on plik wejściowy i przerabia każdą jego linijkę następująco:

1) dodaje na początku wiersza numer tego wiersza w taki sposób, żeby wszystkie wiersze poprzedzone były taką samą ilością znaków (i to mi działa jak trzeba)

2) usuwa z linijki wszelkie nadmiarowe spacje, tj. spacje na początku i na końcu linijki oraz te, które powtarzają się w linijce więcej niż raz pod rząd.

Po zmodyfikowaniu każdej linijki program zapisuje ją do pliku wyjściowego.

Punkt drugi również działa, ale z jednym wyjątkiem - jeśli na końcu linijki wejściowej jest rząd spacji, moja funkcja zawsze zostawia jedną spację na końcu (a nie powinno być żadnej). Próbowałem usuwać tę spację na końcu sprawdzając za pomocą jednego ifa czy ona tam jest i wstawiając w jej miejsce znak 0 (w kodzie ascii jest to null; wyczytałem gdzieś, że tą wartością kończy się każdy string). Jednakże spacja ta mimo to zostaje. Co robię nie tak? Konsultanci przydzieleni do pomocy studentom w projektach nie mają na to pomysłu.

dla danych wejściowych:

dddd
raz   dwa
     trzy     cztery
piec  szesc      
     siedem  s pokpok      fspopjsojfs      
osiem    dziewiec    
    dziesiec   
jedenascie
dwanascie    i tak dalej

dane wyjściowe powinny wyglądać tak:

1. dddd
2. raz dwa
3. trzy cztery
4. piec szesc
5. siedem s pokpok fspopjsojfs
6. osiem dziewiec
7. dziesiec
8. jedenascie
9. dwanascie i tak dalej

kod źródłowy:

#include <fstream>
#include <iostream>
#include <string>
using namespace std;

string int_to_string(int n) //zamiana inta na string polega na tym, że do każdej cyfry dodajemy 48 i dodajemy ją do zwrotnego stringa
{
	string tmp, ret;
	if (n < 0) {
		ret = "-";
		n = -n;
	}
	do {
		tmp += n % 10 + 48;
		n -= n % 10;
	} while (n /= 10);
	for (int i = tmp.size() - 1; i >= 0; i--)
		ret += tmp[i];
	return ret;
}

bool sprawdz_dostepnosc_pliku(string nazwa_pliku) //sprawdzanie czy można otworzyć plik
{
	fstream plik;
	plik.open(nazwa_pliku, ios::in); 
	if (!plik.good())
	{
		cout << "Nie udalo sie odczytac pliku!" << endl;
		system("pause");
		return false; //jesli sie nie udalo
	}
	plik.close();

	return true; //jesli sie udalo
}

int sprawdz_ilosc_linii(string nazwa_pliku)
{
	fstream plik;
	plik.open(nazwa_pliku, ios::in);
	int nr_linii = 0; //zmienna do zliczania ilości linii
	string linia;

	while (!plik.eof()) //pętla idzie linijka po linijce aż do końca pliku
	{
		getline(plik, linia);
		nr_linii++; //i po każdej linijce zwiększa licznik linii o 1
	}
	plik.close();
	return nr_linii;
}

int dlugosc_liczby(int liczba) //funkcja zwraca ilość cyfr w liczbie
{
	int wynik = 0; //licznik cyfr

	while (liczba > 0) //zabiera z liczby jedną cyfrę i zwiększa licznik cyfr
	{
		liczba /= 10;
		wynik++;
	}
	return wynik;
}

string wyczysc_spacje(string tekst)
{
	int i = 0; //numer znaku w "tekst"
	int j = 0; //numer znaku w "wynik"
	string wynik = ""; //zmienna wynikowa
	while (tekst[i] >= 32) //dopóki nie skończyło nam się słowo (dopóki bieżący znak jest zwykłym znakiem
	{
		if (tekst[i] != 32) //jesli dana literka nie jest spacją,
		{
			wynik = wynik + tekst[i]; //to dodajemy ją do linijki wyjściowej
			i++; //i przechodzimy do kolejnej literki
			j++;
		}
		else //jesli mamy do czynienia ze spacją
		{
			if (i > 0)
			{
				wynik = wynik + " "; //to dodamy ją tylko raz (pomijając te spacje, które są na początku)
				j++;
			}
			while (tekst[i] == 32) i++; //a pozostałe spacje pominiemy
		}
	}
	if (wynik[j - 1] == 32) wynik[j - 1] = 0; //usuwanie spacji z końca linijki
	return wynik;
}

string zapisz_do_pliku(int numer_linii, int ilosc_linii, string linia)
{
	string wynik = int_to_string(numer_linii) + "."; //zamieniamy numer linii na string, dodajemy go do stringa zapisywanego do pliku, po czym dodajemy kropkę
	for (int i = 0; i < dlugosc_liczby(ilosc_linii) - dlugosc_liczby(numer_linii) + 1; i++) wynik = wynik + " "; // dopełniamy przestrzeń spacjami, żeby każde słowo było równo
	wynik = wynik + linia; //do stringa zapisywanego do pliku dodajemy treść obrobionego stringa z pliku wejściowego
	return wynik;
}

//================================================================================

int main()
{
	string nazwa_pliku_in; //nazwa pliku wejściowego
	string nazwa_pliku_out; //nazwa pliku wyjściowego
	string linijka; //linia tekstu odczytywana z pliku wejściowego
	string wynik; //linia tekstu zapisywana do pliku wyjściowego
	fstream plik_in;
	fstream plik_out;



	//Obsługa pliku wejściowego
	cout << "Podaj sciezke do pliku wejsciowego: ";
	cin >> nazwa_pliku_in;
	if (!sprawdz_dostepnosc_pliku(nazwa_pliku_in)) return 0;

	//obsługa pliku wyjściowego
	cout << "Podaj sciezke do pliku wyjsciowego: ";
	cin >> nazwa_pliku_out;

	//sprawdzanie ilości linii
	int ilosc_linii = sprawdz_ilosc_linii(nazwa_pliku_in);

	//otwieranie plików do dalszej pracy z nimi
	plik_in.open(nazwa_pliku_in, ios::in);
	plik_out.open(nazwa_pliku_out, ios::out);

	int numer_linii = 0; //zmienna potrzebna do zapisywania numeru linii w pliku wyjściowym

	while (!plik_in.eof()) //bierzemy po kolei każdą linię
	{
		numer_linii++;
		getline(plik_in, linijka); //odczytywanie linii wejściowej z pliku

		linijka = wyczysc_spacje(linijka); //czyszczenie nadmiarowych spacji
		wynik = zapisz_do_pliku(numer_linii, ilosc_linii, linijka); //przygotowywanie linii wyjściowej
		plik_out << wynik << endl; //zapisywanie linii wyjściowej do pliku
	}

	//zamykanie plików
	plik_in.close();
	plik_out.close();

	system("pause");
}

 

1 odpowiedź

+1 głos
odpowiedź 16 grudnia 2015 przez Sedi Stary wyjadacz (10,200 p.)
Hmm, na początek polecałbym zamienić wszystkie z końcówką .eof na getline i zobaczyć co się stanie :)
komentarz 16 grudnia 2015 przez Lexander Nowicjusz (210 p.)
zamieniłem, działanie programu się nie zmieniło
komentarz 16 grudnia 2015 przez Sedi Stary wyjadacz (10,200 p.)

Piszę ten komentarz i piszę i nadal ciężko ogarnąć o co w tym wszystkich chodzi:) Oczywiście nie będę Cię krytykował, bo piszesz ładnie i z komentarzami i do funkcji wszystko wrzucasz :)

Po długim namyślę, myślę, że wiem w czym problem:

for (int i = 0; i < dlugosc_liczby(ilosc_linii) - dlugosc_liczby(numer_linii) + 1; i++) wynik = wynik + " ";

Zauważ, że dla ostatniego wyrazu i tak Ci doda tą spację i myślę, że w tym jest problem. Zamień spację na np. słowo "jabłko" i zobacz, co się będzie działo :P

Jeśli to nie to, spróbuj napisać kod od zupełnego zera i zobaczysz, że nie potrzebujesz zamieniać inta na stringa :), a długość linii można określić za pomocą string.length();, i kilka innych ciekawostek :)

Pozdrawiam :)

komentarz 19 grudnia 2015 przez Lexander Nowicjusz (210 p.)
Napisałem tę funkcję od nowa w inny sposób i działa, ale wielkie dzięki za odpowiedź :)

Zamiast tej funkcji podobno można też użyć trim(), ale w poleceniu projektu jest wspomniane, żeby nie używać gotowych funkcji klasy string, dlatego musiałem to robić na około.

Pozdrawiam :)
komentarz 20 grudnia 2015 przez Sedi Stary wyjadacz (10,200 p.)
Naprawdę nie pozwalają Wam na studiach korzystać z gotowych funkcji ? o.O

Oczywiście ma to swoje plusy, ale to często wymyślanie koła na nowo. Można by to porównać do sytuacji w której profesor karze uczniom chodzić po ścianach, zamiast po schodach :P

Pozdrawiam :)

Podobne pytania

0 głosów
1 odpowiedź 3,428 wizyt
pytanie zadane 15 grudnia 2015 w C i C++ przez pineapple505 Nowicjusz (120 p.)
0 głosów
3 odpowiedzi 3,510 wizyt
pytanie zadane 9 września 2016 w C i C++ przez Platiniumekk Początkujący (250 p.)
0 głosów
3 odpowiedzi 4,633 wizyt
pytanie zadane 12 sierpnia 2018 w C i C++ przez VegaOrionis Początkujący (350 p.)

92,575 zapytań

141,424 odpowiedzi

319,649 komentarzy

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

...