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!

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