Reading input in loop until sentinel value is reached in C++ - c++

I'm relatively new to C++ and I'm trying to write some code that asks a user to enter numbers and use -999 as a sentinel value to end the input loop. The numbers they enter must populate an array to be used in a binary tree later. The issue I'm having is the loop doesn't terminate if -999 is entered, and I also don't know how to read those values into the array without specifying how large the array is. The program must dynamically size the array based on how many inputs were given. I have attached my code. Any help is greatly appreciated!
#include <iostream>
#include <string.h>
//#include "binarySearchTree.h"
//#include "binaryTree.h"
using namespace std;
int i;
int n;
struct Node {
int data;
struct Node* left;
struct Node* right;
}
Node(int val)
{
data = val;
left = NULL;
right = NULL;
};
int main() {
//struct Node* root = new Node(1);
cout << "Enter values up to -999: \n";
int numbers[] = {};
for(int i =0; i!=999; i++){
cin >> numbers[i];
}
cout << "\nYour numbers are: ";
for(int j=0; j<=sizeof(numbers) ; j++){
cout << numbers[j] << " ";
}
return 0;
}

Here is a program that does what you want.
#include <iostream>
#include <vector>
// never, ever use using namespace std;
int main()
{
std::vector<int> input; // this is the way to spell "an array that can grow as needed"
// int numbers[] = {}; is not one.
int number;
while (std::cin >> number // check whether the input is successful, i.e. a number
// is entered. entering a non-number or an
// end-of-file indicator is a failure
&& number != -999) // and whether that number is not -999
{
input.push_back(number); // add it to the end of our growing-as-needed array
}
for (auto i : input) // that's how you enumerate entries in the array
{
std::cout << i << " ";
}
std::cout << "\n"; // print a newline when you are done
}
Live demo

Beside all other problems, the main problem is here:
for(int i =0; i!=999; i++){
cin >> numbers[i];
}
You are reading from the standard input into the i-th element of the array numbers. You are comparing i with 999, which basically makes no sense. Why comparing i? And why comparing it with 999, instead of -999?
Let's try to fix it. Start with an empty infinite loop:
while (true) {
// Read
// Check
// Use
}
Read an integer:
while (true) {
// Read
int val;
cin >> val;
// Check
// Use
}
Now let's check if we managed to read something and if not let's exit from the loop.
while (true) {
// Read
int val;
cin >> val;
// Check
if (cin.fail()) {
break;
}
// Use
}
We need to exit from the loop also if we read a -999:
while (true) {
// Read
int val;
cin >> val;
// Check
if (cin.fail()) {
break;
}
if (val == -999) {
break;
}
// Use
}
Now you want to put it in the i-th position of numbers, so:
int i = 0;
while (true) {
// Read
int val;
cin >> val;
// Check
if (cin.fail()) {
break;
}
if (val == -999) {
break;
}
// Use
numbers[i] = val;
++i;
}
Ok, now we have a working loop (hopefully). What other problems you have in your code?
int numbers[] = {};
j<=sizeof(numbers)
You cannot define arrays without a compile time size in C++. Use std::vector<>.
Then, the sizeof operator doesn't do what you think it does. Save it for (much?) later. Use std::vector::size(). But for starters, you can assume that 1000 numbers will be enough for everyone (Bill Gates docet), and keep the count in variable i:
#include <iostream>
using namespace std;
int main()
{
cout << "Enter values. Use -999 to stop entering values.\n";
int numbers[1000]; // We accept 1000 numbers at most 🤮
int i = 0;
while (true) {
// Read
int val;
cin >> val;
// Check
if (cin.fail()) {
break;
}
if (val == -999) {
break;
}
// Use
numbers[i] = val;
++i;
}
cout << "Your numbers are: ";
for (int j = 0; j < i; j++) {
cout << numbers[j] << " ";
}
cout << '\n';
return 0;
}
Switching to std::vector<> is much better. And learn Why is "using namespace std;" considered bad practice?:
#include <iostream>
#include <vector>
int main()
{
std::cout << "Enter values. Use -999 to stop entering values.\n";
std::vector<int> numbers;
while (true) {
// Read
int val;
std::cin >> val;
// Check
if (std::cin.fail()) {
break;
}
if (val == -999) {
break;
}
// Use
numbers.push_back(val);
}
std::cout << "Your numbers are: ";
for (int j = 0; j < numbers.size(); j++) {
std::cout << numbers[j] << " ";
}
std::cout << '\n';
return 0;
}
Finally, if you think that while(true) {} is ugly, you can use other versions of the same loop, e.g.:
for (int val; std::cin >> val && val != -999;) {
numbers.push_back(val);
}

