0

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;

}
Mat
  • 202,337
  • 40
  • 393
  • 406
Mr_leighman
  • 313
  • 1
  • 6
  • 22
  • 1
    Why did you mix C's scanf and C++'s cin? As a c++ programmer I could never successfully get c's functions to work. – Hossein Oct 31 '11 at 12:59
  • 1
    If this is homework, make sure you tag the question as such, as it is considered poor form to pretend that an obvious class exercise is a "real" programming problem (and the approach to responding is very different). – Kerrek SB Oct 31 '11 at 12:59
  • No Kerrek SB it is not a class homework question, the question is from a text book and I am self learning – Mr_leighman Oct 31 '11 at 13:02
  • Hossein - Did not realize scanf() was C's and cin was C++'s so now I know! - thanks. – Mr_leighman Oct 31 '11 at 13:06
  • Like @Hossein says, don't mix `cin` with the old C functions (like `scanf`), the input buffering will most likely not be able to handle it. Use one or the other. – Some programmer dude Oct 31 '11 at 13:08
  • @user993858: Fair enough, but that means it's still not an actual programming problem you need to solve, but rather a learning exercise. So would you like a flat-out full solution, or hints, or general "How to write idiomatic C++" advice? – Kerrek SB Oct 31 '11 at 13:16

3 Answers3

2

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...

Mr_leighman
  • 313
  • 1
  • 6
  • 22
  • "Originally I had problems with just using 'cin>>name' in the class function" - should be: Originally I had problems with just using 'cin>>name' in the 'struct'function. – Mr_leighman Nov 05 '11 at 20:33
0

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");

Ankur
  • 12,676
  • 7
  • 37
  • 67
0

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;
Community
  • 1
  • 1
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • Note that `std::cin >> id` will probably leave characters in the buffer. It might be a good idea to follow it with `std::cin.ignore( INT_MAX, '\n' );`, or to use `std::getline` for all input, putting the line in an `std::istringsstream` to convert it. – James Kanze Oct 31 '11 at 13:39
  • @JamesKanze: Quite possibly; I haven't read through the entire design document. It's probably best not to mix token extraction and line reading, though, so yes, `getline()` throughout would be a good idea. – Kerrek SB Oct 31 '11 at 14:14
  • @KerrekSB This separation is particularly useful if you have to recover from errors, since it provides an automatic resynchronization point; just throw out the line where you find the error, and try again with a new line. – James Kanze Oct 31 '11 at 15:05
  • Thanks James, could you be more specific on using std::istringsstream to convert the std::getline. i.e an actual workable piece of code example? – Mr_leighman Oct 31 '11 at 19:05
  • @user993858: This has been done a million times over on StackOverflow; just search a bit and you will find. If you really want, I can amend the example... – Kerrek SB Oct 31 '11 at 19:12
  • I used this code in the functions std::string name; std::string mystring; std::cout << "Please enter your name: "; std::getline(std::cin, name); std::cout << "Please enter your id: "; std::getline(std:: cin, mystring); std::istringstream strin(mystring); strin >> student_id; – Mr_leighman Oct 31 '11 at 20:29
  • But when I tried to use the same in the main program body I get error:182 D:\leigh's stuff2\Programming\Question_1_ch_8.cpp [Warning] destructor needed for `strin' !!! – Mr_leighman Oct 31 '11 at 20:30
  • Yes sure Kerrek SB, if you can amend example, that would be helpful. – Mr_leighman Nov 03 '11 at 09:17