Problem z zadaniem z kwotami rozliczeń

0

Cześć mam problem z zadaniem oto jego treść,,
Organizacja plików: Wszystkie pliki oddawane do sprawdzenia należy zapisać we wspólnym folderze o nazwie będącej
numerem indeksu, umieszczonym na pulpicie. Oddajemy tylko źródła programów (pliki o rozszerzeniach .cpp i .h)!!!
Napisać pomocnicze biblioteki oraz program główny dla następującego zadania:
Centralna Policja Podatkowa raz w roku kontroluje zeznania podatkowe obywateli Fiskustanu. Lista
podatników nazywa się "podatnicy.txt" i zawiera ich dane uporządkowane rosnąco wg nazwiska
i dalej imienia w formacie (kolejne linie):
NIP (10-cyfrowy numer identyfikacji podatkowej)
Nazwisko Imię (oddzielone odstępem)

Plik z rozliczeniami podatników nazywa się "rozliczenia.txt" i zawiera liczbę linii zgodną z liczbą
podatników. Każda linia zawiera kwotę rozliczenia odpowiadającego jej podatnika zapisaną
z dokładnością do 2 miejsc dziesiętnych, np.:

195.67
0.00
-312.50

Kwoty rozliczeń mogą być liczbami dodatnimi (niedopłaty podatku), ujemnymi (nadpłaty) lub
zerami (podatek rozliczony). Należy wydrukować do pliku "wyniki.txt" listę zawierającą dane
podatników wraz z odpowiadającymi im kwotami rozliczenia, uporządkowaną malejąco wg
nazwiska i dalej imienia podatnika, w następującym formacie (kolejne linie):

Nazwisko
Imię
NIP (numer identyfikacji podatkowej)
Kwota rozliczenia (zaokrąglona do liczby całkowitej)

Wymagania formalne:
Program powinien być zapisany w trzech plikach: kontener.h, dane.h i glowny.cpp (wolno rozbić
kontener na kontener.h i kontener.cpp, podobnie z dane.h i dane.cpp).
W pliku dane.h należy umieścić strukturę implementującą dane przetwarzane w programie,
przechowywane w kontenerze, wraz z odpowiednimi metodami. Tu powinny znaleźć się też
wszystkie pomocnicze funkcje, sprawdzające poprawność danych (na przykład poprawność numeru
NIP). Nie należy umieszczać w tym pliku funkcji formatujących dane do wydruku, ani żadnych
innych funkcji używających operacji wejścia-wyjścia.
W pliku kontener.h należy umieścić strukturę odpowiadającą użytemu abstrakcyjnemu typowi
danych. Można użyć szablonu lub konkretnej struktury z typem elementu odpowiadającym
strukturze zbudowanej w pliku dane.h. Należy umieścić w kontenerze i implementować tylko te
metody, które będą używane w programie głównym. Implementacja nie może zależeć od typu
elementu, powinna działać tak samo po zmianie tego typu na jakikolwiek inny. Nie może też być tu
żadnych operacji wejścia wyjścia ani formatowania wydruku kontenera.
W pliku glowny.cpp umieszczamy program główny korzystający z plików kontener.h i dane.h oraz
funkcje formatujące wydruk i inne funkcje korzystające z operacji wejścia-wyjścia.
Niedozwolone jest korzystanie z kontenerów i algorytmów z biblioteki standardowej C++.
Zapisu do pliku wynikowego nie wolno rozpocząć przed odczytaniem całości plików
wejściowych.

