-2

I'm trying to create C++ code to take user input separated by a comma and feed it into an int array to then sort it all with even columns. For some reason when I feed it into the array the program shuts on me. I can't even have it print the array, and I'm not quite sure why.

sample:

Welcome to Please Help Me Sort Grades!!! :)
Please enter student grades:10,20,30,10,20,30,50,90,10,50

Unsorted:
  Grade  ID
     10   1
     20   2
     30   3
     10   4
     20   5
     30   6
     50   7
     90   8
     10   9
     50  10

Sorted:
  Grade  ID
     10   1
     10   4
     10   9
     20   2
     20   5
     30   3
     30   6
     50   7
     50  10
     90   8

Process finished with exit code 0

code:

#include <iostream>
#include <cmath>
#include <iomanip>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <string>
#include <vector>

using namespace std;
// Global Variables and Libraries are declared


using namespace std;


int main() {

    cout << setprecision(20) << fixed;

    int size = 30;
    int StudentID[size];
    int StudentGrades[size];
    string commaList;
    vector<int> grades;
    int MinGrade;
    int MinID;

    //char * token is a char pointer. We will discuss them in a later chapter
    char *token = NULL;

    cout << "Please enter a comma separated list of grades: ";
    getline(cin, commaList);
    //character array that will hold comma seperated list after its copied over
    char gradesCharArr[commaList.size()];
    strcpy(gradesCharArr, commaList.c_str());
    //gives you the location of the first ',' thats encountered in the array
    token = strtok(gradesCharArr, ",");
    //Iterate through each "," that is found until there are none left
    while(token != NULL){
        //convert the grade from a string to an int and push it into the vector
        grades.push_back(stoi(token));
        //find next occurrence of ","
        token = strtok(NULL, ",");
    }

    for(int i = 0; i < size; i++){
        if(i > grades.size()){
            StudentGrades[i] =0;
            StudentID[i] = 0;
        }
        else {
            StudentGrades[i] = grades.at(i);
            StudentID[i] = i + 1;
        }
    }

    cout << "Unsorted: " << endl;
    //Print grades back to show they are properly tokenized
    for(int i = 0; i < grades.size(); i++){
        cout << StudentGrades[i] << setw(10) << StudentID[i] << endl;
    }

    for(int i = 0; i < size; i++)                                               // for the first initial round where we will put the official
    {                                                                           // max number when found (i)
        for(int j = i + 1; j < size; j++)                                       // for the second subround (j) here the code is comparing the max
        {                                                                       // value of the array at j and the array at i until we get
            if(StudentGrades[j] < StudentGrades[i])                                         // the ultimate max number. In order to do that though we will
            {                                                                   // shift the values up one place in the Array and place the
                MinGrade = StudentGrades[i];                                        // max number in it's proper place in MyArray.
                MinID = StudentID[i];
                StudentGrades[i] = StudentGrades[j];
                StudentID[i] = StudentID[j];
                StudentGrades[j] = MinGrade;
                StudentID[j] = MinID;
            }
        }
    }

    cout << "Sorted:" << endl;
    for(int i = 0; i < grades.size(); i++){
        cout << StudentGrades[i] << setw(20) << StudentID[i] << endl;
    }

    return 0;
}

