Odczyt/zapis pliku, suma cyfr, ciąg.

0

Mam plik cyfry.txt, w którym znajduje się 1000 liczb naturalnych, każda w nowym wierszu mniejszych niż 109. Program ma zapisywać rozwiązania w pliku zadanie4.txt.
a) ile jest liczb parzystych?
b) największa i najmniejsza suma cyfr
c) wypisać wszystkie liczby których cyfry tworzą ciąg rosnący
Moje wypociny:

#include <cstdlib>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>

using namespace std;

int main(int argc, char *argv[]){
	fstream plik,plik1;
	int parzyste=0,liczba=0,liczba_a=0,najw=0,najw_l=0,najm=81,najm_l=0,suma=0;
	string wyraz;
	bool rosnace=1;
	char sciezka[256];
	//-------------
	cout<<"Podaj sciezke do pliku\n\nsciezka: ";
	cin>>sciezka;
	plik.open("cyfry.txt", ios::in);
	plik1.open("zadanie4.txt", ios::out);
	//-------------
	for (int i=1;i<=1000;i++){
		getline(plik,wyraz);
		stringstream konw(wyraz);
		konw>>liczba;
		if (liczba%2==0) parzyste++;
	}
	plik1<<"a)\n\nParzystych liczb: "<<parzyste<<"\n\n";
	//-------------
	for (int j=1;j<=1000;j++){
		getline(plik,wyraz);
		stringstream konw(wyraz);
		konw>>liczba;
		liczba_a=liczba;
			while (liczba!=0) {
			suma+=liczba%10;
			liczba/=10;
		}
		if (suma>najw) {
			najw=suma; 
            		najw_l=liczba_a;
		}
		if (suma<najm) {
			najm=suma; 
            		najm_l=liczba_a;
		}
	}
	plik1<<"b)\n\nNajwieksza sume cyfr: "<<najw<<" ma liczba: "<<najw_l<<"\nNajmniejsza sume cyfr: "<<najm<<" ma liczba: "<<najm_l<<"\n\n";
	//-------------	
	plik1<<"c)\n\n";
	for (int k=1;k<=1000;k++){
		getline(plik,wyraz);
		stringstream konw(wyraz);
		konw>>liczba;
		liczba_a=liczba;
		liczba=liczba%10;
		if (liczba!=0&&rosnace==1) {
			liczba/=10;
			if (liczba%10<liczba && rosnace==1){
				rosnace=1;
				liczba=liczba%10;
			}else {
				rosnace=0;
				}
		}
		if (rosnace==1) plik1<<liczba_a<<endl;
	}
	//-------------
	plik.close();
	plik1.close();
	system("PAUSE");
	return EXIT_SUCCESS;
}

Co z tego wychodzi:
a) 495 - myślę, że dobrze
b) najmniejsza i największa tak samo - ostatnia liczba w pliku i suma jej cyfr
c) wypisują się same zera

Co z tym zrobić, żeby działało?

1

"Przewiń" plik przed kolejnym odczytem (seekg()).
Odnośnie punktu c - masz zły algorytm.
Ogólnie popracuj nad strukturą programu (dobrze żeś go określił).

(Zapomniałem napisać wcześniej.) Zeruj zmienną suma w każdym przebiegu pętli.

0

Po co 3 razy czytasz ten sam plik? Do każdego pkt a, b,c napisz sobie odpowiednią funkcję. Czytaj plik stosując te funkcje na każdej wczytanej liczbie aż do EOF.

0

Dla usprawnienia kontaktu chciałbym na początku wyjaśnić, że moja wiedza programistyczna jest minimalna. Więc proszę nie zadawać pytań po co i dlaczego coś robię.
Wracając do tematu, przed przerabianie struktury wrzuciłem seekg() i teraz w b) największa suma cyfr 29811 :O - ostatniej liczby, najmniejsza suma cyfr 25(dobrze policzona) - pierwszej liczby. W c) wypisuje pierwsza i druga liczbę. Odnośnie algorytmu z punktu c założenie było takie, że dopóki liczba nie jest równa 0 i cyfry są rosnące ma sprawdzać czy kolejna cyfra jest mniejsza i dzielić liczbę. Wyszło co wyszło.
Co do struktury, mogłoby to tak wyglądać?

	while (!plik.eof()){
		getline(plik,wyraz);
		stringstream konw(wyraz);
		konw>>liczba;
		funkcja1(liczba);
		funkcja2(liczba);
		funkcja3(liczba);
	}

Proszę również o jakieś sugestie/gotowce/poprawki do algorytmów z b i c bo nie mam pomysłu.

1

Przy Twoich umiejętnościach lepiej pozostań przy tym, co już masz. Oczywiście wprowadzając poprawki.
Zobacz co dopsałem w poprzednim poście (to rozwiązuje problem z punktem b).

A teraz ten nieszczęsny i najtrudniejszy punkt c). Jak pisałem musisz zmninić algorytm. Po pierwsze zakładając, że chodzi o ciąg rosnący od lewej do prawej sprawdź czy cyfra stojąca po prawej stronie jest większa od tej po lewej. Stwierdzenie, że tak nie jest wyklucza liczbę. Po drugie dużo prościej byłoby to przeprowadzić na reprezentacji tekstowej liczby, ale można i tak jak próbujesz. Z uwagi na to, że zaczynasz od skrajnej prawej to lewa powinna być mniejsza.

1

dziel i zwyciężaj kolego :) napisz sobie takie funkcje do tych pkt:

 
bool czyParzysta(int);
int sumaCyfr(int);
bool czyRosnacy(int);

ich nazwy chyba mówią co powinny robic ;)
przedmówca już opisał jak zrobić algorytm do c