Related

How to declare an array without size known at compile-time?

I am trying to implement random_function(), which outputs the amount of random numbers within a range (user input), and count_function() to count for the value that the user wants to look up in the outputted random numbers. I made the random numbers to be saved in an array called randomlist[] so that it can be used to count for the value from the outputted random numbers. However, I cannot declare an array without its fixed size in the header file and define its size in the count_function.cpp. So I cannot use randomlist[] in the count_function() without redefining it (which is meaningless...).
Is there a way to declare array without defining its size, in the header file?
Here is the source code:
header file:
#pragma once
using namespace std;
class Rand
{
public:
// Rand();
int range,min,max;
char key;
void Random_function();
void Count_function();
// randomlist[]; something like this, which that is not possible in c++
};
This is randomfunction.cpp:
#include <iostream>
#include "random_function.hpp"
using namespace std;
void Rand::Random_function()
{
beginning:
cout << "Enter amount of numbers to generate: ";
cin >> range;
if (range<=0 || cin.fail())
{
cout <<"Error! Please enter valid number and try again! "<<endl;
goto beginning;
}
else
{
reenter:
cout << "Enter minimum boundary: ";
cin >> min;
cout << "Enter maximum boundary: ";
cin >> max;
cout << "\n";
srand((unsigned)time(NULL));
if(max<min || cin.fail())
{
cout << "\nError! Please enter the valid value and try again! " << endl;
goto reenter;
}
else
{
int randomlist[range]; //I defined the size of the randomlist here but I want to use this outside of the random_fucntion() as well.
for(int i=0 ; i < range; i++)
{
randomlist[i] = min + (rand() % static_cast<int>(max - min + 1));
cout <<i+1<<". "<< randomlist[i] <<endl;
}
}
cout <<"\n"<< "Total random numbers generated: " << range<< endl;
cout <<"Do you want to continue? y/n"<<endl;
cin >> key;
if(key=='y')
{
Count_function();
cout <<"Do you want to restart? y/n"<<endl;
cin >> key;
if(key=='y')
{
goto beginning;
}
else
{
exit(0);
}
}
else
{
cout <<"Do you want to restart? y/n"<<endl;
cin >> key;
if(key=='y')
{
goto beginning;
}
else
{
exit(0);
}
}
}
}
void Rand::Count_function()
{
int n,count=0;
reenter2:
cout<<"Enter the value to count for: ";
cin>>n;
if(cin.fail())
{
cout<<"Please enter valid value to count for"<<endl;
goto reenter2;
}
else
{
for(int i=0 ; i <range; i++)
{
if(randomlist[i]==n)
{
count++;
}
}
}
cout <<"The number of '"<<n<<"'s in the given list is: "<< count <<endl;
}
main:
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <random>
#include "random_function.hpp"
using namespace std;
int main()
{
Rand call;
call.Random_function();
}
When you want to use an array, but the size cannot be known at compile-time, the generally accepted approach in C++ is to use a std::vector.

Simple Encryption program array

