The point of this program is for the user to enter the grade of a certain amount of students up to 50, from a range of grades A,B,C,D, or F. At the end, the program is then supposed to show how many students got each grade. Whenever I test the following code, whatever I input for the for loop repeats every time, such that if I input for it to do the grades 3 students, whatever letter I enter for student 1 will be the same grade for every student, so if one student has an A, they all will have an A. I also have to use arrays for this program because it's for college. Sorry if there's not enough information, this is my first time posting.
#include<iostream>
#include<iomanip>
#include<string>
void gradeTotals();
using namespace std;
int x,z,a=0,b=0,c=0,d=0,f=0,i=0;
char grade[50];
int main()
{
cout<<"Please enter the number of students"<<endl;
cin>>x;
for (i=0;i<x;i++)
{
int y;
y=i+1;
cout<<"Please enter a letter grade of A,B,C,D, or F for student "<<y<<endl;
cout<<"All grades must be uppercase"<<endl;
cin>>z;
grade[i]=z;
gradeTotals();
}
}
void gradeTotals()
{
if (grade[i]=='A')
{
a++;
}
else if (grade[i]=='B')
{
b++;
}
else if (grade[i]=='C')
{
c++;
}
else if (grade[i]=='D')
{
d++;
}
else if (grade[i]=='F')
{
f++;
}
cout<<a<<endl;
cout<<b<<endl;
cout<<c<<endl;
cout<<d<<endl;
cout<<f<<endl;
}
It looks like your if statements are not doing what you expect. For instance:
if (grade[i]='B')
{
// This code will *always* execute
}
You ought to be using the double equals == to compare a value, and a single equals = to assign a value.
(Edit after additional code change)
Inside the for-loop, you are trying to use cin to read in a single character. However, since the z is an integer, cin is looking for a valid integer, which does not happen to include 'A' or 'B', etc.
Perhaps you should try using a getline() or get().
The problem lies in having your input variable as an int, take in a char.
What happens is that when you perform cin >> z;, the character that was input by the user is recognized as an invalid input by the >> operator and therefore does not extract the character.
As such, z does not get any value, the character stays in the stream, and the >> operator continues to fail to extract the character until the loop ends.
Therefore, you can solve your problem by making your input variable a char instead.
Here's a link to help you better understand how to avoid such problems in the future.
Thank you for reading.
Related
I'm new to programming, and I'm trying to learn C++ by myself, and I'm following "Programming principles and practice using C++".
I was trying to do an exercise that, after various other steps, asked me to
" ...change the body of the loop so that it reads just one double each time around. Define two variables to keep track of which is the smallest and which is the largest value you have seen so far. Each time through the loop write out the
value entered. If it’s the smallest so far, write the smallest so far after the number. If it is the largest so far, write the largest so far after the number".
I wrote the following code so far:
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
inline void keep_window_open() { cout<<"\nType a character to exit: "; char ch; cin>>ch; }
int main()
{
double val1 = 0, smallest = 0, largest = 0;
int flag = 0;
while (cin >>val1) {
if (val1=='|')
break;
else
cout <<val1 <<'\n';
if (flag==0) {
smallest = val1;
cout <<smallest <<" it's the smallest value so far.\n";
}
if (val1<smallest) {
smallest = val1;
cout <<smallest <<" it's the smallest value so far.\n"; }
else if (val1>largest) {
largest = val1;
cout <<largest <<" it's the largest value so far.\n"; }
++flag;
}
keep_window_open();
return 0;
}
My problem is that when I input a character, e.g. 'c', the program ends, although the program should end, hypothetically, only when I enter '|', and I get:
c
Type a character to exit:
Process returned 0 (0x0) execution time : ...
Press any key to continue.
and "keep_window_open()" doesn't wait for a character to be entered. I just can't understand what happens, and why. Does anyone have a clue?
Well, I think the problem is in the way you defined your loop expression.
Neither cin nor its operator ">>" return a true / false value that you can work with. They return an iStream object which could be a dubious translation to true or false via an automated casting that happens behind the curtains. They will however return null when the input cannot be set inside your variable like in the case of trying to put 'c' into a double, and null translates into false.
What I suggest for you is to create a simple while(true) loop and when you get the "|" character from the user(as a string) you break the loop. until then the loop continues. then inside the loop parse your value and work on it according to your logic(minimum / maximum)
Problem
while (cin >>val1) reads input into a double. If you input something that cannot be read as a double like "|" then this will fail and cause your loop to exit.
You then try to read more input while cin is in an error state.
Solution
Call cin.clear() to first clear any error flags and then cin.ignore(1000, '\n') to throw away anything left hanging in the input stream.
inline void keep_window_open()
{
cout << "\nType a character to exit: ";
char ch;
cin.clear();
cin.ignore(1000, '\n');
cin >> ch;
}
Note
if (val1=='|')
break;
This code will never be true because if you try to input the pipe character your while loop will fall through before ever getting to it.
I checked many links on Stack and to other site. Most of it does it what is supposed to do, but not "exactly" how I want to. Here is the problem and the best solution that i found on online.
I want to enter a number, float for example and input should be checked if is a float or not.
I'm using this snippet found online. Also to mention that i need to repeat validation each time for loop its iterated.The "n" is entered separately before this function and its in "private".It does its job perfectly, except ...If you enter "55" (number), it checks and validates. That's ok.
If you enter "dfgfd" stuff (not a number), it checks and repeats question. That's ok.
If you enter "dfgdfgdg55",it checks and repeats question. It's also ok. If you enter "55dfgfd" stuff, it checks and NOT repeats. That's NOT OK.It just discarding characters after numbers.I want to discard this also.So correct input should be JUST "55" entered.(Number 55 is just a example number entered when prompted).Also I tried this on a simpler function "model".First to enter "55", second to enter "55gdf". They been presented on screen as "55" and "55". Then i added some code afterwards to compare these numbers. They are not the same!
#include <iostream>
using namespace std;
int Provera_kucanja()
{
cout<<endl;
cout<<"Input boundary for an array"<<endl;
cin>>n;
while (cin.fail() || !(n>0))
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout<<"You didnt entered number, please try again... "<<endl;
cin>>n;
}
cout<<endl;
return 0;
}
float Unos_brojeva()
{
cout<<"\n";
cout<<"Now you must enter number into array:\n "<<endl;
for (int i = 0; i < n ; i++)
{
cout<<"Input "<<"["<<i<<"]"<<" number in array: ";
float r;
cin>>r;
while (cin.fail())
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout<<"You didnt entered number, please try again... "<<endl;
cout<<"Input "<<"["<<i<<"]"<<" number in array: ";
cin>>r;
}
unos[i]=r;
}
cout<<endl;
cout<<"Now show unsorted array members: "<<endl;
for(int i = 0; i < n; i++)
{
cout<<"This is "<<"["<<i<<"]"<<" member of array named 'unos': "<<unos[i]<<endl;
}
cout<<"\n"<<endl;
cin.get();
return 0;
}
int main(){
Provera_kucanja();
Unos_brojeva();
}
On the down side using suggested answers is that when user enters something like "ghfg" , result of this conversion is a ZERO!. So suggested answers is no-go's.
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
using namespace std;
int main()
{
string A_number;
char* An_array=new char[A_number.length()];
cout<<"Enter value for A_number: ";
cin>>A_number;
strcpy(An_array,A_number.c_str());
float n=atof(An_array);
cout<<"Value entered is: "<<n;
cin.get();
return 0;
}
The line:
cin >> r
is going to try to read a valid float, even if there is bad trailing information after it.
You are saying the problem occurs when someone enters 55x, in this case you think it should not be considered a valid number.
There is an answer to your problem here: https://stackoverflow.com/a/19717896/312594
What you have to do is read the entire data in as a string and confirm that only characters that are possible as float input (digits, ., +, -, etc.) are in the input, and in the correct possible order. Only after you validate the input do you convert the input to float (via cin or some other mechanism).
In most cases you should accept 55x as 55 since that's probably what the user wants, but if you do want to be strict you have to perform the additional validation yourself.
p.s. - I almost hate to say this as I do not want to sound biased, but as you're learning C++ you may find it useful to write all of your code, including prompts, in English. If you later ask for help on StackOverflow, it will be easier for more people to understand what you are trying to do and therefore to help you out.
Sounds like you want to read in the input as strings (or possibly whole lines), and then you can test those strings any way you like.
I'm trying to make a program in which the user enters in a number and a letter representing what unit of measurement their using (ex inches=i, feet=f, etc) then the letter inputted is used on a series of if statements to see which function to go to convert the number to how many meters it would be. I added an input validation for the units of measure(which are being used as a string variable).My problem is when I input the letter I want to use the program thinks what I entered is invalid even when the input is correct. I removed the input validation and also noticed that the string doesn't even go through any of the if statements. The code is something like this the #include included:
#include <iostream>
#include <string>
using namespace std;
float inTOmeters(float);
float ftTOmeters(float);
float cmTOmeters(float);
float yTOmeters(float);
int main{
float measurement, measurement;
string unit;
cout<<"Enter the number you want to be measured"<<endl;
cin>>measure;
cout<<"Now enter the unit of measurement you want to use"<<endl;
cout<<"i=inches, f=feet, c=centimeters, y=yards, m=meters"<<endl;
cin<<unit;
while(unit !="i"||unit !="m"||unit !="c"||unit !="y"||unit !="f"){
cout<<"Invalid input pick from I, m, c, y, or f"<<endl;
cin>>unit;
}
if(unit=="i"){
measurementm=inTOmeters(measurement);
}
if(unit=="c"){
measurementm=cmTOmeters(measurement);
}
if(unit=="f"){
measurementm=ftTOmeters(measurement);
}
if(unit=="y"){
measurementm=yTOmeters(measurement);
}
else{
measurementm=measurement;
}
cout<<"your measurement will be"<<measurementm<<"in meters."<<endl;
}
I didn't include the functions because I know they work. My question is how do I make it so my loop and if statements function when given the correct input? Also how do I make it so the code accepts capital letters of the correct input?
There are a few problems I see with your program right off the bat. From the code you've provided the variable measure has not been declared and you've declared two variables named measurement.
As for the input, have you thought about handling it with a switch statement? You can use characters for the different cases and write the default case to handle any invalid input.
Lastly, instead of a while loop you could just have your function int main with a return of return main(); which would be a fine way to loop this simple program.
As mentioned, this code has numerous problems and could not possibly compile. Try this:
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
float inTOmeters(float);
float ftTOmeters(float);
float cmTOmeters(float);
float yTOmeters(float);
int main()
{
float input, measurement=0.0;
char unit;
cout<<"Enter the number you want to convert:"<<endl;
cin>>input;
cout<<"Now enter the unit of measurement you want to use:"<<endl;
cout<<"i=inches, f=feet, c=centimeters, y=yards, m=meters"<<endl;
while(true){
cin >> unit;
unit = std::toupper(unit);
if(unit=='I'){
measurement=inTOmeters(measurement);
}
else if(unit=='C'){
measurement=cmTOmeters(measurement);
}
else if(unit=='F'){
measurement=ftTOmeters(measurement);
}
else if(unit=='Y'){
measurement=yTOmeters(measurement);
}
else if(unit=='M'){
measurement = input;
}
else if(unit=='X'){
break;
}
else{
cout << "'" << unit << "'" << "is invalid. Choose i, m, c, y, or f." << endl;
continue;
}
cout << input << " is " << measurement << " in meters." << endl;
break;
}
}
A few errors
You never input unit, you need cin >> unit; somewhere.
Logic error, you used 'or' when you should of used 'and'.
while(unit !="i" && unit !="m" && unit !="c" && unit !="y" && unit !="f"){
cout<<"Invalid input pick from I, m, c, y, or f"<<endl;
cin>>unit;
}
I you think about it a minute you'll realise that unit does not equal "i" OR unit does not equal "m" is always true.
The error is when I run the program and type n to end choosing
it doesn't end and keeps repeating the first cout and the default value:
#include <iostream>
using namespace std;
int main()
{
int x;
float y,result=0,paid,change;
do {
cout<<"enter another choose or press (n/N) to end choosing ";
cin>>x;
switch (x)
{
case 1:
{
int a=5;
cout<<"enter the wighte you want in (Kg) : ";
cin>>y;
result=a*y;
break;}
default:
cout<<"wrong choooose "<<endl;
}
}
while (x='n');
cout<<"your total= "<<result<<endl;
cout<<"mony value paid = ";
cin>>paid;
change =paid-result;
cout<<"the change = "<<change<<endl;
return 0;
}
The problem is that x is an integer, which you then compare to a character literal.
This works well when using old C-style standard I/O, which uses int instead of char, but doesn't work in C++ where the types are distinct. This means that the input on the line
cin>>x;
will fail if you do not enter a valid integer.
Change the type of x to char and it should work.
There is also the problem with the assignment instead of the condition inside while.
Sorry, I totally missed that you're using C++ I/O here.
You declare x as an int, yet you enter the character literal 'n'. The conversion will fail with C++ I/O streams, so x is never set. Don't confuse your data types; if you want to read a char then read a char, same for int.
Try something like this instead:
int x = 0;
do {
if(!(cin >> x)) {
cout << "enter a valid number" << endl;
// clear fail flag
cin.clear();
// consume newline
cin.ignore(std::numeric_limits<streamsize>::max(), '\n');
} else {
// your logic here
}
} while( x != -1 );
while (x='n');
That is not a comparison, it is an assignment, and the character 'n' when converted to an integer will always evaluate to true, so your loop never ends.
Your next problem will be that you want to exit the loop when the input is 'n', not the other way around, so it should be...
while(x != 'n');
Also realize that, if the user enters 110, the loop will exit. x is an int, and the integral value of the character literal 'n' is 110. It will also fail for 'N'.
I have been given a task of inputting some student data, like
option 1: Enter student name and id.
option 2: input i.d (verify against student id - input option 1), input upto 10 grades for the student and then calculating the average and letter grade for the student
option 3: output the student name, id and letter grade.
The program has to be written in a Class like structure - with declared variables and functions in the structure.
I have also been given the task for entering the details of 3 students using the Class structure. For simplicity sakes for now I am just writing a program for one student.
The program compiles O.K
First specific encountered problem: When I select option 'I' the program lets me input the student name and that's it! - skips the id input for some reason and continues on.
The problem is that I have been using cin>>and also scanf() as my main input methods - but these and system("Pause") have not been serving me well - I understand system("pause") is not very efficient. In the past I have been advised to use a real string type to represent strings like std::string class from the <string> library.
I would therefore appreciate any help with string classes so I can learn of them.
I believe there may be some other problems with my program but any advice with the string classes thing and my 'first specific encountered problem' would helpful to start of with.
So I have written the following program to represent my answer.
#include <iostream>
#include <cstdio>
#include <math.h>
using namespace std;
struct classroom{
char name;
int student_id;
float grades[10];
int num_tests;
float average;
float letter_grade;
void enter_name_id(void);
void enter_grade(int);
void average_grades(int);
void letter_grades(void);
void output_name_id_grade(void);
};
void classroom::enter_name_id(){
cout<<"\n Please enter name of student: \n"<<"\n";
cin>>name;
cout<<"\n Please enter student i.d number: \n"<<"\n";
scanf("%d",student_id);
cout<<"\n"<<student_id;
system("PAUSE");
}
void classroom::enter_grade(int n_tests){
if(n_tests<=10){
cout<<"\n Please enter student test grade: \n"<<"\n";
cin>>grades[n_tests];
}
else{
cout<<"\n You have reached your max number of grades entered!!"<<"\n";
}
system ("PAUSE");
}
void classroom::average_grades(int n_tests){
float sum=0;
int i;
for(i=0;i<n_tests;i++){
sum =sum+grades[i];
}
average=sum/(float)n_tests;
system ("PAUSE");
}
void classroom::letter_grades(void){
if(average>=90){
letter_grade=65;
}
if(average>=80&&average<90){
letter_grade=66;
}
if(average>=70&&average<80){
letter_grade=67;
}
if(average>=60&&average<70){
letter_grade=68;
}
if(average<60){
letter_grade=70;
}
system ("PAUSE");
}
void classroom::output_name_id_grade(void){
cout<<"\ Name I.D Grade "<<"\n";
cout<<name <<" ";
cout<<student_id<<" ";
cout<<(char)letter_grade<<"\n";
system ("PAUSE");
}
int main()
{
classroom a;
char option,answer,ans;
int a_num_tests, id;
a_num_tests=0;
for( ; ;){
cout<<"\nEnter 'I' for Name and I.d, 'G' for grades or 'O' for Data output "<<"\n";
cin>>answer;
switch(answer){
case'I':
a.enter_name_id();
break;
case'G':
cout<<"\n Please enter student i.d number: "<<"\n";
scanf("%d",id);
cout<<"\n"<<id;
if(id==a.student_id){
a_num_tests++;
a.enter_grade(a_num_tests);
cout<<"\n Would you like to enter another grade? 'Y' or 'N': "<<"\n";
cin>>ans;
while(ans=='y'||'Y'){
a_num_tests++;
a.enter_grade(a_num_tests);
cout<<"\n Would you like to enter another grade? 'Y' or 'N': "<<"\n";
cin>>ans;
}
a.average_grades(a_num_tests);
a.letter_grades();
}
else{
cout<<"\n You have entered the wong i.d number!!! \n"<<"\n";
break;
}
case 'O':
a.output_name_id_grade();
break;
default:
cout<<"\n Wong Entry "<<"\n";
break;
}
}
system ("PAUSE");
return 0;
}
Hi again for all those whom want to know, this code worked for me:
void classroom::enter_name_id(void){
cout << " Please enter your name\n>";
std::cin.ignore( 25, '\n' );
cin.getline( name,25);
cout << " Type id\n>";
cin>>student_id;
return;
}
Not sure how this line works: 'std::cin.ignore( 25, '\n' );'!!!
But never the less it was needed in order to prevent the compiler skipping
the next line: 'cin.getline( name,25);'
Originally I had problems with just using 'cin>>name' in the class function and this is why I have asked the questions for alternative real string types.
If anyone has more to add to this question, please do so.
I would like to say thank you again to all my fans out there whom have contributed to this progress we have made together.
Sail on...
So many things to say... why would you write << "\n" << "\n"?? You can just put the entire string in one piece, << "\n\n"... anyway.
For input/output, just stick with iostreams, and don't mix and match C library functions without good cause. Perhaps like so:
std::string name;
int id;
std::cout << "Please enter your name: ";
std::getline(std::cin, name);
std::cout << "Please enter the ID: ";
std::cin >> id; // see below
Maybe this answer is of some use to you. The input operations should be checked for errors, if you want to write serious code.
Note that token extraction (>>) reads word by word, so std::cin >> name will only read one single word. For something like a name, we prefer getline() for that reason.
If you run your program from the command line, you won't need all those system("pause") calls, either...
Update: It's not generally a good idea to mix token extraction (>>) with line reading (getline()), since the former doesn't gobble up newlines while the latter does. Best to stick to just one of the two, whichever is more appropriate for the input format.
If you only use line reading, you still have to process each line, perhaps again by token extraction. To do so, you need a string stream. Include <sstream> and replace the last line by:
std::string line; // you can put this at the top with the other declarations
std::getline(std::cin, line);
std::istringstream iss(line);
iss >> id;
scanf causes buffer problem. You need to clear the buffer after using it.
fflush(stdin). this will clear your buffer and input will stop for id and other inputs.
Also you can use getch() instead of system ("PAUSE");