Writing array of objects in a file

This is a discussion on Writing array of objects in a file within the C++ Programming forums, part of the General Programming Boards category; I am having trouble writing and reading array of objects. this program is representing the trouble that I am having ...

  1. #1
    Registered User
    Join Date
    Jan 2011
    Location
    India
    Posts
    9

    Writing array of objects in a file usyng write()

    I am having trouble writing and reading array of objects.
    this program is representing the trouble that I am having in real one.
    I want to write class objects in a file "Stu.txt" and then read it so that i can display its contents the program is giving garbage value after 3 objects.
    i don't know why? I have search through net but can't find any solution.
    I don't have any idea about the problem.

    I am using borland 5.0.2 in windows xp sp2
    And one more thing why the contents of Stu.txt are displayed in form of symbols
    that too only values of those variables which are not char?
    I have provided the output just in case.
    Please help me...
    Thanks in advance.

    Here is my code.


    Code:
    #include <fstream.h>
    #include <iostream.h>
    #include <stdio.h>
    #include <windows.h>
    
    //definition for class student
    class Student {	char name[10];
    						char grade;
    						float marks;
                      int rn;
    				public :
    					void getdata()
    					{	cout<<"\nenter name "; gets(name);
    						cout<<"enter grade ";	cin>>grade;
    						cout<<"enter marks ";	cin>>marks;
                      cout<<"enter roll no ";	cin>>rn;
    					}
    
    					void display()
    					{	cout<<"\nName ";puts(name);
    						cout<<"Grade "<<grade;
    						cout<<"\nMarks "<<marks;
                      cout<<"\nroll no "<<rn;
    					}
    				 };
    
    	int main()
    		{
    			Student arts[5];
    			fstream filin;            
    //defining fstream objects
              filin.open("Stu.txt",ios::in|ios::out);  
    //opening the file Stu.txt
    			if(!filin)                
    //if filin is zero
    			{
    				cout<<"\ncannot open file.";
    				return 1;
    			}
    			cout<<"\nEnter details of students";        
    //Entering data
    			for(int i=0;i<5;i++)
    			{	arts[i].getdata();
    				filin.write((char*)&arts[i],sizeof(arts[i]));      
     //writing in Stu.txt
    			}
    			filin.close();    
     //closing file Stu.txt
    			filin.open("Stu.txt",ios::in|ios::out);  
    //opening file Stu.txt
    			if(!filin)     
    //checking again for filin
    			{
    				cout<<"\ncannot open file.";
    				return 1;
    			}
    			filin.seekg(0);
    			cout<<"\nthe contents of stu.txt are ";
    			for(int i=0;i<5;i++)
    			{	filin.read((char*)&arts[i],sizeof(arts[i]));	
    //reading from file
    				arts[i].display();
    			}
    			filin.close();     
    //closing file Stu.txt
             system("pause"); 
    /*for pause progam as the program
                                automatically exits which enables
                                user to see results*/
    		}
    Output

    enter name ay
    enter grade A
    enter marks 41
    enter roll no 1

    enter name ak
    enter grade A
    enter marks 42
    enter roll no 2

    enter name am
    enter grade A
    enter marks 43
    enter roll no 3

    enter name af
    enter grade A
    enter marks 44
    enter roll no 4

    enter name as
    enter grade A
    enter marks 45
    enter roll no 5

    the contents of stu.txt are

    enter name ay
    enter grade A
    enter marks 41
    enter roll no 1

    enter name ak
    enter grade A
    enter marks 42
    enter roll no 2

    enter name am
    enter grade A
    enter marks 43
    enter roll no 3

    enter name af
    enter grade
    // here are the errors - no grade
    enter marks 2.28266e-36
    // garbage value
    enter roll no 1627389952
    // garbage value

    enter name s
    // missing a in name as
    enter grade
    // missing grade
    enter marks 9.13139e-36
    // garbage value
    enter roll no 0
    // garbage value
    Last edited by Salem; 01-12-2011 at 12:52 AM. Reason: Use [code][/code] tags for posting CODE!!

  2. #2
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,801
    #1. Your code is difficult to read due to lack of formatting.


    #2.
    Code:
    void getdata()
    { cout<<"\nenter name "; gets(name);
    cout<<"enter grade "; cin>>grade;
    cout<<"enter marks "; cin>>marks;
    cout<<"enter roll no "; cin>>rn;
    
    void display()
    { cout<<"\nName ";puts(name);
    cout<<"Grade "<<grade;
    cout<<"\nMarks "<<marks;
    cout<<"\nroll no "<<rn;
    }
    }
    You're mixing C/C++ I/O, you should avoid doing this. gets in particular should absolutely be avoided, prefer fgets if you really needed to use C input for this purpose here. There is a very nice cin.getline() function that is perfect for what you want which could easily take the place of the gets call.

    As for the puts, there is no need again to be using C output when simply stating cout<<"\nName " << name; would do just fine.


    #3.
    Code:
    #include <fstream.h>
    #include <iostream.h>
    #include <stdio.h>
    #include <windows.h>
    The first two of these are old versions of the C++ headers. If you can, you should have:
    Code:
    #include <fstream>
    #include <iostream>
    #include <cstdio>
    There is no reason to have the windows.h header since there is nothing there that your code needs from it.


    #4.
    Code:
    system("pause");
    /*for pause progam as the program
    automatically exits which enables
    user to see results*/
    }
    Calls to system in general should be avoided. A call to cin.get (or two) can accomplish the same thing more safely. In addition to the headers you've already got, I believe the system function needs the stdlib.h/cstdlib header - pick one (hopefully the later). You should also consider an explicit return 0; or something to that effect at the end of your program.


    #5.
    Code:
    filin.open("Stu.txt",ios::in|ios::out);
    ...
    filin.close();
    ...
    filin.open("Stu.txt",ios::in|ios::out);
    ...
    filin.seekg(0);
    The open mode for the first call to open should be ios_base::out since you have no need to do any reading at this point. The second open call should be ios_base::in since all you're going to be doing at this point is reading from the file. The seekg is completely unnecessary. Opening the file will set the "get" pointer to the start of the file, there is no need to explicitly state "go to the beginning before you start reading".

    Alternately you could just open the file once in read/write mode and use the seekg in between your write/read attempts without closing the file and having to reopen it.



    #6. There is a problem in your read loop. When you've finished reading the first "roll no" there is a newline character left in the stream that needs to be dealt with before you go back to reading the next students name. Otherwise you'd skip the gets call and not be able to enter data for the name. A cin.get call would likely do the job.


    #7.
    And one more thing why the contents of Stu.txt are displayed in form of symbols
    that too only values of those variables which are not char?
    The actual contents of the stu.txt file appear as they do because of how you are writting data to the file using the write function. You pass a stream of bytes of a particular length to the write function which ends up writting those bytes exactly as they appear in memory. The funny characters are because of the binary representation of the float and int variables your class has. If you use << to write the values to the file, then you'd see the text converted version of those values but then you'd have problems reading and displaying them back to the user because the length of the data would not necessarily be fixed liked they are when using write.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  3. #3
    Registered User
    Join Date
    Jan 2011
    Location
    India
    Posts
    9
    First of all thanks i will surely follow your advices.

    But one more problem has has occurred now (i think this one is due to that #7 point you
    stated) -
    now when the the program asks for second student it skips the name part.


    enter name ay
    enter grade A
    enter marks 41
    enter roll no 1

    enter name enter grade

    One more thing i need to know can write whole array through one write f(x)
    after calling getdata() for all objects(same goes for read())?

    #1

    I was a frustrated, after hours of programming i could not get the base of my program right but i won't do it again.
    I am school boy working for my school project so i don't have much experience and
    Patience which got me frustrated.

    #2

    Can teach me a little more about fgets?
    Its header file and parameters and anything that i need to know.

    #3

    I know about them. its just that i copied the code from my textbook in hurry.
    but i think windows is needed for system("pause") although i won't use it again.

    #5

    I know about these but i used copy-paste here from another code.

    #6

    I don't have any idea about what you are saying. Can you explain and give solution
    for it since i think this is were the problem is?

    #7

    thanks about this one I didn't had a clue about them.

    Thank again you saved me the trouble of asking this to my teacher as i can't beer her
    and when i showed her the real program she didn't even had a clue of what was going on.
    Last edited by Dynamis; 01-11-2011 at 09:12 AM.

  4. #4
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,801
    But one more problem has has occurred now (i think this one is due to that #7 point you
    stated) -
    now when the the program asks for second student it skips the name part.
    No, that's because of what I mentioned in #6...
    Code:
    void getdata()
    {
        cout<<"\nenter name "; gets(name);
        cout<<"enter grade "; cin>>grade;
        cout<<"enter marks "; cin>>marks;
        cout<<"enter roll no "; cin>>rn;
    }
    Processing input works differently depending on what you are trying to read. When you reach your cin>>rn code, you enter a numeric value and press the return key. The value is converted and stored into the rn variable but the newline is kept in the input buffer and can be read/processed in subsequent input operations. This is where the rules can be confusing... if you were to read another numeric value at this point, the existing newline in the input buffer would be skipped and the input operation would block (wait for input) until you entered another number and then pressed the enter key once more. But, in your loop you go back to the gets call which read character input instead of numeric input. The processing of character data here is handled differently than if you were trying to read a number for instance. Here, the existing newline that is still in the buffer from the previous cin>>rn statement is interpreted as you - the user - having pressed the enter key without really entering anything. Nothing gets stored in the name field and the effect is that your code appears to skip that statement altogether. This fault is therefore due to the newline that is left over from a previous input. What needs to happen - probably after the cin>>rn statement is you must throw away the trailing newline in the input buffer so that when you next attempt to read the name it does not skip over that line. This can be done in a couple ways one of which is:
    Code:
    void getdata()
    {
        ...
        cout<<"enter roll no "; cin>>rn;
        cin.get();  // Eat up the leftover newline character
    }
    Another way to deal with a leftover newline would be to call cin.ignore(). With this in place, your second (and subsequent) calls to the getdata function will not skip the input of the name field.


    ************************************************** *****************

    Can teach me a little more about fgets?
    Its header file and parameters and anything that i need to know.
    fgets is prototyped in the stdio.h/cstdio headers. It would be used as such:
    Code:
    fgets(name,sizeof(name),stdin);
    For your program I would recommend cin.getline instead:
    Code:
    cin.getline(name,sizeof(name));
    ...this is a C++ solution and therefore fits more with the rest of your program. Putting everything together, I would have the getdata function look as such:
    Code:
    void getdata()
    {
        cout<<"\nenter name "; cin.getline(name,sizeof(name));
        cout<<"enter grade "; cin>>grade;
        cout<<"enter marks "; cin>>marks;
        cout<<"enter roll no "; cin>>rn;
        cin.get();
    }

    ************************************************** *****************

    #3

    I know about them. its just that i copied the code from my textbook in hurry.
    but i think windows is needed for system("pause") although i won't use it again.
    No, see #4:
    In addition to the headers you've already got, I believe the system function needs the stdlib.h/cstdlib header - pick one (hopefully the later).
    If you've made the change mentioned above to deal with the skipping of the input, then all you would need to replace a system call is another cin.get() call at the bottom of the main function.

    ************************************************** *****************

    #6

    I don't have any idea about what you are saying. Can you explain and give solution
    for it since i think this is were the problem is?
    Already done in the first part of this post.


    ************************************************** *****************
    Change the display function from:
    Code:
    void display()
    { cout<<"\nName ";puts(name);
    cout<<"Grade "<<grade;
    cout<<"\nMarks "<<marks;
    cout<<"\nroll no "<<rn;
    }
    To:
    Code:
    void display()
    { cout<<"\nName " << name;
    cout<<"\nGrade "<<grade;
    cout<<"\nMarks "<<marks;
    cout<<"\nroll no "<<rn;
    }

    ************************************************** *****************



    One more thing i need to know can write whole array through one write f(x)
    after calling getdata() for all objects(same goes for read())?
    Well, you currently call write once in each iteration of the loop. If you want a single write call, you could move it to after the loop and instead of writing one chunk of data simply write 5 chunks worth (one for each student in the array) all at once... you control how many bytes are written in that call, it is after all the second parameter to that particular function. Something similar can be done when reading from the file.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  5. #5
    Registered User
    Join Date
    Jan 2011
    Location
    India
    Posts
    9
    I have made the changes as you said....

    Code:
    #include <fstream>
    #include <iostream>
    #include <stdio>
    #include <stdlib>
    
    //definition for class student
    class Student {
    						char name[10];
    						char grade;
    						float marks;
                      int rn;
    
    				public :
    
    		void getdata()
    		{
                   	                                cout<<"\nenter name "; cin.getline(name,10);
    						cout<<"enter grade ";	cin>>grade;
    						cout<<"enter marks ";	cin>>marks;
                                                    cout<<"enter roll no ";	cin>>rn;
                                                    cin.get();
    		}
    
    		void display()
    		{
                   	                                cout<<"\nName "<<name;
    						cout<<"\nGrade "<<grade;
    						cout<<"\nMarks "<<marks;
                                                    cout<<"\nroll no "<<rn;
    		}
    	};
    
    	int main()
    		{
    			Student arts[5];
    			fstream filin;            				//defining fstream objects
    
                            filin.open("Stu.txt",ios::out);  	//opening the file Stu.txt
    			if(!filin)                				//if filin is zero
    			{
    				cout<<"\ncannot open file.";
    				return 1;
    			}
    
    			cout<<"\nEnter details of students";
             //Entering data
    			for(int i=0;i<5;i++)
    			{
             	                arts[i].getdata();
    				filin.write((char*)&arts[i],sizeof(arts[i]));
                //writing in Stu.txt
    			}
    
    			filin.close();     					//closing file Stu.txt
    
    			filin.open("Stu.txt",ios::in);  	//opening file Stu.txt
    			if(!filin)     						//checking again for filin
    			{
    				cout<<"\ncannot open file.";
    				return 1;
    			}
    			cout<<"\nthe contents of stu.txt are ";
    			for(int i=0;i<5;i++)
    			{
             	                filin.read((char*)&arts[i],sizeof(arts[i]));		//reading from file
    				arts[i].display();
    			}
    			filin.close();     //closing file Stu.txt
    
             cin.get();
    
            return 0;
    		}
    
    output
    
    enter name ay
    enter grade A
    enter marks 41
    enter roll no 1
    
    enter name ak
    enter grade A
    enter marks 42
    enter roll no 2
    
    enter name am
    enter grade A
    enter marks 43
    enter roll no 3
    
    enter name af
    enter grade A
    enter marks 44
    enter roll no 4
    
    enter name as
    enter grade A
    enter marks 45
    enter roll no 5
    
    the contents of stu.txt are 
    
    enter name ay
    enter grade A
    enter marks 41
    enter roll no 1
    
    enter name ak
    enter grade A
    enter marks 42
    enter roll no 2
    
    enter name am
    enter grade A
    enter marks 43
    enter roll no 3
    
    // here are the errors -
    enter name af 
    enter grade                                      //  no grade 
    enter marks 2.28266e-36                // garbage value
    enter roll no 1627389952                // garbage value
    
    enter name s                                    // missing a in name as
    enter grade                                      // missing grade
    enter marks 9.13139e-36                 // garbage value
    enter roll no 0                                   // garbage value
    but the problem still exists... why? i can't figure it out.
    if it is due to cstdio or cstdlib which i didn't include because when included it the program gave error -
    noname00.cpp(3,2) : Unable to open include file 'CSTDIO.h'
    noname00.cpp(4,2) : Unable to open include file 'CSTDLIB.h'
    which means my complier doesn't have these header file. if this is were the problem is then please tell me from where to download it.
    If the header file is not the problem then whay to due?
    please help me the the submission deadline is next week.

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,725
    Quote Originally Posted by Dynamis
    which means my complier doesn't have these header file. if this is were the problem is then please tell me from where to download it.
    There are no standard headers named <stdio> and <stdlib>. However, there are standard headers named <cstdio> and <cstdlib>, or in the C version, <stdio.h> and <stdlib.h>. That said, you don't need them here.

    You also need to format your code properly and use appropriate using declarations and using directives, or fully qualify names from the std namespace. For example:
    Code:
    #include <fstream>
    #include <iostream>
    
    //definition for class student
    class Student {
        char name[10];
        char grade;
        float marks;
        int rn;
    
    public:
    
        void getdata()
        {
            using std::cout;
            using std::cin;
            cout << "\nenter name ";
            cin.getline(name, 10);
            cout << "enter grade ";
            cin >> grade;
            cout << "enter marks ";
            cin >> marks;
            cout << "enter roll no ";
            cin >> rn;
            cin.get();
        }
    
        void display()
        {
            using std::cout;
            cout << "\nName " << name;
            cout << "\nGrade " << grade;
            cout << "\nMarks " << marks;
            cout << "\nroll no " << rn;
        }
    };
    
    int main()
    {
        using namespace std;
        Student arts[5];
        fstream filin;
    
        filin.open("Stu.txt", ios::out);
        if (!filin)
        {
            cout << "\ncannot open file.";
            return 1;
        }
    
        cout << "\nEnter details of students";
        //Entering data
        for (int i = 0; i < 5; i++)
        {
            arts[i].getdata();
            filin.write((char*)&arts[i], sizeof(arts[i]));
        }
    
        filin.close();
    
        filin.open("Stu.txt", ios::in);
        if (!filin)
        {
            cout << "\ncannot open file.";
            return 1;
        }
        cout << "\nthe contents of stu.txt are ";
        for (int i = 0; i < 5; i++)
        {
            filin.read((char*)&arts[i], sizeof(arts[i]));
            arts[i].display();
        }
        filin.close();
        cin.get();
    
        return 0;
    }
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Registered User
    Join Date
    Jan 2011
    Location
    India
    Posts
    9
    Name:  untitled.jpg
