C++ Vector Array / WhileLoop - c++

I am reading C++ Programming In Easy Steps 4th and have read in to something I am having trouble understanding. I've only just started reading it the other day.
I had a particularly hard time getting my head around vector arrays and elements when I done that section of the book, I still don't feel confident about it despite taking a bunch of time to try and understand them, so I plan to re-visit that again. I'm now on a later part of the book however which is demonstrating loops and here is the code that I am having trouble with (Just one line):
#include <iostream>
#include <vector> // Include vector support (Vector function library)
using namespace std;
int main()
{
//Declaring an integer vector and an integer variable for loop counter
vector <int> vec ( 10 );
int i = 0;
//Now inserting a while loop to assign a counter value to an element of the vector on each iteration
while ( i < vec.size() )
{
i++; //Increment the counter
vec[ i -1 ] = i; // Assign count to element
cout << " | " << vec.at ( i -1 );
}
return 0;
}
I understand everything, but this line:
vec[ i -1 ] = i; // Assign count to element
I'm not sure what this is doing exactly particularly the i -1 part? Can someone break this down for me in an easy to understand way? I'm going to quickly re-visit the section on vector arrays and see if I can get an understanding.

Vector indicies start at 0. A vector of 10 elements is indexed from 0 to 9. Assuming your goal is to load the array consecutively with the numbers 1 to 10, and since you start i at 0 and increment it before using it in the index expression, you need to subtract 1 from it to get the proper index.
This piece of code does the same thing.
vector<int> vec(10);
int i = 0;
while (i < vec.size())
{
vec[i] = i + 1;
i++;
}
i = 0;
while (i < vec.size())
{
cout << i << ": " << vec.at(i) << endl;
i++;
}

It may help you if you break the code down to what the while loop is actually accomplishing by individual statements (you would see similar if you were running through the while loop with a debugger and also adding watch statements such as i-1):
#include <iostream>
#include <vector> // Include vector support (Vector function library)
using namespace std;
int main()
{
//Declaring an integer vector and an integer variable for loop counter
vector <int> vec ( 10 ); // vector of 10 elements: 0...9
int i = 0; // i starts with the value of 0
// replace while loop with the individual statements the loop accomplishes
// note also that vec.size() = 10
// while (i < vec.size())
// increment i to 1 (started as 0, from above)
i++; //Increment the counter
vec[ 0 ] = i; // i - 1 = 0 here - Assign count to element
cout << " | " << vec.at ( 0 );
// increment i to 2
i++; //Increment the counter
vec[ 1 ] = i; // i - 1 = 1 here - Assign count to element
cout << " | " << vec.at ( 1 );
// continue to i = 9 ...
// increment i to 10
i++; //Increment the counter
vec[ 9 ] = i; // i - 1 = 9 here - Assign count to element
cout << " | " << vec.at ( 9 );
return 0;
}

you're assigning the numbers 1 to 1o to your vector.
vec[i-1] = i
follows directly after i++ which means,for your first index you're assigning a value a count/step more than index.
Put simply,let's follow the first 4 values of i and the elements inserted into the vector:
i = 0;
i = 1;here vec[ 1 - 1] = vec[0] = 1
i = 2;here vec [2 - 1] = vec[1] = 2
i = 3;and finally vec[ 2 ] = 3

Vectors are wrapper classes for arrays (Source:Link to C++ reference ) that also do some really cool things like use templates for allocators, provide dynamic space, and use stl iterators.
So, vectors can be accessed like arrays using the [ ] operator. The two code snippets are identical:
First, the array form:
//Allocate and assign array
int* arr[5]={1,2,3,4,5};
//Print the 3rd element, note that the first index corresponds to 0.
std::cout<< arr[2] <<std::endl;
//Reassign the 2nd element:
arr[1]=54;
Now the vector version:
//Allocate and assign vector
std::vector<int> arr( {1,2,3,4,5} );
//Print the 3rd element, note that the first index corresponds to 0.
std::cout<< arr[2] <<std::endl;
//Reassign the 2nd element:
arr[1]=54;
A tip for the wise: Accessing vectors like this can be dangerous since the size of an array can be changed elsewhere in code. Instead consider the following for assignment:
std::vector<int> arr( {1,2,3,4,5} );
int index=0;
for(std::vector<int>::iterator it = arr.begin(); it!= arr.end(); ++it){
if(index++ == 3){
(*it) = 54;
}
}