0

Coś takiego uskrobałem:

#include <cstdlib>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>

using namespace std;

bool czyParzysta(int a){
	if (a%2==0) return 1; else return 0;
}
int sumaCyfr(int a){
	int suma=0;
	while (a!=0){
			suma+=a%10;
			a/=10;
	}
	return suma;
}
bool czyRosnacy(int a){
	int b=a%10;
	while (a!=0){
		a/=10;
		if (a%10>b) return 0;
		b=a%10;
	}
	return 1;
}

int main(int argc, char *argv[]){
    fstream plik,plik1;
	int parzyste=0,liczba=0,liczba_a=0,najw=0,najw_l=0,najm=81,najm_l=0,rosnace[1000],i=0;
	string wyraz;
    char sciezka[256];
	cout<<"Podaj sciezke do pliku\n\nsciezka: ";
	cin>>sciezka;
	plik.open("cyfry.txt", ios::in);
	plik1.open("zadanie4.txt", ios::out);
	while (!plik.eof()){
		getline(plik,wyraz);
		stringstream konw(wyraz);
		konw>>liczba;
		if (czyParzysta(liczba)) parzyste++;
		if (sumaCyfr(liczba)>najw){
			najw=sumaCyfr(liczba);
			najw_l=liczba;
		}
		if (sumaCyfr(liczba)<najm){
			najm=sumaCyfr(liczba);
			najm_l=liczba;
		}
		if (czyRosnacy(liczba)){
			rosnace[i]=liczba;
			i++;
		}
	}
	i=0;
	plik1<<"a)\nParzystych liczb: "<<parzyste;
	plik1<<"\n\nb)\nNajwieksza sume cyfr: "<<najw<<" ma liczba: "<<najw_l<<"\nNajmniejsza sume cyfr: "<<najm<<" ma liczba: "<<najm_l<<"\n\n";
	plik1<<"c)\n";
	while (rosnace[i]!=0){
		plik1<<rosnace[i]<<endl;
		i++;
	}
    plik.close();
	plik1.close();
    system("PAUSE");
    return EXIT_SUCCESS;
}

Jak zrobię tak, że wypisuje rosnące przy czytaniu pliku to wychodzi ok, ale chciałem żeby były na końcu więc zapisuję je do tabeli. Niestety w tym przypadku wypisują mi się też jakieś fikcyjne liczby.

1

alokujesz tablicę w pamięci:

 
int rosnace[1000];

Ale to tylko przydzielenie pamięci w której dopóki nic w niej nie wpiszesz są "śmieci". Zrób licznik to zliczania ile jest rosnących i puść w pętli for wyświetlanie. Możesz też wyzerować całą tabele zanim jej użyjesz.

0

Zmieniłem pętlę while na

	for (int j=0;j<=i-1;j++){
		plik1<<rosnace[j]<<endl;
	}

Wszystko działa, dzięki za pomoc.

EDIT:
Tak mi przyszło do głowy. Można bez dodatkowego licznika.

	for (i-=1;i>=0;i--){
		plik1<<rosnace[i]<<endl;
	}
0

while (!plik.eof()){
getline(plik,wyraz);
//...
}

Wychodzisz poza plik! Po odczycie a nie przed sprawdź czy plik nie osiągnął końca.

Nie jest ci potrzebny obiekt pośredniczący, ąby odczytać liczbę. Wystarczy:

 plik >> liczba;

Algorytm wyszukiwania "liczby których cyfry tworzą ciąg rosnący". Czy liczba jednocyfrowa tworzy taki ciąg, albo na przykład liczba 112. A Twój ich nie odrzuca!

0

Trochę się gubię. Moim skromnym zdaniem to nie ma znaczenia czy sprawdzamy na początku czy na końcu z wyjątkiem gdy plik jest pusty, bo wtedy jeśli sprawdzamy na końcu to najpierw nastąpi odczyt a później sprawdzenie.

plik >> liczba;

Cały plik do jednej zmiennej?

a%10>=b || a==0
0

Trochę się gubię. Moim skromnym zdaniem to nie ma znaczenia czy sprawdzamy na początku czy na końcu z wyjątkiem gdy plik jest pusty, bo wtedy jeśli sprawdzamy na końcu to najpierw nastąpi odczyt a później sprawdzenie.

Ma. Stan pliku (strumienia) jest zależny od przeprowadzonej na nim operacji. Jeżeli nic nie będziesz odczytywał to jego stan nie ulegnie zmianie. Zatem sprawdzanie stanu przed odczytem jest bez sensu, chyba że już wcześnie została przeprowadzona na nim jakaś operacja.
Odczytanie ostatnie liczby nie oznacza, że zostanie ustawiony odpowiedni znacznik. Stanie się to dopiero po odczytania kolejnej liczby, której oczywiście nie będzie. A wtedy do Twoja zmiennej pójdą śmieci.

plik >> liczba;
Cały plik do jednej zmiennej?

Jeżeli zawiera tylko jedną liczbę czemu nie. Ale na poważnie. Oczywiście, że nie cały tylko jedna liczba. Wczytanie jednej liczby ze strumienia wejściowego wygląda tak (dla przypomnienia):

cin >> liczba;

Czaisz? Właściwie nie ma róznicy.

a%10>=b || a==0

Widzę, że się starasz. Przypatrz się dobrze funkcji czyRosnące(). Z takim warunkiem wszystkie liczby zostaną odrzucone, ale pierwszy z nich jest dobry. Pozostało już tylko odrzucić liczby jednocyfrowe. A to chyba nie problem.

1 użytkowników online, w tym zalogowanych: 0, gości: 1