Views: 686
Size:  144.3 KB@laserlight: but that code doesn't work in borland 5.0.2. it give errors. i have uploaded the image untitled.jpg

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,725
    Quote Originally Posted by Dynamis
    but that code doesn't work in borland 5.0.2. it give errors.
    Change your compiler. It looks fine on inspection, and compiles without even a warning on the Comeau online compiler, the MinGW port of g++ 3.4.5 and MSVC10. Therefore, in all likelihood it is your compiler that is at fault.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    Jan 2011
    Location
    India
    Posts
    9
    but i can't change my compiler my school won't allow that.
    isn't there anything else one can do to compile the code without garbage value that i latest posted in borland 5.0.2 or on TC++ 4.5.
    Last edited by Dynamis; 01-12-2011 at 03:22 AM.

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,725
    Quote Originally Posted by Dynamis
    but i can't change my compiler my school won't allow that.
    Refer to this incomplete list of C++ compilers. It is written by Professor Bjarne Stroustrup, who is a Distinguished Professor and holder of the College of Engineering Chair in Computer Science at Texas A&M University, as well as the designer and original implementer of C++. Try compiling the test program that is shown. I suspect that your compiler will fail to compile it, thus you can use it as proof when you approach your instructors.

    Quote Originally Posted by Dynamis
    isn't there anything else one can do to compile the code without garbage value that i latest posted.
    What you posted is not some "garbage value". It is a list of compile errors; notice the stuff in parentheses, e.g., (15, 3). The first number is the line number where the error was detected (not necessarily where the error actually is), though I am not sure about the second number (which does not seem to be a column number, as I thought it might be).

    You could try removing the using declarations and using directive. It would make the code incorrect, but possibly allow it to compile on your compiler.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    Registered User
    Join Date
    Jan 2011
    Location
    India
    Posts
    9
    Quote Originally Posted by laserlight View Post

    What you posted is not some "garbage value".
    I didn't meant that pic. i was saying about this

    Code:
    output of the code in post #5
    // here are the errors -
    enter name af 
    enter grade                              //  no grade 
    enter marks 2.28266e-36                  // garbage value
    enter roll no 1627389952                // garbage value
    
    enter name s                             // missing a in name as
    enter grade                             // missing grade
    enter marks 9.13139e-36                 // garbage value
    enter roll no 0                         // garbage value
    Please help me with these garbage values...
    Last edited by Dynamis; 01-12-2011 at 09:27 PM.

  12. #12
    Registered User
    Join Date
    Jan 2011
    Location
    India
    Posts
    9
    thanks laserlight the program works fine on dev C++ 4.9.9.2.
    Can you explain me what was wrong in the code which i posted in post #5 and what you did to make it work on your code as i don't know what is going in it(using namespace, using std::cout, using std::cin)?
    is their any way to make using namespace work on borland 5.0.2 as dev C++ is declaring error in clrscr(), textcolor(), random(), randomize(), gotoxy() and cputs() or is there any alternative to these f(x) ?
    Last edited by Dynamis; 01-13-2011 at 01:26 AM.

  13. #13
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,604
    Quote Originally Posted by hk_mp5kpdw View Post
    fgets is prototyped in the stdio.h/cstdio headers. It would be used as such:
    Code:
    fgets(name,sizeof(name),stdin);
    For your program I would recommend cin.getline instead:
    Code:
    cin.getline(name,sizeof(name));
    ...this is a C++ solution and therefore fits more with the rest of your program. Putting everything together, I would have the getdata function look as such:
    Code:
    void getdata()
    {
        cout<<"\nenter name "; cin.getline(name,sizeof(name));
        cout<<"enter grade "; cin>>grade;
        cout<<"enter marks "; cin>>marks;
        cout<<"enter roll no "; cin>>rn;
        cin.get();
    }
    cin.getline() is also bad since it works with C-style strings.
    I recommend you change the declaration of name to
    std::string name;
    And use
    std::getline(name, std::cin);
    instead.
    This is the obvious C++ solution.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  14. #14
    Registered User
    Join Date
    Jan 2011
    Location
    India
    Posts
    9
    Thanks everyone without your help i wouldn't have been able to compile my program successfully.

  15. #15
    Registered User
    Join Date
    Jan 2011
    Location
    India
    Posts
    9
    since my questions are answered i wanted to close the thread but i don't know how to so if anyone else can do it then please close the thread.
    Thank you.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Writing a text file to an array?
    By Raen in forum C Programming
    Replies: 11
    Last Post: 10-15-2010, 06:26 PM
  2. Can you help me about tolower() in file
    By nctar in forum C Programming
    Replies: 7
    Last Post: 05-12-2010, 10:04 AM
  3. Formatting a text file...
    By dagorsul in forum C Programming
    Replies: 12
    Last Post: 05-02-2008, 03:53 AM
  4. Writing an array of struct to file
    By stellastarr in forum C Programming
    Replies: 10
    Last Post: 03-25-2006, 05:59 PM
  5. what does this mean to you?
    By pkananen in forum C++ Programming
    Replies: 8
    Last Post: 02-04-2002, 02:58 PM

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