|
 |
|
 |
01-11-2005, 03:51 PM
|
#1 (permalink)
|
|
Registered User
Join Date: Sep 2004
Posts: 21
|
Problem with linked list Database
Hello again, I just started a new semester at school and already have ran into a problem.
The assignment is to build a menu driven program that manages info on students, courses and grades for a school. I am given a student.dat, course.dat, and grade.dat files.
My problem is where to begin? Do I make each class for students, courses and grades each a linked list?
And after that, how do I find info on a student, do I have to transverse the course linked list to find all the info I need? The grades file has student ID's, classes and grades, course file only have class num and name, and student file has Fname, Lname, ID, and phone #.
Any help will be appriciated.
Tst
|
|
|
01-11-2005, 11:31 PM
|
#2 (permalink)
|
|
[code][/code] enforcer
Join Date: Mar 2003
Location: Netherlands
Posts: 1,545
|
Quote:
|
And after that, how do I find info on a student, do I have to transverse the course linked list to find all the info I need?
|
What do you need exactly?
- Do you have to show all the students info (names, phone AND grades and classes).
- Or do you have to display a very specific students info?
The latter can't be done with linked lists. They are not designed for random access. However, you could traverse the list, but only show the desired student, for examply by its first name or ID. Compare ID's from student class with ID in grades.dat for example.
Do you also want to add new students to the dat file? Or new courses to the course file? Etcetera.
Anyway, start with thinkin about the world you are talking about. This is called domain problem analysis.
Here is my view on what a student is:
Code:
#ifndef STUDENT_H
#define STUDENT_H
#include <string>
using std::string;
struct Student
{
string _FirstName;
string _LastName;
string _ID;
double _PhoneNumber;
};
#endif //STUDENT_H
And so on with other classes.
Then I was experimenting with a StudentLinkedList:
Code:
#ifndef STUDENTLINKEDLIST_H
#define STUDENTLINKEDLIST_H
#include "Student.h"
#include <iostream>
using std::cout;
using std::endl;
struct Node
{
Student* Item;
Node *Next;
};
class StudentLinkedList
{
public:
void AddItem(Student* itm);
void ShowItems();
StudentLinkedList() : m_nodeStart(0){ }
~StudentLinkedList();
private:
Node* m_nodeStart;
};
void StudentLinkedList::AddItem(Student* itm)
{
Node* p = m_nodeStart;
m_nodeStart = new Node;
m_nodeStart->Next = p;
m_nodeStart->Item = itm;
}
void StudentLinkedList::ShowItems()
{
for(Node* p = m_nodeStart; p != 0; p = p->Next)
cout<<p->Item->_FirstName << endl;
}
StudentLinkedList::~StudentLinkedList()
{
Node* p;
while(m_nodeStart != 0)
{
p = m_nodeStart;
m_nodeStart = m_nodeStart->Next;
delete p;
}
}
#endif //STUDENTLINKEDLIST_H
This list could be generalized (templates) if needed. Depends on if you need more Linked lists. You aren't very clear about it.
Then here is a quick test:
Code:
#include <iostream>
#include <string>
#include <climits>
#include "Student.h"
#include "StudentLinkedList.h"
using std::cin;
using std::numeric_limits;
using std::streamsize;
using std::string;
//Optional function: depends on IDE. Remove if not needed.
void wait_for_enter();
int main( int argc, char *argv[] )
{
Student aStudent;
aStudent._FirstName = "Alex";
StudentLinkedList theStudents;
theStudents.AddItem(&aStudent);
theStudents.ShowItems();
wait_for_enter();
return 0;
}
//---------------------------------------------------
void wait_for_enter()
{
cout << "press <enter> to continue...";
// Reset failstate, just in case.
cin.clear();
string line;
getline( cin, line);
}
So basically these are my very first thoughts. From here I could build the things I need, if I only new exactly what I need. See if this starter helps.
Anyway, the questions that remain are:
- Do you want to modify info? If so, what exactly?
- Do you have to build a linked list of courses and grades as well? If so, do you have to traverse these lists as well for some reason?
Etcetera etcetera. If you're stuck, then post the requirements more accurately next time you post. This way I will know how to analyse things and how to setup a design exactly.
Your current skillset is also relevant. If you mention "menu driven" then I can think of a few designs. But some may be too much right now. That's why.
Good luck!
__________________
Last edited by Valmont; 01-12-2005 at 12:05 AM.
|
|
|
01-12-2005, 06:58 PM
|
#3 (permalink)
|
|
Registered User
Join Date: Sep 2004
Posts: 21
|
OK, by menu driven I mean there is a menu that it returns to after each command is given,
1. add/modify grade
2. remove grade
3. grade of one student
4. grades from one course
5. student list
6. course list
7. exit
The main problem I'm having is that when you do 3. grades of one student, it needs the fname and lname of the person, not in the grade file, but in the student file. If you could explain what I'm supposed to do here, it would be wonderful. I only mentioned linked lists because the teacher suggested it so I figured it would be the easiest
|
|
|
01-12-2005, 10:41 PM
|
#4 (permalink)
|
|
Registered User
Join Date: Sep 2004
Posts: 21
|
I decided to just go with 3 arrays. I figure I can just look through each array til I find the info I am looking for. Hopefully it won't be graded on efficency, it shouldn't being that its the first week of class yet
|
|
|
01-12-2005, 11:33 PM
|
#5 (permalink)
|
|
[code][/code] enforcer
Join Date: Mar 2003
Location: Netherlands
Posts: 1,545
|
Oh wait a minute. Linked lists aren't a requirement? In that case use std::vector. You can find it in <vector> header. Although I really think you should learn the std::map container. To be found int <map>.
So.
Anyway, the grades file has an student_ID and the student file has a student_ID. Use this to your advantage.
I'll be back later.
__________________
Last edited by Valmont; 01-13-2005 at 12:14 AM.
|
|
|
01-13-2005, 12:58 AM
|
#6 (permalink)
|
|
[code][/code] enforcer
Join Date: Mar 2003
Location: Netherlands
Posts: 1,545
|
Quote:
|
Originally Posted by toast28
OK, by menu driven I mean there is a menu that it returns to after each command is given,
1. add/modify grade
2. remove grade
3. grade of one student
4. grades from one course
5. student list
6. course list
7. exit
The main problem I'm having is that when you do 3. grades of one student, it needs the fname and lname of the person, not in the grade file, but in the student file. If you could explain what I'm supposed to do here, it would be wonderful. I only mentioned linked lists because the teacher suggested it so I figured it would be the easiest
|
How are going to lookup the student's info to start with? By ID?
And how is the course.dat file related to the rest? It only holds the class numbers and the course-names right?
__________________
|
|
|
01-13-2005, 02:55 PM
|
#7 (permalink)
|
|
Registered User
Join Date: Sep 2004
Posts: 21
|
Yes, the primary way of getting info will be through the Student ID #. And yes the course.dat just has class number and a full name. I made 3 arrays, students and courses are pretty straight forward, but grades will have 3 fields per entry; ID, Classnum, and Grade. For ID, it will point to the record in students array of that student. For Classnum, it will point to the classnum in courses array.
After finally settling on a data type this program doesn't seem nearly as complicated as it first did.
Thanks for your help Valmont.
P.S. Are you the only one that answers questions here? I see your name in almost every thread.
|
|
|
01-13-2005, 03:51 PM
|
#8 (permalink)
|
|
Registered User
Join Date: Sep 2004
Posts: 21
|
Now I must have some logic error in my program. I am trying to output all students grades to the screen. I get the first one out OK, but then it doesn't want to output anything after their names for students 1-x. Here is a snip of my code, if anyone can see where I went wrong logically, please tell me.
Code:
counter=0;
if (input =="*")
{//do all students
ID=students[counter].ID;
first=students[counter].firstname;
count=0;
while(first!="")
{
cout << setw(12) << left << students[counter].firstname;
cout << setw(12) << left << students[counter].lastname;
cout << setw(6) << left << students[counter].ID;
num=grades[count].classnum;
while(num!="")
{
if(ID==grades[count].ID)
{
grade=grades[count].lettergrade;
classnum=grades[count].classnum;
counting=0;
while(courses[counting].name!="")
{
if(courses[counting].num==classnum)
{
cout << setw(31) << left <<courses[counting].name;
cout << setw(7) << left << courses[counting].num;
cout << setw(1) << grade << endl;
}//end if
counting++;
}//end while
}//end if
count++;
num=grades[count].classnum;
}//end while
counter++;
first=students[counter].firstname;
}//end while
Last edited by Valmont; 01-14-2005 at 03:45 AM.
|
|
|
01-13-2005, 06:08 PM
|
#9 (permalink)
|
|
[code][/code] enforcer
Join Date: Mar 2003
Location: Netherlands
Posts: 1,545
|
No I do standard C++ only. Others do other things.
__________________
|
|
|
01-14-2005, 03:47 AM
|
#10 (permalink)
|
|
[code][/code] enforcer
Join Date: Mar 2003
Location: Netherlands
Posts: 1,545
|
I haven't looked properly at your code yet but did you learn the ways of classes and structs yet?
And besides, don't hesitate to post the complete code if you're communicating with me. I don't get offended by long codes.
Besides, you could use a trick or one or two. First the complete code. And tell me your current concrete skillset. I was working silently on the menu program, but I haven't got a clue if you would understand it.
__________________
|
|
|
01-14-2005, 09:42 AM
|
#11 (permalink)
|
|
Registered User
Join Date: Sep 2004
Posts: 21
|
Umm, what do you mean my skill set? how proficient am I? I'd say pretty good, I've been working on C++ code for 5 years and am taking 400 level college classes.
I figured out my logic error, I wasn't resetting a variable. But now a I have a simple problem that is giving me a headache. I have input as a string for student grade list, you either enter a 4 digit ID number or * to see all students. I have the * part done right, but if its an ID entered, how do I get input changed to an int?
Here is all my code, please don't be too brutal.
Code:
//create a menu based system that reads in 3 files; student, grades, and classes
//and allows the user to add/modify a grade, remove a grade, print a student grade report
//print a course grade report, list all students, and list all classes.
#include <iostream>
#include <fstream>
#include <string>
#include <ctype.h>
#include <iomanip>
#include <ctype.h>
using namespace std;
struct student
{
string firstname;
string lastname;
int ID;
string phone;
};
struct grade
{
int ID;
string classnum;
char lettergrade;
};
struct course
{
string num;
string name;
};
//subroutine menu
//used to print out the menu choices
// returns the number that they choose
char menu()
{
char menuchoice =0;
cout << endl << endl << endl << endl
<< "1. Add/Modify Grade" << endl
<< "2. Remove Grade" << endl
<< "3. Student Grade Report" << endl
<< "4. Course Grade Report" << endl
<< "5. List Students" <<endl
<< "6. List Courses" << endl
<< "7. Exit" << endl;
cout << endl << endl << "Enter the number of what you would like to do -> ";
cin >> menuchoice;
return menuchoice;
}
//function to add/modify a grade
void add(grade grades[], course courses[], student students[])
{
int ID,counter;
string num,classnum,name;
char letter;
grade tempgrade;
bool inlist=false;
cout << "Please enter a student ID ->";
cin >> ID;
cout << endl << "Please enter a course number ->";
cin >> num;
cout << endl << "Please enter a grade ->";
cin >> letter;
toupper(letter);
//toupper(num.c_str());
if (letter==char("Q"))
{
cout << "Quitting"<< endl;
return;
}
if( (letter==char('A')) || (letter==char('B')) || (letter==char('C'))
|| (letter==char('D')) || (letter==char('E')) || (letter==char('F'))
|| (letter==char('I')) ) //valid letters
{
counter=0;
classnum=courses[counter].num;
while (courses[counter].num!="")
{
if (courses[counter].num==num)
{
inlist=true;
cout << "Course number OK" << endl;
}
counter++;
classnum=courses[counter].num;
}//end while
if(!inlist)
{
cout << "Course number not in database" << endl;
return;
}
//check if ID is valid
counter=0;
name=students[counter].firstname;
inlist=false;
while (name!="")
{
if(students[counter].ID==ID)
{
inlist=true;
cout << "Student ID OK"<< endl;
}
counter++;
name=students[counter].firstname;
}
if(!inlist)
{
cout << "Student ID not in database" << endl;
return;
}
//check if student already has a grade
tempgrade = grades[0];
counter =0;
inlist=false;
while (tempgrade.classnum!="")
{
if (grades[counter].ID == ID)
{
if(grades[counter].classnum==num) //its a match, just modify
{
grades[counter].lettergrade=letter;
cout << "Student " << ID << " in " << num
<< " has been changed to " << letter << endl;
inlist=true;
}
}
counter++;
tempgrade=grades[counter];
}
if(!inlist)//need to add to database
{
cout << "Adding Student " << ID << " to database" << endl;
grades[counter].ID = ID;
grades[counter].classnum=num;
grades[counter].lettergrade=letter;
}
}
else
{
cout << "Invalid Letter Grade" << endl;
return;
}
}
// function to remove a grade
void remove(grade grades[], course courses[], student students[])
{
int ID,counter;
string num,name,classnum;
bool inlist;
cout << "Please enter a Student ID ->";
cin >>ID;
cout << "Please enter a course number ->";
cin >> num;
//check if ID is in database
inlist=false;
counter=0;
name=students[counter].firstname;
while(name!="")
{
if (students[counter].ID==ID)
{
inlist=true;
cout <<"Student ID OK" << endl;
}
counter++;
name=students[counter].firstname;
}// end while
if(!inlist)
{
cout << "Student ID not found" << endl;
return;
}
//check course number
counter=0;
inlist=false;
classnum=courses[counter].num;
while(classnum!="")
{
if(courses[counter].num==num)
{
cout << "Course Number OK" << endl;
inlist=true;
}
counter++;
classnum=courses[counter].num;
}//end while
if(!inlist)
{
cout <<"Course Number not in database"<< endl;
return;
}
counter=0;
while(grades[counter].ID!=ID)
{
counter++;
}
while(grades[counter].classnum!="")
{
grades[counter].classnum=grades[counter+1].classnum;
grades[counter].ID=grades[counter+1].ID;
grades[counter].lettergrade=grades[counter+1].lettergrade;
counter++;
}
grades[counter-1].classnum="";//reset so loops stop right
cout << "Student " << ID << " was removed from " << num << endl;
}
// function to vew a student grade report
void studgrad(grade grades[], course courses[], student students[])
{
int ID,counter,count, counting;
string first,num,classnum;
char grade;
string input;
bool newstudent=true;
cout << "Please enter a Student ID ->";
cin >> input;
cout << setw(12) << left << "First Name";
cout << setw(12) << left << "Last Name";
cout << setw(8) << left << "ID";
cout << setw(31) << left << "Course Name";
cout << setw(7) << left << "Num";
cout << setw(1) << "Grade" << endl;
counter=0;
if (input =="*")
{//do all students
ID=students[counter].ID;
first=students[counter].firstname;
count=0;
while(first!="")
{
cout << setw(12) << left << students[counter].firstname;
cout << setw(12) << left << students[counter].lastname;
cout << setw(6) << left << students[counter].ID;
count=0;
ID=students[counter].ID;
num=grades[count].classnum;
while(num!="")
{
if(ID==grades[count].ID)
{
grade=grades[count].lettergrade;
classnum=grades[count].classnum;
counting=0;
if(!newstudent)
{
cout << endl;
cout << " ";
}//end if
while(courses[counting].name!="")
{
if(courses[counting].num==classnum)
{
cout << setw(31) << left <<courses[counting].name;
cout << setw(7) << left << courses[counting].num;
cout << setw(1) << grade;
newstudent=false;
}//end if
counting++;
}//end while
}//end if
count++;
num=grades[count].classnum;
}//end while
counter++;
first=students[counter].firstname;
newstudent=true;
cout << endl;
}//end while
}
else //output for one student
{
//validate student ID
//StringToInt(input,ID);
}
}
//function to view a course grade report
void courgrad(grade grades[], course courses[], student students[])
{
string input, num,name;
int count,counter,ID;
bool inlist=false;
char grade;
cout<<"Please enter a course number ->";
cin >> input;
cout << setw(12) << left << "First Name";
cout << setw(12) << left << "Last Name";
cout << setw(8) << left << "ID";
cout << setw(31) << left << "Course Name";
cout << setw(7) << left << "Num";
cout << setw(1) << "Grade" << endl;
if(input=="*") //do all courses and students
{
count=0;
ID=students[count].ID;
while(name!="")
{
//if(grades[count].ID=
}//end while
}//endif
else //just one course
{ //check if input is valid
count=0;
num=grades[count].classnum;
while(num!="")
{
if (grades[count].classnum==input)
{
inlist=true;
}//end if
count++;
num=grades[count].classnum;
}//end while
if(!inlist)
{
cout << "Course number not found." << endl;
return;
}//end if
//start output of data
count=0;
num=grades[count].classnum;
while(num!="")
{
if(grades[count].classnum==input)
{
ID=grades[count].ID;
grade=grades[count].lettergrade;
counter=0;
name= students[counter].firstname;
while(name!="")
{
if(students[counter].ID==ID)
{
cout << setw(12) << left << students[counter].firstname;
cout << setw(12) << left << students[counter].lastname;
cout << setw(6) << left << ID;
cout << setw(31) << left << courses[count].name;
cout << setw(7) << left << courses[count].num;
cout << setw(1) << left << grade << endl;
}
counter++;
name=students[counter].firstname;
}//end while
}
count++;
num=grades[count].classnum;
}//endwhile
}//end else
}
//function to view a list of all students in a class
void liststud(student students[])
{
cout << endl << endl;
cout<<setw(12) << left << "First Name" << setw(12) << left << "Last Name";
cout<<setw(6) << left << "ID";
cout<<setw(13) <<left << "Phone" << endl;
int counter=0;
string name=students[counter].firstname;
while(name!="")
{
cout << setw(12) << left << students[counter].firstname;
cout << setw(12) << left << students[counter].lastname;
cout << setw(6) << left << students[counter].ID;
cout << setw(13) << left << students[counter].phone;
cout << endl;
counter++;
name=students[counter].firstname;
}// end while
}
// function to display all courses listed
// simple loop til the end of course array
void listcourses(course courses[])
{
cout << endl << endl << endl;
cout << setw(7) << left << "Num";
cout << setw(31) << left << "Course Name" << endl;
int counter=0;
string num=courses[counter].num;
while (num!="")
{
cout << setw(7) << left << courses[counter].num;
cout << setw(31) << left << courses[counter].name;
cout << endl;
counter++;
num=courses[counter].num;
}//end while
}
// exit function
// must save data back to file before exiting
void myexit(grade grades[], course courses[], student students[])
{
int count;
string name;
ofstream outfile;
outfile.open("student.out");
count =0;
name = students[count].firstname;
while(name!="")
{
outfile << setw(12)<< left<< students[count].firstname
<< setw(12) << left << students[count].lastname
<< setw(6) << left << students[count].ID
<< setw(13) << left << students[count].phone << endl;
count++;
name=students[count].firstname;
}//end while
outfile.close();
outfile.open("course.out");
count =0;
name=courses[count].num;
while(name!="")
{
outfile << setw(7) << left << courses[count].num
<< setw(31) << left << courses[count].name << endl;
count++;
name=courses[count].num;
}// end while
outfile.close();
outfile.open("grade.out");
count =0;
name=grades[count].classnum;
while(name!="")
{
outfile << setw(6) << left << grades[count].ID
<< setw(7) << left << grades[count].classnum
<< setw(1) << left << grades[count].lettergrade << endl;
count++;
name=grades[count].classnum;
}//endwhile
outfile.close();
cout << "Files written." << endl;
}
void readdata(char* argv[],grade grades[], course courses[], student students[])
{
string first, last, phone;
int ID,counter;
char letter;
ifstream infile1 (argv[1]);
infile1 >> first >> first >>first >>first; // clear the first line
counter=0;
while (!infile1.eof())
{
infile1 >> first >> last >> ID >> phone;
students[counter].firstname=first;
students[counter].lastname = last;
students[counter].ID = ID;
students[counter].phone=phone;
counter++;
}//end while
infile1.close();
ifstream infile2 (argv[2]);
infile2 >> first >> first;
counter=0;
while (!infile2.eof())
{
infile2 >> first;
getline(infile2,last);
courses[counter].name=last;
courses[counter].num=first;
counter++;
};//end while
infile2.close();
ifstream infile3 (argv[3]);
getline(infile3,first);
//infile3 >>ID >> first >> first;
counter=0;
while(!infile3.eof())
{
infile3 >> ID >> first >> letter;
grades[counter].ID=ID;
grades[counter].classnum=first;
grades[counter].lettergrade=letter;
counter++;
};//end while
infile3.close();
}
int main(int argc,char* argv[])
{
char item;
string first,last,phone;
student students[1000];
grade grades[10000];
course courses[9999];
readdata(argv,grades,courses,students);
while(item!=7)
{
item = menu();
if(item==int('A'))
item=1;
else if(item==int('a'))
item=1;
if(item==int('R'))
item=2;
else if(item==int('r'))
item=2;
if(item==int('S'))
item=3;
else if(item==int('s'))
item=3;
if(item==int('C'))
item=4;
else if(item==int('c'))
item=4;
if(item==int('L'))
item=5;
else if(item==int('l'))
item=5;
if(item==int('D'))
item=6;
else if(item==int('d'))
item=6;
else if(item ==int('E'))
item=7;
else if(item ==int('e'))
item=7;
if (item ==1)
add(grades, courses, students);
else if (item ==2)
remove(grades, courses, students);
else if (item ==3)
studgrad(grades, courses, students);
else if (item ==4)
courgrad(grades, courses, students);
else if (item ==5)
liststud(students);
else if (item ==6)
listcourses(courses);
};//end while
myexit(grades, courses, students);
return 0;
}//end main
|
|
|
01-14-2005, 10:21 AM
|
#12 (permalink)
|
|
Registered User
Join Date: Sep 2004
Posts: 21
|
I have a little bit of an update, I got the course grade * thing working, but now have a bug in the regular part. If CS240 is entered, it doesn't output the classname or classnumber. I see the problem, count is way to high, but have to go to work, no time to fix it.
Code:
//create a menu based system that reads in 3 files; student, grades, and classes
//and allows the user to add/modify a grade, remove a grade, print a student grade report
//print a course grade report, list all students, and list all classes.
#include <iostream>
#include <fstream>
#include <string>
#include <ctype.h>
#include <iomanip>
#include <ctype.h>
using namespace std;
struct student
{
string firstname;
string lastname;
int ID;
string phone;
};
struct grade
{
int ID;
string classnum;
char lettergrade;
};
struct course
{
string num;
string name;
};
//subroutine menu
//used to print out the menu choices
// returns the number that they choose
char menu()
{
char menuchoice =0;
cout << endl << endl << endl << endl
<< "1. Add/Modify Grade" << endl
<< "2. Remove Grade" << endl
<< "3. Student Grade Report" << endl
<< "4. Course Grade Report" << endl
<< "5. List Students" <<endl
<< "6. List Courses" << endl
<< "7. Exit" << endl;
cout << endl << endl << "Enter the number of what you would like to do -> ";
cin >> menuchoice;
return menuchoice;
}
//function to add/modify a grade
void add(grade grades[], course courses[], student students[])
{
int ID,counter;
string num,classnum,name;
char letter;
grade tempgrade;
bool inlist=false;
cout << "Please enter a student ID ->";
cin >> ID;
cout << endl << "Please enter a course number ->";
cin >> num;
cout << endl << "Please enter a grade ->";
cin >> letter;
toupper(letter);
//toupper(num.c_str());
if (letter==char("Q"))
{
cout << "Quitting"<< endl;
return;
}
if( (letter==char('A')) || (letter==char('B')) || (letter==char('C'))
|| (letter==char('D')) || (letter==char('E')) || (letter==char('F'))
|| (letter==char('I')) ) //valid letters
{
counter=0;
classnum=courses[counter].num;
while (courses[counter].num!="")
{
if (courses[counter].num==num)
{
inlist=true;
cout << "Course number OK" << endl;
}
counter++;
classnum=courses[counter].num;
}//end while
if(!inlist)
{
cout << "Course number not in database" << endl;
return;
}
//check if ID is valid
counter=0;
name=students[counter].firstname;
inlist=false;
while (name!="")
{
if(students[counter].ID==ID)
{
inlist=true;
cout << "Student ID OK"<< endl;
}
counter++;
name=students[counter].firstname;
}
if(!inlist)
{
cout << "Student ID not in database" << endl;
return;
}
//check if student already has a grade
tempgrade = grades[0];
counter =0;
inlist=false;
while (tempgrade.classnum!="")
{
if (grades[counter].ID == ID)
{
if(grades[counter].classnum==num) //its a match, just modify
{
grades[counter].lettergrade=letter;
cout << "Student " << ID << " in " << num
<< " has been changed to " << letter << endl;
inlist=true;
}
}
counter++;
tempgrade=grades[counter];
}
if(!inlist)//need to add to database
{
cout << "Adding Student " << ID << " to database" << endl;
grades[counter].ID = ID;
grades[counter].classnum=num;
grades[counter].lettergrade=letter;
}
}
else
{
cout << "Invalid Letter Grade" << endl;
return;
}
}
// function to remove a grade
void remove(grade grades[], course courses[], student students[])
{
int ID,counter;
string num,name,classnum;
bool inlist;
cout << "Please enter a Student ID ->";
cin >>ID;
cout << "Please enter a course number ->";
cin >> num;
//check if ID is in database
inlist=false;
counter=0;
name=students[counter].firstname;
while(name!="")
{
if (students[counter].ID==ID)
{
inlist=true;
cout <<"Student ID OK" << endl;
}
counter++;
name=students[counter].firstname;
}// end while
if(!inlist)
{
cout << "Student ID not found" << endl;
return;
}
//check course number
counter=0;
inlist=false;
classnum=courses[counter].num;
while(classnum!="")
{
if(courses[counter].num==num)
{
cout << "Course Number OK" << endl;
inlist=true;
}
counter++;
classnum=courses[counter].num;
}//end while
if(!inlist)
{
cout <<"Course Number not in database"<< endl;
return;
}
counter=0;
while(grades[counter].ID!=ID)
{
counter++;
}
while(grades[counter].classnum!="")
{
grades[counter].classnum=grades[counter+1].classnum;
grades[counter].ID=grades[counter+1].ID;
grades[counter].lettergrade=grades[counter+1].lettergrade;
counter++;
}
grades[counter-1].classnum="";//reset so loops stop right
cout << "Student " << ID << " was removed from " << num << endl;
}
// function to vew a student grade report
void studgrad(grade grades[], course courses[], student students[])
{
int ID,counter,count, counting;
string first,num,classnum;
char grade;
string input;
bool newstudent=true;
cout << "Please enter a Student ID ->";
cin >> input;
cout << setw(12) << left << "First Name";
cout << setw(12) << left << "Last Name";
cout << setw(8) << left << "ID";
cout << setw(31) << left << "Course Name";
cout << setw(7) << left << "Num";
cout << setw(1) << "Grade" << endl;
counter=0;
if (input =="*")
{//do all students
ID=students[counter].ID;
first=students[counter].firstname;
count=0;
while(first!="")
{
cout << setw(12) << left << students[counter].firstname;
cout << setw(12) << left << students[counter].lastname;
cout << setw(6) << left << students[counter].ID;
count=0;
ID=students[counter].ID;
num=grades[count].classnum;
while(num!="")
{
if(ID==grades[count].ID)
{
grade=grades[count].lettergrade;
classnum=grades[count].classnum;
counting=0;
if(!newstudent)
{
cout << endl;
cout << " ";
}//end if
while(courses[counting].name!="")
{
if(courses[counting].num==classnum)
{
cout << setw(31) << left <<courses[counting].name;
cout << setw(7) << left << courses[counting].num;
cout << setw(1) << grade;
newstudent=false;
}//end if
counting++;
}//end while
}//end if
count++;
num=grades[count].classnum;
}//end while
counter++;
first=students[counter].firstname;
newstudent=true;
cout << endl;
}//end while
}
else //output for one student
{
//validate student ID
//StringToInt(input,ID);
}
}
//function to view a course grade report
void courgrad(grade grades[], course courses[], student students[])
{
string input, num,name;
int count,counter,ID,counting;
bool inlist=false;
char grade;
cout<<"Please enter a course number ->";
cin >> input;
cout << setw(12) << left << "First Name";
cout << setw(12) << left << "Last Name";
cout << setw(8) << left << "ID";
cout << setw(31) << left << "Course Name";
cout << setw(7) << left << "Num";
cout << setw(1) << "Grade" << endl;
if(input=="*") //do all courses and students
{
count=0;
input = courses[count].num;
num=grades[count].classnum;
while(num!="")
{
if(num==input)
{
ID=grades[count].ID;
grade=grades[count].lettergrade;
num=grades[count].classnum;
counter=0;
name=students[counter].firstname;
while(name!="")
{
if(students[counter].ID==ID)
{
cout << setw(12) << left << students[counter].firstname;
cout << setw(12) << left << students[counter].lastname;
cout << setw(6) << left << ID;
counting=0;
name=courses[counting].name;
while(name!="")
{
if(courses[counting].num==num)
{
cout << setw(31) << left << courses[counting].name;
cout << setw(7) << left << num;
cout << setw(1) << left << grade << endl;
}//end if
counting++;
name=courses[counting].name;
}//end while
}
counter++;
name=students[counter].firstname;
}//end while
}//endif
count++;
num=grades[count].classnum;
input=num;
}//end while
}//endif
else //just one course
{ //check if input is valid
count=0;
num=grades[count].classnum;
while(num!="")
{
if (grades[count].classnum==input)
{
inlist=true;
}//end if
count++;
num=grades[count].classnum;
}//end while
if(!inlist)
{
cout << "Course number not found." << endl;
return;
}//end if
//start output of data
count=0;
num=grades[count].classnum;
while(num!="")
{
if(grades[count].classnum==input)
{
ID=grades[count].ID;
grade=grades[count].lettergrade;
counter=0;
name= students[counter].firstname;
while(name!="")
{
if(students[counter].ID==ID)
{
cout << setw(12) << left << students[counter].firstname;
cout << setw(12) << left << students[counter].lastname;
cout << setw(6) << left << ID;
cout << setw(31) << left << courses[count].name;
cout << setw(7) << left << courses[count].num;
cout << setw(1) << left << grade << endl;
}
counter++;
name=students[counter].firstname;
}//end while
}
count++;
num=grades[count].classnum;
}//endwhile
}//end else
}
//function to view a list of all students in a class
void liststud(student students[])
{
cout << endl << endl;
cout<<setw(12) << left << "First Name" << setw(12) << left << "Last Name";
cout<<setw(6) << left << "ID";
cout<<setw(13) <<left << "Phone" << endl;
int counter=0;
string name=students[counter].firstname;
while(name!="")
{
cout << setw(12) << left << students[counter].firstname;
cout << setw(12) << left << students[counter].lastname;
cout << setw(6) << left << students[counter].ID;
cout << setw(13) << left << students[counter].phone;
cout << endl;
counter++;
name=students[counter].firstname;
}// end while
}
// function to display all courses listed
// simple loop til the end of course array
void listcourses(course courses[])
{
cout << endl << endl << endl;
cout << setw(7) << left << "Num";
cout << setw(31) << left << "Course Name" << endl;
int counter=0;
string num=courses[counter].num;
while (num!="")
{
cout << setw(7) << left << courses[counter].num;
cout << setw(31) << left << courses[counter].name;
cout << endl;
counter++;
num=courses[counter].num;
}//end while
}
// exit function
// must save data back to file before exiting
void myexit(grade grades[], course courses[], student students[])
{
int count;
string name;
ofstream outfile;
outfile.open("student.out");
count =0;
name = students[count].firstname;
while(name!="")
{
outfile << setw(12)<< left<< students[count].firstname
<< setw(12) << left << students[count].lastname
<< setw(6) << left << students[count].ID
<< setw(13) << left << students[count].phone << endl;
count++;
name=students[count].firstname;
}//end while
outfile.close();
outfile.open("course.out");
count =0;
name=courses[count].num;
while(name!="")
{
outfile << setw(7) << left << courses[count].num
<< setw(31) << left << courses[count].name << endl;
count++;
name=courses[count].num;
}// end while
outfile.close();
outfile.open("grade.out");
count =0;
name=grades[count].classnum;
while(name!="")
{
outfile << setw(6) << left << grades[count].ID
<< setw(7) << left << grades[count].classnum
<< setw(1) << left << grades[count].lettergrade << endl;
count++;
name=grades[count].classnum;
}//endwhile
outfile.close();
cout << "Files written." << endl;
}
void readdata(char* argv[],grade grades[], course courses[], student students[])
{
string first, last, phone;
int ID,counter;
char letter;
ifstream infile1 (argv[1]);
infile1 >> first >> first >>first >>first; // clear the first line
counter=0;
while (!infile1.eof())
{
infile1 >> first >> last >> ID >> phone;
students[counter].firstname=first;
students[counter].lastname = last;
students[counter].ID = ID;
students[counter].phone=phone;
counter++;
}//end while
infile1.close();
ifstream infile2 (argv[2]);
infile2 >> first >> first;
counter=0;
while (!infile2.eof())
{
infile2 >> first;
getline(infile2,last);
courses[counter].name=last;
courses[counter].num=first;
counter++;
};//end while
infile2.close();
ifstream infile3 (argv[3]);
getline(infile3,first);
//infile3 >>ID >> first >> first;
counter=0;
while(!infile3.eof())
{
infile3 >> ID >> first >> letter;
grades[counter].ID=ID;
grades[counter].classnum=first;
grades[counter].lettergrade=letter;
counter++;
};//end while
infile3.close();
}
int main(int argc,char* argv[])
{
char item;
string first,last,phone;
student students[1000];
grade grades[10000];
course courses[9999];
readdata(argv,grades,courses,students);
while(item!=7)
{
item = menu();
if(item==int('A'))
item=1;
else if(item==int('a'))
item=1;
else if(item==int('R'))
item=2;
else if(item==int('r'))
item=2;
else if(item==int('S'))
item=3;
else if(item==int('s'))
item=3;
else if(item==int('C'))
item=4;
else if(item==int('c'))
item=4;
else if(item==int('L'))
item=5;
else if(item==int('l'))
item=5;
else if(item==int('D'))
item=6;
else if(item==int('d'))
item=6;
else if(item ==int('E'))
item=7;
else if(item ==int('e'))
item=7;
if (item =='1')
add(grades, courses, students);
else if (item =='2')
remove(grades, courses, students);
else if (item =='3')
studgrad(grades, courses, students);
else if (item =='4')
courgrad(grades, courses, students);
else if (item =='5')
liststud(students);
else if (item =='6')
listcourses(courses);
};//end while
myexit(grades, courses, students);
return 0;
}//end main
|
|
|
01-14-2005, 12:03 PM
|
#13 (permalink)
|
|
[code][/code] enforcer
Join Date: Mar 2003
Location: Netherlands
Posts: 1,545
|
Quote:
|
I've been working on C++ code for 5 years and am taking 400 level college classes.
|
In that case, why not start to program object oriented. That doesn't mean encapsulation only, but also independency. Besides that. Consistancy as well. My credo always stands:
Programming is communicating
- Since you have structs of a Student, Grade and Course, you are able to see the true domain problem: Student s, Grade s and Course s. Encapsulate these structs in classes, with the names: Students, Grades and Classes.
- Store all the students, grades and classes in a vector. That vector is obviously in the classes I just mentioned.
So the classes are just wrappers for the vector.
Code:
#include "Student.h"
#include <fstream>
#include <vector>
using std::vector;
using std::ifstream;
using std::ofstream;
//And so forth.
class Students
{
public:
Students();
vector<Student>& get_students();
void create_database();
private:
vector<Student> _vecStudents;
};
Do this for the Grades class and Courses class as well.
Now these classes are the classes that matter actually. Therefore, consider this our domain to keep it simple but clear.
Now there is your function handling.
Your functions are long and often misleading. Or not clear at all. Suppose I am a stranger to your library. How would I know what a courgrad() is? Make so any fool could understand what it does.
Furthermore, lot of your functions are extremely long. Keep a simple rule:
If a function or method has 25 lines of code or more, then split it up.
We want to keep things readable.
Also make sure that the responsabilities for your the things you create are clear. Don't let them do two or more things. Let it do only 1 and 1 thing only.
Ok, let's think object oriented. You have 5 years experiance or so. I expect you to understand the things I post below this.
First of all we want the menu seperated from the rest. We also don't want return it an int. We don't like throwing "menu-int's" all over the application.
So we implement the Command Design pattern:
This way, we can modify our view but also our controller(s) or concrete command implementations without affecting the other entities.
The code below is complete and working. Notice how it supports submenu's. Just like in MS Windows or a GUI Linux environment. Take it and play with it. -- Create your own menu's and submenus in the main() function.
- The Lookup submenu is obviously for finding and printing items on screen. Like all students, or a specific one. Whatever. I implemented one demo Print Command.
- Convince yourself that proper clean-up is done. What is required to guarantee proper clean-up?
- What is needed to support an "undo" command for everything you change in the database(s) and/or table(s)?
- Would you even like to clean up main() and therefore create an Application class, and let that class to all the pre-initialization?
main.cpp
Code:
#include "Command.h"
int main()
{
Menu MainMenu( "Main Menu" );
Menu* LookupMenu = new Menu( "Search and Print Menu" );
MainMenu.add( LookupMenu );
MainMenu.add( new QuitCmd );
LookupMenu->add( new PrintCmd );
LookupMenu->add( new ReturnCmd );
MainMenu.execute();
return 0;
}
Command.h
Code:
#ifndef COMMAND_H
#define COMMAND_H
#include <vector>
#include <string>
using std::string;
using std::vector;
//Abstract.
class Command
{
public:
Command(const string name);
virtual ~Command();
virtual bool execute() = 0;
string get_name();
private:
//Protect copy ctor and assignment.
Command(const Command&);
Command& operator=(const Command& rho);
const string _sName;
};
//------------------------------------------
class Menu : public Command
{
public:
Menu(const string name);
virtual ~Menu();
void add(Command* pCommand);
bool execute();
private:
Menu(const Menu&);
Menu& operator=(const Menu& rho);
Command* select(int index);
void show();
int get_user_input();
vector<Command*> _vecMenuItemCommands;
};
//------------------------------------------
class PrintCmd : public Command
{
public:
PrintCmd();
~PrintCmd();
bool execute();
private:
PrintCmd(const PrintCmd&);
PrintCmd& operator=(const PrintCmd& rho);
};
//------------------------------------------
class ReturnCmd : public Command
{
public:
ReturnCmd();
~ReturnCmd();
bool execute();
private:
ReturnCmd(const ReturnCmd&);
ReturnCmd& operator=(const ReturnCmd& rho);
};
//------------------------------------------
class QuitCmd : public Command
{
public:
QuitCmd();
~QuitCmd();
bool execute();
private:
QuitCmd(const QuitCmd&);
QuitCmd& operator=(const QuitCmd& rho);
};
#endif //COMMAND_H
Command.cpp
Code:
#include "Command.h"
#include <iostream>
using std::cout;
using std::endl;
using std::cin;
// CLASS COMMAND //
Command::Command(const string name) :
_sName(name)
{ }
Command::~Command()
{ }
string Command::get_name()
{
return _sName;
}
// CLASS MENU //
Menu::Menu(const string name) :
Command(name)
{ }
Menu::~Menu()
{
Command* p;
unsigned sz=_vecMenuItemCommands.size();
for(int i = 0; i < sz; ++i)
{
p = _vecMenuItemCommands[i];
delete p;
}
}
void Menu::add(Command* pCommand)
{
_vecMenuItemCommands.push_back( pCommand );
}
bool Menu::execute()
{
Command* pCmd;
do
{
show();
int userInput = get_user_input();
pCmd = select( userInput );
}
while( pCmd->execute() );
return true;
}
void Menu::show()
{
cout << endl << "*** " << get_name() << " ***" << endl;
for(int i=0; i<_vecMenuItemCommands.size(); ++i)
{
cout << i+1 << ". " << _vecMenuItemCommands[i]->get_name() << endl;
}
}
Command* Menu::select(int index)
{
return _vecMenuItemCommands[index-1];
}
| | | |