Dodatkowe punkty:
Za obsługę wejścia odporną na błędy użytkownika i za poprawne komentarze, w tym w
bibliotekach pomocniczych: cel funkcji, warunki wstępne, warunki końcowe, sytuacje wyjątkowe
i ewentualnie zwracany wynik, przyznawane będą dodatkowe punkty. Obsługa wejścia odporna na
błędy użytkownika powinna wyglądać następująco:
• w przypadku gdy niepoprawne są dane podatnika (czyli nieprawidłowość wystąpiła w pliku
podatnicy.txt), podatnik ten nie jest wpisywany do plik wynikowego, a odpowiadająca mu
linia w pliku rozliczenia.txt jest pomijana,
• w przypadku gdy dane podatnika są poprawne, a niepoprawna jest kwota rozliczenia (czyli
nieprawidłowość wystąpiła w pliku rozliczenia.txt), podatnik jest wpisywany do pliku
wynikowego, przy czym zamiast kwoty rozliczenia pojawia się adnotacja „DO
WERYFIKACJI”.
Kolejne punkty podwyższające ocenę można uzyskać zapewniając w programie obsługę
nieograniczonej liczby podatników zapisanych w plikach wejściowych oraz obsługę wielu imion
podatników podanych z odstępami w linii za nazwiskiem.
Dodatkowe punkty będą również przyznane za weryfikację poprawności numeru NIP. Ostatnia,
dziesiąta cyfra NIP jest cyfrą kontrolną obliczaną według poniższego algorytmu:

  1. Pomnożyć każdą z pierwszych dziewięciu cyfr odpowiednio przez wagi: 6, 5, 7, 2, 3, 4, 5, 6, 7.
  2. Zsumować wyniki mnożenia.
  3. Obliczyć resztę z dzielenia przez 11 – powinna być ona zgodna z cyfrą kontrolną.

NIP jest tak generowany, aby nigdy w wyniku tego dzielenia nie wyszła liczba 10."

Oto mój kod
nip.h

#ifndef NIP_H_INCLUDED
#define NIP_H_INCLUDED
#include<iostream>
#include<fstream>
#include<sstream>
#include<cstdlib>
#include<string>
#include<exception>
#include<stdexcept>
#include"kontener.h"
#include<algorithm>
#include<cmath>
#include<math.h>
using namespace std;
struct Podatnik
{

private:
   
    string nazwisko;
    string imie;
    string NIP;
    double kwota;
    bool do_weryfiacji=false;
public:
    
    Podatnik(string naz=" ",string im=" ",string p=" ",double k=0.0,bool w=false)
    {
        nazwisko=naz;
        imie=im;
        NIP=p;
        kwota=k;
        do_weryfiacji=w;
    }
  
    void wstawPodatnika(string a,string b,string c,double d,bool e)
    {
        nazwisko=a;
        imie=b;
        NIP=c;
        kwota=d;
        do_weryfiacji=e;
    }
   
    void wypiszPodatnika()
    {
        cout<<imie<<" "<<nazwisko<<" "<<NIP<<" "<<kwota<<" "<<do_weryfiacji<<" , ";
    }
    string getNazwisko(){return nazwisko;}
    string getImie(){return imie;}
    string getNIP(){return NIP;}
    double getKwota(){return kwota;}
    bool getDoWeryfiacji(){return do_weryfiacji;}
    bool operator<(const Podatnik& other) const {
     if (nazwisko == other.nazwisko)
            return imie < other.imie;
        return nazwisko > other.nazwisko;
    }
    
    
    bool sumaKontrolna()
    {
        int pomoc=0,suma=0;
        int pomocnicza[9] = {6,5,7,2,3,4,5,6,7};
        for(int i=0;i<=9;i++)
        {
            pomoc = NIP[i]*pomocnicza[i];
            suma +=pomoc;
            pomoc=0;
        }
        if(suma%11!=10)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
};

struct Lista{

private:

    struct Node{
       
        Podatnik dane;
        Node*nast;
        Node(Podatnik d,Node*N=nullptr)
        {
           dane=d;
           nast=N;
        }
    };
    
    Node*pocz;
   
    int ileJest;
    
    public:
    Lista()
    {
        pocz=nullptr;
        ileJest=0;
    }
  
    ~Lista()
    {
        Node*nowy=pocz;
        while(nowy!=nullptr)
        {
            Node*szuk;
            szuk=nowy->nast;
            delete nowy;
            nowy=szuk;
        }
    }
    