Building a simple program that multiplies the ASCII value of chars in a string by 3 to encrypt and then divide by 3 to decrypt. So far I got the encryption part down but whenever I enter what the encryption gave and try to decrypt it doesn't work. I think it has something to do with the buffer stream but I could be wrong if anyone could help.
#include<iostream>
using namespace std;
int main()
{
string message;
int charValue;
int counter;
int encrypt;
char choice;
char quit = 'N';
while (quit == 'N')
{
cout << "Enter E to encrypt or D to Decrypt\n";
cin >> choice;
toupper(choice);
cout << "Enter text no spaces: ";
cin >> message;
int messagelen = message.length();
string stringArray[255];
if (choice == 'E')
{
for (counter = 0; counter < messagelen; counter++) //*3 to ascii val
{
stringArray[counter] = message[counter] * 3;
}
for (counter = 0; counter < messagelen; counter++)
{
cout << stringArray[counter];
}
}
else
{
for (counter = 0; counter < messagelen; counter++) // divide 3 to ascii val
{
stringArray[counter] = message[counter] / 3;
}
for (counter = 0; counter < messagelen; counter++)
{
cout << stringArray[counter];
}
}
cout << "\nY to go again N to quit";
cin >> quit;
}
return 0;
}
This is a working implementation, although I agree with the other answer that you should use encrypt and decrypt functions. I found quite a few other bugs with your code working through it. You should enable all warnings with -Wall -Werror and fix them:
#include <iostream>
#include <vector>
#include <sstream>
int main()
{
// removed some unused variables
std::string message;
size_t counter;
char choice;
char quit;
// use vector of int instead of array of strings
std::vector<int> encryptArray;
// change to do while loop. Not particularly necessary, but I think
// it makes more sense in this case. Your condition is broken. If the
// user enters 'Y' at the end to go again, then the quit == 'N'
// condition is false and the program terminates.
do
{
std::cout << "Enter E to encrypt or D to Decrypt\n";
std::cin >> choice;
// toupper returns a value, you need to assign it to choice.
// Not capturing the return value makes this a noop.
choice = toupper(choice);
if (choice == 'E')
{
std::cout << "Enter text no spaces: ";
std::cin >> message;
size_t messagelen = message.length();
// initialize vector to input message length size
encryptArray = std::vector<int>(messagelen);
for (counter = 0; counter < messagelen; counter++) //*3 to ascii val
{
encryptArray[counter] = message[counter] * 3;
}
// Note, this 2nd loop is more work than you need, you could
// simply put the std::cout line in the loop above below the
// assignment
for (counter = 0; counter < messagelen; counter++)
{
// added the separator just for clarity. You could also print
// hex bytes
std::cout << encryptArray[counter] << "|";
}
}
else
{
// all the data we care about is in the vector now
for (counter = 0; counter < encryptArray.size(); counter++) // divide 3 to ascii val
{
// you don't want to /3 what's in the message here, you want
// to /3 the encrypted values, which are in the vector
encryptArray[counter] = encryptArray[counter] / 3;
}
// plenty of ways to convert the vector to a string, this is not
// a "modern" way.
// Note, you could skip this loop entirely, and in the one
// above, simply do ss << (char)(encryptArray[i] / 3);
// Not necessary to write the data back to encryptArray first.
std::stringstream ss;
for (size_t i=0; i<encryptArray.size(); ++i)
{
ss << (char)encryptArray[i];
}
std::cout << "decrypted string: " << ss.str() << std::endl;
}
std::cout << "\nY to go again N to quit: ";
std::cin >> quit;
} while(quit != 'N'); // loop until quit == N
return 0;
}
Finally, I removed using namespace std;, here's why
Things get squirrely working with stdin on godbolt, but here's a working demonstration, at least initially.
It would genuinely help you to break this down into smaller problems. Let's "encrypt" a std::string into a std::vector<int>:
std::vector<int> encrypt_msg(std::string s) {
std::vector<int> v;
for (auto ch = s.begin(); ch != s.end(); ch++) {
v.push_back(static_cast<int>(*ch) * 3);
}
return v;
}
Then let's "decrypt" a message, performing the transformation in reverse.
std::string decrypt_msg(std::vector<int> v) {
std::string s;
for (auto i : v) {
s += static_cast<char>(i / 3);
}
return s;
}
Now you can test and see that your individual functions that do one thing work, and putting together the overall program should be much easier.

I am getting debug error "abort() has been called"

So the problem is that when I run this code compiler ask me to enter value when I enter value and hit enter an error pop saying abort() has been called. Here is my code. how can I remove this error?
#include <iostream>
#include<string>
using namespace std;
class binary
{
private:
string num;
public:
void display();
void chkBin();
};
void binary::chkBin()
{
int x=0;
for (int i = 0; i <= num.length(); i++)
{
if (num.at(i) != '0' && num.at(i) != '1')
{
x = -1;
}
}
if (x==-1)
{
cout << "The number is not binary";
}
else if (x==1)
{
cout << "The number is binary";
}
}
void binary::display()
{
cout << "Enter a number"<<endl;
cin >> num;
}
int main()
{
binary b;
b.display();
b.chkBin();
return 0;
}
The loop condition i <= num.length() is what makes your program throw std::out_of_range (and then abort). That's because num[num.length()] is out of bounds. You can only access num[0] to num[num.length() - 1] (inclusive) so the loop condition should have been i < num.length().
Also, int x=0; should probably be int x=1; for it to be able to print The number is binary.
When you want to go through the whole range, you can (since C++11) use a range-based for loop instead which makes it easier to avoid mistakes like this.
Example:
void binary::chkBin()
{
for (auto ch : num) // a range-based for loop
{
if (ch != '0' && ch != '1')
{
std::cout << "The number is not binary\n";
return;
}
}
std::cout << "The number is binary\n";
}

how to keep storing users inputs in a while loop in c++

The user will enter a list of numbers. The user should enter as many numbers as the user wishes. All the numbers should be stored in a variable, I am not trying to add them all up.
#include <iostream>
using namespace std;
int main()
{
// declare variables
double number,listOfNumbers;
bool condition;
cout << "Enter a starting number: ";
cin >> number;
condition = true;
while (condition)
{
if(number > 0)
{
cout << "Enter another number (type 0 to quit): ";
listOfNumbers = number;
cin>>listOfNumbers;
}
else
{
condition=false;
}
}
cout << listOfNumbers;
return 0;
}
Use a std:vector to hold the numbers, eg:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
// declare variables
double number;
vector<double> listOfNumbers;
cout << "Enter numbers (type 0 to quit): ";
while ((cin >> number) && (number != 0))
{
listOfNumbers.push_back(number);
}
for(number : listOfNumbers)
cout << number << ' ';
return 0;
}
Some small modifications and the use of a std::listor std::vector to store the values, the vector will grow dynamicly as you run the program and relocate if it runs out of space, the list will allocate space for every new item both works here.
I also never use using namespace std although it is very common in tutorials to do.
The syntax auto const &i in last for loops requires some of the later C++ standards it will give you a unmutable reference to the item.
#include <iostream>
#include <list>
int main() {
// declare variables
double number;
std::list<double> listOfNumbers;
bool condition;
std::cout << "Enter a starting number: ";
std::cin >> number;
condition = true;
while (condition) {
if (number > 0) {
listOfNumbers.push_back(number);
std::cout << "Enter another number (type 0 to quit): ";
std::cin >> number;
} else {
condition = false;
}
}
for (auto const &i : listOfNumbers) {
std::cout << i << std::endl;
}
return 0;
}

How to cin values into a vector

I'm trying to ask the user to enter numbers that will be pushed into a vector,
then using a function call to count these numbers.
why is this not working? I'm only able to count the first number.
template <typename T>
void write_vector(const vector<T>& V)
{
cout << "The numbers in the vector are: " << endl;
for(int i=0; i < V.size(); i++)
cout << V[i] << " ";
}
int main()
{
int input;
vector<int> V;
cout << "Enter your numbers to be evaluated: " << endl;
cin >> input;
V.push_back(input);
write_vector(V);
return 0;
}
As is, you're only reading in a single integer and pushing it into your vector. Since you probably want to store several integers, you need a loop. E.g., replace
cin >> input;
V.push_back(input);
with
while (cin >> input)
V.push_back(input);
What this does is continually pull in ints from cin for as long as there is input to grab; the loop continues until cin finds EOF or tries to input a non-integer value. The alternative is to use a sentinel value, though this prevents you from actually inputting that value. Ex:
while ((cin >> input) && input != 9999)
V.push_back(input);
will read until you try to input 9999 (or any of the other states that render cin invalid), at which point the loop will terminate.
You need a loop for that. So do this:
while (cin >> input) //enter any non-integer to end the loop!
{
V.push_back(input);
}
Or use this idiomatic version:
#include <iterator> //for std::istream_iterator
std::istream_iterator<int> begin(std::cin), end;
std::vector<int> v(begin, end);
write_vector(v);
You could also improve your write_vector as:
#include <algorithm> //for std::copy
template <typename T>
void write_vector(const vector<T>& v)
{
cout << "The numbers in the vector are: " << endl;
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
}
Other answers would have you disallow a particular number, or tell the user to enter something non-numeric in order to terminate input. Perhaps a better solution is to use std::getline() to read a line of input, then use std::istringstream to read all of the numbers from that line into the vector.
#include <iostream>
#include <sstream>
#include <vector>
int main(int argc, char** argv) {
std::string line;
int number;
std::vector<int> numbers;
std::cout << "Enter numbers separated by spaces: ";
std::getline(std::cin, line);
std::istringstream stream(line);
while (stream >> number)
numbers.push_back(number);
write_vector(numbers);
}
Also, your write_vector() implementation can be replaced with a more idiomatic call to the std::copy() algorithm to copy the elements to an std::ostream_iterator to std::cout:
#include <algorithm>
#include <iterator>
template<class T>
void write_vector(const std::vector<T>& vector) {
std::cout << "Numbers you entered: ";
std::copy(vector.begin(), vector.end(),
std::ostream_iterator<T>(std::cout, " "));
std::cout << '\n';
}
You can also use std::copy() and a couple of handy iterators to get the values into the vector without an explicit loop:
std::copy(std::istream_iterator<int>(stream),
std::istream_iterator<int>(),
std::back_inserter(numbers));
But that’s probably overkill.
you have 2 options:
If you know the size of vector will be (in your case/example it's seems you know it):
vector<int> V(size)
for(int i =0;i<size;i++){
cin>>V[i];
}
if you don't and you can't get it in you'r program flow then:
int helper;
while(cin>>helper){
V.push_back(helper);
}
If you know the size of the vector you can do it like this:
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> v(n);
for (auto &it : v) {
cin >> it;
}
}
One-liner to read a fixed amount of numbers into a vector (C++11):
#include <algorithm>
#include <iterator>
#include <iostream>
#include <vector>
#include <cstddef>
int main()
{
const std::size_t LIMIT{5};
std::vector<int> collection;
std::generate_n(std::back_inserter(collection), LIMIT,
[]()
{
return *(std::istream_iterator<int>(std::cin));
}
);
return 0;
}
If you know the size use this
No temporary variable used just to store user input
int main()
{
cout << "Hello World!\n";
int n;//input size
cin >> n;
vector<int>a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
//to verify output user input printed below
for (auto x : a) {
cout << x << " ";
}
return 0;
}
You need a second integer.
int i,n;
vector<int> V;
cout << "Enter the amount of numbers you want to evaluate: ";
cin >> i;
cout << "Enter your numbers to be evaluated: " << endl;
while (V.size() < i && cin >> n){
V.push_back(n);
}
write_vector(V);
return 0;
You probably want to read in more numbers, not only one.
For this, you need a loop
int main()
{
int input = 0;
while(input != -1){
vector<int> V;
cout << "Enter your numbers to be evaluated: " << endl;
cin >> input;
V.push_back(input);
write_vector(V);
}
return 0;
}
Note, with this version, it is not possible to add the number -1 as it is the "end signal".
Type numbers as long as you like, it will be aborted when you type -1.
cin is delimited on space, so if you try to cin "1 2 3 4 5" into a single integer, your only going to be assigning 1 to the integer, a better option is to wrap your input and push_back in a loop, and have it test for a sentinel value, and on that sentinel value, call your write function. such as
int input;
cout << "Enter your numbers to be evaluated, and 10000 to quit: " << endl;
while(input != 10000) {
cin >> input;
V.push_back(input);
}
write_vector(V);
You can simply do this with the help of for loop
->Ask on runtime from a user (how many inputs he want to enter) and the treat same like arrays.
int main() {
int sizz,input;
std::vector<int> vc1;
cout<< "How many Numbers you want to enter : ";
cin >> sizz;
cout << "Input Data : " << endl;
for (int i = 0; i < sizz; i++) {//for taking input form the user
cin >> input;
vc1.push_back(input);
}
cout << "print data of vector : " << endl;
for (int i = 0; i < sizz; i++) {
cout << vc1[i] << endl;
}
}
#include<iostream>
#include<vector>
#include<string>
using namespace std;
int main()
{
vector<string>V;
int num;
cin>>num;
string input;
while (cin>>input && num != 0) //enter any non-integer to end the loop!
{
//cin>>input;
V.push_back(input);
num--;
if(num==0)
{
vector<string>::iterator it;
for(it=V.begin();it!=V.end();it++)
cout<<*it<<endl;
};
}
return 0;
};
#include<iostream>
#include<vector>
#include<sstream>
using namespace std;
int main()
{
vector<string> v;
string line,t;
getline(cin,line);
istringstream iss(line);
while(iss>>t)
v.push_back(t);
vector<string>::iterator it;
for(it=v.begin();it!=v.end();it++)
cout<<*it<<endl;
return 0;
}
In this case your while loop will look like
int i = 0;
int a = 0;
while (i < n){
cin >> a;
V.push_back(a);
++i;
}
The initial size() of V will be 0, while int n contains any random value because you don't initialize it.
V.size() < n is probably false.
Silly me missed the "Enter the amount of numbers you want to evaluate: "
If you enter a n that's smaller than V.size() at that time, the loop will terminate.
Just add another variable.
int temp;
while (cin >> temp && V.size() < n){
V.push_back(temp);
}
#include<bits/stdc++.h>
using namespace std;
int main()
{
int x,n;
cin>>x;
vector<int> v;
cout<<"Enter numbers:\n";
for(int i=0;i<x;i++)
{
cin>>n;
v.push_back(n);
}
//displaying vector contents
for(int p : v)
cout<<p<<" ";
}
A simple way to take input in vector.
These were two methods I tried. Both are fine to use.
int main() {
int size,temp;
cin>>size;
vector<int> ar(size);
//method 1
for(auto i=0;i<size;i++)
{ cin>>temp;
ar.insert(ar.begin()+i,temp);
}
for (auto i:ar)
cout <<i<<" ";
//method 2
for(int i=0;i<size;i++)
{
cin>>ar[i];
}
for (auto i:ar)
cout <<i<<" ";
return 0;
}
would be easier if you specify the size of vector by taking an input :
int main()
{
int input,n;
vector<int> V;
cout<<"Enter the number of inputs: ";
cin>>n;
cout << "Enter your numbers to be evaluated: " << endl;
for(int i=0;i<n;i++){
cin >> input;
V.push_back(input);
}
write_vector(V);
return 0;
}
I ran into a similar problem and this is how I did it. Using &modifying your code appropriately:
int main()
{
int input;
vector<int> V;
cout << "Enter your numbers to be evaluated: "
<< '\n' << "type "done" & keyboard Enter to stop entry"
<< '\n';
while ( (cin >> input) && input != "done") {
V.push_back(input);
}
write_vector(V);
return 0;
}
cout << "do you like to enter the sem 2 score "<<endl;
cin >> sem2;
if (sem2 == 'Y' || sem2 == 'y')
{
cout << "enter your subject count ";
cin >> subjectcount;
cout << " enter your scores :";
for (int i = 0; i < subjectcount; i++)
{
double ip;
cout << (i+1) << " st score ";
cin >> ip;
sem2score.push_back(ip);
}
}
You can extract numbers by this way:
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
int aux;
char c='\n';
char a;
while(scanf("%d", &aux))
{
cout<<aux<<endl;
if(scanf("%c",&a) && a==c)
break;
}
return 0;
}