Thank you so much in advance :)

  • Variable length arrays are not a commonly valid feature in C++. – Yunnosch Jun 27 '20 at 19:23
  • what is your question? Is the output not what you expect? – 463035818_is_not_an_ai Jun 27 '20 at 19:30
  • Ya so I wanted the output to be like the sample but instead, it just exits before anything is printed @ idclev 463035818 – Katie Kelly Jun 27 '20 at 19:31
  • also, did you mean that variable-length arrays as in the StudentID and StudentGrade arrays? @Yunnosch – Katie Kelly Jun 27 '20 at 19:33
  • I mean especially this array definition with a size which gets determined at runtime by calling a function. `char gradesCharArr[commaList.size()];` – Yunnosch Jun 27 '20 at 19:35
  • 1
    they meant: `int StudentID[size];` is not allowed in standard c++. Use `std::vector` when you need a dynamically sized array instead – 463035818_is_not_an_ai Jun 27 '20 at 19:35
  • 1
    RE:`For some reason when I feed it into the array the program shuts on me`... What result did the debugger yield? – kesarling He-Him Jun 27 '20 at 19:36
  • The debugger had nothing, I would type in the letter grades and then it would exit @d4rk4ng31. it would stop on the line {cout << "Unsorted: " << endl;} – Katie Kelly Jun 27 '20 at 19:37
  • Because you did not set in the breakpoint – kesarling He-Him Jun 27 '20 at 19:37
  • What debugger are you using? – kesarling He-Him Jun 27 '20 at 19:37
  • 1
    it comes as an extension for some compilers. You need to read your compilers manual to know how it works and what you are allowed to do with them and what not. Neither did you specify the compiler you are using nor everybody using C++ knows all details of variable lenght arrays (but they do know `std::vector`). See here for details: [Why aren't variable-length arrays part of the C++ standard?](https://stackoverflow.com/questions/1887097/why-arent-variable-length-arrays-part-of-the-c-standard) – 463035818_is_not_an_ai Jun 27 '20 at 19:38
  • I am using CLion, Typically using variables in this fashion has never resulted in an error like this. Usually can work with variable length arrays. – Katie Kelly Jun 27 '20 at 19:38
  • Also, it is a really bad practice to use `using namespace std;`... even once. (I really have no idea why you're including that twice). is that a typo? – kesarling He-Him Jun 27 '20 at 19:38
  • Hmm... are you sure you set the breakpoint? – kesarling He-Him Jun 27 '20 at 19:39
  • Ya I had set the breakpoint there and it goes into the stl.vector.h fie and highlights the { __throw_out_of_range_fmt(__N("vector::_M_range_check: __n " "(which is %zu) >= this->size() " "(which is %zu)"), __n, this->size()); } and then it just exits. I don't know too much about the inner workings of C++ to know what this part means, just know that is where it exits. – Katie Kelly Jun 27 '20 at 19:41
  • Does [this](https://stackoverflow.com/questions/18796782/c-vector-m-range-check-error) help? – kesarling He-Him Jun 27 '20 at 19:44
  • 1
    Hmm... plus, the code that you've provided does not even compile in MVCC... – kesarling He-Him Jun 27 '20 at 19:47
  • 1
    The shown code has at least one apparent bug related to a buffer/array overruns, due to unsafe programming practices. The non-standard C++ used to created variable-length array results in a `char` array being one `char` to few in size, due to mixing of C and C++-style character string handling, and failure to account for the C-style terminating `\0`. This results in memory corruption and undefined behavior. Do you have [a good C++ textbook](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) with examples of how to correctly handle character strings in C++? – Sam Varshavchik Jun 27 '20 at 19:48
  • Unfortunately, I do not have a textbook :/ I only have this example that our teacher gave us to help us on our first part of our program to convert the string to what I'm thinking to be the vector. To then compare it: https://drive.google.com/file/d/13Gv3ZMT4M9lbDVuvuBVr1o_lor3ozJia/view?usp=sharing – Katie Kelly Jun 27 '20 at 19:58
  • 1
    It says access denied, but anyway, you got the problem :) Reach out if you need anymore help :) – kesarling He-Him Jun 27 '20 at 20:02

3 Answers3

1

The error spotted by Mateus Melo is correct. There is one more in the for loop for sorting items. The size should be grades.size() in both for statements to sort properly here

  for (int i = 0; i < size; i++)                                               // for the first initial round where we will put the official
  {                                                                           // max number when found (i)
    for (int j = i + 1; j < size; j++)                                       // for the second subround (j) here the code is comparing the max

Replacing with grades.size() should produce expected result :)

Also taking input would be better with this code

  cout << "Please enter a comma separated list of grades: ";
  getline(cin, commaList);
  size_t as = commaList.size();
  //character array that will hold comma seperated list after its copied over
  char* gradesCharArr = new char[as+1]();// [a /*commaList.size()*/] ;
  commaList.copy(gradesCharArr, commaList.size());
Valeca
  • 122
  • 8
0

In your first for loop, when i is equal to grades.size(), you access a position i of grades that is invalid. Change your if to:

    if(i>=grades.size())

and your code will work just fine.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
  • 1
    By the way, I don't know if this is an exercise or something like that and you must use all of this c string functions and the selection sort algorithm, but you are missing all the amazing c++ features that would make your life so much easier! – Mateus Melo Jun 27 '20 at 19:58
  • Well, I know this sounds unbelievable, but I met a guy yesterday using Turbo C++... – kesarling He-Him Jun 27 '20 at 20:05
  • It does sound unbelievable. – Mateus Melo Jun 27 '20 at 20:08
  • 1
    I know right? You're new here. If you lurk around a bit more, you'll find questions to which the one line perfect answer would be stop using Borland C++ XD – kesarling He-Him Jun 27 '20 at 20:09
  • 1
    I would not use `>` in the condition –  Jun 27 '20 at 20:13
  • 1
    If you don't use, when i is equal to grades.size()+1, the code will enter the else instructions and the same problem will happen again. – Mateus Melo Jun 27 '20 at 20:18
0
for(int i = 0; i < size; i++){
    if(i >= grades.size()){
        StudentGrades[i] =0;
        StudentID[i] = 0;
    }
    else {
        StudentGrades[i] = grades.at(i);
        StudentID[i] = i + 1;
    }
}

This is where the problem is. You see, the indices in C++ start with 0. So, when your i becomes grades.size() it goes out of bounds for the vector. That is what the debugger basically told you by the error:

{ __throw_out_of_range_fmt(__N("vector::_M_range_check: __n " "(which is %zu) >= this->size() " "(which is %zu)"), __n, this->size()); }

So, you need to change that condition to:

if(i==grades.size())


Also, on a side note, when you're using vector indices, it is better to use size_t instead of plain old int, as all vector functions require size_t and if they do not find that, they will give the usual overflow error

Hope this helps :)

kesarling He-Him
  • 1,944
  • 3
  • 14
  • 39