Related

Arrays Outputting the Wrong Numbers in C++

My goal is to have a player input a bunch of numbers for an array then that array is written into a text file. Another part of it is to be able to receive a bunch of numbers from a text file and put them into a sorted array of highest to lowest then output that array. But for some reason, I'm getting a lot of errors, ones that i feel like with some research I can fix. Unfortunately, there is one very confusing situation where I test to make sure the unsorted array is correct by outputting each element of the array. This is not a part of the final program but a test for now. I have a for loop that does so and it works perfectly, outputting each number as expected. Then in the next for loop, the exact same thing is supposed to happen but the numbers being outputted are all messed up. I do not understand how. Code below
void readFile(string fName) {
string fileName = fName + ".txt";
ifstream myFile(fileName);
char c;
string num;
int count = 0;
// Bring the array from file to int array
while (!myFile.eof()) {
myFile.get(c);
if (isspace(c) && num != "") {
int n = stoi(num);
intArray[count] = n;
count++;
num = "";
continue;
}
if (!myFile.eof()) {
num += c;
}
}
for (int i = 0; i < 10; i++) {
cout << intArray[i] << endl;
}
// Sort the array higest to lowest
for (int i = 0; i < 10; i++) {
cout << intArray[i] << " ";
for (int j = 9; j >= i; j--) {
if (j == 0) {
continue;
}
if (intArray[j] > intArray[j - 1]) {
int temp = arr[j];
intArray[j] = intArray[j - 1];
intArray[j - 1] = temp;
}
}
cout << endl;
}
}
sorry about the formatting above, its being weird so imagine the code is within the function.
This is what this outputs:
1
2
3
4
5
6
7
8
99
234
1
1
1
1
1
1
1
1
1
1
The numbers before the series of 1's is the actual array, the 1's is what is apparently the array according the cout in the last section of code where it says cout << intArray[i]
Your array does appear to be sorted. The reason for all the ones being printed is due to the location of the cout << within the outer loop.
Consider what your array looks like after your first iteration through the inner loop:
234,1,2,3,4,5,6,7,8,99
Now consider that you've incremented i to 1 in the outer loop. When you index your array intArray[i], the ith element is now 1 because you correctly moved it there. Each time, you're moving your smaller elements up one position in the array, then indexing to the position where the 1 is.
Don't try to print the sorted array while you're sorting it. Instead loop over it and print it after the sort.

How do I add the elements of this vector together?

