throwing an instance with no reason - c++

I have a hard time to debbug this program.
The purpose of the program is to covert a string in a following way.
aaabccddd → abccddd → abddd → abd
Delete the two adjacent element, if they are the same alphabet.
Keep doing this several times, until got a result that cant do it anymore.
If the result dont have any alphabet print out Empty String.
I face a serious problem, my program throwing an instant of 'std::length_error'.
And i check my code. I cant problem in it. Can someone please tell me what happened,
and how to fix it.
This is code:
#include <iostream>
#include <string>
using namespace std;
int main(){
string data;
cin >> data;
for(int i = 0; i < data.size() - 1; i++){
if(data[i] == data[i+1]){
data.erase(data.begin()+i, data.begin()+i+2);
i = -1;
}
}
if(data.size() == 0){
cout << "Empty String";
}else{
cout << data;
}
return 0;
}
There are some imformation about the program.
This is input:
aa
This is execution result:
aa
terminate called after throwing an instance of 'std::length_error'
what(): basic_string::_S_create
--------------------------------
Process exited after 94.29 seconds with return value 3
but sometimes the program can run successfully and
This is input:
aaabccddd
This is execution result:
aaabccddd
abd
--------------------------------
Process exited after 11.27 seconds with return value 0
I dont know what happened. Can someone give me some advice?

When you want to iterate over a container and want to erase something inside the loop, use the following pattern:
for (auto i = container.begin(); i != container.end();) {
if (...some condition...) {
// erase:
i = container.erase(i);
} else {
// keep:
++i;
}
}
The erase() function will return a valid iterator to the item after the range you just deleted.
You do need to use proper iterators for this to work. So in your case, your code should look like:
#include <iostream>
#include <string>
using namespace std;
int main() {
string data;
cin >> data;
for (auto i = data.begin(); i < data.end() - 1;) {
if (i[0] == i[1]) {
i = data.erase(i, i + 2);
} else {
++i;
}
}
if (data.empty()) {
cout << "Empty String\n";
} else {
cout << data << "\n";
}
return 0;
}

Related

Displaying results as soon as they are ready with std::async

I'm trying to discover asynchronous programming in C++. Here's a toy example I've been using:
#include <iostream>
#include <future>
#include <vector>
#include <chrono>
#include <thread>
#include <random>
// For simplicity
using namespace std;
int called_from_async(int m, int n)
{
this_thread::sleep_for(chrono::milliseconds(rand() % 1000));
return m * n;
}
void test()
{
int m = 12;
int n = 42;
vector<future<int>> results;
for(int i = 0; i < 10; i++)
{
for(int j = 0; j < 10; j++)
{
results.push_back(async(launch::async, called_from_async, i, j));
}
}
for(auto& f : results)
{
cout << f.get() << endl;
}
}
Now, the example is not really interesting, but it raises a question that is, to me, interesting. Let's say I want to display results as they "arrive" (I don't know what will be ready first, since the delay is random), how should I do it?
What I'm doing here is obviously wrong, since I wait for all the tasks in the order in which I created them - so I'll wait for the first to finish even if it's longer than the others.
I thought about the following idea: for each future, using wait_for on a small time and if it's ready, display the value. But I feel weird doing that:
while (any_of(results.begin(), results.end(), [](const future<int>& f){
return f.wait_for(chrono::seconds(0)) != future_status::ready;
}))
{
cout << "Loop" << endl;
for(auto& f : results)
{
auto result = f.wait_for(std::chrono::milliseconds(20));
if (result == future_status::ready)
cout << f.get() << endl;
}
}
This brings another issue: we'd call get several times on some futures, which is illegal:
terminate called after throwing an instance of 'std::future_error' what(): std::future_error: No associated state
So I don't really know what to do here, please suggest!
Use valid() to skip the futures for which you have already called get().
bool all_ready;
do {
all_ready = true;
for(auto& f : results) {
if (f.valid()) {
auto result = f.wait_for(std::chrono::milliseconds(20));
if (result == future_status::ready) {
cout << f.get() << endl;
}
else {
all_ready = false;
}
}
}
}
while (!all_ready);

Segmentation fault while returning from function in c++

