personGR Δημοσ. 15 Δεκεμβρίου 2011 Δημοσ. 15 Δεκεμβρίου 2011 Καλησπέρα, έχω τον παρακάτω κώδικα στο vstudio 2010, τον οποίο, όταν τον τρέχω μου πετάει το Debug Assertion Failed! πρόβλημα. Ναι, είναι για εργασία το όλο θέμα, αλλά η χρήση pointers είναι καθαρά προσωπική επιλογή γιατί θέλω να καταλάβω καλά πως λειτουργούν μέσα στις κλάσεις. Μπορεί κάποιος να μου εξηγήσει γιατί στραβώνει; #include <iostream> #include <stdlib.h> #include <string> using namespace std; class Student {private: char *name; int M; float *marks; int N; int id; int subjects; float MO; int sub_passed; int sub_failed; float max_mark; float min_mark; public: Student(int pl, float *v, char *name_temp,int a); ~Student(); void setData1(int AFM, int mathimata, float vathmologia[]); void setData2(); void getData(); }; Student::Student(int pl, float *v, char *name_temp, int a) { if(a==0){ a=strlen("NO_NAME_GIVEN"); name = new char[a]; name = "NO_NAME_GIVEN"; } else { name = new char[a]; name = name_temp; } N = pl; marks = new float[N]; if (marks != 0) { for (int i=0; i<N; i++) marks = v; } id = 0; subjects = 0; MO=0; sub_passed=0; sub_failed=0; max_mark=0; min_mark=0; cout << "Student initialized.\n"; } Student::~Student() { delete [] marks; delete [] name; cout << "Student destroyed.\n"; } void Student::setData1(int AFM, int mathimata, float vathmologia[]){ if (AFM>1 && AFM<9999) id = AFM; if (mathimata>0 && mathimata<9) subjects = mathimata; for(int i=0; i<N; i++){ if (vathmologia>=1.0 && vathmologia<=10.0) marks = vathmologia; } } void Student::setData2(){ float sum=0,max = -1, min = 11; int sum1=0, sum2=0; for(int i=0;i<N;i++) { sum = sum + marks; if (marks>max) max = marks; if (marks<min) min = marks; if (marks>5) sum1 += 1; if (marks<5) sum2 += 1; } MO = sum/N; max_mark= max; min_mark = min; sub_passed = sum1; sub_failed = sum2; } void Student::getData() { cout<<"\n\n"; cout<<"(where the result is 0, invalid input was given.)\n"; cout<<"\nGiven name is: "<<name<<endl; cout<<"\nRegistration Number: "<<id<<endl; cout<<"\nSubjects attended: "<<subjects<<endl; for(int i=0;i<N;i++) cout<<"\nMark got in subject No."<<i+1<<": "<<marks; cout<<"\n\nAverage of all subjects: "<<MO<<endl; cout<<"\nHighest Mark: "<<max_mark<<endl; cout<<"\nLowest Mark: "<<min_mark<<endl; cout<<"\nSubjects passed: "<<sub_passed<<endl; cout<<"\nSubjects failed to pass: "<<sub_failed<<endl; cout<<"\n"; } int main(void) { int mhtrwo, plithos,length; float *vathmoi; char onoma[40]; cout << "Type Name: "; gets(onoma); length = strlen(onoma); cout << "Type Identification Number: "; cin >> mhtrwo; cout << "Type number of subjects: "; cin >> plithos; vathmoi = new float[plithos]; for(int i=0; i<plithos; i++){ cout << "Type mark for subject No."<<i+1<<": "; cin >> vathmoi; } Student s1(plithos,vathmoi,onoma,length); s1.setData1(mhtrwo, plithos, vathmoi); s1.setData2(); s1.getData(); delete [] vathmoi; system("pause"); return 0; } Ο όλος κώδικας λειτουργεί ως εξής: Το πρόγραμμα ζητάει όνομα, μητρώο, πόσα μαθήματα πέρασε έδωσε κάποιος και τις βαθμολογίες του σε αυτά, υπολογίζει ΜΟ, max/min βαθμολογίες και αριθμό μαθημάτων που πέρασε ή κόπηκε. Ελέγχει όλες τις τιμές(setData1/setData2) και τις εκτυπώνει (getData). Ξέρω, είναι πανεύκολο, αλλά κολλάω στη χρήση pointers (ειδικα αυτόν του name) - αλλιώς τρέχει τέλεια.
Stavros_Ribo Δημοσ. 16 Δεκεμβρίου 2011 Δημοσ. 16 Δεκεμβρίου 2011 Αν και το είδα στα γρήγορα βρήκα κάποιες εναλλακτικές λύσεις. Αρχικά να σου πω, πως όταν για π.χ. έχεις name = new char[a]; name = name_temp; τότε ουσιαστικά η πρώτη εντολή που κάνεις δεν χρειάζεται. Με την name = new char[a]; λες ο δείκτης name να δείχνει σε μία περιοχή της μνήμης όπου δημιουργούνται πλήθος α από char. Αν μετά κάνεις name = name_temp; τότε ουσιαστικά βάζεις τον δείκτη να δείχνει κάπου αλλού αχρηστεύοντας την προηγούμενη περιοχή μνήμης που είχες δεσμεύσει. Αρχικά, αν θες όρισε στα include καλύτερα την βιβλιοθήκη #include<cstring> ώστε να μπορείς να χρησιμοποιήσεις συναρτήσεις όπως strlen και strcpy. με τη συνάρτηση strcpy(buf1, buf2) μπορείς να αντιγράψεις το buf2 στο buf1. π.χ. χρησιμοποίησέ το αντί για name = "NO_NAME_GIVEN"; βάλε strcpy(name,"NO_NAME_GIVEN"); Αντί για την gets μπορείς να βάλεις επίσης την cin αλλά δεν νομίζω ότι αλλάζει κάτι. Απλά έτσι τρέχει σε εμένα. Τέλος πάντων δεν είναι πολύ καλό να την χρησιμοποιείς την gets. Στη main τώρα ορίζεις έναν στατικό πίνακα onoma[40] και περνάς στον constructor της Student την διεύθυνση της μηδενικής θέσης. Άρα ουσιαστικά βάζεις τον pointer name, να δείχνει σε αυτή τη θέση(την διεύθυνση του μηδενικού στοιχείου του πίνακα onoma[40]). Άρα στο τέλος πας και ζητάς delete [] name, που δεν είναι σωστό μιας και δεν μπορεί να κάνει delete τον pointer που δείχνει σε στατικό π.χ. πίνακα. Άρα μια λύση: όρισε στη main char *onoma=new char[40]; (αντί για char onoma[40]; ) και μαζί με strcpy(name,"NO_NAME_GIVEN"); θα τρέξει μια χαρά το πρόγραμμα και θα αποδεσμεύσει σωστά τη μνήμη στο τέλος. Άλλη λύση θα ήταν αφήνοντας στη main το char onoma[40],στην Student() αντί για name = name_temp; να βάλεις και πάλι strcpy(name,name_temp); (εδώ πρέπει να έχεις γράψει σίγουρα και το name = new char[a]; και να μην το παραλήψεις όπως θα μπορούσες να κάνεις στην προηγούμενη περίπτωση) ώστε να αντιγράψει στο name το name_temp. και πάλι θα αποδεσμεύσει σωστά τη μνήμη.
3c0r1z Δημοσ. 16 Δεκεμβρίου 2011 Δημοσ. 16 Δεκεμβρίου 2011 Καλημέρα, δεν ξέρω αν έχεις περιορισμούς όσον αφορά την λύση της άσκησης, κάλα είναι μιας και μιλάμε για C++ άσκηση να χρησιμοποιείσεις std::string αντί char* και std::vector<float> αντί float*. Την χρήση δεικτών μπορείς να την μάθεις αργότερα όταν θα έχεις εξοικειωθεί καλύτερα με την γλώσσα και τον debugger. Καλή συνέχεια. http://www.cplusplus.com/reference/
personGR Δημοσ. 16 Δεκεμβρίου 2011 Μέλος Δημοσ. 16 Δεκεμβρίου 2011 Thanks παιδιά, θα το κοιτάξω και θα ενημερώσω @Stavros_Ribo έβαλα gets γιατί νομίζω ότι cout "κλωτσάει" άμα έχει κενό το string. Δεν το έχω ψάξει ιδιαίτερα βέβαια, αν και είδα κάτι για μια συνάρτηση getline, είμαι άπειρος όμως ακόμα και δε θέλω να βάλω πράματα που δε μας έχει πει ο καθηγητής.
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα