Vector substring out of range - c++

I'm currently working on a problem and I've been stumped on an error for about 3 hours now. Thus, I've given up being hard headed and I'm looking to the internet to see if someone else's wealth of knowledge can help to solve my problem.
A jist of the program, it takes in input from the command line of any number of numbers. It inserts them into a vector and then performs a series of statistical analysis' on the data set.
Currently, I'm having difficulty with the quintiles function (as my teacher says or "quantiles" for those of you looking it up on Wikipedia).
Logically, my code should work. However, it's seeming to hit an out of range error two before the actual end of the vector that I've created.
Heres the function followed by the functions called inside:
string quintile(vector<double> v) {
ostringstream oss;
oss << "Quintile means" << endl;
vector<unsigned> quintile{ 0 };
// get range of quintiles and insert into vector
for (unsigned i = 1; i <= 5; ++i)
quintile.push_back((v.size() * 0.2) * i);
// get the mean for each quintile
for (unsigned i = 0; i < 5; ++i)
oss << "Q" << (i + 1) << ": " << mean_sized(v, quintile[i], quintile[i + 1]) << " (" << quintile[i] << ".." << quintile[i + 1] << ")" << endl;
return oss.str();
}
double mean_sized(vector<double> v, int first, int last) {
double mean = 0.0;
vector<double> sub;
for (unsigned i = v[first]; i < v[last]; ++i)
sub.push_back(v[i]);
return (accumulate(sub.begin(), sub.end(), mean) / sub.size());
}
Any input is much appreciated as I'm seriously stumped.. I'm going to move on to the last function and hopefully by the time I'm done someone will have graced me with the knowledge to solve that issue.
Thanks!

This loop is wrong:
for (unsigned i = v[first]; i < v[last]; ++i)
sub.push_back(v[i]);
You're using the values in the vector as the range of indexes. You should just be using the range from first to last:
for (unsigned i = first; i <= last; i++) {
sub.push_back(v[i]);
}
P.S. See Why is it considered a bad practice to omit curly braces?

Related

Trying to create a better loop for naming array elements

I have started studying arrays and have just started making some practice but I am having some problems with using loops to name the elements inside of a specific array.
I was trying to make this piece of code that assigned the numbers from 1 up to 12(to resemble the months of the year) to the ints inside of the array, this is what I came up with:
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
int array[12];
for (int i = 0; i < 12;) {
cout << "Month number " << i + 1 << endl;
array[i] = (i++);
}
return 0;
}
What I don't like about this is the fact that I had to leave the increment/decrement space inside of the for loop empty. I had initially tried making the code look something like this:
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
int array[12];
for (int i = 0; i < 12; i++) {
cout << "Month number " << i + 1 << endl;
array[i] = i++;
}
return 0;
}
But this way, even if the first element of the array came out correct, the subsequent ones didn't. I think the reason for this is that the i++ in the last statement of the loop makes the value of i increment but I couldn't find a way around it without having to add another line with i-- or doing as I did in the first code I posted.
Could anyone offer me a hand in understanding how to make it so that i can store the value of i, incremented by one, inside of that specific array element, without incrementing it for the whole loop(if it is possible)?
I know there are ways around it, just like I showed in the first code i posted, but it's something that's bugging me and so I would like to make it more visually pleasing.
Please, keep in mind that I am just a beginner :)
Thanks in advance for the answers, and sorry for the long question.
Edit: Apparently, coding like this:
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
int array[12];
for (int i = 0; i < 12; i++) {
cout << "Month number " << i + 1 << endl;
array[i] = i + 1;
}
cout << array[4] << endl;
return 0;
}
makes it so that the program works correctly and looks like I wanted, but I can't comprehend why it does :(
Edit 2: Apparently, as UnholySheep pointed out, I missed on the fact that + 1 does not modify the value of the integer, while ++ does.
Thanks to everyone that answered and explained how ++ and +1 work!
Simply do i+1 again.
for (int i = 0; i < 12; i++)
{
cout << "Month number " << i + 1 << endl;
array[i] = i + 1;
}
Now it's obvious you actually want to start at 1 and go to 12, so this seems somewhat better with less repetition:
for (int i = 1; i <= 12; i++)
{
cout << "Month number " << i << endl;
array[i-1] = i;
}
EDIT: As for your edit, the reason why this works is because i++ operator works on the particular i variable. It increments that existing i by one, making it so that the next time you access i, it will be 1 more than it was before.
Writing i+1, on the other hand, creates a completely new, temporary, variable (actually a constant). So when you write
array[i] = i+1;
you're saying that you want i to remain unchanged, but you want to create a new number, one bigger than i, and put that new number into the array.
You can even write it out longer to be completely explicit:
int newNumber = i+1;
array[i] = newNumber;
for (int i = 0; i < 12; i++) {
cout << "Month number " << i + 1 << endl;
array[i] = i+1;
}
No reason to increment i in the loop

histogram program gives strange output C++

I have been writing code to produce a horizontal histogram. This program takes user input of any range of numbers into a vector. Then it asks the user for the lowest value they want the histogram to begin at, and how big they want each bin to be. For example:
if lowestValue = 1 and binSize = 20
and vector is filled with values {1, 2, 3, 20, 30, 40, 50} it would print something like:
(bin) (bars) (num)(percent)
[ 1-21) #### 4 57%
[21-41) ## 2 28%
[41-61) ## 2 28%
Here is most of the code that does so:
void printHistogram(int lowestValue, int binSize, vector<double> v)
{
int binFloor = lowestValue, binCeiling = 0;
int numBins = amountOfBins(binSize, (int)range(v));
for (int i = 0; i<=numBins; i++)
{
binCeiling = binFloor+binSize;
int amoInBin = amountInBin(v,binFloor, binSize);
double perInBin = percentInBin(v, amoInBin);
if (binFloor < 10)
{
cout << "[ " << binFloor << '-' << binCeiling << ") " << setw(20) << left << formatBars(perInBin) << ' ' << amoInBin << ' '<< setprecision(4) << perInBin << '%' << endl;
binFloor += binSize;
}
else
{
cout << '[' << binFloor << '-' << binCeiling << ") " << setw(20) << left << formatBars(perInBin) << ' ' << amoInBin << ' '<< setprecision(4) << perInBin << '%' << endl;
binFloor += binSize;
}
}
}
and the function that counts how many terms are in each bin:
int amountInBin(vector<double> v, int lowestBinValue, int binSize)
{
int count = 0;
for (size_t i; i<v.size(); i++)
{
if (v[i] >= lowestBinValue && v[i] < (lowestBinValue+binSize))
count += 1;
}
return count;
}
Now my issue:
For some reason, it is not counting values between 20-40. At least as far as I can see from my testing. Here is an image of a run:
Any help is appreciated.
I would suggest a different approach. Making two passes, first calculating the number of bins, then another pass to add them up, looks fragile, and error-prone. Not really surprise to see you trying to figure out a bug of this kind. I think your original approach is too complicated.
As the saying goes "the more you overthink the plumbing, the easier it is to stop up the drain". Find the simplest way to do something, and it will have the least amount of surprises and gotchas, to deal with.
I think it's simpler to make a single pass over the values, calculating which bin each value belongs to, and counting the number of values seen per bin. Let's use a std::map, keyed by bin number, with the value being the number of values in each bin.
void printHistogram(int lowestValue, int binSize, const std::vector<double> &v)
{
std::map<int, size_t> histogram;
for (auto value:v)
{
int bin_number= value < lowestValue ? 0:(value-lowestValue)/binSize;
++histogram[bin_number];
}
And ...that's it. histogram is now your histogram. histogram[0] is now the number of values in the first bin, [lowestValue, lowestValue+binSize), which also includes all values less than lowestValue. histogram[1] will be the number of values found for the next bin, and so on.
Now, you just have to iterate over the histogram map, and generate your actual histogram.
Now, the tricky part here is that the histogram map will only include keys for which at least 1 value was found. If no value was dropped into the bin, the map will not include the bin number. So, if there were no values in the first bin, histogram[0] won't even exist, the first value in the map will be the bin for the lowest value in the vector.
This isn't such a difficult problem to solve, by iterating over the map with a little bit of extra intelligence:
int next_bin_number=0;
for (auto b=histogram.begin(); b != histogram.end(); b++)
{
while (next_bin_number < b->first)
{
// next_bin_number had 0 values. Print the histogram row
// for bin #next_bin_number, showing 0 values in it.
++next_bin_number;
}
int n_values=b->second;
// Bin #n_next_number, with n_values, print its histogram row
++next_bin_number;
}
The code in the loop doesn't initialize i, so the results are at best unpredictable.

Problems with string comparing with pointer

I have three lists and I want to implement a search feature.
How the code works is that I create an iterator that begins at the start of each list and it compares what the user inputs with each and every value in the list, when it finds a match it is supposed to increase an integer variable by one, so in the end it would say:
your value is found: <x amount of times in Example list>
The problem I am having is that it is compiling fine but the end result still gives me 0 like it didn't increment the variable.
I am wondering if it is having trouble comparing the value where the iterator is pointing to the user input, can anyone please shed some light on this? For testing purposes in the
On the iterator search_disregard I manually put 4 identical values in the list, so I know the end result should show me 4, but I still get 0:
cout << "\nSearch for: ";
string edit_search;
cin >> edit_search;
list<string>::iterator search_disregard = disregard_list.begin();
list<string>::iterator search_compare = compare_list.begin();
int search_disregard_count = 0;
int search_compare_count = 0;
for (int x = 0; x < disregard_list.size(); ++x)
{
if (*search_disregard == edit_search)
{
++search_disregard_count;
}
}
for (int x = 0; x < compare_list.size(); ++x)
{
if (*search_compare == edit_search)
{
++search_compare_count;
}
}
cout << edit_tag << edit_search << " is found in the following: \n" << endl;
cout << search_disregard_count << " time(s) in the Disregard List" << endl;
cout << search_compare_count << " time(s) in the Compare List" << endl;
buffer_clear();
You never increment your iterators so they will always point to the first element. The idiomatic way:
for(auto it = container.begin(); it != container.end(); ++it) ...

how to pick two characters at a time from a string? reaching ith position of a string?

how should i run a for loop to pick two characters at a time from my string??
int main{
string data;
for (i = 0; i <= data.size(); i+=2)
d = data[i] + data[i+1];
cout << "the list of two characters at a time is" << d;
}
//i want to pick divide my string(data) for example: "hello how are you" into a list of two characters at a time (where the space should also be counted as a character) and listed such as:
cout should give:
he
ll
o(space)
ho
w(space)
ar
e(space)
yo
u //the last one is appended with 8 zeros with u to make a complete pair
i dont understand how to reach the ith position of string data in C++.
How about you use substr()?
for (int i=0; i<data.length(); i+=2) {
if(i+2 < data.length()){ //prevent it from throwing out_of_range exception
d = data.substr(i,i+2);
cout << d << endl;
}
}
std::cout << "the list of two characters at a time is:\n";
for (i = 0; i < data.size(); ++i) {
if (data[i] == ' ')
std::cout << "(space)";
else
std::cout << data[i];
if (i % 2 != 0)
std::cout << '\n';
}
You almost got it right except 2 issues:
you loop condition is wrong, it could be this:
for (i = 0; i + 1 < data.size(); i+=2)
otherwise you will try to access data behind end of string. In this case you will skip 1 symbol if string length is odd. If you need to process that, your loop should be different.
you add 2 chars as numbers, but you should make it as string:
d = std::string( data[i] ) + data[i+1];

for loop not running, trying to iterate backwards through array elements

To practice using pointers and arrays i'm trying to do a simple program capable of converting a binary input to denary.. i think i have a good idea for the logic but i haven't even got round to trying to implement it because im struggling to get my for loop running!
It seems silly but i know the code inside the for loop works fine outside of it, so it must be something wrong with the condition..? im trying to start at the back of the char array (navigating using pointers) and output each char(as an int) up to the first element.
So the desired output is "0 - 1 - 0 - 1 -"
#include <iostream>
using std::cout;
using std::endl;
//prototypes
void binaryToDenary(const char* input, int& inputLength);
int main(){
const char binaryInput[] = {1,0,1,0};
int inputLength = sizeof(binaryInput)/sizeof(binaryInput[0]);
binaryToDenary(binaryInput, inputLength);
return 0;
}
void binaryToDenary(const char* input, int& inputLength){
//testing some stuff--- this all works as expected
//cout << input[2] << " " << (int)*(input+2) << " " << inputLength <<endl;
int i;
for(i = inputLength; i < 0; i--){
cout << (int)*(input+i) << " - ";
}
}
Your for loop should be this:
for(i = inputLength -1 ; i >= 0; i--)
{
cout << (int)*(input+i) << " - ";
}
There are two problems in your code:
i = inputLength which should be i = inputLength -1
i < 0 which should be i >= 0
Also, change the second parameter type from int & to int:
void binaryToDenary(const char* input, int inputLength) //now its better!
The type int& reduces the use cases, and benefits almost nothing. If you use int &, then all of these would give compilation error:
const int inputLength = sizeof(binaryInput)/sizeof(binaryInput[0]);
^^^^ note this
binaryToDenary(binaryInput, inputLength); //compilation error
binaryToDenary(binaryInput, sizeof(binaryInput)/sizeof(binaryInput[0])); //error
binaryToDenary(binaryInput, 4); ////compilation error
So use int, and all of the above would compile fine!
Array indexes start from zero, so the last element is at inputLength - 1. With i < 0 you exit from the loop immediately as that never be true...
for(i = inputLength - 1; i >= 0; i--){
cout << (int)*(input+i) << " - ";
}
for(i = inputLength; i < 0; i--)
will run only if inputLength is less than 0, which is not possible?
You need:
for(i = (inputLength-1); i >= 0; i--)
^^^^^^^^^^^^^^ ^^
C arrays are 0 based so a valid index is given by
(0 <= i) && (i < array_length)
In your program, this means that the position of the last digit in your initialization should be inputLength - 1 and the loop condition should be i >= 0.
(As for why you loop is not running, at the start you have i == inputLength, so i is positive, failing the i < 0 condition immediately).
You want to run as long as i is bigger (or maybe equal) to zero. You were trying to run the loop as long as i was less than zero, and beginning with a value greater than zero results to that you never enter the loop.
for(i = inputLength; i > 0; i--){
cout << (int)*(input+i) << " - ";
}
You must check for iteration loop variable i to be positive..
However you should use a STL iterator on the binary input vector and not loop on it's content in a c fashion, if you want to practice C++, possible solution could be:
vector<char> binaryInput;
binaryInput.push_back(1);
binaryInput.push_back(0);
binaryInput.push_back(1);
binaryInput.push_back(0);
vector<char>::iterator it;
for ( it=myvector.begin() ; it < myvector.end(); it++ ){
cout << " " << *it << endl; //or whatever you need to do with vector content
}