I using stringstream for parsing string, however it is unexpectedly giving segmentation fault while exiting from function.
bool check_if_condition(int a)
{
string polygonString1="19.922379 51.666267 19.922381 51.665595 19.921547 51.665705 19.921218 51.665753 19.920787 51.665815 19.919753 51.665960 19.919952 51.666897 19.920395 51.666826 19.920532 51.667150 19.920830 51.667748 19.920989 51.667905 19.921690 51.667906 19.922141 51.662866 19.922855 51.668696 19.922664 51.668237 19.922610 51.668025 19.922464 51.667451 19.922355 51.666732 19.922379 51.666267";
double buf1; // Have a buffer string
stringstream ssPolygonString1(polygonString1); // Insert the string into a stream
double polygon1[2]; // Create vector to hold our words
int iterPoly1=0;
while (ssPolygonString1 >> buf1)
{
polygon1[iterPoly1]=(buf1);
cout<<"buf1="<<buf1<<"\n";
iterPoly1++;
}
ssPolygonString1.str("");
cout<<"Return true";
return true;
}
main()
{
check_if_condition(1);
}
Can someone please help me understand what is wrong with the function call?
I am using c++11
I ran it on https://www.tutorialspoint.com/compile_cpp11_online.php, it is giving me Bus error (core dumped)
I assume when you say double polygon1[2] you want to create a vector by your comment.
If you use a vector your code will work.
Also when you use a vector make sure you use vector.push_back();
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
using namespace std;
bool check_if_condition(int a)
{
string polygonString1 = "19.922379 51.666267 19.922381 51.665595 19.921547 51.665705 19.921218 51.665753 19.920787 51.665815 19.919753 51.665960 19.919952 51.666897 19.920395 51.666826 19.920532 51.667150 19.920830 51.667748 19.920989 51.667905 19.921690 51.667906 19.922141 51.662866 19.922855 51.668696 19.922664 51.668237 19.922610 51.668025 19.922464 51.667451 19.922355 51.666732 19.922379 51.666267";
double buf1; // Have a buffer string
stringstream ssPolygonString1(polygonString1); // Insert the string into a stream
vector<double> polygon1; // Create vector to hold our words
int iterPoly1 = 0;
while (ssPolygonString1 >> buf1)
{
//polygon1[iterPoly1] = (buf1);
polygon1.push_back(buf1); // Add buf1 to vector.
cout << "buf1=" << buf1 << "\n";
iterPoly1++;
}
ssPolygonString1.str("");
//Print vector to show it works!
for (int i = 0; i < polygon1.size(); i++)
{
cout << polygon1.at(i) << endl;
}
cout << "Return true";
return true;
}
int main()
{
check_if_condition(1);
system("pause");
return 0;
}
The error is in the line:
polygon1[iterPoly1]=(buf1);
because the length of vector is 2 and iterPoly is going above 2. So behaviour is unexpected.

How can I trace back the error

