I am working on a program that takes in grades from the user and returns the max, min, avg, median, and standard deviation. I keep encountering this error whenever I try to run my code:
File: c:\program files (x86)\microsoft visual studio 12.0\vc\include\vector
Line: 1201
Expression: Vector subscript out of range
Could someone tell me what I'm doing wrong? No matter what I do, I can't seem to fix it. Completely new to coding in C++, so if you could explain in-depth that would be extremely helpful.
This is the block of code it is referring to in the vector file:
#if _ITERATOR_DEBUG_LEVEL == 2
if (size() <= _Pos)
{ // report error
_DEBUG_ERROR("vector subscript out of range");
_SCL_SECURE_OUT_OF_RANGE;
}
Specifically pointing to this line:
_DEBUG_ERROR("vector subscript out of range");
My code:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
void enterGrades()
{
int count = 0;//initialize count
int grade;//initialize grade variable
int maxGrade = 0;
vector<int> gradeList;//initialize vector
vector<int>::iterator gradeListIt;//initialize iterator
do {
cout << "Enter grades [0 to exit]: ";//enter grades
cin >> grade;//user input
count += 1;//for each grade, increase count
gradeList.push_back(grade);//append grades to vector
} while (grade != 0);
};
int maxNum(vector<int> gradeList)
{
int largest = gradeList[0];//initialize largest number
int length = gradeList.size();
gradeList.resize(length);
for (int value = 0; value < length; value++)//traverse vector
{
if (gradeList[value] > largest)//if current value > largest
largest = gradeList[value];//set largest to that value
}
return largest;//return largest
};
int minNum(vector<int> gradeList)
{
int smallest = gradeList[0];
int length = gradeList.size();
gradeList.resize(length);
for (int value = 0; value < length; value++)
{
if (gradeList[value] < smallest)
smallest = gradeList[value];
}
return smallest;
};
int avgNum(vector<int> gradeList)
{
int total = 0;
int length = gradeList.size();
gradeList.resize(length);
for (int value = 0; value < length; value++)
{
total += value;
}
return total / length;
};
//int stdDev (vector<int>& gradeList)
//{
// int variance = 0;
// int avg = avgNum(vector<int>& gradeList);
// int length = gradeList.size();
// for(int value = 1; value < length; value++)
// {
// variance = variance + pow(value - avg, 2);
// }
// variance = pow(variance / length, 0.5);
// return variance;
//
//};
int main()
{
vector<int> gradeList;//initialize vector
vector<int>::iterator gradeListIt;//initialize iterator
enterGrades();//
cout << "Maximum grade is: " << maxNum(gradeList) << endl;
cout << "Minimum grade is: " << minNum(gradeList) << endl;
cout << "Average grade is: " << avgNum(gradeList) << endl;
}
Also, in my main function; can I call other functions like I did in my output statements?
Giving things the same name doesn't make them the same thing.
After enterGrades returns, the vector named "gradeList" in main is still empty.
When you try access the first element of an empty vector, you get an error.
Your main should look like this:
int main()
{
std::vector<int> gradeList = enterGrades();
cout << "Maximum grade is: " << maxNum(gradeList) << endl;
cout << "Minimum grade is: " << minNum(gradeList) << endl;
cout << "Average grade is: " << avgNum(gradeList) << endl;
}
Changing the implementation of enterGrades to fit is left as an exercise.
Also, this thing that you keep doing:
int length = gradeList.size();
gradeList.resize(length);
doesn't make sense, as it's resizing a vector to the size it already had.
Remove it.
You're also repeatedly declaring an iterator for no reason at all.
You also probably want to review what average you're supposed to calculate, as you're calculating the average index in a vector, not the average value.
And watch out for those integer divisions.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 15 days ago.
Improve this question
Here is my program, it is using c++ and I done it on MacOS VSCode.
Library:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <string>
#include <iomanip>
using namespace std;
Function:
float* read_data(int& size){
int a_size = 0;
static float a[10];
float* temp = a;
cout << "Please enter values, and press 'Q' when finished: ";
for (int i = 0; i < size; i++){
cin >> a[i];
if (cin.fail()){
break;
}else{
a_size++;
}
}
cin.clear();
size = a_size;
return temp;
}
Main function:
int main(){
int size1 = 10;
int size2 = 10;
int size3 = 0;
float array[10];
float addarray[10];
float longarray[20];
float* ptr = array;
float* addptr = addarray;
float* longptr = longarray;
cout << fixed << setprecision(2);
ptr = read_data(size1);
cout << setw(15) << "Original array" << setw(5) << "=" << setw(5) << "{ " << *ptr;
for (int i = 0; i < size1; i++){
cout << ", " << *(ptr + i);
}
cout << " }" << endl;
for (int i = 0; i < size1; i++){
*(longptr + size3) = *(ptr + i);
size3++;
}
addptr = read_data(size2);
for (int i = 0; i < size2; i++){
*(longptr + size3) = *(addptr + i);
size3++;
}
cout << setw(15) << "New array" << setw(5) << "=" << setw(5) << "{ " << *longptr;
for (int i = 0; i < size3; i++){
cout << ", " << *(longptr + i);
}
cout << " }" << endl;
return 0;
}
The main objective of the program was to prompt the user for an array, maximum of 10 elements. Prompting the user was done using the float* read_data(int& size) function.
The program would echo or print out the inputted array.
After that, the user was prompt for a second time using the same function to get another array of elements, in this case is a list of float values.
Then, the program would use a dynamic data allocation (DMA) technique to combine the two array into one long array. The new array will be printed out and the program is terminated.
Problem
As I said before, the program are supposed to prompt the user for inputs every time the read_data() were called.
I called the function twice. It did run twice, but failed to prompt the user for input the second time around.
I thought the problem was due to the cin.fail() arguments. That is why I tried to mess with the cin.ignore() and cin.clear() either by removing them or only using one of them.
I am honestly at lost on what is the root of the problem.
The heart of the issue is that you want users to enter 'Q', a char, into your float variable.
Here's a small example:
#include <iostream>
int main() {
int a;
std::cin >> a;
if (std::cin.fail()) {
std::cout << "Fail.\n";
} else {
std::cout << "All clear.\n";
}
std::cin >> a;
std::cout << (2 * a) << '\n';
}
Output:
~/tmp
❯ ./a.out
Q
Fail.
0
~/tmp
❯ ./a.out
3
All clear.
3
6
So, you can see that you were on the right track. The issue is that if std::cin did fail, you are now responsible to clean up your mess.
std::cin.clear() is a good start. It resets the fail flag bits. But the stream is still in a bad state. What you haven't done is clean it up completely.
You're calling std::cin.ignore(), but leaving the parameter list empty.
Something like this is best practice:
#include <iostream>
#include <limits>
int main() {
int a;
std::cin >> a;
if (std::cin.fail()) {
std::cout << "Fail.\n";
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cin.clear();
} else {
std::cout << "All clear.\n";
}
std::cin >> a;
std::cout << (2 * a) << '\n';
}
Output:
~/tmp
❯ ./a.out
Q
Fail.
3
6
While that should fix address the question, your code is still fundamentally broken.
EDIT
Here's a mini-code review:
#include <iostream>
#include <algorithm> // These includes
#include <cmath> // are
#include <cstdlib> // not
#include <string> // used
#include <iomanip>
using namespace std; // Bad practice
// You should not attempt to return a C-style array
float* read_data(int& size){ // Why is the size being passed by reference?
int a_size = 0;
static float a[10]; // Not doing what you think
float* temp = a;
cout << "Please enter values, and press 'Q' when finished: ";
for (int i = 0; i < size; i++){ // Formatting; should be ") {"
cin >> a[i];
if (cin.fail()){ // Addressed above; root cause of your question
break;
}else{
a_size++;
}
}
cin.clear();
size = a_size;
return temp;
}
// While I assume the goal of the assignment is to get familiar with pointers,
// This assignment is trivial with vectors.
int main(){
int size1 = 10; // If declared const/constexpr, you'd only need one **
int size2 = 10; // These are bad names
int size3 = 0; // Front loading declarations is bad practice.
float array[10]; // ** And could use that variable here to avoid the magic number
float addarray[10];
float longarray[20]; // Not dynamic per your requirements.
float* ptr = array; // Still not dynamic, also unnecessary given the prior declarations
float* addptr = addarray;
float* longptr = longarray;
cout << fixed << setprecision(2);
ptr = read_data(size1);
// The first cout is not good, what do you think *ptr will print?
cout << setw(15) << "Original array" << setw(5) << "=" << setw(5) << "{ " << *ptr;
for (int i = 0; i < size1; i++){
cout << ", " << *(ptr + i); // The pointers can still use array syntax
}
cout << " }" << endl;
for (int i = 0; i < size1; i++){
*(longptr + size3) = *(ptr + i);
size3++;
}
addptr = read_data(size2);
for (int i = 0; i < size2; i++){
*(longptr + size3) = *(addptr + i);
size3++;
}
// As soon as you start repeating yourself, consider writing a function.
// The logic will only live in one place, and only need to be changed in
// one place.
cout << setw(15) << "New array" << setw(5) << "=" << setw(5) << "{ " << *longptr;
for (int i = 0; i < size3; i++){
cout << ", " << *(longptr + i);
}
cout << " }" << endl;
return 0;
}
A lot going on that is less than great. The biggest flub appears to be the static array. static in this scenario extends the lifetime of the variable until the end of the program. So, when you call this function the second time, you overwrite the first array with the second because there's only ever one array for every call of that function. In the future, I would refrain from grabbing random code online and just dumping it in your program unless you know what it does.
Now, let's move on to a working solution.
The first thing I'm going to do is state the requirements as I understood them.
Have the user enter data to fill two arrays of floats.
Each array should hold a maximum of ten elements.
The user enters "Q" to indicate that they are finished entering data.
Print the first array.
Tack the second array on to the end of the first, in a dynamic fashion.
Print the combined array.
Anytime you get an assignment, your first task should be to restate the problem in your own words. This will clarify requirements and you will demonstrate to yourself that you understand the problem to be solved.
What makes this interesting is the "Q" to quit. Note that I'm using double quotes. We will read all of our data as strings, and we have to convert to float as needed.
std::stof() exists, but it's not as simple as just calling it. That function can throw exceptions, and we want to ensure that only actual float values get converted.
So we'll wrap that call in a function of our own. Here's an example:
#include <exception>
#include <iostream>
#include <string>
class bad_user_input : public std::exception {
const char* what() const noexcept override {
return "User input was not valid.";
}
};
float convert_string_to_float(const std::string& val) {
std::size_t marker = 0;
float f = 0.0f;
try {
f = std::stof(val, &marker);
} catch(...) {
throw bad_user_input();
}
// Was the entire value entered a float?
if (marker != val.length()) {
throw bad_user_input();
}
// Getting here means a valid float was entered.
return f;
}
int main() {
float f = 0.0f;
// Test the function
try {
f = convert_string_to_float("5.6");
} catch(...) {
std::cerr << "Issue.\n";
}
std::cout << f << "\n\n";
f = 0.0f;
try {
f = convert_string_to_float("5.6cat");
} catch(...) {
std::cerr << "Issue.\n";
}
std::cout << f << "\n\n";
f = 0.0f;
try {
f = convert_string_to_float("Q");
} catch(...) {
std::cerr << "Issue.\n";
}
std::cout << f << '\n';
}
Output:
❯ ./a.out
5.6
Issue.
0
In convert_string_to_float
stof: no conversion
Issue.
0
Now that we can convert strings to floats, with guarantees, we are ready to read values. To test that we're reading correctly, we also want to be able to print our arrays:
#include <exception>
#include <iostream>
#include <string>
class bad_user_input : public std::exception {
const char* what() const noexcept override {
return "User input was not valid.";
}
};
float convert_string_to_float(const std::string& val) {
std::size_t marker = 0;
float f = 0.0f;
try {
f = std::stof(val, &marker);
} catch(...) {
throw bad_user_input();
}
// Was the entire value entered a float?
if (marker != val.length()) {
throw bad_user_input();
}
// Getting here means a valid float was entered.
return f;
}
void read_array_from_user(float* arr, int& size, const int maxCapacity, std::istream& sin = std::cin) {
size = 0;
std::string input;
while (size < maxCapacity && std::getline(sin, input)) {
if (input == "Q" || input == "q" || input.length() == 0) {
return;
}
try {
arr[size] = convert_string_to_float(input);
} catch(const std::exception& e) {
std::cerr << "Bad input. Reason: " << e.what() << "\nTry again.\n";
continue;
}
++size;
}
}
void print_array(float* arr, int size, std::ostream& sout = std::cout) {
sout << "{ ";
for (int i = 0; i < size; ++i) {
sout << arr[i] << (i == size - 1 ? " " : ", ");
}
sout << "}\n";
}
int main() {
constexpr int maxArrayCapacity = 10;
float arrayOne[maxArrayCapacity];
int arrayOneSize = 0;
read_array_from_user(arrayOne, arrayOneSize, maxArrayCapacity);
print_array(arrayOne, arrayOneSize);
}
Output:
~/tmp
❯ ./a.out
1
2
3
4
q
{ 1, 2, 3, 4 }
~/tmp took 3s
❯ ./a.out
1
2
Q
{ 1, 2 }
~/tmp took 2s
❯ ./a.out
1
2
3
4
5
6
{ 1, 2, 3, 4, 5, 6 }
~/tmp took 4s
❯ ./a.out
1
2
3
4
5
6
7
8
9
0
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }
~/tmp took 5s
❯ compilecpp tmp_repair.cpp
~/tmp
❯ ./a.out
1
2
3
4
5
6
7
8
9
0
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }
~/tmp took 4s
❯ ./a.out
1
2
3
q
{ 1, 2, 3 }
~/tmp took 2s
❯ ./a.out
1
2b
Bad input. Reason: User input was not valid.
Try again.
2
3
Q
{ 1, 2, 3 }
~/tmp took 3s
❯ ./a.out
1
2
3
Q
{ 1, 2, 3 }
~/tmp took 2s
❯ ./a.out
1
2
3
{ 1, 2, 3 }
So, we can read an array with a maximum of 10 values. The reading is robust enough to handle typos or obviously bad input. But we don't have to read 10 values, it's the maximum. We keep track of the actual size ourselves.
Take note on how simple the main() function is because we put our sub-tasks into their own functions.
Reading the second array only requires a few lines in our main() now.
int main() {
constexpr int maxArrayCapacity = 10;
float arrayOne[maxArrayCapacity];
int arrayOneSize = 0;
read_array_from_user(arrayOne, arrayOneSize, maxArrayCapacity);
print_array(arrayOne, arrayOneSize);
float arrayTwo[maxArrayCapacity];
int arrayTwoSize = 0;
read_array_from_user(arrayTwo, arrayTwoSize, maxArrayCapacity);
print_array(arrayTwo, arrayOneSize);
}
Easy-peasy there. Now we need to combine the arrays "dynamically."
We know the sizes of our two arrays, so we know the size of the final array. Now we just need to allocate the memory on the heap. I'm not going to use new, which is what I assume you're supposed to do. My reasoning is that C++ has had better methods for managing dynamic allocations since 2011.
#include <memory>
// ...
int main() {
constexpr int maxArrayCapacity = 10;
float arrayOne[maxArrayCapacity];
int arrayOneSize = 0;
read_array_from_user(arrayOne, arrayOneSize, maxArrayCapacity);
print_array(arrayOne, arrayOneSize);
float arrayTwo[maxArrayCapacity];
int arrayTwoSize = 0;
read_array_from_user(arrayTwo, arrayTwoSize, maxArrayCapacity);
print_array(arrayTwo, arrayTwoSize);
int combinedArraySize = arrayOneSize + arrayTwoSize;
// This is considered dynamic; it's allocated on the heap
auto combinedArray = std::make_unique<float[]>(combinedArraySize);
int idx = 0;
for (int i = 0; i < arrayOneSize; ++i) {
combinedArray[idx] = arrayOne[i];
++idx;
}
for (int i = 0; i < arrayTwoSize; ++i) {
combinedArray[idx] = arrayTwo[i];
++idx;
}
print_array(combinedArray.get(), combinedArraySize);
}
Output:
~/tmp
❯ ./a.out
1
2
q
{ 1, 2 }
3
4
5
q
{ 3, 4, 5 }
{ 1, 2, 3, 4, 5 }
Hopefully, the most gnarly stuff is over where you get the user input, mostly due to the requirement that users can enter a letter to signal they're done. And that makes sense since now you have to do type conversions. Other languages like python make it possible with a lot less LOC (Lines Of Code) on your part. The task itself is not difficult, but ensuring users behave is a whole other beast. If you're allowed to assume well-behaved input will always be provided, you can simplify the code quite a bit.
I basically need to make an array and put it in the private member section, and have it work the random number generator. Im not even sure if my teacher is asking for an array to hold the 1000 values, or if I need to make an array for each variable (zero, one, ....). The rubric states to use the private member array to hold the count of values returned from calls to the random generator.
3 hours of youtube videos.
class Gen
{
private:
int Numbergenerated;
public:
Gen();
void set_Numbergenerated(int);
int get_Numbergenerated();
void gener();
void display(int zero, int one, int two, int three, int four, int five, int six, int seven, int eight, int nine);
};
Gen::Gen()....
void Gen::set_Numbergenerated(int n)...
int Gen::get_Numbergenerated()...
void Gen::gener()
{
int result_of_gener;
result_of_gener = rand() % 10;
set_Numbergenerated(result_of_gener);
}
void display....
int main()
{
Gen g;
unsigned seed;
int zero = 0, one = 0, two = 0, three = 0, four = 0, five = 0, six = 0, seven = 0, eight = 0, nine = 0, count, num;
seed = time(0);
srand(seed);
cout << "Press Enter key to begin generating numbers" << endl;
cin.get();
for (count = 0; count <= 1000; count++)
{
g.gener();
num = g.get_Numbergenerated();
cout << "Generation " << "+" << count << ":\t" << "Number generated: " << num << endl;
switch (num)
{
case 0: zero++;
break;.....
g.display(zero, one, two, three,four,five, six, seven, eight, nine);
`````````````
*******spots with ...... placed to save space, probably unimportant parts.
Once you fill the array with 1000 elements, you can use the count function to determine the number of occurrences of a specific value in the array. Here is how.
So, assuming you are using C++ arrays, we can declare the array in the private section of your class:
// An array of ints, with 1000 elements.
std::array<int,1000> randomNumberArray;
We can assume your set_Numbergenerated function adds a new random number to the array, so, in main(), we can generate and insert 1000 random numbers:
/** Generate 1000 random numbers to fill the array. */
for (size_t i = 0; i < 1000; i++)
{
g.gener();
}
Since our array is a private member, and not directly accessible from main, we can add a public member function to Gen to access the array for us. We can also tell this method to count the number of occurrences of a specific value in the array (a great C++ algorithm):
// Return the number of occurrences of 'val' in the array.
int Gen::get_Occurrences(int val) {
return std::count(this->randomNumberArray.begin(), this->randomNumberArray.end(), val);
}
Finally, we can call this method for each number of interest (0 through 9), and give the result of each to the display method call in main:
g.display(g.get_Occurrences(0), g.get_Occurrences(1), g.get_Occurrences(2),
g.get_Occurrences(3), g.get_Occurrences(4), g.get_Occurrences(5),
g.get_Occurrences(6), g.get_Occurrences(7), g.get_Occurrences(8), g.get_Occurrences(9));
These and a few other minor edits produced the output:
Press Enter key to begin generating numbers
Occurrences of each number [0 - 9]: 95 87 106 112 107 96 109 104 100 84
The problem is a little ambiguous. I tried to keep as much of your code as I could, but I may have removed parts that were required to be in the assignment.
The numberGenerated is a confusing variable. It seems that the more important thing you are trying to track is the frequencies of each digit. To do this, I created a 10 element vector which is zeroed by the constructor.
Then, as each number is stored into the object, the corresponding bucket in the array is incremented.
Note that the constructor also calls the seed function for the random number generator.
#include <iostream>
#include <random>
#include <string>
#include <vector>
class Gen {
private:
int Numbergenerated;
unsigned seed;
std::vector<int> frequencies;
public:
Gen();
void set_Numbergenerated(int);
int get_Numbergenerated();
void generate_random_number();
void display();
};
Gen::Gen()
{
seed = time(0);
srand(seed);
for (int i = 0; i < 10; i++) {
frequencies
.push_back(0);// create and zero 10 buckets in our frequencies vector
}
}
void Gen::set_Numbergenerated(int n)
{
Numbergenerated = n;
frequencies[n] = frequencies[n] + 1;
}
int Gen::get_Numbergenerated()
{
return Numbergenerated;
}
void Gen::generate_random_number()
{
int result_of_generate;
result_of_generate = rand() % 10;
set_Numbergenerated(result_of_generate);
}
void Gen::display(){
int sum = 0;
for(int i = 0; i < 10; i++) {
std::cout << i << "'s: " << frequencies[i] << " ";
sum += frequencies[i];
}
std::cout << std::endl;
std::cout << "Total generated: " << sum << std::endl;
}
int main()
{
Gen g;
std::cout << "Press Enter key to begin generating numbers" << std::endl;
// std::cin.get();
for (int count = 0; count < 1000; count++) {
g.generate_random_number();
int num = g.get_Numbergenerated();
std::cout << "Generation " << "+" << count << ":\t" << "Number generated: "
<< num << std::endl;
}
g.display();
}
Read a sequence of double values into a vector. Think of each value as
the distance between two cities along a given route. Compute and print
the total distance (the sum of all distances). Find and print the smallest
and greatest distance between two neighboring cities. Find and print the
mean distance between two neighboring cities.
The problem that I am having is that I am getting a debugging error stating that my vector subscript is out of range. I can't seem to see where that is occurring.
#include "pch.h"
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cmath>
using std::cout;
using std::cin;
using std::vector;
using std::string;
int main()
{
// Read a sequence of double values into a vector
vector <double> distance; // declaring the vector named "distance"
double sum = 0;
double smallest;
double greatest;
for (double x; cin >> x;) { // read into distance, to terminate putting values in vector use anything that is not of variable type of vector
distance.push_back(x); // put distance into vector
cout << '\n';
for (int i = 0; i < distance.size(); i = i + 1) { // keeping track of elements in vector by displaying them
cout << distance[i] << '\n';
}
}
for (int i = 0; i < distance.size(); i = i + 1) { // adding up all values of vector by iterating through all elements
sum = sum + distance[i];
}
cout << "The total sum of all the elements in the vecotr is: " << sum << '\n';
for (int i = 0; i < distance.size(); i = i + 1) { // determining the smallest value in the vector
if (smallest <= distance[i]) {
smallest = distance[i];
}
}
cout << "The smallest value in the vector is: " << smallest << '\n';
for (int i = 0; i < distance.size(); i = i + 1) { // determining the greatest value in the vector
if (greatest >= distance[i]) {
greatest = distance[i];
}
}
cout << "The smallest value in the vector is: " << smallest << '\n';
cout << "The mean distance between two neigbouring cities is: " << sum / distance.size() << '\n';
}
Bjarne wants you to find the appropriate function in the standard library for the particular problem.
E.g.
auto total_distance = std::accumulate(distance.begin(), distance.end(), 0.);
"The sum of the elements are..."
Look around https://en.cppreference.com/w/cpp/algorithm most of the function calls you want/need are described there.
Run your program like
myprog < inputdoubles.txt
I am extremely confused. I have to follow these specific guidelines:
Make a program that will compute and output the average of 10 exam scores, entered by the user. Finish the function, so that the main will work correctly. Feel free to modify the main as you please as well.
I do not believe we need to change the main and do not believe we should use 10 variables. Here is the code I must add to, I believe the main is finished. Your help is very appreciated!!!!
#include <iostream>
using namespace std;
NOT ADD CODE HERE!!!
float calculateAverageTestScore(int amountOfScores);
int main(void)
{
const int NUMBER_OF_SCORES = 10;
cout << "The average test score was: " << calculateAverageTestScore(NUMBER_OF_SCORES) << endl;
return 0;
}
//INPUT: an amount of test scores
//OUTPUT: the average of these scores
//This function will obtain amountOfScores test scores from the user, and return
//their average - to be used elsewhere.
float calculateAverageTestScore(int amountOfScores)
{
float average;
//add code here
return average;
}
Should do the trick.
#include <iostream>
#include <string>
float calculateAverageTestScore(int amountOfScores);
int main() {
const int NUMBER_OF_SCORES = 10;
const float score = calculateAverageTestScore(NUMBER_OF_SCORES);
std::cout << "The average test score was: " << score << '\n';
}
float calculateAverageTestScore(int amountOfScores) {
float sum = 0;
std::string buffer;
for (int i = 0; i < amountOfScores; ++i) {
std::cout << "score #" << i + 1 << ": ";
std::getline(std::cin, buffer);
sum += std::stof(buffer); // TODO: Error handling
}
return sum / amountOfScores;
}
I've encountered a problem while trying to create a code which converts decimal numbers to binary, using functions. At first I created the code using only main function and it worked fine, but decided to modify it to use function. I believe code is written right, however when I try to cout my answer I get a big number like 115120160758866453687091316369641637416.
This is the code
#include <iostream>
#include <math.h>
using namespace std;
int* unsigned_dec(int dec_M) { //function for converting absolute part of numbers
int bin[8] = { 0,0,0,0,0,0,0,0 };
int ind = 7;
int arr_ind = 0;
for (int base = (int)abs(dec_M); base > 0; base = base / 2) {
if (base % 2 == 0) {
bin[arr_ind] = 0;
ind--;
}
else {
bin[arr_ind] = 1;
ind--;
}
arr_ind++;
}
return bin;
}
int main() {// main function
int dec_N;
cin >> dec_N;
int* bin_main = unsigned_dec(dec_N); //we are not sure if we are assigning the returned value of function to array in correct
for (int i = 0; i <= 7; i++) {
cout << bin_main[i];
}
cout << endl;
return 0;
}
then I tried to change the cout code to
cout << bin_main[0] << bin_main[1] << bin_main[2] << bin_main[3] << bin_main[4] << bin_main[5] << bin_main[6] << bin_main[7] << endl;
And this worked fine.
Then I wrote the same 2nd variant of cout in other way
cout << bin_main[0];
cout << bin_main[1];
cout << bin_main[2];
cout << bin_main[3];
cout << bin_main[4];
cout << bin_main[5];
cout << bin_main[6];
cout << bin_main[7];
cout << endl;
and my code started to cout the same strange number. I think that all 3 ways of couts are almost the same (especially 2 and 3), but don't understand what makes it not to work.
int bin[8] = { 0,0,0,0,0,0,0,0 };
is allocated on stack. You should either allocate bin on heap
auto bin = std::unique_ptr<int, std::default_deleter<int[]>>(new int[8]);
or even better, use std::vector
you are returning pointer to local array of intbin[] in unsigned_dec. This array on stack of function unsigned_dec will get invalidated once another function from main gets called i.e cout operator .
As others have already mentioned: A function should never return a pointer to a local variable. Local variable is not valid when the function returns.
A better way is to use a vector and just make the function return the vector.
Something like:
#include <iostream>
#include <math.h>
using namespace std;
//function for converting absolute part of numbers
vector<int> unsigned_dec(int dec_M) {
vector<int> bin; // Create a vector
bin.resize(8, 0); // Fill it with 8 elements initialized to zero
int arr_ind = 0;
// Note: added check for arr_ind being valid
for (int base = (int)abs(dec_M); base > 0 && arr_ind < 8; base = base / 2) {
if (base % 2 == 0) {
bin[arr_ind] = 0;
}
else {
bin[arr_ind] = 1;
}
arr_ind++;
}
return bin; // Return the vector
}
int main() {
int dec_N;
cin >> dec_N;
vector<int> bin_main = unsigned_dec(dec_N);
for (int i = 0; i < bin_main.size(); i++) {
cout << bin_main[i];
}
cout << endl;
return 0;
}