Like Tree1Likes

need help as a c++ beginner; just a few questions with code and everything in here!

This is a discussion on need help as a c++ beginner; just a few questions with code and everything in here! within the C++ Programming forums, part of the General Programming Boards category; hello everyone the project is to make a program that grades several multiple-choice exams. The exam has less than 80 ...

  1. #1
    Registered User
    Join Date
    Nov 2013
    Posts
    12

    need help as a c++ beginner; just a few questions with code and everything in here!

    hello everyone

    the project is to make a program that grades several multiple-choice exams. The exam has less than 80 questions, each answered with a letter in the range of ‘a’ through ‘f’. The data are stored on several files such as exam1.dat.

    A typical input exam data file (exam1.dat) looks like:


    abcdefabcdefabcdefab
    1234567 abcdefabcdefabcdefab
    9876543 abddefbbbdefcbcdefac
    5554446 abcdefabcdefabcdef
    4445556 abcdefabcdefabcdefabcd

    in which the first line is the key, consisting of a string of n characters (0<n < 80). The remaining lines on the file are exam answers, and consist of a student ID number, a space, and a string of n characters.

    the program has a capability of repeatedly asking for a new data file in each while loop until users input a key word “exit”. Once “exit” is encountered, the while loop terminates and the program ends. this is one of the parts i am stuck on. where and how do i put an exit command or option? like i wanna say: if something, cin exit...i doubt that right, so ya, how do i do this? and where do i put it in my code? i know it has to be in the while loop right?

    we have to apply the length( ) of string to the first line of the above data file for determining the number of questions in the problem. since we have to make several functions, i decided to make a infile/outfile function as seen, and i wanna make a length function. however, i dont know how to do the length function. i am sure its something like void size, since i call the function "length.size" but what do i put inside it besides the loop? If a student gives more answers than needed, the extra answers will be automatically cut. if a student provides less number of answers, the remaining unanswered questions are considered incorrect. i kinda get the idea behind this and i seen a few examples, but its like not able to form from my head. some guidance on this part would be appreciated as well

    After users input an exam data file, the program asks users to input another grade-curving file name (e.g., gradeCurving.dat). This second file contains the information to convert a percentile score to a curved grade in levels of ‘A’ through ‘E’.


    A 90
    B 80
    C 70
    D 60
    E 50

    the program asks users to input an output file name such as score1.dat. The output file will store the scores for each student in a format: student ID number, a space, a percentile score, and a curved grade in ‘A’ though ‘E’. which i have done as seen in the code. The program should also compute and display the following statistics for the graded answers: Average score, Maximum score, and Minimum score. i need help on this part...how do i make average max and min? i never got the idea in class and all the time i needed assistant on this part. what easy way to know how? example or project example might help

    output on a data file looks like:


    1234567 90% A
    9876543 85% B
    5554446 95% A
    4445556 75% C
    5551112 80% B
    Statistics:
    Average Score: 85%
    Minimum Score: 95%
    Maximum Score: 75%

    and here is my code so far

    Code:
    #include "stdafx.h"
    #include <iostream>
    #include <string>
    #include <fstream>
    #include <assert.h>
    
    
    using namespace std;
    
    
    void openfiles(ifstream& infile, ofstream& outfile);
    
    
    void size();
    
    
    int main()
    {
        int num_student = 4, count, length, score2, w[6];
    
    
        ifstream infile, curvingfile; char x;
    
    
        ofstream outfile; float score;
    
    
        string  key, answer, id;
    
    
        do {
            openfiles(infile, outfile); // function calling
    
    
            infile >> key; // answer key
    
    
            for (int i = 0; i < num_student; i++) // loop over each student
    
    
            {
                infile >> id;
    
    
                infile >> answer;
    
    
                count = 0;
    
    
                length = key.size(); // length represents number of questions in exam from exam1.dat
                                     // size is a function....
    
    
                for (int j = 0; j < length; j++) // loop over each question
                {
                    if (key[j] == answer[j])
    
    
                        count++;
                }
    
    
                score = (float) count / length; 
    
    
                score2 = (int)(score * 100);
    
    
                outfile << id << "     " << score2 << "%";
    
    
                if (score2 > 90)//<-----w[0]
    
    
                    outfile << "A" << endl;
    
    
                else if (score2 > 80)//<-----w[1]
    
    
                    outfile << "B" << endl;
    
    
                else if (score2 > 70)//<-----w[2]
    
    
                    outfile << "C" << endl;
    
    
                else if (score2 > 60)//<-----w[3]
    
    
                    outfile << "D" << endl;
            }
            cout << "Would you like to attempt a new trial? (y/n): ";
    
    
            cin >> x;
        
        } while (x == 'y' || x == 'Y');
    
    
        return 0;
    }
    
    
    void openfiles(ifstream& infile, ofstream& outfile)
    {
        string name1, name2, name3;
         
        cout << "Input the name for the exam file: ";
    
    
        cin >> name1;
    
    
        infile.open(name1.c_str());
    
    
        cout << "Input the name for the curving file: ";
    
    
        cin >> name2;
    
    
        infile.open(name2.c_str());
    
    
        cout << "Input the name for the output: ";
    
    
        cin >> name3;
    
    
        outfile.open(name3.c_str());
    
    
    }


    ***i hope its right asking here. it may be a bit extra questions, but hey. its only my first 2 months introduced to programming and i am already at such advanced stuff. i wish i knew how the class will turn out to be so i would have watched tutorials at least from the summer and got some idea before hand. i didnt even know the class is gonna be c++ programming. i thought its like general computer information. so yea. i appreaciate any help in advanced! who knows, one day i am sure ill become someone who'll be helping back....***

  2. #2
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,447
    > void openfiles(ifstream& infile, ofstream& outfile)
    > string name1, name2, name3;
    Why do you prompt for 3 files, when you only have two file references?
    Why do you open infile twice?

    > the program has a capability of repeatedly asking for a new data file in each while loop until users input a key word “exit”.
    You need to make openfiles() return some kind of status then, which you can test for in main.

    Eg.
    Code:
    cin >> name1;
    if ( name1 == "exit" ) return false;
    /// rest of code to input filenames...
    return true;
    FYI, massive question dumps in walls of text put people off.
    Keep it short and simple, then people can see what it is you're after.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  3. #3
    Registered User
    Join Date
    Nov 2013
    Posts
    12
    Quote Originally Posted by Salem View Post
    > void openfiles(ifstream& infile, ofstream& outfile)
    > string name1, name2, name3;
    Why do you prompt for 3 files, when you only have two file references?
    Why do you open infile twice?

    > the program has a capability of repeatedly asking for a new data file in each while loop until users input a key word “exit”.
    You need to make openfiles() return some kind of status then, which you can test for in main.

    Eg.
    Code:
    cin >> name1;
    if ( name1 == "exit" ) return false;
    /// rest of code to input filenames...
    return true;
    FYI, massive question dumps in walls of text put people off.
    Keep it short and simple, then people can see what it is you're after.
    i prompt for 3 files because there is two input files, the exam1.dat and grading curve, so in that case, it'd be name1 and name2, then the output is name3, which is the third quote.

    so i am confused now, dide you assume i made a mistake with 3 names and so you set "name1==exit" as some random other file? where do i include this in the void function or the main? i am thinking its the void because you said rest of code ask for input files...so do i pit that instead of name1 part? should this be like after name 2 and before name 3 the out file?

    also, how can i make it shorter? people will in that case tell me they dont know what i am talking about, and the rules state the questions should be detailed to be clear. if i make it shorter, i am not sure if a person will know what i am talking about...
    Last edited by catastrophe; 11-03-2013 at 11:45 AM.

  4. #4
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,185
    Quote Originally Posted by catastrophe View Post
    i prompt for 3 files because there is two input files, the exam1.dat and grading curve, so in that case, it'd be name1 and name2, then the output is name3, which is the third quote.
    But you only have infile and outfile. Once you open infile with your name2, then your first file is gone and exists no more (in your program).
    Quote Originally Posted by catastrophe View Post
    so i am confused now, dide you assume i made a mistake with 3 names and so you set "name1==exit" as some random other file?
    Nope. You yourself said that if the user types "exit" you want to stop, so there you go.

    Quote Originally Posted by catastrophe View Post
    where do i include this in the void function or the main? i am thinking its the void because you said rest of code ask for input files...so do i pit that instead of name1 part? should this be like after name 2 and before name 3 the out file?
    You could (I suppose) read the text around the code, you know, the English part. "You need to make openfiles() return some kind of status". That suggests you should be looking at the openfiles function.

    Quote Originally Posted by catastrophe View Post
    also, how can i make it shorter? people will in that case tell me they dont know what i am talking about, and the rules state the questions should be detailed to be clear. if i make it shorter, i am not sure if a person will know what i am talking about...
    If you get to the point where you have six not-really-related questions, you're already in too deep of a hole. There's no reason to put "how to make an exit option in a menu", "how to find the length of a string", and "how to find the average of a set of numbers" in one post.

  5. #5
    Registered User
    Join Date
    Nov 2013
    Posts
    12
    Quote Originally Posted by tabstop View Post
    But you only have infile and outfile. Once you open infile with your name2, then your first file is gone and exists no more (in your program).

    ya, the infile is name 1 and name 2. and the outfile is name 3. whats wrong about that? perhaps a code explanation might help clear this up.

    Nope. You yourself said that if the user types "exit" you want to stop, so there you go.

    but i dont get though, if as i am saying name1 and name 2 are the INFILE itself, like infile is storage for name1 and name2, why is the code above
    Code:
    do {		openfiles(infile, outfile) { // function calling
    
    
    			cin >> name1;
    			if (name1 == "exit") return false;
    		};
    
    
    		return true;
    only name1=="exit"? what if name2 is also exit? the useronly has otion to exit name 1, not name 2. so...

    You could (I suppose) read the text around the code, you know, the English part. "You need to make openfiles() return some kind of status". That suggests you should be looking at the openfiles function.

    so like this:

    Code:
    do {		openfiles(infile, outfile) { // function calling
    
    
    			cin >> name1;
    			if (name1 == "exit") return false;
    		};
    
    
    		return true;


    If you get to the point where you have six not-really-related questions, you're already in too deep of a hole. There's no reason to put "how to make an exit option in a menu", "how to find the length of a string", and "how to find the average of a set of numbers" in one post.
    in that case, i would make for every question a thread?

  6. #6
    Registered User whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    7,627
    only name1=="exit"? what if name2 is also exit? the useronly has otion to exit name 1, not name 2. so...
    Good point. My suggestion would be to handle all input with one string. The reason you would use one string is so you have only one variable to check for "exit". Depending on what question you asked the person using your program, you can assign the input to name1, name2, or name3.

    in that case, i would make for every question a thread?
    No, if it all has to do with one assignment then one thread is enough. I think the point of everyone's complaining is that if you need to be hand-held through the entire assignment because you have 5 or 6 questions, you might get ignored. You didn't do anything wrong, per se.

  7. #7
    Registered User
    Join Date
    Nov 2013
    Posts
    12
    Quote Originally Posted by whiteflags View Post
    Good point. My suggestion would be to handle all input with one string. The reason you would use one string is so you have only one variable to check for "exit". Depending on what question you asked the person using your program, you can assign the input to name1, name2, or name3.

    wait actually, i came up with this

    Code:
    int openfiles(ifstream& infile, ofstream& outfile){
    	string name1, name2, name3;
    
    
    	cin >> name1; name2; name3;
    	if (name1 == "exit" || name2 == "exit" || name3 == "exit" ) return false;
    	 
    	cout << "Input the name for the exam file: ";
    
    
    	cin >> name1;
    
    
    	infile.open(name1.c_str());
    
    
    	cout << "Input the name for the curving file: ";
    
    
    	cin >> name2;
    
    
    	infile.open(name2.c_str());
    
    
    	cout << "Input the name for the output: ";
    
    
    	cin >> name3;
    
    
    	outfile.open(name3.c_str());
    
    
    	return true;
    }

    No, if it all has to do with one assignment then one thread is enough. I think the point of everyone's complaining is that if you need to be hand-held through the entire assignment because you have 5 or 6 questions, you might get ignored. You didn't do anything wrong, per se.
    ok thnx

  8. #8
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,185
    Quote Originally Posted by catastrophe View Post
    ya, the infile is name 1 and name 2. and the outfile is name 3. whats wrong about that? perhaps a code explanation might help clear this up.
    Code:
    //Assuming all the necessary header things
    infile.open("file1.txt");
    infile.open("file2.txt");
    //at this point any calls to infile will ONLY read from file2
    //there is no way to read from file1
    
    //which is a shame because you need to read from file1
    //but you can't
    Quote Originally Posted by catastrophe View Post
    if as i am saying name1 and name 2 are the INFILE itself,
    Not sure where you got that, but that statement doesn't really have any relationship with reality. infile is a file stream that can point to one file (at a time) and one only.

    Quote Originally Posted by catastrophe View Post
    only name1=="exit"? what if name2 is also exit? the useronly has otion to exit name 1, not name 2. so...
    You could check name2 as well, if you want to give them a chance to change their mind.

    Quote Originally Posted by catastrophe View Post
    in that case, i would make for every question a thread?
    It's generally considered bad form to have unrelated questions in the same thread.

  9. #9
    Registered User
    Join Date
    Nov 2013
    Posts
    12
    ok, my professor told us that thats how the code would be, so he might be wrong, because he is the one that wrote that infile has two variable, and outfile one variable. so if name1 and name 2 are the two and name3 is the oufile, where is the mistake in that? what do i need to add to make the two input files?

    aside from that, here is the updated code i have accomplished so far.

    Code:
    #include "stdafx.h"#include <iostream>
    #include <string>
    #include <fstream>
    #include <assert.h>
    
    
    using namespace std;
    
    
    int openfiles(ifstream& infile, ofstream& outfile);
    
    
    void size();
    
    
    int main()
    {
    	int num_student = 4, count, length, score2, w[6];
    
    
    	ifstream infile, curvingfile; char x;
    
    
    	ofstream outfile; float score;
    
    
    	string  key, answer, id;
    
    
    	do {
    		openfiles(infile, outfile);  // function calling
    
    
    		infile >> key; // answer key
    
    
    		for (int i = 0; i < num_student; i++) // loop over each student
    
    
    		{
    			infile >> id;
    
    
    			infile >> answer;
    
    
    			count = 0;
    
    
    			length = key.size(); // length represents number of questions in exam from exam1.dat
    								 // size is a function....
    
    
    			for (int j = 0; j < length; j++) // loop over each question
    			{
    				if (key[j] == answer[j])
    
    
    					count++;
    			}
    
    
    			score = (float) count / length; 
    
    
    			score2 = (int)(score * 100);
    
    
    			outfile << id << "     " << score2 << "%";
    
    
    			if (score2 > 90)//<-----w[0]
    
    
    				outfile << "A" << endl;
    
    
    			else if (score2 > 80)//<-----w[1]
    
    
    				outfile << "B" << endl;
    
    
    			else if (score2 > 70)//<-----w[2]
    
    
    				outfile << "C" << endl;
    
    
    			else if (score2 > 60)//<-----w[3]
    
    
    				outfile << "D" << endl;
    		}
    		cout << "Would you like to attempt a new trial? (y/n): ";
    
    
    		cin >> x;
    	
    	} while (x == 'y' || x == 'Y');
    
    
    	return 0;
    }
    
    
    int openfiles(ifstream& infile, ofstream& outfile)
    {
    	string name1, name2, name3;
    
    
    	cin >> name1; name2; name3;
    	if (name1 == "exit" || name2 == "exit" || name3 == "exit" ) return false;
    	 
    	cout << "Input the name for the exam file: ";
    
    
    	cin >> name1;
    
    
    	infile.open(name1.c_str());
    
    
    	cout << "Input the name for the curving file: ";
    
    
    	cin >> name2;
    
    
    	infile.open(name2.c_str());
    
    
    	cout << "Input the name for the output: ";
    
    
    	cin >> name3;
    
    
    	outfile.open(name3.c_str());
    
    
    	return true;
    }
    i still am not sure how exactly am i supposed to do the void size function.

  10. #10
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,185
    Quote Originally Posted by catastrophe View Post
    ok, my professor told us that thats how the code would be, so he might be wrong, because he is the one that wrote that infile has two variable, and outfile one variable. so if name1 and name 2 are the two and name3 is the oufile, where is the mistake in that? what do i need to add to make the two input files?
    You can reuse the name, provided that you have read everything you need to read from file1 before you open file2. You certainly can't try to open them both into the same file stream and then try to read from them. (And given you are trying to open all the files from this single function without doing any processing, there's no way you can get that reading done.)

    Quote Originally Posted by catastrophe View Post
    i still am not sure how exactly am i supposed to do the void size function.
    You have "length = key.size();" in your code, and that should be just about the entirety of the use of size in your program, as the answer key string, and the student answer strings, are the only thing you need to know the size of. (You will find the "size" of your other input file, in terms of the number of students, by the simple expedient of processing all the students in the file. It is neither necessary nor desirable to try to get the size ahead of time.) (And for that matter, you may be able to get away without finding the size of the student answer strings either, depending on how you set up your check-answer function.)

  11. #11
    Registered User
    Join Date
    Nov 2013
    Posts
    12
    Quote Originally Posted by tabstop View Post
    You can reuse the name, provided that you have read everything you need to read from file1 before you open file2. You certainly can't try to open them both into the same file stream and then try to read from them. (And given you are trying to open all the files from this single function without doing any processing, there's no way you can get that reading done.)


    You have "length = key.size();" in your code, and that should be just about the entirety of the use of size in your program, as the answer key string, and the student answer strings, are the only thing you need to know the size of. (You will find the "size" of your other input file, in terms of the number of students, by the simple expedient of processing all the students in the file. It is neither necessary nor desirable to try to get the size ahead of time.) (And for that matter, you may be able to get away without finding the size of the student answer strings either, depending on how you set up your check-answer function.)
    so there is no need for me to make the void size()? then why did people kept telling me to make one XD...cause i looked at a string table and it didnt have any function related except just like what i have; length=key.size()....ok so i am over with this part...

    for the use name again, you mean "infile name 1" and infile name2?

  12. #12
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,185
    Quote Originally Posted by catastrophe View Post
    for the use name again, you mean "infile name 1" and infile name2?
    That would look something like:
    Code:
    infile.open("file1.txt");
    //now process file1
    infile >> answerstring;
    //whatever other data you need, you need to get it now
    infile.open("file2.txt");
    //file1 is now closed, so all the reading will happen from file2
    infile >> curvedata;

  13. #13
    Registered User
    Join Date
    Nov 2013
    Posts
    12
    so so far its like this:

    Code:
    int openfiles(ifstream& infile, ofstream& outfile){
        string name1, name2, name3, answerstring, curvedata;
    
    
        cin >> name1; name2; name3;
        if (name1 == "exit" || name2 == "exit" || name3 == "exit" ) return false;
         
        cout << "Input the name for the exam file: ";
    
    
        cin >> name1;
    
    
        infile.open(name1.c_str());
    
    
        infile >> answerstring;
    
    
        cout << "Input the name for the curving file: ";
    
    
        cin >> name2;
    
    
        infile.open(name2.c_str());
    
    
        infile >> curvedata;
    
    
        cout << "Input the name for the output: ";
    
    
        cin >> name3;
    
    
        outfile.open(name3.c_str());
    
    
        return true;
    }
    would i then have to change ifstream in main, curvingfile, to curvedata? and for string answer, answer is used somewhere in the main so i cant delete that as well for the answerstring. i just defined those two new variables in the string of my int openfiles. is that right? here the code for main

    Code:
    ifstream infile, curvingfile; char x;
    
    
        ofstream outfile; float score;
    
    
        string  key, answer, id;
    also, do you know how a void function for size isnt needed? what about this part that asks
    If a student gives more answers than needed, the extra answers will be automatically cut. if a student provides less number of answers, the remaining unanswered questions are considered incorrect.
    isnt that part supposed to be with the void function because if length is more it would cut it? how would i implement this? cause i have no idea how c++ will cut extra answers automatically...
    Last edited by catastrophe; 11-03-2013 at 02:17 PM.

  14. #14
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,185
    Quote Originally Posted by catastrophe View Post
    would i then have to change ifstream in main, curvingfile, to curvedata? and for string answer, answer is used somewhere in the main so i cant delete that as well for the answerstring. i just defined those two new variables in the string of my int openfiles. is that right?
    The thing to keep in mind (which I fear you may just be learning right now, for one reason or another) is that there is no communication between one function and another function, except via passing arguments and return statements. You can do what you like in your openfiles function, and everything that happens there is completely independent of what happens in the main function. Just because you give two variables the same name does not cause them to be magically linked. Any information you read in your openfiles function can not be passed to, or used by, your main function unless you return it. So you can read that answerstring in your openfiles function. If you do so, once you leave the function and go back to main, that information disappears completely and is not recoverable. It is gone.

    If your openfiles function is supposed to open three files, then either those three (two is not enough) file handles must be passed in by reference (so the function can change them and have those changes be returned to the main) or you must return some object that has those three (two is not enough) file handles in it (as you can only return one object from a function). Currently you're going for option 1, but three are still required.

    Quote Originally Posted by catastrophe View Post
    also, do you know how a void function for size isnt needed? what about this part that asks isnt that part supposed to be with the void function because if length is more it would cut it? how would i implement this? cause i have no idea how c++ will cut extra answers automatically...
    You can use .size with the read-in answer string, just the same way you use .size with the answer key string. But there's nothing there for you to write; that function already exists (and you've already used it); it's not something new. And you can do that if you like (it may well make your checking-answer loop look a little more neat and tidy) -- but you can very easily write your answer-checking loop without that knowledge, assuming you can tell whether you have gotten to the end of a string.

  15. #15
    Registered User
    Join Date
    Nov 2013
    Posts
    12
    Quote Originally Posted by tabstop View Post
    The thing to keep in mind (which I fear you may just be learning right now, for one reason or another) is that there is no communication between one function and another function, except via passing arguments and return statements. You can do what you like in your openfiles function, and everything that happens there is completely independent of what happens in the main function. Just because you give two variables the same name does not cause them to be magically linked. Any information you read in your openfiles function can not be passed to, or used by, your main function unless you return it. So you can read that answerstring in your openfiles function. If you do so, once you leave the function and go back to main, that information disappears completely and is not recoverable. It is gone.

    If your openfiles function is supposed to open three files, then either those three (two is not enough) file handles must be passed in by reference (so the function can change them and have those changes be returned to the main) or you must return some object that has those three (two is not enough) file handles in it (as you can only return one object from a function). Currently you're going for option 1, but three are still required.

    i am so confused right now. what option do you mean i used? what am i supposed to add/change? i just need the program to read the two in files input by user, then output to an ouput file the student stuff and the average score, minimum score, and maximum score.

    You can use .size with the read-in answer string, just the same way you use .size with the answer key string. But there's nothing there for you to write; that function already exists (and you've already used it); it's not something new. And you can do that if you like (it may well make your checking-answer loop look a little more neat and tidy) -- but you can very easily write your answer-checking loop without that knowledge, assuming you can tell whether you have gotten to the end of a string.
    so how do i do the if extra answers to cut it and if less to count extra as wrong?

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Beginner questions
    By c++urious in forum Programming Book and Product Reviews
    Replies: 1
    Last Post: 06-14-2010, 04:16 PM
  2. Some beginner questions.
    By Kitt3n in forum C++ Programming
    Replies: 1
    Last Post: 05-15-2010, 04:18 PM
  3. Some beginner questions.
    By Meikj in forum C++ Programming
    Replies: 3
    Last Post: 05-01-2009, 11:37 AM
  4. A few beginner's questions
    By Megidolaon in forum C++ Programming
    Replies: 33
    Last Post: 10-24-2008, 09:21 AM
  5. 2 beginner questions
    By GCat in forum C++ Programming
    Replies: 15
    Last Post: 11-24-2004, 02:55 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21