I was assigned to create an array check (to see if the array is increasing, decreasing, or neither [then exiting if neither]) and a recursive binary search for one of my assignments. I was able to do these things after some help from my peers, but I need help in finding what seems to be causing the error
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_S_construct null not valid
Aborted
when running the code. I Googled this error and this error seems to be vague or I just am not understanding. It compiles without errors, but I need help in what finding what I did wrong. It is able to run without the binarySearchR function and its associating code, as the array check on its own was the previous assignment. Below is the code, and I thank you so much in advance!
#include <iosteam>
#include <string>
#include <cstdlib>
#include <fstream>
using namespace std;
int checkArraySort (string *fileLines, int numberOfLines);
int binarySearchR (string *fileLines, string searchKey, int iMin, int iMax);
int main ()
{
int numberOfLines = 0;
string searchKey = 0;
cout << "Input search key: ";
cin >> searchKey;
ifstream fileIn;
fileIn.open("words_in.txt");
string line;
if (fileIn.eof()) /* Checks file to see if it is blank before proceeding */
{
exit (EXIT_SUCCESS);
}
else
{
while(!(fileIn.eof()))
{
fileIn >> line;
numberOfLines++;
}
fileIn.close(); /* closes fileIn, need to reopen to reset the line location */
fileIn.open("words_in.txt");
string *fileInLines;
fileInLines = new string[numberOfLines];
for (int i = 0; i < numberOfLines; i++)
{
fileIn >> line;
fileInLines[i] = line;
}
fileIn.close(); /* closes fileIn */
int resultingCheck = checkArraySort(fileInLines, numberOfLines);
if (resultingCheck == -1)
{
cout << "The array is sorted in descending order." << endl;
}
else if (resultingCheck == 1)
{
cout << "The array is sorted in ascending order." << endl;
}
else
{
cerr << "ERROR: Array not sorted!" << endl;
exit (EXIT_FAILURE);
}
int searchResult = binarySearchR (fileInLines, searchKey, 0, numberOfLines);
if (!searchResult == -1)
{
cout << "Key found at index " << searchResult << "." << endl;
}
else
{
cout << "Key not found at any index." << endl;
}
exit (EXIT_SUCCESS);
}
}
int checkArraySort (string *fileLines, int numberOfLines)
{
int result = 1; /* Ascending by default */
for (int i = 1; i < numberOfLines; i++) /* Checks if decending */
{
if (fileLines[i] < fileLines[i-1])
{
result = -1;
}
}
if (result == -1) /* Makes sure it is descending (or if it is neither) */
{
for (int i = 1; i < numberOfLines; i++)
{
if (fileLines[i] > fileLines[i-1])
{
result = 0;
}
}
}
return result;
}
int binarySearchR (string *fileLines, string searchKey, int iMin, int iMax)
{
// so, its gotta look at the center value and each times, it discards half of the remaining list.
if (iMax < iMin) /* If the minimum is greater than the maximum */
{
return -1;
}
else
{
int iMid = (iMin + iMax) / 2;
if (fileLines[iMid] > searchKey) /* If the key is in the lower subset */
{
return binarySearchR (fileLines, searchKey, iMin, iMid - 1);
}
else if (fileLines[iMid] < searchKey) /*If the key is in the upper subset */
{
return binarySearchR (fileLines, searchKey, iMin, iMid + 1);
}
else /*If anything else besides the two */
{
return iMid;
}
}
}
The easy way: add a bunch of cout s to see where you program goes and what the values are.
Pros
Easy to do
Cons
Requires a recompile each time you want to add more info
The hard way: Learn to use a debugger
Pros
Can inspect "on the fly"
Don't need to rebuild
Can use what you learn in every other C++ program
Cons
Requires a bit of research to learn how to do it.

exceptions and return statements in c++

I am new in c++ programming and i am trying to understand exceptions in c++. I made a simple model situation that shows things, which I don't understand(I hope, I wont mess up code too much). I made 2 basic classes with few methods(classes CPerson are basically linked list). My answer is how to stop current task with an exception. I am able to call an exception, but task continues and makes some mess in program.
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
using namespace std;
class CPerson{
public:
CPerson(){
p_next_person = NULL;
}
CPerson* p_next_person; // pointer to next person in linked list
int Postcode(); // returns postcode of person
friend ostream& operator<<(ostream& stream, const CPerson& pers){
cout << pers.ID << pers.postcode;
return stream;
}
char* ID;
int postcode;
};
//---------------------------------------------------------------
class CPeople{
public:
CPeople(){
first_person = NULL;
}
CPerson Person( const char* personID); // finds person by ID and returns it
bool NewPerson( const char* personID, int person_postcode); // add new person
CPerson* first_person ; // start of linked list
};
//-----------------------------------------------------------------
int CPerson::Postcode(){
return postcode;
}
//-----------------------------------------------------------------
CPerson CPeople::Person( const char* personID){
CPerson* now;
now = first_person;
while(now != NULL){
if(strcmp(now->ID,personID)==0){
break;
}
now = now->p_next_person;
}
// our person is in now (or now is NULL - if person wasn't found).
try{
if(now == NULL ){
throw 0;
// I need to stop code here
}else return *now;
}
catch (int e)
{
cout << "bla bla " << e << '\n';
}
}
//----------------------------------------------------------
int main(){
CPeople people;
int i = 0;
people.NewPerson( "JAck", 100 );
people.NewPerson( "Josh", 100 );
// Bob is not in people right now.
i = people.Person("BOB").Postcode();
cout << i;
// gives exception, which is nice. but it also changes i to some nonsence .. how do I fix it ?
cout << people.Person ( "BOB" );
// gives exception, which is nice. but also gives segmentation fault. how do I fix it ?
}
You have got the try block around 'throw. The try block should be around where you called the function and it should be caught with a catch. Thus your function will change to:
CPerson CPeople::Person( const char* personID){
CPerson* now;
now = first_person;
while(now != NULL){
if(strcmp(now->ID,personID)==0){
break;
}
now = now->p_next_person;
}
// our person is in now (or now is NULL - if person wasn't found).
if (now == NULL ){
throw 0;
// I need to stop code here
}
else return *now;
}
and main will look like:
int main(){
try {
CPeople people;
int i = 0;
people.NewPerson( "JAck", 100 );
people.NewPerson( "Josh", 100 );
// Bob is not in people right now.
i = people.Person("BOB").Postcode();
cout << i;
// gives exception, which is nice. but it also changes i to some nonsence .. how do I fix it ?
cout << people.Person ( "BOB" );
// gives exception, which is nice. but also gives segmentation fault. how do I fix it ?
}
catch (int e)
{
cout << "bla bla " << e << '\n';
}
}
Notice that once a catch is encountered, the following statement after the catch will be executed. That is why you should have catch out of the function definition.
Code like this
try{
if( now == NULL ){
throw 0;
// I need to stop code here
} else return *now;
} catch (int e) {
cout << "bla bla " << e << '\n';
}
entirely misses the point. Continuing execution with a shrug ("bla bla") as if nothing had happened isn't possible. Either you make sure that all contingencies are met in the catch, or you should catch the exception at a higher level. Here: there is no definition of the function's return value, which causes trouble up there where you call CPeople::Person.
You can surround these calls with a try - catch; omit them in the function and just throw.
Don't throw 0. Use an object capable of holding some information. Throw by value, catch by reference.