    void wypisz()
    {
        Node*nowy=pocz;
        while(nowy!=nullptr)
        {
            nowy->dane.wypiszPodatnika();
            nowy=nowy->nast;
        }
    }
    
    void wstaw(Podatnik p)
    {
        Node*nowy;
        nowy=new Node(p);
        if(pocz==nullptr)
        {
            pocz=nowy;
            return;
        }
        else
        {
            Node*szuk=pocz;
            while(szuk->nast!=nullptr)
            {
                szuk=szuk->nast;
            }
            szuk->nast=nowy;
        }
        ileJest++;
    }
    
          void zapisz() {
                ofstream wyniki_plik("wyniki.txt");
                Node* nowy = pocz;
                
            while (nowy != nullptr) {
            wyniki_plik << nowy->dane.getNazwisko() << endl;
            wyniki_plik << nowy->dane.getImie() << endl;
            wyniki_plik << nowy->dane.getNIP() << endl;

            double roundedKwota = round(nowy->dane.getKwota());

            if(nowy->dane.getDoWeryfiacji())
            {
                wyniki_plik<<"Do weryfikacji: "<<endl;
            }
            else
            {
                wyniki_plik << roundedKwota << endl;
            }
            wyniki_plik << endl;

            nowy = nowy->nast;
        }

        wyniki_plik.close();
    }
    };
    #endif // NIP_H_INCLUDED

main.cpp

#include"nip.h"
#include<iostream>
#include<fstream>
#include<sstream>
#include<istream>
#include<cstdlib>
#include<exception>
#include<stdexcept>
#include<string>
#include<math.h>
using namespace std;

int main()
{
    
    string nazwa;
    cout << "Podaj nazwe pliku: " << endl;
    cin >> nazwa;
    try{
        ifstream plik;
        plik.open(nazwa.c_str(),ios::in);
        if(!plik.good())
        {
            throw logic_error("Plik nie dziala");
        }
        string linia;
        Lista lista;
        while (getline(plik, linia)) {
            Podatnik os;
            string nazwisko=os.getNazwisko();
            string imie=os.getImie();
            string nip=os.getNIP();
            double kwota=os.getKwota();
            bool do_weryfiacji=os.getDoWeryfiacji();
            nip = linia;
            getline(plik, linia);
            size_t pozycja = linia.find(' ');
            nazwisko = linia.substr(0, pozycja);
            imie = linia.substr(pozycja + 1);
            getline(plik, linia); // pusta linia
            getline(plik, linia);
            try {
                kwota = stod(linia);
                if (os.sumaKontrolna()) {
                    os.wstawPodatnika(nazwisko,imie,nip,kwota,do_weryfiacji);
                }
            } catch (invalid_argument) {
                if (os.sumaKontrolna()) {
                        kwota = 0;
                        do_weryfiacji = true;
                        os.wstawPodatnika(nazwisko,imie,nip,kwota,do_weryfiacji);
                    }
                }
        }
        lista.wypisz();
        lista.zapisz();
        plik.close();
    }
    catch(exception &e)
    {
        cout<<e.what()<<endl;
    }

    return 0;
}

Powiem tak nie wiem gdzie się zgubiłem problem polega na tym iż po wpisaniu nazwy pliku np.podatnicy.txt nie wyświetla się jego zawartość przy podaniu nazwy błednej np podatnik.txt reaguje dobrze że plik nie działa na dodatek jak się wyświetli to pokazuje wartości na przykładzie podatnicy.txt np jan kowalski jakiś nip kwota i 1.e344242,1.e45353
(coś w tym stylu) jak to zrobić żeby 1.e344242,1.e45353 się nie wyświetlało nawet takich wartości w pliku nie ma więc nie wiem skąd one się biorą proszę o pomoc sprawdzeniu mojego kodu gdzie może być ten błąd i czy zrozumiałem zgodnie z treścią zadanie chce wiedzieć czy gdzieś w kodzie popełniłem błędy z góry dziękuje

0

@martinez345:

Brawo
Wygrałeś nagrodę dnia za najdłuzszy blok tekstu.

0

A gdzie dodajesz podatników do listy ?
Poza tym... Twoja implementacja kontenera powinna być generyczna - tak jak np. std::vector.

2

odpal debuger i idź krok po korku(chociaż wyżej odpowiedziano w zasadzie o nie wczytywaniu danych).

ale jedziemy:

  1. Weź spójrz na to co ty robisz
Podatnik os;
string nazwisko=os.getNazwisko();

i czego oczekujesz po getNazwisko w tym dokładnie momencie?

W ogóle ta cała logika i wołanie w pętli getLine. Kolego prosta sprawa

            getline(plik, linia);
            size_t pozycja = linia.find(' ');
            nazwisko = linia.substr(0, pozycja);
            imie = linia.substr(pozycja + 1);
            getline(plik, linia); // pusta linia
            getline(plik, linia);

jasno w zadaniu określono format prawda?
po prostu czytaj z pliku 4 pierwsze linie i z tego składaj osoby pseudo kod

std::size_t counter = 0;
        while (getline(plik, linia)) {
        switch(counter): {
        case 0: os.imie = linia; break;
        case 1: os.nazwisko = linia; break;
        case 2: os.nip = linia; break;
        case 3: os.kwota = linia; break;
        default:
        break;
        }
        counter++;
        if (counter > 3)
          counter =0;
}

jakiś tam wstaw podatnika nie potrzebny albo zrób to przez konstruktor najpierw pobierz dane do zmiennych lokalnych i nimi zainicjuj nowy obiekt bo po coś masz go prawda?

I ta obsługa błędów wyjątkami. Nie będę się tu rozwodził jak stosuje się wyjątki ale robisz to źle. Zasadniczo poczytaj o tym zwróć uwagę tez na zamykanie pliku. Idzie exception a ty go zamykasz wewnątrz try.
późno już więc nie katuję cie dalej ale powiedzmy pierwsza iteracja do poprawy.

0

Jeśli mówimy string nazwisko=os.getNazwisko(); to ma za zadanie wywołać metode getNazwisko() która ona pobiera string nazwisko z struktury prywatnej jeśli chodzi o poprawki które ja sam dokonałem

bool sumaKontrolna(string NIP);
int main()
{
    string nazwa;
    cout << "Podaj nazwe pliku: " << endl;
    cin >> nazwa;
    ifstream plik;
    plik.open(nazwa.c_str(),ios::in);
    Podatnik os;
    Lista lista;
    try{
        if(!plik.good())
        {
            throw logic_error("Plik nie dziala");
        }
        string nazwisko=os.getNazwisko();
        string imie=os.getImie();
        string nip=os.getNIP();
        double kwota1=os.getKwota();
        string kwota=to_string(kwota1);
        bool do_weryfiacji=os.getDoWeryfiacji();
        size_t counter = 0;
        string linia;
        while (getline(plik, linia)) {
            getline(plik, linia);
            size_t pozycja = linia.find(' ');
            nazwisko = linia.substr(0, pozycja);
            imie = linia.substr(pozycja + 1);
            getline(plik, linia); // pusta linia
            getline(plik, linia);
            switch(counter) {
            case 0: imie = linia; break;
            case 1: nazwisko = linia; break;
            case 2: nip = linia; break;
            case 3: kwota=linia; break;
            default:
            break;
            }
            counter++;
            if (counter > 3)
              counter =0;
            try {
                kwota = stod(linia);
                if (sumaKontrolna(nip)) {
                    os.wstawPodatnika(nazwisko,imie,nip,kwota1,do_weryfiacji);
                    lista.wstaw(os);
                }
            } catch (invalid_argument) {
                if (sumaKontrolna(nip)) {
                        kwota1 = 0;
                        do_weryfiacji = true;
                        os.wstawPodatnika(nazwisko,imie,nip,kwota1,do_weryfiacji);
                        lista.wstaw(os);
                    }
                }
        }
        lista.wypisz();
        lista.zapisz();
        plik.close();
    }
    catch(exception &e)
    {
        cout<<e.what()<<endl;
    }
    return 0;
}
bool sumaKontrolna(string NIP)
{
        int pomoc=0,suma=0;
        int pomocnicza[9] = {6,5,7,2,3,4,5,6,7};
        for(int i=0;i<=9;i++)
        {
            pomoc = NIP[i]*pomocnicza[i];
            suma +=pomoc;
            pomoc=0;
        }
        if(suma%11!=10)
        {
            return true;
        }
        else
        {
            return false;
        }
}

zrobiłem w ten sposób zawartość plików się wyświetla ale są na nim jakieś dziwne liczby jak te dziwne liczby usunąć??

0
martinez345 napisał(a):

Jeśli mówimy string nazwisko=os.getNazwisko(); to ma za zadanie wywołać metode getNazwisko() która ona pobiera string nazwisko z struktury prywatnej jeśli chodzi o poprawki które ja sam dokonałem

bool sumaKontrolna(string NIP);
int main()
{
    Podatnik os;
  ...
        string nazwisko=os.getNazwisko();
        string imie=os.getImie();
        string nip=os.getNIP();
        double kwota1=os.getKwota();

zrobiłem w ten sposób zawartość plików się wyświetla ale są na nim jakieś dziwne liczby jak te dziwne liczby usunąć??

Z dumą bronisz os.getnazwisko() , tyle że w obiekcie os nic nie ma, jest pusty.
Sam sobie rzucasz kłody, przez to że konstruktor Podatnik'a jest efektywnie bezargumentowy (wszystkie argumenty domyślne). Gdyby argumenty były wymagane, kompilator by się upomniał.

Klasa jest zrobiona bez wcześniejszej refleksji jak będzie zasilana danymi. Albo metoda XxxxReadFromFile(iostream & ) (lepiej) , albo operator >> (pomysł gorszy stylowo, nie zachowuje konwencji C++) a tam kod rozwinięty z podanego przez @revcorey
(wizja moja - inni mogą mieć inne. Ja w projekcie typu dydaktycznego w klasie bym umieścił wiedzę jak sie ma wczytać, niech zewnętrze używa jako "czarnej skrzynki")

revcorey napisał(a):

odpal debuger i idź krok po korku

Po 200% tak.
Taki projekt i w twoim @martinez345 procesie nauki z czasem będzie miał niewielką wartość, jest pełen problemów projektowych, koderskich i w kiepskim stylu, i nie będzie radyklanie lepszy - ale wspaniała okazja do nauki debugera

0

Jeśli mówimy string nazwisko=os.getNazwisko(); to ma za zadanie wywołać metode getNazwisko() która ona pobiera string nazwisko z struktury prywatnej jeśli chodzi o poprawki które ja sam dokonałem

To ja akurat wiem co ona w zamyśle robi, tylko co według ciebie da wywołanie getNAziwsko na obiekcie z domyślnymi wartościami? Prześledź flow swojego programu.
o chłopie nie wiem co to za zamysł był poniżej ale

while (getline(plik, linia)) {
            getline(plik, linia);
            size_t pozycja = linia.find(' ');
            nazwisko = linia.substr(0, pozycja);
            imie = linia.substr(pozycja + 1);
            getline(plik, linia); // pusta linia
            getline(plik, linia);
            switch(counter) {
            case 0: imie = linia; break;
            case 1: nazwisko = linia; break;
            case 2: nip = linia; break;
            case 3: kwota=linia; break;
            default:
            break;
            }
            counter++;
            if (counter > 3)
              counter =0;

pomyśl o tym zadaniu tak jak byś to przepisywał z kartki na kartkę. Wziałbyś pierwszą linie i skopiował na druga kartkę, potem drugą, trzecią i czwarta i tak miał byś dane jednej osoby skopiowane. Nie wiem po co ci te substr i inne.

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