I have a C++ project to do for my class and it's quite intricate, to me at least. I've got the general idea and concept down, but i'm running into some other problems when it comes to the arrays and file stuff. Below is what the project consists of
You will be building and modifying a class roster system for a Teacher to manage his class roster and their final grades. This program
will use functions for the various menu options, and you will work with
the data in arrays or vectors. The program will provide a menu system that allows for the teacher to perform tasks until he chooses to close the program. The program will read and write to a file called
classroster.txt. Any and all additions, deletions, or changes to the roster will be saved in classroster.txt file.
This file will contain the names of each of the students in the class with their grade. See the following for an example listed below of how the data would be stored in the classroster.txt file. You should work with the data using arrays or vectors.
Jim Jones C
Kevin James B
Marc Cohen A+
When the program starts it should read the data from the classroster.txt into arrays or vectors. While the program is running it should use the arrays or vectors for the functions while using the program. When the program ends it should overwrite the classroster.txt file if something has been changed. The
programs menu will offer the following options and will allow the user to keep performing functions until they choose to exit the program ( hint !!!!! you will need to use a loop for the menu system)
Add A New Student-
This will allow the user to add a new student to the system. The system should prompt for the new students full name and then grade.
It should validate that the grade is in the following values
(A+, A, A-, B+, B, B-,C+,C, C-, D+, D, D-, F) and if not
in the approved list it should prompt the user for a valid grade.
Change a Students Grade-
This will find the student in question and change the grade. If the specified student doesn’t exist the program should print an error message telling the user that you couldn’t find the specified student to
change their grade.
Remove a Student-
Will remove a student and their grade from the roster. If the specified student doesn’t exist the program should print an error message telling the user that you couldn’t find the specified student to remove.
Display Class Roster–
(Bonus Points if you can display the names is alphabetical order) This
function will display the list of all the students and their grades on
the screen that looks like this:
Student Name Grade
Jim Jones C
Kevin James B-
Marc Cohen A+
This is what i have so far, it's obviously not done yet
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
const int num_of_students;
const int new_student = 1, change_grade = 2, remove_student = 3, display_roster = 4, quit = 5;
int classroster[num_of_students];
int student_grade[num_of_students];
string possible_grades[13] = {"A+", "A", "A-", "B+", "B", "B-", "C+", "C", "C-", "D+", "D", "D-", "F"};
int choice;
ofstream class_file;
cout << "How many students do you have in your class?" << endl;
cin >> num_of_students;
cout << "---MENU---" << endl;
cout << "1. Add A New Student" << endl;
cout << "2. Change A Students Grade" << endl;
cout << "3. Remove A Student" << endl;
cout << "4. Display Class Roster" << endl;
cout << "5. Quit" << endl;
cout << "Enter your choice: ";
cin >> choice;
if (choice == new_student) {
for (int index = 0; index < num_of_students; index++) {
class_file.open("classroster.txt");
cout << "What is the name of the student you want to add? ";
getline(cin, classroster);
if (student_grade == possible_grades) {
cout << "What is the final grade of this student? ";
getline(cin, student_grade);
}
else {
"Please enter a valid grade!"
}
cout << "Student added!";
}
}
else if (choice == change_grade) {
class_file.open("classroster.txt");
cout << "What is the name of the student whose grade you want to change? ";
getline(cin, )
}
else if (choice == remove_student) {
}
else if (choice == display_roster) {
}
else if (choice == quit) {
}
else {
cout << "Please enter a valid choice!"
}
system("PAUSE");
return 0;
}
First, to answer your question, here's one way to search an array of student names:
int index = -1;
for(int k=0; k<num_of_students; ++k)
{
if(names[k] == name)
index = k;
}
And here's a way to change the array of grades:
student_grade[index] = 3;
More generally, you taking the wrong approach. Your code does not compile, so it looks as if you're writing it all out before testing any of it. As they never seem to teach in school, you should start with something small and simple, add complexity a little at a time, test at every step, and never add to code that doesn't work.
Let's start with the number of students:
int main() {
const int num_of_students;
cout << "How many students do you have in your class?" << endl;
cin >> num_of_students;
return(0);
}
Try to compile this, and you'll find that there's something wrong. Fix it and try constructing an array of int and filling it in. Once that's working, try an array of string. Small steps.
You realy should be using maps for this question, its makes the most sense. Here is code to read in the map from a file. After you have the map all the operations you need are already implemented in the STL. I realize you may need to use vector but I'd like to think you wouldn't be penalized for being clever and actually writing a proper solution.
#include <map>
#include <fstream>
#include <iostream>
using namespace std;
int main(){
map<string,string> data;
fstream fs("classroster.txt");
while(fs.good()){
string fname, lname, grade;
fs >> fname;
fs >> lname
fs >> grade;
fname += lname; //Concat Names to get full
if(grade == "A") //Check other grades as well.
data.emplace(fname,grade);
}
while(1){
string option;
std::cout << "Options:" << endl;
cin >> option;
//Your option selection code here
}
return 0;
}
EDIT:
maps are also sorted by key name so printing alphabetically is very easy, no sorting required.
for(auto& pairs : data)
cout << pairs.first << " " << pairs.second << endl;
Related
Not sure how I was supposed to formulate the title.
I'm writing a program that asks for a students name, and if the name is not "stop", then it asks for a course name. If the course name is not "stop", it asks for a grade, then returns to ask for another course until the course name is "stop". Then it asks for another student and does the whole thing again until the student name is "stop". Then it prints all the students with their courses and grades.
Here is my code:
#include <iostream>
#include <vector>
using namespace std;
struct student{
public:
string name;
string course;
int grade;
}student_t;
void input(){
cout << "Please type the name of a student: " << endl;
getline(cin, student_t.name[i]);
if (student_t.name.compare("stop")){
break;
}
else {
cout << "Please type a course name: " << endl;
getline(cin, student_t.course);
if (student_t.course.compare("stop")) {
break;
}
else {
cout << "Please type the grade: " << endl;
cin >> student_t.grade;
}
}
}
int main() {
int i;
vector<student> input(i);
for (i = 0; i < 20; ++i){
student[i].input();
}
cout << student_t.name << " - " << student_t.course << " - " << student_t.grade << endl;
return 0;
}
It does not work at all..
I'm new to C++ so I dont really know why.
Any ideas?
I can give one or two recommendations.
Instead of checking if every step is wrong (i.e. equals "stop"), focus on what is right (i.e. what's the next things to read). From a mental perspective, I find it much easier to think about what has to be right for the program to progress as intended, as opposed to "What can go wrong here?" at every step. Your input() could then be (in pseudo code):
if (student_t.name is not "stop")
{
Read_course_name();
if (student_t.course is not "stop")
{
Read_grades();
// Done
return(StudentInfo);
}
}
// Ending up here means "stop" was typed so deal with that
// in a meaningful way
...
Take a look at https://en.wikipedia.org/wiki/Separation_of_concerns and then ask yourself, -Is the input() function really an input or are there more than one concern that coud be broken out in a separate function?
Cheers
/N
Disclaimer: I am a beginner to programming, so what I say might sound really stupid
I have to make a "Telephone Directory" for school. The program isn't complete, but there are some things that I need to fix before moving on. The array TelephoneNumbers either isn't storing the numbers from the file correctly, or isn't displaying them. For the SeaerchRecords function, the first number in the file is displayed correctly, the second is displayed as "2147483647," and the rest of the numbers display as "0." The modify function also doesn't change the number, and I confirmed this with the while in the function. The string array works perfectly fine, however. May someone explain what I'm doing incorrectly?
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
string TelephoneNames[100];
int TelephoneNumbers[100];
void ModifyRecords(); //Function to Modify Records
void SearchRecords(); //Function to Search Records
void DeleteRecords(); //Function to Delete Records
int main()
{
fstream inputFile;
fstream outputFile;
char choice;
inputFile.open("Telephone Names.txt"); //To store
for (int count=0;count<100;count++) //file names
{ //into a
inputFile >> TelephoneNames[count]; //string
}
inputFile.close();
inputFile.open("Telephone Numbers.txt");//To store
for (int count=0;count<100;count++) //file #'s
{ //into a
inputFile >> TelephoneNumbers[count];//string
}
inputFile.close();
//Display options available
cout << " Hello, do you want to:\n";
cout << " ======================\n";
cout << "-Modify Records|Enter M\n";
cout << "-Search Records|Enter S\n";
cout << "-Delete Records|Enter D\n";
//Store choice
cin >> choice;
//Send to different function
if (choice=='M'||choice=='m')
{
ModifyRecords();
}
if (choice=='S'||choice=='s')
{
SearchRecords();
}
return 0;
}
void ModifyRecords()
{
string name;
string newname;
int newnumber;
int count=0;
cout << "Enter the name of the person: ";
cin >> name;
for (count=0;TelephoneNames[count]!=name;count++)//To determine where in the strings the new numbers need to be
{
}
cout << "Enter the new name of the person: ";
cin >> newname;
cout << "Enter the new number of the person: ";
cin >> newnumber;
TelephoneNames[count]={newname};
TelephoneNumbers[count]={newnumber};
count=0;
while (count<6)
{
cout << TelephoneNames[count] << endl;
cout << TelephoneNumbers[count] << endl;
cout << endl;
count++;
}
}
void SearchRecords()
{
string name;
int count=0;
cout << "Enter the name of the person you would like to find: ";
cin >> name;
for (count=0;TelephoneNames[count]!=name;count++)//To determine where in the strings the new numbers need to be
{
}
cout << "Name: " << TelephoneNames[count] << endl;
cout << "Number: " << TelephoneNumbers[count] << endl;
}
Since there is no any answer still and I don't see exactly the problem at this point I'll provide some suggestions how you can find a problem in your code.
In any programming situation when you can't find a bug, first task is to locate it as much precisely as you can and check all input data and assumptions. Usually, debugger is used for such purposes, but you can just output text in console before creating final version of your program.
To start with, you must check that you really received names and telephones from your file:
inputFile.open("Telephone Names.txt"); //To store
for (int count=0;count<100;count++) //file names
{ //into a
inputFile >> TelephoneNames[count]; //string
cout << TelephoneNames[count] << endl; //WE MUST SEE WHAT IS REALLY STORED IN TelephoneNames
}
inputFile.close();
inputFile.open("Telephone Numbers.txt");//To store
for (int count=0;count<100;count++) //file #'s
{ //into a
inputFile >> TelephoneNumbers[count];//string
cout << TelephoneNumbers[count] << endl; //WE MUST SEE WHAT IS REALLY STORED IN TelephoneNumbers
}
inputFile.close();
Ok, when it is checked and you are defenitely sure there is no problem in your data we can move to SeaerchRecords function doing the same procedure. We must check what is happening while you are searching:
for (count=0;TelephoneNames[count]!=name;count++)//To determine where in the strings the new numbers need to be
{
cout << "Search step: " << count << " name " << name << " found name " << TelephoneNames[count] << " number " << TelephoneNumbers[count] << endl;
}
Doing so you will locate your bug rather quickly. The problem can be in input files format, in difference of "name" and stored names format etc.
I'll provide several additional suggestion how you can improve your code.
1) Try to use const declarations for such commonly used things as number of records (const int NUMBER_OF_RECORDS = 100; insted of just putting '100' everywhere), it will reduce the amout of work and possible bugs. 2) Try to check all possible problems that you program can encounter if someting is wrong with data. What will happen if you have less than 100 records in your files now? Program crush or silent reading of unappropriate data which is even worse. Check that you haven't reach file end on any step of reading along with current check that you've reached you number of records and do something in case of unappropriate data.
3) Check the possible problems with conditions in your cycles not to run them infinite number of times. Now your condition for(count=0;TelephoneNames[count]!=name;count++)
will execute forever if there is no such name or just crush the program on count 100 or more. You should check that count doesn't exceed that value. Good luck!
I am trying to create a program that ask for sales amount and displays total salary and writes the entry to a file. However my program has is only writing the last entry to the file. I have searched online for 2hours for a solution and cant find one.
I want all of the input to write to my file not just the last one
#include <fstream>
#include <iostream>
#include <iomanip>
using namespace std;
void SavingFile(); //Declartion
void Calculate();
char FileName[20];
double GrossPay;
double TotalSalary;
int employeeID=0;
char response;
int i=1;
int main()
{
SavingFile();
}
void SavingFile()
{
cout << "\nEnter the name of the file you want to create: ";
cin >> FileName;
do
{
employeeID++;
cout << endl << endl << "Enter sales amount for sales person ID " << employeeID <<" : $";
cin >> GrossPay;
Calculate();
cout <<"Sales amount for ID " << employeeID <<" : $" << TotalSalary <<endl;
cout <<endl <<endl;
do
{
ofstream Employee(FileName);
Employee <<"Employee ID: "<< employeeID <<" Sales Amount: $" << TotalSalary <<endl;
cout << endl;
i++;
}
while
(employeeID == i);
cout << "Do you want to process another employee ? (y/n): ";
cin >> response;
}
while ( (response == 'Y') || (response == 'y') );
}
void Calculate() // definition
{
TotalSalary = (GrossPay * .10) + 150;
//return TotalSalary;
}
You are overwriting the file every time you write to it.
If you want to append to the file, you need to open the file using the ios_base::app flag in addition to ios_base::out.
In your code, you must replace this:
ofstream Employee(FileName);
with this:
ofstream Employee(FileName, ios_base::out | ios_base::app);
To learn more, you can read this page on the constructor of the ofstream class. Among other things, you will find a description of the various flags you can use and what they mean.
I won't rewrite your code for you, but I'll explain the logic that you need to rewrite.
In a loop, you read a value, and call Calculate, which sets a global variable called TotalSalary. The cout probably looks ok. Try adding a cout into the while loop where you are outputting the file, and you'll see that the values aren't what they used to be.
The problem is that every time you call Calculate, you overwrite TotalSalary. You're not saving these values anywhere, but by looping through, you're assuming that the values are still there.
The solution is to write to the output file at the same time as you write to your cout. Open the ofstream at the top of main, and just output to there like you are outputting to cout.
There's no need to open the file each time in a loop, and in fact you shouldn't. (Though appending would help, if that's what you should have been doing.)
I'm new to C++. I decided to not watch the next tutorial and put my skills to use, by making a funny Mind Reader application. I'm pleased with myself, however, even though I've ironed out most bugs, I still have one concerning the exit function. I read the C++ documentation for it, and I'm not sure what I did wrong. I did exit(0);. I have a very weird error, which is:
no match for call to '(std::string {aka std::basic_string<char>}) (int)
I have searched online, however I am still unaware of what the problem is. My error is on line 59 (marked in the code):
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
int main()
{
//declaring variables to be used later
string name;
string country;
int age;
//header goes below
cout << "#######################################";
" ############ MIND READER ############"
"#######################################\n\n";
//asks if the user would like to continue and in not, terminates
cout << "Would like you to have your mind read? Enter y for yes and n for no." << endl;
cout << "If you do not choose to proceed, this program will terminate." << endl;
string exitOrNot;
//receives user's input
cin >> exitOrNot;
//deals with input if it is 'y'
if (exitOrNot == "y"){
cout << "Okay, first you will need to sync your mind with this program. You will have to answer the following questions to synchronise.\n\n";
//asks questions
cout << "Firstly, please enter your full name, with correct capitalisation:\n\n";
cin >> name;
cout << "Now please enter the country you are in at the moment:\n\n";
cin >> country;
cout << "This will be the final question; please provide your age:\n\n";
cin >> age;
//asks the user to start the sync
cout << "There is enough information to start synchronisation. Enter p to start the sync...\n\n";
string proceed;
cin >> proceed;
//checks to see if to proceed and does so
if (proceed == "p"){
//provides results of mind read
cout << "Sync complete." << endl;
cout << "Your mind has been synced and read.\n\n";
cout << "However, due to too much interference, only limited data was aquired from your mind." << endl;
cout << "Here is what was read from your mind:\n\n";
//puts variables in sentence
cout << "Your name is " << name << " and you are " << age << " years old. You are based in " << country << "." << endl << "\n\n";
cout << "Thanks for using Mind Reader, have a nice day. Enter e to exit." << endl;
//terminates the program the program
string exit;
cin >> exit;
if (exit == "e"){
exit(0); // <------------- LINE 59
}
}
}
//terminates the program if the input is 'n'
if (exitOrNot == "n"){
exit(0);
}
return 0;
}
Thanks
The local variable exit shadows other identifiers from outer scopes with the same name.
To illustrate with a smaller example:
int main()
{
int i;
{
int i;
i = 0; // assign to the "nearest" i
// the other i cannot be reached from this scope
}
}
Since the only exit visible is an object of type std::string, the compiler sees exit(0) as a call to operator()(int) and throws a hissy fit when it doesn't find one among std::string members.
You can either qualify the name (std::exit(0);) or rename the variable. And since all of your code is in main you can simply say return 0; instead.
Try using return 0; or return EXIT_SUCCESS;. It's the exact same thing. Also, you can only input one word into a cin. Instead, use getline(cin, string name); If it still doesn't work, add a cin.ignore(); before your getline(cin, string name);, like this:
//stuff
string country;
cout << "Now please enter the country you are in at the moment:\n\n";
cin.ignore();
getline(cin, country);
//stuff
return 0;
The problem is arrising because you declared a standard keyword as the name of a local variable.
Now as the local variable is of type sting it is not able to take it as its value.
I'm writing a file matching program for a project for school. The idea is that one program allows you to enter info as follows: 1000 (acct number) Jane Doe 54.50 (balance). Then allow you to enter the account number and a transaction amount for the second program to combine and update a new master file.
The programs are working together just fine (the second one takes information from the first, including any transactions and updates the new balance - searching by account number) but the problem I am running into is with the name.
---Wasn't clear here. When I ask for a name and I put in a single string of characters, the program works fine, if I try to put in a full name, like Jane Doe I go into the loop mentioned below.
I've tried char name[20] which puts me into an infinite loop and I have to 'x' out of the program and I've tried assigning first and lastName to string. That worked for the writing but the program that takes the input file oldMaster and the transaction file inTransaction then outputs a new file newMaster, doesn't recognize the name.
I've tried getline also which isn't working for me, probably programmer error.
Should this be done as an array, if that's possible for this? I think I'm getting hung up on the fact that I am editing files. Answers are fine - but I like to figure it out on my own, just looking for a little guidance on where to go from here.
Hopefully this was fairly clear - if not I'll be happy to explain again in a different way. Just frustrated that I'm this close and can't solve it.
Thanks in advance!
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <iomanip>
using namespace std;
void createOldMaster()
{
ofstream oldMaster;
int accountNum;
double balance;
char name[15];
oldMaster.open("oldmast.dat", ios::out);
if(!oldMaster)
{
cout << "Unable to open the file." << endl;
exit(1);
} // end if
cout << "Enter the account number (0 to exit)." << endl;
while(true)
{
cout << "Account Number: ";
cin >> accountNum;
if(accountNum == 0)
break;
else
{
\\ This is where it hangs up if I use a first and last name
cout << "\nName: ";
cin >> name;
cout << "\nBalance : " << endl;
cin >> balance;
oldMaster << accountNum << " " << name << " " << balance << endl;
}
}
} //end createOldMaster
void createTransaction()
{
ofstream inTransaction;
int accountNum;
double balance;
inTransaction.open("trans.dat");
if(!inTransaction)
{
cout << "Unable to open the transaction file." << endl;
exit(1);
}
cout << "Enter the account number and balance (0 to exit): " << endl;
while(true)
{
cout << "Account Number: " << endl;
cin >> accountNum;
if(accountNum == 0)
break;
else
{
cout << "Balance: " << endl;
cin >> balance;
inTransaction << accountNum << " " << balance << endl;
}
}
} //end createTransaction
int main()
{
createOldMaster();
createTransaction();
return 0;
}
Your best bet is to use as much of the standard C++ library as you can. Have a reference handy, maybe even a copy of the C++ standard if you're so inclined, and look for shortcuts to make your work easier and your code shorter.
Avoid primitive arrays and primitive strings wherever possible. Instead of primitive arrays try to use std::vector. Instead of primitive strings try to use std::string. Instead of C's FILE* try to use std::ofstream and std::ifstream. If you need to prohibit two accounts with the same account number then choose a C++ container that guarantees unique elements. If you need to find an element in a container try to use a member function of the container for the search, and if that doesn't exist then a standard search function from the standard C++ algorithms.
Reuse and steal mercilessly.