Witam spotkał się ktoś takim błędem:
"Unhandled exception at 0x104e8dcb in Projekt Poprawa.exe: 0xC0000005: Access violation reading location 0xfeeefeee."
W programie działam na tablicach dynamicznych
Witam spotkał się ktoś takim błędem:
"Unhandled exception at 0x104e8dcb in Projekt Poprawa.exe: 0xC0000005: Access violation reading location 0xfeeefeee."
W programie działam na tablicach dynamicznych
tak (odpowiedź jest na tyle pełna na ile pozwala pytanie).
Wychodzisz poza tablicę albo zwalniasz tablicę 2 razy itd.
Tylko, że ten błąd pojawia się nie przy wpisywaniu danych do tablicy, ale gdy chce np. odczytać z niej dane albo zapisać te dane do pliku
Funkcja zapisująca:
void zapis_produkt(char *in,Produkt *s,int dlugosc_produkt) // funkcja zapisująca baze do pliku
{
ofstream plik(in, ios::out | ios::ate) ;
// plik<<dlugosc_produkt<<endl; // zapisujemy ilosc produktow jako 1 wartosc w pliku
for(int i=0 ; i<dlugosc_produkt ; ++i)
{
plik<<s[i].numer<<endl;
plik<<s[i].kategoria<<endl;
plik<<s[i].nazwa_produktu<<endl;
plik<<s[i].ilosc<<endl;
plik<<s[i].cena<<endl;
}
}
Funkcja wypisująca
void wypisz_produkt(Produkt *s,int rozmiar_produkt)
{
for(int i=0 ; i<rozmiar_produkt ;)
{
cout<<"Nr."<<s[i].numer<<endl;
cout<<"kategoria : "<<s[i].kategoria<<endl;
cout<<"nazwa_produktu : "<<s[i].nazwa_produktu<<endl;
cout<<"dostepna ilosc : "<<s[i].ilosc<<endl;
cout<<"Cena : "<<s[i].cena<<endl;
cout<<"- - - - - - - - - - - - -\n";
i++;
if(i % 5==0) system("pause"); // wyswietlamy po 5 wpisow i czekamy na klawisz
}
}
No i co z tego? Pokaż jak tworzysz ową tablicę.
Pierwsza deklaracja
Produkt *s = new Produkt [dlugosc_produkt];
Druga deklaracja
case '1':
{
system("cls");
int n;
cout<<"ile produktow chcesz dodac:";
cin >> n;
if(n>dlugosc_produkt)
{
delete[]s;
Produkt *s = new Produkt [n+dlugosc_produkt];
if(n>dlugosc_produkt) ? A to niby czemu?
Jeśli mam 10 produktów, chce dodać 1, to wg ciebie nie nalezy tej tablicy powiększyć? o_O
Fakt, na początku miałem jeszcze zwiększaną tą tablice przy pierwszej deklaracji.
Po usunięciu warunku dzieje się to samo
No to przykro mi ale te skrawki kodu które pokazałeś nie mają jako takich błędów, a z fusów wróżyć trudno.
Czemu, za mało, dosyć prosto to wygląda:
if(n>dlugosc_produkt)
{
delete[]s;
Produkt *s = new Produkt [n+dlugosc_produkt];
zwalnia s (to poziom wyżej), potem tworzy nowe lokalne s i pewnie gubi do niego wskaźnik. "Wyższe" s jest usunięte i wskazuje na śmieci, a "niższe" s jest gubione, i leci wyjątek ;).
Oto mój kod
#include "stdafx.h"
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <time.h>
using namespace std;
struct Produkt
{
int numer; // numer w bazie
string kategoria; // kategoria produktu
string nazwa_produktu; // nazwa produktu
int ilosc; // ilosc produktow na magazynie
double cena; // cena produktu
};
struct Klient
{
int numer; // numer w bazie
string login; // login klienta
int punkty; // posiadane punkty
};
struct Pomocnicza
{
int numer; // numer w bazie
string kategoria; // kategoria produktu
string nazwa_produktu; // nazwa produktu
int ilosc; // ilosc produktow na magazynie
double cena; // cena produktu
};
int rozmiar_produkt(char *in)
{
string nazwa_produktu , kategoria;
int numer, ilosc;
double cena;
ifstream plik(in);
int rozmiar_produkt = 0;
while(!plik.eof())
{
plik>>numer;
plik>>kategoria;
plik>>nazwa_produktu;
plik>>ilosc;
plik>>cena;
rozmiar_produkt += 1;
}
plik.close();
return rozmiar_produkt;
}
int rozmiar_klient(char *in)
{
string login , imie;
int numer;
int punkty;
ifstream plik(in);
int rozmiar_klient = 0;
while(!plik.eof())
{
plik>>numer;
plik>>login;
plik>>punkty;
rozmiar_klient += 1;
}
plik.close();
return rozmiar_klient;
}
//*************************************************************************
void zpliku_produkt(char *in,Produkt *s,int &dlugosc_produkt)
{
ifstream plik(in);
//plik>>dlugosc_produkt; //pobranie dlugosci bazy produktow
// cout<<"Ile produktow : " << dlugosc_produkt;
for(int i=0;i<dlugosc_produkt;++i)
{
plik>>s[i].numer;
plik>>s[i].kategoria;
plik>>s[i].nazwa_produktu;
plik>>s[i].ilosc;
plik>>s[i].cena;
}
}
//******************************************************************************************
void zpliku_klient(char *in,Klient*w,int &dlugosc_klient)
{
ifstream plik(in);
//plik>>dlugosc_klient; //pobranie dlugosci bazy danych klientow
//cout<<"\nIle Klientow : " << dlugosc_klient<<endl<<endl;
for(int i=0;i<dlugosc_klient;++i)
{
plik>>w[i].numer;
plik>>w[i].login;
plik>>w[i].punkty;
}
}
//******************************************************************************************
void wypisz_produkt(Produkt *s,int rozmiar_produkt)
{
for(int i=0 ; i<rozmiar_produkt ;)
{
cout<<"Nr."<<s[i].numer<<endl;
cout<<"kategoria : "<<s[i].kategoria<<endl;
cout<<"nazwa_produktu : "<<s[i].nazwa_produktu<<endl;
cout<<"dostepna ilosc : "<<s[i].ilosc<<endl;
cout<<"Cena : "<<s[i].cena<<endl;
cout<<"- - - - - - - - - - - - -\n";
i++;
if(i % 5==0) system("pause"); // wyswietlamy po 5 wpisow i czekamy na klawisz
}
}
//******************************************************************************************
void wypisz_klient(Klient *w,int rozmiar_klient)
{
for(int i=0 ; i<rozmiar_klient ; )
{
cout<<"Nr."<<w[i].numer<<endl;
cout<<"login : "<<w[i].login<<endl;
cout<<"punkty : "<<w[i].punkty<<endl;
cout<<"- - - - - - - - - - - - -\n";
i++;
if(i % 5==0) system("pause");
}
}
//******************************************************************************************
void zapis_produkt(char *in,Produkt *s,int dlugosc_produkt) // funkcja zapisująca baze do pliku
{
ofstream plik(in, ios::out | ios::ate) ;
// plik<<dlugosc_produkt<<endl; // zapisujemy ilosc produktow jako 1 wartosc w pliku
for(int i=0 ; i<dlugosc_produkt ; ++i)
{
plik<<s[i].numer<<endl;
plik<<s[i].kategoria<<endl;
plik<<s[i].nazwa_produktu<<endl;
plik<<s[i].ilosc<<endl;
plik<<s[i].cena<<endl;
}
}
//******************************************************************************************
void zapis_klient(char *in,Klient *w,int dlugosc_klient) // funkcja zapisująca baze do pliku
{
ofstream plik(in, ios::out | ios::ate) ;
// plik<<dlugosc_klient<<endl; // zapisujemy ilosc klientow jako 1 wartosc w pliku
for(int i=0 ; i<dlugosc_klient ; ++i)
{
plik<<w[i].numer<<endl;
plik<<w[i].login<<endl;
plik<<w[i].punkty<<endl;
}
}
//******************************************************************************************
void dodaj_do_bazy_produkt(Produkt *s,int n, int &dlugosc_produkt) //funkcja dodająca produkty do bazy
{
for(int i=0;i<n;++i)
{
int j=i + dlugosc_produkt; // nowe wpisy dodajemy na koncu bazy
s[j].numer = j+1;
cout<<"Dodaj: "<< i+1 <<" produkt:"<<endl;
cout<<"Podaj kategorie :\n";
cin>>s[j].kategoria;
cout<<"Podaj nazwe_produktu:\n";
cin>>s[j].nazwa_produktu;
cout<<"Podaj ilosc danego produktu :\n";
cin>>s[j].ilosc;
cout<<"Podaj cene Produktu :\n";
cin>>s[j].cena;
}
dlugosc_produkt+=n;
}
//*******************************************************************************************
void dodaj_do_bazy_klient(Klient *s,int n, int &dlugosc_klient) //funkcja dodająca klientów do bazy
{
for(int i=0;i<n;++i)
{
int j=i + dlugosc_klient; // nowe wpisy dodajemy na koncu bazy
s[j].numer = j+1;
cout<<"login :\n";
cin>>s[j].login;
cout<<"Punkty:\n";
cin>>s[j].punkty;
}
dlugosc_klient+=n;
}//******************************************************************************************
// Funkcja sprawdza czy podany użytkownik figuruje w bazie klientów
int szukaj(Klient *w,int &dlugosc_klient)
{
int login;
string szukany_login;
cout <<" Podaj login: "<<endl;
cin >> szukany_login;
int licznik = 0;
char wybor;
for(int i=0;i<dlugosc_klient;++i)
{
if(w[i].login == szukany_login) // sprawdzamy czy dany klient występuje w bazie
{
cout<<"\t\t- - - - - - - - - - - - -\n\n";
cout<< "\t\tJestes zalogowany jako "<< w[i].login<<endl
<<"\n\n\t\tTwoja liczba punktow to: "<<w[i].punkty<<endl<<endl;
cout<<"\t\t- - - - - - - - - - - - -\n\n";
return w[i].numer;
}
else
{
licznik=licznik+1; //gdy klient niewystępuje w bazie zwiększamy licznik
}
}
if (licznik!=0) cout <<"Niema takiego klienta\n\n";
getchar();
}
//*******************************************************************************************
int kup(Produkt *s,int &dlugosc_produkt, Klient *w, int &dlugosc_klient, int znaleziony_klient)
{
int licznik = 0;
int punkty=0;
int numer;
cout<<"Podaj numer: "<<endl;
cin >> numer;
for(int i=0;i<dlugosc_produkt;++i)
{
if (s[i].numer==numer) //sprawdzamy czy dany produkt znajduje się w bazie
{
s[i].ilosc=s[i].ilosc-1;
if (s[i].ilosc<0)
{
cout<<"\n--------------";
cout<<"\n-BRAK TOWARU-";
cout<<"\n--------------"<<endl;
s[i].ilosc=0;
punkty=0;
}
else
{
cout<<"Nr."<<s[i].numer<<endl;
cout<<"kategoria : "<<s[i].kategoria<<endl;
cout<<"nazwa_produktu : "<<s[i].nazwa_produktu<<endl;
cout<<"dostepna ilosc : "<<s[i].ilosc<<endl;
cout<<"Cena : "<<s[i].cena<<endl;
cout<<"- - - - - - - - - - - - -\n";
punkty=s[i].cena / 10; //Za każde wydane 10 zł przyznawany jest 1 punkt
for(int i=0;i<dlugosc_klient;++i) //klinentowi, ktory kupil produkt przypisujemy punkty
if (znaleziony_klient==w[i].numer)
{
w[i].punkty+=punkty; //dodajemy punkty do puli punktow posiadanych przez klienta
}
}
//return punkty;
}
}
return numer;
}
//*******************************************************************************************************
void rabat(Klient *w, Produkt *s, int numer, int znaleziony, int &dlugosc_produkt, int dlugosc_klient)
{
int punkty;
for(int i=0;i<dlugosc_klient;++i)
if (znaleziony==w[i].numer)
{
punkty=w[i].punkty;
/*w[i].punkty=0;
w[i].numer;
w[i].login;
w[i].punkty; /*
}
for(int i=0;i<dlugosc_produkt;++i)
{
/*s[i].numer;
s[i].kategoria;
s[i].nazwa_produktu;
s[i].ilosc;
s[i].cena;*/
if (numer==s[i].numer)
{
cout <<"Cena po rabacie : " <<endl;
cout<<"Nr." <<s[i].numer<<endl;
cout<<"kategoria : "<<s[i].kategoria<<endl;
cout<<"nazwa_produktu : "<<s[i].nazwa_produktu<<endl;
cout<<"dostepna ilosc : "<<s[i].ilosc<<endl;
cout<<"Cena : "<<s[i].cena-punkty<<endl;
cout<<"- - - - - - - - - - - - -\n";
}
}
}
//*******************************************************************************************************
int _tmain(int argc, _TCHAR* argv[])
{
int dlugosc_klient, dlugosc_produkt; // zmienne przechowywujace wielkosc bazy
int znaleziony_klient, numer;
char * klienci = ("klienci.txt");
char * produkty = ("produkty.txt");
char znak, login, wybor, kto;
string login_admin;
int enter;
dlugosc_produkt=rozmiar_produkt(produkty)-1;
dlugosc_klient=rozmiar_klient(klienci)-1;
Produkt *s = new Produkt [dlugosc_produkt+1];
Klient *w = new Klient [dlugosc_klient+10];
zpliku_produkt(produkty, s, dlugosc_produkt);
zpliku_klient(klienci, w, dlugosc_klient);
zapis_produkt(produkty, s, dlugosc_produkt);
zapis_klient(klienci, w, dlugosc_klient);
tu: // miejsce wyskoku
do
{
system("cls");
cout << " WITAMY W SKLEPIE\n\n";
cout<<" Administrator" << "\t\t\twcisnij - 1\n";
cout<<" Klient" << "\t\t\t\twcisnij - 2\n";
cout<<" Wyloguj" << "\t\t\t\twcisnij - 0\n";
cin >> kto;
switch (kto)
{
case '1':
{
do
{
//cout<<" Podaj login: ";
//cin>>login_admin;
//if (login_admin=="admin")
//{
system("cls");
cout<<" Dodaj Produkt" << "\t\t\twcisnij - 1\n";
cout<<" Dodaj klienta" << "\t\t\twcisnij - 2\n";
cout<<" Pokaz Produkty" << "\t\t\twcisnij - 3\n";
cout<<" Pokaz klientow" << "\t\t\twcisnij - 4\n";
cout<<" Wyloguj" << "\t\t\t\twcisnij - 0\n";
cin >> wybor;
switch (wybor)
{
case '1':
{
system("cls");
int n;
cout<<"ile produktow chcesz dodac:";
cin >> n;
int a = n;
int b = dlugosc_produkt;
// zapis_produkt(produkty, s, dlugosc_produkt);
delete[]s;
dlugosc_produkt=rozmiar_produkt(produkty)-1;
Produkt *s = new Produkt [dlugosc_produkt+n];
zpliku_produkt(produkty, s, dlugosc_produkt);
//Pomocnicza *p = new Pomocnicza [dlugosc_produkt];
dodaj_do_bazy_produkt(s,n,dlugosc_produkt);
zapis_produkt(produkty, s, dlugosc_produkt);
wypisz_produkt(s, dlugosc_produkt);
break;
}
case '2':
{
system("cls");
int n;
cout<<"ilu klientow chcesz dodac:";
cin >> n;
dodaj_do_bazy_klient(w,n,dlugosc_klient);
break;
}
case '3':
{
wypisz_produkt(s, dlugosc_produkt);
system("pause");
break;
}
case '4':
{
wypisz_klient(w, dlugosc_klient);
system("pause");
break;
}
}
}
while(wybor!='0');
goto tu; //po skonczeniu petli wyskakujemy do glownego menu
}
case '2':
{
znaleziony_klient=szukaj(w,dlugosc_klient);
if (znaleziony_klient)
{
do
{
cout<<" Wypisz produkty" << "\t\twcisnij - 1\n";
cout<<" Kup" << "\t\t\twcisnij - 2\n";
cout<<" Wyloguj" << "\t\t\twcisnij - 0\n";
cin >> wybor;
switch(wybor)
{
case '1':
{
wypisz_produkt(s, dlugosc_produkt);
break;
}
case '2':
{
numer=kup(s,dlugosc_produkt,w,dlugosc_klient,znaleziony_klient);
if (numer>dlugosc_produkt)
{
cout<<"Niema takiego produktu\n"<<endl;
}
else
{
cout<<"Czy chcesz skorzystac z rabatu ? T/N \n";
cin >> wybor;
wybor=toupper(wybor); // funkca zamieniająca małą literę na dużą
if (wybor=='T')
rabat(w,s,numer,znaleziony_klient,dlugosc_produkt,dlugosc_klient);
}
}
}
}
while (wybor!='0');
}
_sleep(500); //opóźniamy program o 500 ms
}
}
}
while (kto!='0');
zapis_produkt(produkty, s, dlugosc_produkt);
zapis_klient(klienci, w, dlugosc_klient);
delete[]s;
delete[]w;
return 0;
}
I co mamy z tą 500-linijkową kobyłą zrobić?
Co wiecej widze tam jakieś goto co jeszcze bardziej zniechęca do babrania się w tym kodzie.
Moje rady?
klajter napisał(a)
Czemu, za mało, dosyć prosto to wygląda:
if(n>dlugosc_produkt)
{
delete[]s;
Produkt *s = new Produkt [n+dlugosc_produkt];
>
> zwalnia s (to poziom wyżej), potem tworzy nowe lokalne s i pewnie gubi do niego wskaźnik. "Wyższe" s jest usunięte i wskazuje na śmieci, a "niższe" s jest gubione, i leci wyjątek ;).
w jakim sensie gubie wskźnik?
Faktycznie dość ewidentny błąd ;]
Produkt *s = new Produkt [n+dlugosc_produkt];
Tworzysz tutaj nową zmienną o nazwie s, która "zasłania" twoje stare s. Po wyjściu z tego bloku if() {} ta nowa zmienna s znika, a stara zmienna s jest zwolniona. W ten sposób kolejne zwolnienie s powoduje błąd.
zmień to na:
s = new Produkt [n+dlugosc_produkt];
Dzięki wielkie za pomoc, wszystko teraz śmiga jak należy, a co do poprawy na obiektowe, to niebardzo już mam na to czas, ale dzięki za rade na pewno by to lepiej wyglądało