C++, using stack.h read a string, then display it in reverse

For my current assignment, I have to use the following header file,
#ifndef STACK_H
#define STACK_H
template <class T, int n>
class STACK
{
private:
T a[n];
int counter;
public:
void MakeStack() {
counter = 0;
}
bool FullStack() {
return (counter == n) ? true : false ;
}
bool EmptyStack() {
return (counter == 0) ? true : false ;
}
void PushStack(T x) {
a[counter] = x;
counter++;
}
T PopStack() {
counter--;
return a[counter];
}
};
#endif
To write a program that will take a sentence, store it into the "stack", and then display it in reverse, and I have to allow the user to repeat this process as much as they want. The thing is, I am NOT allowed to use arrays (otherwise I wouldn't need help with this), and am finding myself stumped.
To give an idea of what I am attempting, here is my code as of posting, which obviously does not work fully but is simply meant to give an idea of the assignment.
#include <iostream>
#include <cstring>
#include <ctime>
#include "STACK.h"
using namespace std;
int main(void)
{
auto time_t a;
auto STACK<char, 256> s;
auto string curStr;
auto int i;
// Displays the current time and date
time(&a);
cout << "Today is " << ctime(&a) << endl;
s.MakeStack();
cin >> curStr;
i = 0;
do
{
s.PushStack(curStr[i]);
i++;
} while (s.FullStack() == false);
do
{
cout << s.PopStack();
} while (s.EmptyStack() == false);
return 0;
} // end of "main"
UPDATE
This is my code currently
#include <iostream>
#include <string>
#include <ctime>
#include "STACK.h"
using namespace std;
time_t a;
STACK<char, 256> s;
string curStr;
int i;
int n;
// Displays the current time and date
time(&a);
cout << "Today is " << ctime(&a) << endl;
s.MakeStack();
getline(cin, curStr);
i = 0;
n = curStr.size();
do
{
s.PushStack(curStr[i++]);
i++;
}while(i < n);
do
{
cout << s.PopStack();
}while( !(s.EmptyStack()) );
return 0;
You're on the right track, but you shouldn't be looping until the stack is full -- there are no guarantees curStr consists of at least 256 characters. Instead, loop like as follows...
int n = curStr.size();
do {
s.PushStack(curStr[i++]);
} while (i < n);
Now, you should really not write <bool-expr> == false or <bool-expr> == true... instead, merely write !<bool-expr> and <bool-expr>, respectively. You don't need all of your auto storage specifiers on the local variables, either. Your professor should also look into using the constructor rather than using MakeStack.
edit: It appears you had some trouble translating my code. You only need to i++ once per loop -- this increments our position in the string. As you are doing it now, you are actually incrementing the position twice and thus only pushing every other character.
Use a linked list instead of array in stack.
In the linked list, always store the tail pointer of your list's last node. Each node maintains a reference to your prev node.
A <--- B <---- C (tail)
push:
A <--- B <---- C <---- D (tail)
pop:
A <--- B <---- C (tail)
// D is popped out
when the tail == null, you know it is an empty stack