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

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";
}

Related

Reading input in loop until sentinel value is reached in 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);
}

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.

C++ how to restart the loop if user just presses enter or if the input is invalid?

I'll start by saying I have worked on this for 3 days now and this is only my second semester programming. I know this question is probably easy for most, but I really have very little experience.
The code I have written all works as intended except the invalid/blank entry validation. Anything I have found and tried just breaks other parts of the code or doesn't work at all.
Here are the instructions given in the homework for the part I am having issues with:
"Any invalid input for the menu will simply redisplay the menu.
Option 1 will prompt for a userName. An empty name will be ignored."
Here is my code. Any help is greatly appreciated.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
vector<string> usernames;
void listMenu();
void addName();
void listNames();
void removeName();
int main()
{
char entry;
bool exit = false;
while (exit == false)
{
cout << "Choose from the following menu: \n";
listMenu();
cin >> entry;
if (entry == '\n')
{
listNames();
}
if (entry == '1')
{
addName();
}
else if (entry == '2')
{
listNames();
}
else if (entry == '3')
{
removeName();
}
else if (entry == 'x' || entry == 'X')
{
exit = true;
}
}
usernames.clear();
return 0;
}
void listMenu()
{
string menu[4] = { "1. Add a username","2. List all usernames","3. Delete a username","X. Exit" };
for (int i = 0; i < 4; i++) {
cout << menu[i] << endl;
}
}
void addName()
{
string name;
cout << "Enter a username: " << endl;
cin >> name;
usernames.push_back(name);
}
void listNames()
{
int n = 1;
cout << "**************\n";
for (auto& x : usernames)
{
cout << n <<". "<< x <<endl;
n++;
}
cout << "**************\n";
}
void removeName()
{
int x;
cout << "Which username would you like to remove?\n";
listNames;
cin >> x;
usernames.erase(usernames.begin()+x);
}
You can test your input and clear it if it's invalid. Using cin.fail, cin.clear and cin.ignore.
#include<iostream>
using namespace std;
bool cond;
int main() {
int n;
do {
cout << "Enter an integer number:";
cin >> n;
cond = cin.fail();
cin.clear();
cin.ignore(INT_MAX, '\n');
} while(cond);
return 0;
}

Error handling with c++

I need to do some error handling in c++ that corrects user input if it's a letter or a string. I need to use .at(), .length(), and atoi to handle this. I'm not sure how/where to implement those is the problem.
#include <iostream>
#include <stdlib.h>
#include <string>
#include <time.h>
using namespace std;
int main() {
srand(time(0));
int number;
number = rand() % 50 + 1;
int guess;
int x;
for (x = 5; x > 0; x--) {
cout << "Guess my number, it's between 0-50. You have 5 guesses: ";
cin >> guess;
if (guess < number){
cout << "Your guess was too low" << endl;
}
else if (guess > number){
cout << "You guess was too high" << endl;
}
else {
cout << "You're exactly right!" << endl;
break;
}
} while (guess != number){
break;
}
return 0;
}
The best approach to input validation is to write a function that reads into a std::string, checks whatever is needed, and only returns a value when it passes the tests:
int get_value() {
std::string input;
int value = -1;
while (value < 0) {
std::cout << "Gimme a value: ";
std::getline(std::cin, input);
try {
value = std::stoi(input);
} catch(...) {
value = -1;
}
}
return value;
}

Using variables declared inside an if else construct later in the program results in an undeclared identifier error

This program is pretty self explanatory, so I won't really get into the purpose of what its for.
My main problem right now is on lines 82, 89, 95, and 101, I'm getting "Undeclared Identifier" errors for "arr" and "input" when i compile.
Is this because I declared them inside of an if else if construct, and if so, is there any way to get around this. Thanks for any help in advance!!!!
Here is the code
#include <iostream>
#include <string>
using namespace std;
template<class T> void selectionSort(T arr[], T num)
{
int pos_min;
T temp;
for (int i = 0; i < num - 1; i++)
{
pos_min = i;
for (int j = i + 1; j < num; j++)
{
for (arr[j] < arr[pos_min])
{
pos_min = j;
}
}
if (pos_min != i)
{
temp = arr[i];
arr[i] = arr[pos_min];
arr[pos_min] = temp;
}
}
}
int main()
{
char check = 'C';
while (toupper(check) != 'Q')
{
char dataType;
int num = 0;
cout << "What kind of data do you want to sort?" << endl;
cout << " For integer enter i, for string enter s, for character enter c. ";
cin >> dataType;
//User input dataType
if (toupper(dataType) == 'I')
{
int arr[100];
int input;
cout << " You've chosen Integer dataType" << endl;
}
else if (toupper(dataType) == 'S')
{
string arr[100];
string input;
cout << " You've chosen String dataType" << endl;
}
else if(toupper(dataType) == 'C')
{
char arr[100];
char input;
cout << " You've chosen Character dataType" << endl;
}
else
{
cout << "Not a recognizable dataType. Shuting down..." << endl;
return -1;
}
//User input # of num
cout << "How many num will be sorted? ";
cin >> num;
for (int i = 0; i < num; i++)
{
cout << "Enter an input of the dataType you selected: ";
cin >> input;
arr[i] = input;
}
//Display user input
cout << "The data as you entered it: ";
for (int i = 0; i < num; i++)
{
cout << arr[i];
cout << " ";
}
cout << endl;
//Sort user input by calling template functon selectionSort
selectionSort(arr, num);
//Display sorted user input
cout << "After sorting your data by calling selectionSort: ";
for (int i = 0; i < num; i++)
{
cout << arr[i];
cout << " ";
}
cout << endl;
//Query user to quit or continue
cout << " Would you like to continue? Enter 'Q'. Enter anything else to continue.";
cin >> check;
}
return 0;
}
It is because you declared them inside an if/else block. Once the block completes, these variable go out of scope and are no longer accessible.
One way around this would be to always read in the input as character data, then convert it into the specified type after the fact. See atoi for how to convert from char to int.
A variable can never have unknown type. Even inside a template, the type of every variable is fixed for any particular instantiation.
Which suggests a solution. All the code that works on a variable with multiple types can be placed into a template function.
You may find the template syntax for passing an arbitrary length array of arbitrary element type useful:
template<typename T, size_t N>
void func1( T (&arr)[N] )
{
//...
}
But you really don't even need to pass the array. Just pass a type, and use that type when creating the array inside the function.
template<typename T>
void process_it()
{
T arr[100];
T input;
// now work on them
}
Either way, you'll need to call this function from inside all the if/else branches, where the exact type is known.