Wytłumaczenie dlaczego tak nie wolno

0

Witam.

Ostatnio pomagałem na forum i napisałem taki kod.

#include<iostream>
#include<windows.h>
#include<cstdlib>
#include<fstream>
#define nazwa_pliku "ksiazki.txt"
using namespace std;
 
void dodaj_ksiazke(int ile=1);
void wyswietl_ksizki();
 
string imie,nazwisko,tyt,wyd;
int nr_bib;
 
int main(int argc,char *argv[])
{
int x,ilosc=1;
 
    cout<<"*******************MENU********************"<<endl;
    cout<<"1.Dodawanie ksiazki"<<endl;
    cout<<"2.Wyswietl ksiazki"<<endl;
    cout<<"3.Wyswietl ksiazki posortowane według numeru bibliotecznego"<<endl;
    cout<<"4.Wyswietl ksiazki posortowane według tytulu"<<endl;
    cout<<"5.Wyjscie z programu."<<endl;
    cout<<"Wybieram : ";
    cin>>x;
    switch(x)
{
   case 1:
   cout<<"Podaj ile chcesz wprowadzic ksiazek: ";cin>>ilosc;
   dodaj_ksiazke(ilosc);
   system("pause");
   main();
 
   break;
   case 2:
 
   break;
   case 3:
 
   break;
   case 4:
 
   break;
   case 5:
 
   #undef nazwa_pliku
   exit(0);
 
   break;
   default:
   cout<<"Program nie posiada funkcji o takim numerze: "<<x<<endl;
   cout<<"Wcisnij dowolny klawisz aby powrocic do menu "<<endl;
   cin.get();
   main();
   break;
 
}
 
}
 
void dodaj_ksiazke(int ile=1)
{
ofstream mojStrumien(nazwa_pliku,ios::app);
if(mojStrumien)
{
for(int i=0;i<ile;i++)
{
     cout << "Podaj imie: ";         cin>>imie; 
     cout << "Podaj nazwisko: ";         cin>>nazwisko;
     cout << "Podaj tytul: ";         cin>>tyt;
     cout << "Podaj wydawnictwo: ";         cin>>wyd;
     cout << "Podaj numer biblioteczny: ";         cin>>nr_bib;
 
        mojStrumien 
        << "Imie autora: " << imie  <<endl
        << "Nazwisko autora: " << nazwisko <<endl
        << "Tytul: " << tyt <<endl
        << "Wydawnictwo: " << wyd  <<endl
        << "Numer biblioteczny: " << nr_bib  <<endl
 
          << endl;
 
}
else
{
 
cout << "BŁĄD: nie można otworzyć pliku." << endl;
cout<<"Wcisnij dowolny klawisz aby wrocic do menu "<<endl;
cin.get();
main();
 
}
 
}
 
}
void wyswietl_ksizki()
{
    string linia;
    fstream plik;
 
    plik.open(nazwa_pliku, ios::in);
    if(plik.good() == true)
    {
        while(!plik.eof())
        {
            getline(plik, linia);
            cout << linia << endl; 
        }
        plik.close();
 
    }
    else
    {
        cout << "BlaD: nie mozna otworzyc pliku." << endl;
        cout<<"Wcisnij dowolny klawisz aby wrocic do menu "<<endl;
        cin.get();
        main();
    }
 
}

I dostałem takie uwagi od jednego z użytkowników forum. I proszę o wyjaśnienie a poniżej jest cytat tego użytkownika.

Zmienne globalne, wywoływanie main();, #define #undef a potem napisanie z ręki nazwy pliku, formatowanie... nie rób tak!

0

Jeszcze using namespace std powinien wymienic😉

0

Wszystko co tu jest to co wymienił to zmniejsza czytelność kodu, zmienne globalne są złe ponieważ możesz sobie przez przypadek zmienić wartości przechowywane w zmiennej - po prostu zapomnisz w końcu do czego ona była. Takie wywołanie main widzę pierwszy raz, i nie wygląda ono dobrze, #define nie jest potrzebne - lepiej unikać mark ponieważ mają czasem zachowanie zupełnie inne niż to które dla nich się przewidziało. Ogólnie najlepiej podzielić kod na klasy w każdej z nich wyróżnić pola i metody prywatne i publiczne wtedy zyskujesz na czytelności i dodatkowo masz większą łatwość w zmianach czegoś w kodzie.

1

Zmienne globalne

Ich największa zaleta, to jest dostępność w obszarze całego programu, staje się też największą słabością jak przychodzi do debugowania programu aby odkryć, w którym miejscu są one źle modyfikowane, oraz/albo ma się aplikację wielowątkową. Poza tym ich nazwy jako globalne nie mogą się powtórzyć co sprawia, że jak w jakimś ja wiem, programie do księgowości chcesz użyć nazwy przelicznik, czy próg to staje się to kłopotliwe jak tych przeliczników czy progów będzie kilka/kilkanaście rodzajów. Te problemy z nimi są na tyle poważne, że zalecane jest z nich zrezygnować niż potem się męczyć.
Akceptowalnym, choć też nie idealnym zastępstwem dla zmiennych globalnych jest implementacja wzora projektowego Singleton, tyle że tutaj znów zadanie to staje się nietrywialne jak trzeba i wielowątkowość w nim obsłużyć.

#define

W C to była jedyna dostępna alternatywa, w C++ mamy const typ zmienna = stała_wartość;. Z define jest taki problem, że propaguje się globalnie, podczas gdy stała const jest w zakresie ważności klasy/funkcji - przy #define może zatem wystąpić kolizja nazw podczas niefortunnego includowania plików.
Poza tym makra tworzone przy pomocy #define z racji tego, iż ciało makra jest na pałę wklejane do kodu niosą ze sobą w Peruna pułapek, tym bardziej, że wywołuje się je podobnie jak funkcje. Ot przykład chcesz mieć makro które podnosi do kwadratu:

#define KWADRAT(x) x * x

i tera sobie je wołasz w kodzie:

int a = KWADRAT(4);

ok, wszystko wydaje się działać. Problem się zacznie, jak wywołasz je tak :]

int a = KWADRAT(2 + 2);

a to dlatego, że wstawiając na pałę makro KWADRAT rozwija się do postaci:

int a = 2 + 2 * 2 + 2;

#define za to używa się do stworzenia tak zwanego strażnika nagłówka który nie pozwala na wklejenie jakiegoś pliku .h wielokrotnie:

#ifndef JAKAŚ_UNIKATOWA_NAZWA
#define JAKAŚ_UNIKATOWA_NAZWA
<tu zawartość pliku .h>
#endif
1

Oczywiście jak masz program, która ma pięć funkcji na krzyż to zmienne globalne czy define nie są katastrofą. Ale mimo wszystko lepiej jest tego unikać i od początku uczyć się dobrych praktyk.
Zmienne globalne: Im mniejszy zakres tym łatwiej ogarnąć kto, kiedy i dlaczego coś modyfikuje
define: Bezpieczniej użyć constexpr
main: Standard stanowczo odradza ręczne wywoływanie main. Pamiętaj, że zanim odpalane jest main, to jakoś trzeba zainicjalizować właśnie zmienne globalne, statyczne, etc. Kompilatorów jest kilka, każdy może to inaczej implementować... lepiej nie kusić losu ;)

0

Bardzo dziękuje za wszystkie odpowiedzi. Jestem amatorem programistą i się jeszcze uczę. Obecnie chodzę do liceum dlatego nie mam takiego doświadczenia ale liczę że przez dalszą naukę moje doświadczenie wzrośnie i nie będę robił takich błędów.

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