C++ program not entering a for loop using vector - c++

I was practicing with vector, I wanted to push an element using push_back(); using a for loop, but the program doesn't even enter the for loop, help!!!
#include <iostream>
#include <vector>
using namespace std;
int main()
{
cout << "check ";
int val;
vector<char> vec;
cout << "check " << endl << "Its in the game";
//those two "check" were to confirm if the program is even running and is it a
problem while declaring the vector
for(int i = 0; i < vec.size(); i++){
cout << "enter element for vector" << endl;
cin >> val;
vec.push_back(val);
}
}

Your vector is empty. The for loop starts at zero, which is not less than zero, so the for loop never runs.

Your vector is literally empty, which means vec.size() is 0.So It will never enter the loop. If you know what your vector size is gonna be, you should define it as
std::vector<int> vec(vec_size);
for(int i=0;i<vec_size;++i)
{
//whatever.....
}
Or you could have used a while loop.
while(std::cin>>val)
{
//do your thing....
}

Related

How to determine number of values added to vector in C++?

I'm trying to build a little task using C++ in which I need to allow the user to determine up front how many gross_paychecks they would like to place in a vector called 'gross_paychecks_vector'.
So far this is what I have:
vector<double> gross_paychecks_vector (5);
double gross_paychecks;
// Add 5 doubles to vector
cout << "Please enter an integer" << endl;
cin >> gross_paychecks;
for(gross_paychecks = 0; gross_paychecks <= gross_paychecks_vector; ++gross_paychecks ){
cin >> gross_paychecks;
}
Right now I'm somewhat lost because I'm not sure whether to switch the vector to something like vector<double> gross_paychecks {} because it throws an error in the for loop.
Also I'm not sure how to go with the for loop (should I actually use a for-loop or something else?). I need to accept input from the user as long as it has not met the numbers of gross_paychecks that he/she has specified.
You probably want this:
vector<double> gross_paychecks_vector; // initially the vector is empty
...
cout << "How many paychecks:" << endl;
cin >> gross_paychecks;
for (int i = 0; i < gross_paychecks; i++)
{
double value;
cin >> value;
gross_paychecks_vector.push_back(value); // add new value to vector
}
// display values in vector
for (auto & value : gross_paychecks_vector)
{
cout << value << "\n";
}
Additionally. If you want to use modern C++ features, you would use:
#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
int main()
{
std::vector<double> grossPaychecks{};
std::cout << "How many paychecks:\n";
size_t numberOfPaychecks{0};
std::cin >> numberOfPaychecks;
// Read all data
std::copy_n(std::istream_iterator<double>(std::cin),numberOfPaychecks, std::back_inserter(grossPaychecks));
// Print all data
std::copy(grossPaychecks.begin(), grossPaychecks.end(), std::ostream_iterator<double>(std::cout,"\n"));
return 0;
}

Multidimensional Vector?

So I recently started learning C++ and I'm trying to figure out how to access a multidimensional vector or a vector with vectors stored inside of it. I've looked all over and I can't find exactly what I'm looking for. I want to be able to test the contents of each vector inside of the multidimensional vector by printing them out. Also whenever I try to see the size of the vector after each iteration, I'm getting random constants for each iteration. They look like they may be memory locations but I'm not sure.
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int numofArrays;
int numofQueries;
vector<vector<int>> arr(numofArrays);
cin >> numofArrays;
cin >> numofQueries;
int arrSize;
int number;
vector<int> indArr;
// Outer loop, appends vectors containing ints to a multidimensional vector
for (int i = 0; i < numofArrays; i++) {
cin >> arrSize; // Getting number of elements from user
// Inner loop, gets user inputted values then creates a vector which is added to the multidimensional vector
for (int x = 0; x < arrSize; x++) {
cin >> number;
indArr.push_back(number);
cout << "Last number added to vector: " << number << endl; // Checking to see if correct numbers are being added.
}
arr.push_back(indArr);
cout << "Multidimensional Vector size: " << arr.size() << endl; // Checking size of vector after each iteration
indArr.clear(); // Empties vector for next iteration
}
return 0;
}
As I am very new to C++, I welcome constructive criticism.
Newly Revised Code:
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int numofArrays;
int numofQueries;
cin >> numofArrays;
cin >> numofQueries;
vector<vector<int>> arr(numofArrays);
// Outer loop, appends vectors containing ints to a multidimensional vector
for (int i = 0; i < numofArrays; i++) {
int arrSize;
vector<int>indArr;
cin >> arrSize; // Getting number of elements from user
indArr.resize(arrSize); // Resizing array for next values
// Inner loop, gets user inputted values then creates a vector which is added to the multidimensional vector
for (int x = 0; x < arrSize; x++) {
int number;
cin >> number;
indArr.push_back(number);
cout << "Last number added to vector: " << number << endl; // Checking to see if correct numbers are being added.
}
arr.push_back(indArr);
cout << "Multidimensional Vector size: " << arr.size() << endl; // Checking size of vector after each iteration
}
int test = arr[0][0];
cout << test;
return 0;
}
Just some tips:
vector<vector<int>> arr(numofArrays); constructs a vector of vectors of size numofArrays. But numofArrays is not yet read from cin, so it is an undefined number. Care with the order of operations.
arr.push_back(indArr); adds a vector at the end of arr.
Hence, in your loop, even if you fix the order of reading numofArrays and declaring arr, you start with an array of size numofArrays, and each cycle you add an element. You will end up with arr holding 2 times numofArrays elements.
Also, indArr is a temporary variable, which you reset each cycle. Although there is nothing wrong about what you are doing, in general is better to keep each variable limited to its scope. If you define indArr inside the loop, it will be automatically cleared and re-created. May not be the most efficient way to do things in all cases, but I'd leave this details for later.
Something like this should work for you:
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int numofArrays;
int numofQueries;
cin >> numofArrays;
cin >> numofQueries; // this is an unused variable
vector<vector<int> > arr;
// Outer loop, set vectors containing ints to a multidimensional vector
for (int i = 0; i < numofArrays; i++) {
int arrSize;
vector<int> indArr;
cin >> arrSize; // Getting number of elements from user
// Inner loop, gets user inputted values then creates a vector which is added to the multidimensional vector
for (int x = 0; x < arrSize; x++) {
int number;
cin >> number;
indArr.push_back(number);
cout << "Last number added to vector: " << number << endl; // Checking to see if correct numbers are being added.
}
arr.push_back(indArr);
cout << "Multidimensional Vector size: " << arr.size() << endl; // Checking size of vector after each iteration
}
return 0;
}
The way you're inspecting the size is correct. For example in your code you're printing the integer number of elements in the first dimension of the array arr.
The odd results you're getting is because of how you're initializing the vector. In the constructor for arr there you specify a size describing the number of default-constructed elements to fill the vector with. However you're providing numofArrays which is an undefined value. Hence you receive random looking vector sizes when you print this out.
The real size of the vector arr's first dimension will be whatever this undefined value is plus one, due to the push_back operation.

Super basic code: Why is my loop not breaking?

for(int i=0;i<50;i++,size++)
{
cin >> inputnum[i];
cout << size;
if(inputnum[i] == '.')
{
break;
}
}
The break breaks the input stream but the size keeps outputting.
The output of size is 012345678910111213...474849.
I tried putting size++ inside the loop but it made no difference. And size afterwards will be equal to 50, which means it went through the full loop.
I forgot to explain that I added the cout << size within the loop to debug/check why it outputted to 50 after the loop even if I only inputted 3 numbers.
I suspect that inputnum is an array of int (or some other numeric type). When you try to input '.', nothing actually goes into inputnum[i] - the cin >> inputnum[i] expression actually fails and puts cin into a failed state.
So, inputnum[i] is not changed when inputting a '.' character, and the break never gets executed.
Here's an slightly modified version of your code in a small, complete program that demonstrates using !cin.good() to break out of the input loop:
#include <iostream>
#include <ostream>
using namespace std;
int main()
{
int inputnum[50];
int size = 0;
for(int i=0;i<50;i++,size++)
{
cin >> inputnum[i];
if (!cin.good()) {
break;
}
}
cout << "size is " << size << endl;
cout << "And the results are:" << endl;
for (int i = 0; i < size; ++i) {
cout << "inputnum[" << i << "] == " << inputnum[i] << endl;
}
return 0;
}
This program will collect input into the inputnum[] array until it hits EOF or an invalid input.
What is inputnum ? Make sure t's a char[]!! with clang++ this compiles and works perfectly:
#include <iostream>
int main() {
int size = 0;
char inputnum[60];
for(int i=0;i<50;i++,size++) {
std::cin >> inputnum[i];
std::cout << size;
if(inputnum[i] == '.') {
break;
}
}
return 0;
}
(in my case with the following output:)
a
0a
1s
2d
3f
4g
5.
6Argento:Desktop marinos$
Your code seams OK as long as you're testing char against char in your loop and not something else.. Could it be that inputnum is some integral value ? if so, then your test clause will always evaluate to false unless inputnum matches the numerical value '.' is implicitly casted to..
EDIT
Apparently you are indeed trying to put char in a int[]. Try the following:
#include <iostream>
int main() {
using namespace std;
int size = 0;
int inputnum[50];
char inputchar[50];
for(int i=0;i<50;i++,size++) {
cin >> inputchar[i];
inputnum[i] = static_cast<int>(inputchar[i]); // or inputnum[i] = (int)inputchar[i];
cout << size << endl; // add a new line in the end
if(inputchar[i] == '.') break;
}
return 0;
}
Then again this is probably a lab assignment, in a real program I'd never code like this. Tat would depend on the requirements but I'd rather prefer using STL containers and algorithms or stringstreams. And if forced to work at a lower-level C-style, I'd try to figure out to what number '.' translates to (simply by int a = '.'; cout << a;`) and put that number directly in the test clause. Such code however might be simple but is also BAD in my opinion, it's unsafe, implementation specific and not really C++.

Why am I getting a timeout(using sstream to parse list of integers separated by commas)?

I am given an input string of n integers, separated by commas (e.g. "23,4,56"). I need to set a stringstream to represent this string and then use it to scan each integer into a vector. The elements of the vector (the integers in the list) will end up being output line by line. I am given the main(), and am simply responsible for writing parseInts(string str). For some reason, I keep getting a timeout. I'm guessing it's something in my while loops, specifically concerning how I am manipulating my sstream with str(), but I can't figure out exactly what is going on. I am new to sstream and C++ so any help would be appreciated!
#include <sstream>
#include <vector>
#include <iostream>
using namespace std;
vector<int> parseInts(string str) {
int a; //will use this to hold the value of the 1st int in the sstream
stringstream list_initial; //will iterate over this sstream
list_initial.str(str); //set sstream to represent input str
vector<int> list_final; //will return this final vector for output in main
while (!list_initial.str().empty()){ //stop iterating at end of string
list_initial>>a; //store leading int value in a
list_final.push_back(a); //add a to end of vector
while (!ispunct(list_initial.str()[0])){ //get to next int in list
list_initial.str(list_initial.str().erase(0,1));
};
list_initial.str(list_initial.str().erase(0,1)); //erase leading comma
};
return list_final;
};
int main() {
string str;
cin >> str;
vector<int> integers = parseInts(str);
for(int i = 0; i < integers.size(); i++) {
cout << integers[i] << "\n";
}
return 0;
}
Your function implementation could be really improved, but following your logic, if you replace the second while line:
while (!ispunct(list_initial.str()[0])){ //get to next int in list
by this one, adding a length check:
while (list_initial.str().size() && !ispunct(list_initial.str()[0])){ //get to next int in list
, then is runs, works well and exits well.
Explanations
This loop was never breaking, because at the end of the process, ispunct() function was never recognizing its parameter, !list_initial.str()[0], as something true : the string list_initial.str() is empty at this moment, then the 0 index doesn't exist.
Please look at the doc on cplusplus.com:
If pos is equal to the string length, the const-version never throws exceptions (no-throw guarantee).
Otherwise, it causes undefined behavior.
Your program was freezing because it didn't found the right condition which could have leaded to leaving the above loop.
Advices
One important thing to talk about your question is : why didn't you find the answer yourself ? One answer for this question is the following : you didn't try to debug your code.
To answer your question, I just debugged your code, and found quickly the problem just by adding this kind of lines around your code, to see what happened:
cout << "list_initial: " << list_initial.str() << endl;
An example for your code, with debug statements added::
#include <sstream>
#include <vector>
#include <iostream>
using namespace std;
vector<int> parseInts(string str) {
cout << "begin parseInts()" << endl; // ###### DEBUG ######
int a; //will use this to hold the value of the 1st int in the sstream
stringstream list_initial; //will iterate over this sstream
list_initial.str(str); //set sstream to represent input str
vector<int> list_final; //will return this final vector for output in main
cout << "begin while 1" << endl; // ###### DEBUG ######
while (!list_initial.str().empty()){ //stop iterating at end of string
list_initial >> a; //store leading int value in a
list_final.push_back(a); //add a to end of vector
cout << "a: " << a << endl; // ###### DEBUG ######
cout << "begin while 2" << endl; // ###### DEBUG ######
while (!ispunct(list_initial.str()[0])){ //get to next int in list
cout << "list_initial: " << list_initial.str() << endl; // ###### DEBUG ######
list_initial.str(list_initial.str().erase(0,1));
};
cout << "endwhile 2" << endl; // ###### DEBUG ######
list_initial.str(list_initial.str().erase(0,1)); //erase leading comma
};
cout << "endwhile 1" << endl; // ###### DEBUG ######
cout << "end parseInts()" << endl; // ###### DEBUG ######
return list_final;
};
int main() {
string str;
cin >> str;
vector<int> integers = parseInts(str);
cout << "begin for" << endl; // ###### DEBUG ######
for(int i = 0; i < integers.size(); i++) {
cout << integers[i] << "\n";
}
cout << "end for" << endl; // ###### DEBUG ######
return 0;
}
This (very basic) debugging technic permits you to quickly find out a bug in your code; just add some cout << ... << endl; lines inside the code to point out some important informations, i.e.: "Which loop is causing freezing?", or "What is the content of this variable at this moment?".
If you put cout << "Entering While loop 1" << endl; before, and cout << "Exiting While loop 1" << endl; after each suspected loop, you may learn many things about what happens during the execution of your program.
With this debugging lines added, you can easily find out that the second loop is looping forever; then you can narrow your bug investigation to this loop.
A stream is an abstract file. It is just a bunch of text that can be understood by things like, for example, cin >> n to convert numbers to integers.
Here's an idea of how to use a stream:
#include <cctype>
#include <ciso646>
#include <iostream>
#include <sstream>
#include <vector>
using namespace std;
vector<int> parse_ints( const string& s )
{
vector<int> ints; // resulting list of ints
istringstream ss(s); // stream of ints separated by (non-digits)
int n; // each int extracted from the stream
// while input an int
while (ss >> n)
{
// save the int
ints.push_back(n);
// skip to next digit
while (ss and !isdigit(ss.peek())) ss.get();
}
return ints;
}
int main()
{
vector<int> xs = parse_ints( "2, 3 ,5; 7 : 11.13\t17abc21" );
for (int x : xs)
cout << x << " ";
cout << "\n";
}
This produces:
2 3 5 7 11 13 17 21
Notice how we can simply skip characters we aren't interested in? In this particular case, we skip all non-digit characters.
Hope this helps.

How to use a sentinel to trigger end of vector?

I'm new to programming (in general) and C++ (in particular). I'm learning vectors and am trying to write a simple program that:
allows the user to enter a vector of students' test scores
when the user types the sentinel (-1 in this case), the vector terminates
outputs a tally of the student's grades
Here's my code:
#include "stdafx.h"
#include <iostream>
#include <vector>
using namespace std;
const int SENTINEL = -1;
vector<int> studentGrades = { 0 };
int myInput;
int main()
{
do
{
cout << "Please enter a student's grade: ";
cin >> myInput;
if (myInput < 1000)
{
studentGrades[myInput]++;
}
studentGrades.push_back(myInput);
} while (myInput != SENTINEL);
cout << "\n";
for (int i = 0; i < 1000; i++)
cout << i << " grade(s) of " << studentGrades[i] << endl;
return 0;
}
Two questions:
1) Can anyone provide guidance on why this code is only allowing me to enter one student's grade?
2) Is the for loop that compute the "tally" correct?
Thanks in advance for taking a look,
Ryan
* REVISED CODE *
# JCx - this is the revised code:
#include "stdafx.h"
#include <iostream>
#include <vector>
using namespace std;
const int SENTINEL = -1;
vector<int> studentGrades = { 0 };
int myInput;
int main()
{
do
{
cout << "Please enter a student's grade (or -1 to QUIT): ";
cin >> myInput;
if (myInput < 1000)
{
studentGrades.at(myInput)++;
}
studentGrades.push_back(myInput);
} while (myInput != SENTINEL);
cout << "\n";
for (int i = 0; i < 1000; i++)
cout << i << " grade(s) of " << studentGrades.at(myInput) << endl;
return 0;
}
and, I'm seeing this error:
Unhandled exception at 0x7707C42D
Microsoft C++ exception: std::out_of_range at memory location 0x0035F890
There's more than one problem. The attempt to access studentGrades[-1] when the users enters your sentinel value, and the fact that the default vector only contains an entry for 0 and the use of push_back.
Let's just walk through some of the problems:
User runs program. User enters 100. studentGrades[100] is out of range. Undefined behaviour occurs as the vector only has one element.
User runs program, enters -1 studentGrades[-1] is out of range.
User runs program, enters 0. studentGrades[0] is in range, incremented to 1. studentGrades.push_back(1) adds an element to the vector studentGrades[1] is now also equal to 1.
As a great starting point, if you swap your subscript vector references for the vector at method as I've shown below you will get out-of-range errors which will help (a lot). The code below still needs work but at least you'll have run-time errors instead of odd behaviour.
int main()
{
do
{
cout << "Please enter a student's grade: ";
cin >> myInput;
if (myInput < 1000)
{
studentGrades.at(myInput)++;
}
studentGrades.push_back(myInput);
} while (myInput != SENTINEL);
cout << "\n";
for (int i = 0; i < 1000; i++)
cout << i << " grade(s) of " << studentGrades.at(myInput) << endl;
return 0;
}
I think if I was implementing this I'd be using std::map instead of a vector. It would let you have a studentGrade[1000] without having to allocate memory for studentGrade[0] to [999] first.
However as you are learning about std::vector check out vector::resize to set the vector big enough for the required elements, std::vector::size to find out whether you need to increase the size. You could then ditch the push_back.
References
vector::at http://www.cplusplus.com/reference/vector/vector/at/
vector::size http://www.cplusplus.com/reference/vector/vector/size/