Search code examples
c++arraysfunctionstructure

Program is ending with taking all input and not displaying anything


hi everyone I am trying to run the following program but after taking one input it terminates and i can't figure out why?In main function where i am taking input of no of student if i take 1 then in inputdata function it will only take input of name and then terminates without displaying and when i take input of 2 then for first it will take complete input of student1 and for student 2 it will take name input and then terminates i even use cin.ignore(); but then didn't even work. can somebody help me? I am beginner in c++ and need your assistance.

#include <iostream>
using namespace std;

struct Student
{
    string name;
    string course;
    int age;
    int marks;
};

void Inputdata(Student Stu[], int size);
void Display(Student s[], int total);
int main()
{
    int num;
    
    cout<<"How many students are there: ";
    cin>>num;
    
    Student S[num];
    Inputdata(S, num);
    Display(S, num);
    
    return 0;
}

void Inputdata(Student Stu[], int size)
{
    for(int i=1; i<=size; i++)  
    {
        cout<<"Enter data for student #:"<<i<<endl;
        cout<<"Enter Name: ";
        cin>>Stu[i].name;
        cout<<"Enter Course: ";
        cin>>Stu[i].course;
        cout<<"Enter Age: ";
        cin>>Stu[i].age;
        cout<<"Enter marks: ";
        cin>>Stu[i].marks;
    }
}

void Display(Student s[], int total)
{
    int sum;
    for(int j=1; j<=total; j++) 
    {
        cout<<"Information of student #:"<<j<<endl;
        cout<<"Name: "<<s[j].name<<endl;
        cout<<"Course:  "<<s[j].course<<endl;
        cout<<"Enter Age: "<<s[j].age<<endl;
        cout<<"Enter marks: "<<s[j].marks<<endl;    
        sum=+s[j].marks;
    }
    cout<<"Average Marks of class"<<sum/total<<endl;
}

Solution

  • Main problem

    The main problem is that in C++, array indices begin at 0, whereas your code begins array indices at 1. This means if you have an array with 3 elements, the indices of these elements should be 0, 1, 2, instead of 1, 2, 3.

    When you use an index that goes past the bound of an array, your program can crash. So if you have an array of size 3, the maximum index is 2, and when you use 3 as an index, your program can crash (or worse, not crash and instead giving you some random value read from memory).

    For this reason, you should replace this for loop in the method Inputdata:

    for(int i=1; i<=size; i++) 
    

    with

    for(int i=0; i<size; i++) 
    

    The same also applies to the for loop in the method Display. With these fixes, your program should compile and run without crashes.

    Side problem

    In your Display method, the calculation of the average mark is incorrect.

    • In the for loop, you use the following code for updating the sum variable: sum=+s[j].marks;. What this means is "Set sum to be +s[j].marks". This does not add the value of s[j].marks to sum, but only overrides the value of sum with s[j].marks. So instead you should use sum += s[j].marks, which is short-hand for sum = sum + s[j].marks.

    • The sum variable is not initialized. If you have a variable like int sum; and then update this variable with sum += some_value, this can create unexpected results. If sum has not been assigned an initial value, it is possible it holds some random value that was stored at the same memory location by a previous part of the program. For this reason, you should always ensure that your variables are initialized, e.g. with int sum = 0;.

    • The sum variable is of type int. This creates a problem at the end, when you want to calculate the average. The data type int can only represent whole numbers, whereas the average is likely to be in between two whole numbers. So for example if sum is 3 and total is 2, then sum/total is 1, because int cannot represent the actual result 1.5. To fix this, you should use e.g. double instead of int. A double can correctly represent 1.5. So your declaration should be e.g. double sum = 0.0;.

    With those fixes, your Display method would then look like this:

        double sum = 0.0;
        for(int j=0; j<total; j++) 
        {
            // ...
            sum+=s[j].marks;
        }
        cout<<"Average Marks of class "<<sum/total<<endl;
    

    Additional notes

    To give you some more feedback on your code: In your main method you declare Student S[num];, where num is a variable read from std::cin. This is known as a "variable-length array" (VLA). While your compiler might accept this code, it is not valid C++ code in the strictest sense. If you compile your program with maximum warnings enabled, the compiler should give you the following warning:

    warning: ISO C++ forbids variable length array 'S' [-Wvla]
       22 |     Student S[num];
          |             ^
    

    I would recommend to use std::vector instead. Here is how your code would look with std::vector:

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    struct Student {
      string name;
      string course;
      int age;
      int marks;
    };
    
    void Inputdata(std::vector<Student> &Stu) {
      for (size_t i = 0; i < Stu.size(); i++) {
        cout << "Enter data for student #:" << i << endl;
        cout << "Enter Name: ";
        cin >> Stu[i].name;
        cout << "Enter Course: ";
        cin >> Stu[i].course;
        cout << "Enter Age: ";
        cin >> Stu[i].age;
        cout << "Enter marks: ";
        cin >> Stu[i].marks;
      }
    }
    
    void Display(const std::vector<Student> &s) {
      double sum = 0.0;
      for (size_t j = 0; j < s.size(); j++) {
        cout << "Information of student #:" << j << endl;
        cout << "Name: " << s[j].name << endl;
        cout << "Course:  " << s[j].course << endl;
        cout << "Enter Age: " << s[j].age << endl;
        cout << "Enter marks: " << s[j].marks << endl;
        sum += s[j].marks;
      }
      cout << "Average Marks of class " << sum / s.size() << endl;
    }
    
    int main() {
      int num;
    
      cout << "How many students are there: ";
      cin >> num;
    
      std::vector<Student> S;
      S.resize(num);
      Inputdata(S);
      Display(S);
    
      return 0;
    }
    

    The reason for this goes into some finer details of C++. If have just begun with C++ and you do not care about the finer details, I would say it is fine to skip over this.

    Basically there are different kinds of memory, the stack and the heap (reference). The stack holds information about which methods have been called, what parameters have been passed to the methods, and which local variables have been used. The heap can hold arbitrary blocks of data. Typically the stack is much smaller than the heap. Variable-length arrays (and also static-length arrays) are allocated on the stack, whereas std::vector allocates memory on the heap. For this reason, std::vector is a better choice when the number of entries you want to store in the array can be very large.

    Another reason for favoring std::vector over variable-length arrays would be the helper functions provided by std::vector. For example, std::vector provides a helper function for obtaining the size of the array, whereas for variable-length arrays, you have to pass the length along with the array to the methods where you want to work with the array. Therefore, using std::vector allows you to write simpler code.