The purpose of my code is to add the elements of a vector together into one integer. This is for Problem #1 on Project Euler:
https://projecteuler.net/problem=1
Here is my code:
int main()
{
int max_count = 1000; //The upper bound
//Loop for filling vector
for (int i = 1; i <= max_count; ++i){
int counter[max_count];
if (counter[i] % 3 == 0|| counter[i] % 5 == 0){
vector <int> start_point = {};
start_point.push_back (counter[i]);
for (auto& n : start_point){
int sum_of_elems = 0;
sum_of_elems += n;
cout << sum_of_elems;
}
}
}
return 0;
}
Currently, my code is outputting the following and I cannot figure out why.
32766143547943202305202750000-4646761603276630-76434810000-76434582500-464677056327662448-4646770403276632766-46467703232766327666032766230586999-970904238-95777621723084852023084852032766-970904244-46467688032766230624075-970911300230826120-1916976912327663276623063434032766230634681-957776214230826120140084992032766-970911280327660003276603276630-4646761603276623058081332766-464676440327663276632766230831712230745153065793306031200003276623074515300-191647711200023084852023074515365793360036000002308224802307451533657937207200-46467616032766000023083171232766230595552230831712032766327660-46467619232766230577342230822480230829920000-46467616032766230822480230829960-46467264032766230540223001920409600-46467247232766327661920409600-46467220832766000000000011072962560230556921230818160-4646738403276619204096000000230510592-1572142422000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001920169263100000170147416279176918919693827240000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
You're reinitializing your sum variable on each loop, so you end up just printing the individual values. You're also mixing looping and summing, which is complicating your code; either skip the vector entirely (just have a summing loop), or fill it completely, then sum it.
I can't give much more useful advice because you've got a lot of associated problems here. You declare counter without initializing it, then read from uninitialized memory to populate start_point.
Point is, most of your variables need to be declared outside the loops (so they're not repeatedly reinitialized from scratch on each loop), your output should be after the loops, and counter needs real data so you're not invoking undefined behavior.
Removing vectors and other unnecessary variables, the code can be simplified to:
#include <iostream>
int main()
{
int max_count = 1000; //The upper bound
int sumOfMultiples = 0;
for (int i = 1; i < max_count; ++i)
if (i % 3 == 0 || i % 5 == 0)
sumOfMultiples = sumOfMultiples + i;
std::cout << "Sum of Multiples of 3 and 5 below 1000 is: " << sumOfMultiples << "\n";
return 0;
}
Output is:
Sum of Multiples of 3 and 5 below 1000 is: 233168

Suitor elimination

I am trying to teach myself C++ and I came across this program project in my book I am working from:
In an ancient land, the beautiful princess Eve had many suitors. She decided on the following procedure to determine which suitor she would marry. First, all of the suitors would be lined up one after the other and assigned numbers.
The first suitor would be number 1, the second number 2, and so on up to the last suitor,number n. Starting at the first suitor she would then count three suitors down the line (because of the three letters in her name) and the third suitor would be eliminated from winning her hand and removed from the line. Eve would then continue, counting three more suitors, and eliminating every third suitor. When she reached the end of the line she would continue counting from the beginning.
For example, if there were six suitors then the elimination process would proceed as follows:
123456 initial list of suitors, start counting from 1
12456 suitor 3 eliminated, continue counting from 4
1245 suitor 6 eliminated, continue counting from 1
125 suitor 4 eliminated, continue counting from 5
15 suitor 2 eliminated, continue counting from 5
1 suitor 5 eliminated, 1 is the lucky winner
Write a program that uses a vector to determine which position you should stand in to marry the princess if there are n suitors. You will find the following function from the Vector class useful:
v.erase(iter);
// Removes element at position iter
For example, to use this function to erase the fourth element from the beginning of a vector variable named theVector , use
theVector.erase(theVector.begin( ) + 3);
The number 3 is used because the first element in the vector is at index position 0.
I have some preliminary code written, but I am having a hard time figuring out how to tell the program after the first suitor (i.e the 3rd suitor) is eliminated to start counting from the fourth suitor, and so on. Perhaps a nested loop would work? I have found solutions online that use a class but it is difficult for me to understand and I feel like there is a simpler way of solving this problem, any help would be greatly appreciated.
#include <iostream>
#include <vector>
using namespace std;
int main ()
{
int n;
vector<int> vec;
cout << "Enter the number of suitors: " << endl;
cin >> n;
// set some values (from 1 to n)
for(int i = 0; i <= n; i++){
vec.push_back(i);
}
// erase third suitor
vec.erase(vec.begin()+2);
// print vector with erased suitor
for(unsigned i = 0; i <= vec.size(); i++){
cout << vec[i] << endl;
}
}
First of all, there are two bugs in your program: you're initially putting [0, n] in the vector, which should be [1, n], and when printing the contents of the vector, you use <= where it should be <.
Now for the actual question. We want to iterate over the vector with steps of size 2 (the second person to the right of the current person):
for (int i = 0; i < vec.size(); i += 2)
However, when we reach the end of the array, we want to continue counting from the front. For this, we can use the modulo operator %:
for (int i = 0; i < vec.size(); i = (i + 2) % vec.size())
This will restrict i to the range [0, vec.size() - 1]. As such, our loop condition is now useless. Instead, we need to take care to terminate the loop when the vector's size is 1:
for (int i = 0; vec.size() > 1; i = (i + 2) % vec.size())
Putting it together, we get the following:
for (int i = 0; vec.size() > 1; i = (i + 2) % vec.size())
vec.erase(vec.begin() + i + 2);
Or equivalently:
for (int i = 2; vec.size() > 1; i = (i + 2) % vec.size())
vec.erase(vec.begin() + i);
The only element that is in the vector when this loop terminates is the number of the lucky suitor.
EDIT: To print out the contents of the vector after each elimination, try this:
for (int i = 2; vec.size() > 1; i = (i + 2) % vec.size())
{
vec.erase(vec.begin() + i);
for (int j = 0; j < vec.size(); j++)
cout << vec[j];
cout << endl;
}
Use relative positioning and take advantage of vec.erase()'s return value.
newpos = vec.erase(pos);
Here 'newpos' is pointing to the element that followed the erased one. Meaning, earsing '3' from {1, 2, 3, 4, 5, 6} gets you pointed to '4'. You can then do
pos = vec.begin();
while (pos != vec.end()) {
erasePos = // compute erasing position relative to 'pos'
// e.g. pos + 2, within bounds
pos = vec.erase(erasePos);
}
You need to do this in a loop.
For that use case where you simply iterate until the end and loop back to the beginning, I would use a list instead of a vector. The program could be :
#include <iostream>
#include <list>
using namespace std;
int main() {
list<int> l;
int n;
int i;
cout << "Enter the number of suitors: ";
cin >> n;
for (i=0; i<n; i++) l.push_back(i);
int delta = 3; // want to remove every third
i = delta;
list<int>::iterator it = l.begin();
while (l.size() > 1) { // loop until only one left
if (--i == 0) { // is it third ?
list<int>::iterator it2 = it++; // move pointer one step further (erase would destroy it)
l.erase(it2); // remove it
i = delta; // rearm counter
}
else it++; // was not third, simply goes on
if (it == l.end()) it = l.begin(); // if at end, go back to begin
}
cout << "Winner is number : " << l.front() + 1 << endl; // add one as our list was 0,1,...n-1
return 0;
}

How to output a missing number in set in c++?

If I have a set in C++, and it contains numbers from 0 to n. I wish to find out the number that is missing from 1 to n and output that and if none of them is missing, then output the number (n+1).
For example, if the set contains, 0 1 2 3 4 5 6 7, then it should output 8
If it contains, 0 1 3 4 5 6, then it should output 2.
I made the following code for this, but it always seems to output 0. I dont know what is the problem.
set<int>::iterator i = myset.begin();
set<int>::iterator j = i++;
while (1)
{
if ( *(j) != *(i)+1 )
{
cout<<*(j)<<"\n";
break;
}
else
{
i++;
j++;
}
}
What is the problem? Thanks!
The problem is that you're advancing i:
set<int>::iterator i = myset.begin(); // <-- i points to first element
set<int>::iterator j = i++; // <-- j points to first element
// i points to second!
while (1)
{ // so if our set starts with {0, 1, ...}
if ( *(j) != *(i)+1 ) // then *j == 0, *i == 1, *i + 1 == 2, so this
// inequality holds
What you meant to do is have j be the next iterator after i:
std::set<int>::iterator i = myset.begin(), j = myset.begin();
std::advance(j, 1);
With C++11, there's also std::next():
auto i = myset.begin();
auto j = std::next(i, 1);
Or, alternatively, just reverse your construction:
std::set<int>::iterator j = myset.begin();
std::set<int>::iterator i = j++; // now i is the first element, j is the second
Or, lastly, you really only need one iterator:
int expected = 0;
for (std::set<int>::iterator it = myset.begin(); it != myset.end();
++it, ++expected)
{
if (*it != expected) {
std::cout << "Missing " << expected << std::endl;
break;
}
}
The easiest stuff: Use count() function of set to check whether an element is present in set or not.
The count() takes an integer argument: The number whose existence in the set is to be checked. If the element is present in set, count() returns a non zero value, else it returns 0.
For example:
#include <iostream>
#include <set>
using namespace std;
int main()
{
set<int> s;
//I insert 0 - 4 in the set.
for(int i=0;i < 5; ++i)
s.insert(i);
//Let 10 be the 'n'.
for(int i = 0; i < 10; ++i)
{
//If i is NOT present in the set, the below condition will be true.
if (!s.count(i))
cout<<i<<" is missing!\n";
}
}
One problem is that you access beyond the end of the set if the set is
dense, which is undefined behavior. Another is that you always output
an element in the set (*j, where j is an iterator into the set);
according to your description, what you want to output is a value which
isn't in the set.
There are a couple of ways of handling this. The simplest is probably
just to maintain a variable expected, initialized with 0 and
incremented each time. Something like the following.
int
firstAvailable( std::set<int> const& allocated )
{
int expected = 0;
for ( auto current = allocated.begin(), end = allocated.end();
current != end && *current == expected;
++ current ) {
++ expected;
}
return expected;
}
If you don't want to return 0 if the list isn't empty, but starts with
some other value, initialize expected with the first element of the
set (or with whatever you want to return if the set is empty).
EDIT:
Of course, other algorithms may be better. For this sort of thing, I usually use a bit map.
The problem with your original code has already been pointed out in the other answers. You're modifying i while assigning j. You can fix this by initializing the iterators as:
set<int>::iterator i = myset.begin();
set<int>::iterator j = i;
j++;
A more elegant solution is to take advantage of the fact that the sum of all values up to n is n * (n + 1) / 2. You can calculate the sum of the actual values, and subtract it from the full sum to obtain the missing value:
int findMissing(const std::set<int>& valSet) {
int valCount = valSet.size();
int allSum = (valCount * (valCount + 1)) >> 1;
int valSum = std::accumulate(valSet.begin(), valSet.end(), 0);
return allSum - valSum;
}
The big advantage of this approach is that it does not rely on using a container where iterators provide the values in sorted order. You can use the same solution e.g. on an unsorted std::vector.
One danger to look out for when using this approach is overflow. With 32-bit ints, it will overflow with approximately 2^16 values. It might actually still work if it overflows, particularly if you use unsigned instead of int, but I did not confirm that.
There's a similar approach that uses the XOR of all values instead of the sum, which does not have the problem with overflow.

Problems with a simple while loop

I'm on the "looping while" segment of a book named c++ programming written by Mike McGrath.
In the book it explains how a while loop works and what it can and cannot do etc. It gives an example code which I understand for the most part except for something that the book does not explain and I was wondering if any of you could explain it.
This is the code:
#include <iostream>
#include <vector>
using namespace std ;
int main(){
vector <int> vec(10) ;
int i = 0 ;
while (i < vec.size()){
i ++ ;
vec[i-1] = i ;
cout << " | " << vec.at(i-1) ;
}
}
Now, this is the way I am reading this, and I'm sure I'm reading it the wrong way because the results make no sense to me:
While i is less than 10 (vector's size) continue executing this code. So integer i is 0, but it increments to 1 at the beginning of the code. Next however, is the part I am so confused about.
It says vec[i-1], why is he subtracting 1? And then making it equal to i? If I try to make it vec[i] = i; the program crashes. So the way I am reading it is, vec[i - 0 ] would have to be 0 since 0 was just incremented to 1 on the previous step of the while loop. Then to display the results he once again calls the command vec.at() to i-1, which further confuses me. I simply do not understand what the -1 means within the vector. Shouldn't what's inside the brackets mean the position within the vector?
Because in the first line of the loop body he's incremented i (making it 1 on the first iteration), so he needed to subtract 1 to get back to valid array indexing (whereby 0 is the first index of an array, and n-1 is the last).
The program crashes when you change that, because you'd be accessing vec[1] to vec[N] (where N is the vector size) instead of vec[0] to vec[N-1], the real valid range of the vector.
He's assigning i so that each vector element contains an incrementing count. It's a bit confusing.
vec[0] = 1
vec[1] = 2
vec[2] = 3
...
vec[9] = 10
It would be better written like this:
int i = 0;
while (i < vec.size()) {
vec[i] = i+1;
cout << " | " << vec[i];
i++;
}
or:
for (int i = 0; i < vec.size(); i++) {
vec[i] = i+1;
cout << " | " << vec[i];
}
As Lightness has pointed out, he need to substract 1 to get back to 0 based indexing. The loop is same as below.
vector<int> vec(10);
int i = 0;
while(i < vec.size())
{
vec[i] = i + 1;
cout << " |" << vec.at(i);
i++;
}
that's why the output printed 1 to 10.
within the vector, [i-1] means minus current value of i by 1 then assign the value as index to vector. (note: the substracted value is not assigned back to i)
same description as above for vec.at(i-1)