Okay, so I know that you guys aren't my own personal programmers but I was wondering if you could help me out a bit here. I work as a teachers assistant while I'm going to school. I know a bit of C++ and was trying to make a basic program to check answers with.
The first part of the program works fine to test the answers against the key, however the second part is what I'm having issues with. I'm trying to find how many students answered what question so I don't have to count them by hand, but I cannot seem to get this down.
What I really need is to be able to print them out like so:
question A B C D E
1 1 12 3 5 7
and so on.
I know I'm probably going to need a nested for loop, but I've been banging my head on this all night. Any help would be appreciated.
#include "stdafx.h"
#include <fstream>
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
void main(){
int numstud=0, numcorrect, i;
string key, id, responses;
ifstream keyfin, studfin;
keyfin.open("answers.dat");
studfin.open("tests.dat");
keyfin >> key;
studfin >> id >> responses;
cout << setw(5) << "Student-Id's" << setw(20) << "# Correct" << endl << endl;
while(!studfin.eof())
{
numstud++;
numcorrect=0;
for(i=0; i<20; i++){
if(responses[i] == key[i])
{
numcorrect++;
}
}
cout << id << setw(20) <<numcorrect << endl;
studfin >> id >> responses;
}
studfin >> id >> responses;
int col[20][5]={0}, j=0;
char ch;
studfin >> id >> responses;
cout << "Question" << setw(10) << "A" << setw(5) << "B" << setw(5) << "C" << setw (5) << "D" << setw(5) << "E";
while (!studfin.eof())
{
for(i=0; i<responses.length(); i++)
{
col[i++][responses[i-'a'] ++];
}
}
}
You have the general idea as far as implementing an histogram of the responses. However there are a few things wrong with the line col[i++][responses[i-'a'] ++].
First assuming responses are lower case, you probably intended responses[i]-'a' rather than responses[i-'a'], to convert the letter grade to a 0,1,2,3,4 index.
Then, it's the content of the table you want to increment, not row and column indices. That is col[i][responses[i]-'a']++.
As a side note, you don't need a second while (!studfin.eof()) loop to update the histogram. You can keep updating it as you are checking answers against the key (and you should not use a second loop unless you reset the input stream that has reached end-of-file by the end of the first loop).
Related
so im new to c++ and i have a project that i am currently doing in school however im stuck on how to get an entire row of info from a user input selection.
here is what my txt file looks like
1 Home Work 5
2 Work Home 5
3 Home School 6
4 School Home 6
5 Work School 8
6 School Work 8
so basically if they input/ cin option 3 but how do i print and obtain the values in row 3 to display and compute later on?
heres my code
#include <iostream>
#include <iomanip>
#include <fstream>
#include <stdlib.h>
#include <string>
#include <cstdlib>
#include <Windows.h>
#include <cmath>
void bookingmenu();
void confirmedbooking(double calc);
double calc;
using namespace std;
int main()
{
ifstream inFile;
string PUP, Dropoff, others, otherstwo;
double distance = 0, calc;
string ON;
int sel;
char choice;
inFile.open("blist.txt");
if (!inFile)
cout << "Error, unable to open text file.\n" << endl;
else
cout << left << fixed << setprecision(2);//how many dp
cout << left << setw(25) << "Option Number" << left << setw(25) << "Pick Up Point" << "Dropoff Point" << endl; //display column header
while (!inFile.eof())
{
inFile >> ON >> PUP >> Dropoff;
if (inFile.fail()) break;
cout << left << setw(25) << ON << left << setw(25) << PUP << Dropoff << endl;
}
cout << "Please select an option for your trip: ";
cin >> sel;
//(im stuck after here)
cout << "You have selection option number " << ON << " and your pickup point is " << PUP << " and your dropoff point is " << Dropoff << endl;
system("pause");
return 0;
}
Make a list of things you need to do:
read file (almost done)
print options in file (done)
put data somewhere we can look it up later (not done)
get option from user (done)
look up option (not done)
print selected option (almost done)
Fixing point 1
The current code reads three fields from the row of data. There are 4 fields. The fourth field needs to be removed from the stream.
int unused;
while (inFile >> ON >> PUP >> Dropoff >> unused) // read unused field into junk variable
{
//print
}
Implementing point 3
Define a structure that can store the data
struct record
{
string PUP;
string Dropoff;
};
Option number will be likely used as the key for looking up the structure, so it doesn't need to be in the structure.
Next we need a container to store these records
If the file is guaranteed to be start with a predictable option number and be listed in a continuous sequential order, we can use a std::vector to store the records. If the list is predictable, sequentially ordered and of known size we can use std::array If not, use an associative table to map the option number to the record. We're not given any guarantees of ordering or size, so I'll demonstrate with std::map
record in;
map<int, record> records; // convenient data structure for look-up
int ON;
int unused; // need to read and dum that last field on the line
while (inFile >> ON >> in.PUP >> in.Dropoff >> unused)
{
records[ON] = in; // store row in datastructure at the option number.
}
If you're smart, you will read the file and print the menu at the same time. Otherwise you're reading the file twice or unnecessary looping through the container of records.
Implementing point 5
Look up the record in the container. If std::map is used, that can be as simple as
record & out = records.at(sel);
at will throw an exception if the option is not in the list. You can either catch and handle the exception or let the program crash.
Fixing point 6
We use the reference to the record to update the existing code to use the correct record.
I wrote a project that calculates the area of the triangle.
I have wrote this program.
#include <iostream>
using namespace std;
int main()
{
int first, two, three;
int all = (first + two) * three;
cout << "Enter first num: ";
cin >> first;
cout << "\nEnter second num: ";
cin >> two;
cout << "\nEnter num three: ";
cin >> three;
cout << "You have choosed to do: (" << first << " + " << two << ") * " << three;
cout << "\n\nThis is equal to: " << all;
return 0;
}
Instead of going down a line and writing cin and cout every time, is there a way to shorten this project and make it shorter.
Maybe like write the cout and the cin in a single line ?
or anything else just to make it look more clean and nice.
it looked messy.
Thanks!
This takes a whole 1 line fewer. Whether it's cleaner or easier to understand is up to you ....
int sides[3];
for (int i=0; i < 3; i++)
{
cout << "Enter side " << i+1 << endl;
cin >> sides[i];
}
It's good to write short code where it makes it clearer, so do keep considering how you can do that. Making it look pretty is a worthy consideration too - again as long as it makes what you're doing clearer.
Clarity is everything!!
If you really want to shorten your project and make it more "clean" you can do it this way.
#include <iostream>
int main()
{
std::string str = "string"; std::cin >> str;
return 0;
}
Like you wanted to write cout and cin in a single line, you could write like that, but I think it's not "clean" to write that way and it's better to drop a line.
And, please don't use using namespace std; its a bad practice.
To make the code more maintainable and readable:
1) Use more meaningful variable names, or if you would name them consecutively, use an array
e.g. int numbers[3]
2) Similarly, when you are taking prompts like this, consider having the prompts in a parallel array for the questions, or if they are the same prompt use something similar to noelicus answer.
I would do something like this:
int numbers[3];
String prompts[3] = {"put your", "prompts", "here"};
for(int i=0; i<3; i++){
cout << prompts[i] << endl;
cin >> numbers[i]
}
//do math
//print output
also, you may want to check to make sure the user has entered a number using this.
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 feel like im doing something really silly wrong. I just want the program to tell the user when they are entering non-doubles, and continue to loop back to the cin where you enter a value.
I want the user to input any number. Then essential do this trivial math and repeat. Its working fine in that regard, the problem comes when some unexpected input like a char gets entered. Then the input somehow sends it into a loop where it loops the math problem, instead of just telling the user that they must type a number and looping back to cin type in a new number.
#include <iostream>
#include <cstdlib>
using std::cout; using std::cin; using std::endl;
long double domath(long double i)
{
cout << i << "/" << 2 << "=" << i/2 << endl;
cout << i/2 << "*" << 10 << "=" << (i/2)*10 << endl << endl;
cout << 5 << "*" << i << "=" << 5*i << "\n\n";
return 0;
}
int main()
{
long double in = 0;
while(true)
{
cin >> in;
if (cin.fail()) {
in = char(int(in));
}
domath(in);
}
system("pause>nul");
return 0;
}
You don't clear the cin in case of fail, and it infinitely tries to parse wrong input to double, failing every time. You need to clear the buffer in case of error:
if (cin.fail()) {
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
in = char(int(in));
}
Also, can't understand what you're trying to achieve with
in = char(int(in));
in is a long double variable and will hold the last value you assigned to it, no need to "convert" it to do math.
Couldn't you try doing something like this?
int x;
if(std::cin >> x)
doSomethingCool(x);
else
std::cout << "Error, not a valid integer!" << std::endl;
Exit your loop on bad input.
I think this just feels more natural/looks cleaner than clearing the buffer and all the other jazz. Just my opinion.
if (cin >> x) - Why can you use that condition?
edit: Bul's answer is still a good one though.
I'm currently working on the book "C++ Primer Plus" and doing some of the programming excersis.
As it seems, I'm having a problem with Xcode(4.3.3) because following code doesn't work how it's supposed to work:
#include <iostream>
#include <string>
struct car
{
std::string maker;
int year;
};
int main()
{
using namespace std;
cout << "How many cars do you wish to catalog? ";
int nCars;
(cin >> nCars).get();
car* aCars = new car[nCars];
for (int i = 0; i < nCars; i++)
{
cout << "\nCar #" << (i + 1) << endl;
cout << "Please enter the make: ";
getline (cin, (aCars + i)->maker);
cout << "\nPlease enter the year made: ";
(cin >> (aCars + i)->year).get();
}
cout << "Here is your collection: \n";
for (int i = 0; i < nCars; i++)
{
cout << (aCars + i)->year << " " << (aCars + i)->maker << endl;
}
delete [] aCars;
return 0;
}
The problem is, I don't have the chance to enter any maker. The program directly goes to the point where I have to enter the year, even though I'm using "(cin >> nCars).get();" to get rid of the newline character.
Am I overlooking something?
Thanks in advance!
I suspect that you may be running on windows and the two-byte newlines are hitting you. You may be able to improve things (for lines that aren't ridiculously long) with ignore:
cin >> nCars;
cin.ignore(1024, '\n');
Note that since you rely on stream numeric processing, entering a non-numeric year such as QQ will result in the programming just finishing without asking for any more input.
You don't need to do math on the years so treat them as strings instead of integers. Then if you need to you can do validation of each year after you get the input.
Ok, guys..I found the problem.
The console within Xcode doesn't work as expected when using cin.get().
I tried the same code in the terminal as well as with Visual Studio (Win 7) and the program works perfectly.
Anyway, thank you all for your advices. I'll try consider them the next time. :)
Cheers!