How to break out of a nested loop? - c++

Is there any way to break this without if/else conditionals for each layer?
#include <iostream>
using namespace std;
int main()
{
for (int i = 0; i < 20; i++)
{
while (true)
{
while (true)
{
break; break; break;
}
}
}
cout << "END";
return 0;
}

You can wrap the logic in a function or lambda.
Instead of break; break; break; (which won't work) you can return;.
#include <iostream>
using namespace std;
int main()
{
auto nested_loops = []
{
for (int i = 0; i < 20; i++)
{
while (true)
{
while (true)
{
// Done with all the looping
return;
}
}
}
};
nested_loops();
cout << "END";
return 0;
}
Or (same effect, different style)
#include <iostream>
using namespace std;
int main()
{
[] {
for (int i = 0; i < 20; i++)
{
while (true)
{
while (true)
{
// Done with all the looping
return;
}
}
}
} ();
cout << "END";
return 0;
}

If you want to break individual loop, then you can use break in their respect loop.
Putting too many or single break within a loop, will only break that loop that it is within it.
#include <iostream>
using namespace std;
int main()
{
[] {
for (int i = 0; i < 20; i++)
{
while (true)
{
while (true)
{
break;
}
break;
}
break;
}
} ();
cout << "END";
return 0;
}

In order to break out of a nested loop, you can use the goto statement.
#include <iostream>
using namespace std;
int main()
{
for (int i = 0; i < 20; i++)
{
while (true)
{
while (true)
{
goto break_outer_loop;
}
}
}
break_outer_loop:
cout << "END";
return 0;
}
Note that goto should generally be avoided. However, for breaking out of a nested loop, it is generally considered acceptable.

Related

Struct doesn't print with cout

I'm trying to print the structure in an array whose int prejetih member is highest.
#include <iostream>
using namespace std;
struct Tekma {
int prejetih;
};
Tekma najvec_kosev(Tekma tekme[]) {
int maksi = 0, index = 0;
for (int i = 0;i < 2;i++) {
if (maksi < tekme[i].prejetih) {
index = i;
maksi = tekme[i].prejetih;
}
}
return tekme[index];
}
void vpis(Tekma tekme[]) {
for (int i = 0;i < 2;i++)
cin >> tekme[i].prejetih;
}
int main() {
Tekma tekme[2];
vpis(tekme);
cout << najvec_kosev(tekme);
}
The compiler reports
C++ no operator matches these operands
operand types are: std::ostream << Tekma
over cout << najvec_kosev(tekme);
Here using a solution with std::vector and fixing your cout problem:
#include <iostream>
#include <vector>
using namespace std;
struct Tekma {
int prejetih;
};
Tekma najvec_kosev(vector<Tekma>& tekme) {
Tekma lowest = tekme[0]
for(auto& t : tekme) {
if(lowest.prejetih < t.prejetih) {
lowest = t;
}
}
return lowest ;
}
void vpis(vector<Tekma>& tekme) {
int input;
while(true) {
cin >> input;
// Check if the input is valid else quit the loop.
if(input == valid) {
Tekma newStruct = {input};
tekme.push(newStruct);
}
else {
// Stop the loop
break;
}
}
}
int main() {
vector<Tekma> tekme;
vpis(tekme);
cout << najvec_kosev(tekme).prejetih; // This fixes your error.
}

Postfix calculation with stack class, C++

I am trying to use a custom stack class to calculate an equation in postfix form. For some reason, the program keeps crashing.
Here is the stack header file
#ifndef aStack_h
#define aStack_h
#include <string>
#include <iostream>
using std::string; using std::cout;
class aStack
{
private:
int top, size;
int *stack;
public:
aStack(int s)
{
size = s;
top = -1;
stack = new int [s];
}
~aStack()
{
delete [] stack;
}
void reset();
void push(int);
void pop();
int getTop();
void getSize()
{
std::cout << size;
}
};
#endif
The class implementation file:
#include "aStack.h"
#include <iostream>
using namespace std;
void aStack::pop()
{
if (top == -1)
{ cout << "Stack is already empty.\n";}
stack[--top];
}
void aStack::push(int v)
{
if (top == size)
{ cout << "Stack is full.\n";}
stack[top++] = v;
}
void aStack::reset()
{
top = -1;
}
int aStack::getTop()
{
return top;
}
Here is the main program
#include <iostream>
#include "aStack.h"
#include <string>
using namespace std;
int main()
{
string equation {"35+1*"};
int op, count = 0, *oparray, result;
aStack stack(equation.length());
for (int i = 0; i < equation.length(); i++)
{
if (isdigit(equation[i]))
{
stack.push(equation[i]);
count++;
}
else
{
oparray = new int [count];
for (int o = 0; o < count; o++)
{
oparray[o] = stack.getTop();
stack.pop();
}
switch(equation[i])
{
case '+':
for (int i =0; i < count; i++)
{
op += oparray[i];
count--;
}
stack.push(op);
break;
case '-':
for (int i =0; i < count; i++)
{
op-=oparray[i];
count--;
}
stack.push(op);
break;
case '*':
for (int i =0; i < count; i++)
{
op*=oparray[i];
count--;
}
stack.push(op);
break;
case '/':
for (int i =0; i < count; i++)
{
op/=oparray[i];
count--;
}
stack.push(op);
break;
}
delete [] oparray;
}
}
result = stack.getTop();
cout << result;
}
I know I should not use the "using namespace std;", I was in a hurry. I doubt that would be the cause of my problems. Any help is greatly appreciated.
Your stack class has miscellaneous problems already pointed out in the comments. With those fixed, only a few bugs in the main program remained.
I've used a std::unique_ptr<> in your array instead of a raw pointer and disabled move semantics so it's neither copyable (because of the unique_ptr) nor moveable.
I also added throwing exceptions if you try to access the stack out of bounds.
#include <cctype>
#include <cstddef>
#include <exception>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <utility>
template<typename T>
class aStack {
public:
using value_type = T;
explicit aStack(size_t c) :
cap(c), stored(0), stack(std::make_unique<value_type[]>(cap)) {}
aStack(aStack&&) = delete; // moving disabled
void reset() noexcept { stored = 0; }
void push(const value_type& v) {
if(stored == cap) throw std::runtime_error("stack is full");
stack[stored++] = v;
}
void push(value_type&& v) {
if(stored == cap) throw std::runtime_error("stack is full");
stack[stored++] = std::move(v);
}
value_type& pop() {
if(stored == 0) throw std::runtime_error("stack is empty");
return stack[--stored];
}
[[nodiscard]] const value_type& top() const {
if(stored == 0) throw std::runtime_error("stack is empty");
return stack[stored - 1];
}
[[nodiscard]] value_type& top() {
if(stored == 0) throw std::runtime_error("stack is empty");
return stack[stored - 1];
}
[[nodiscard]] size_t capability() const noexcept { return cap; }
[[nodiscard]] size_t size() const noexcept { return stored; }
private:
size_t cap, stored;
std::unique_ptr<value_type[]> stack;
};
When it comes to the main program, the major problem was that you forgot to convert the ASCII value of each digit into an integer.
Another problem was the op calculation. You kept the value from the last iteration instead of grabbing a new value from the stack. There was also an extra allocation of memory that was unnecessary so I removed that. You also had shadowing variables, which didn't cause any error, but makes it really hard to read the code.
int main(int argc, char* argv[]) {
if(argc < 2) {
std::cout << "USAGE: " << argv[0] << " <equation>\n";
return 1;
}
std::string equation(argv[1]);
try {
int op, result;
aStack<int> stack(equation.length());
for(size_t ei = 0; ei < equation.length(); ++ei) {
if(std::isdigit(equation[ei])) {
stack.push(equation[ei] - '0'); // from ASCII to digit
} else {
op = stack.pop(); // start with what's on the stack
switch(equation[ei]) {
case '+':
while(stack.size()) {
op += stack.pop();
}
stack.push(op);
break;
case '-':
while(stack.size()) {
op -= stack.pop();
}
stack.push(op);
break;
case '*':
while(stack.size()) {
op *= stack.pop();
}
stack.push(op);
break;
case '/':
while(stack.size()) {
op /= stack.pop();
}
stack.push(op);
break;
default:
throw std::runtime_error("invalid operation");
}
}
}
result = stack.pop();
if(stack.size() != 0)
throw std::runtime_error("stack not empty when calculation ended");
std::cout << result << '\n';
} catch(const std::exception& ex) {
std::cerr << "Exception: " << ex.what() << '\n';
}
}

Why does my RLE code show std out of range for c++?

Whenever I try to run this program, it always shows me the error message
terminate called after throwing an instance of 'std::out_of_range'
What I figured out, when I try to take input as a string then this problem happens. Hence, my loops do not get executed properly.
I really appreciate if anyone can explain me what's wrong with my code!
#include <iostream>
#include <vector>
#include <stdexcept>
#include <string>
using namespace std;
int main()
{
vector<string> compressed_run_lengths_data;
vector<char> compressed_characters_data;
int i;
int count = 1;
bool can_be_compressed = false;
string data;
try
{
cout << "Enter the data to be compressed: ";
getline(cin, data);
for (i = 0; i < data.size(); ++i)
{
if (!isalpha(data.at(i)))
{
throw runtime_error("error: invalid input");
}
}
if (!data.empty())
{
i = 1;
while (i <= data.size())
{
if (data.at(i - 1) == data.at(i))
{
count++;
if (count > 1)
{
can_be_compressed = true;
}
}
else
{
compressed_characters_data.push_back(data.at(i - 1));
compressed_run_lengths_data.push_back(to_string(count));
count = 1;
}
++i;
}
if (can_be_compressed)
{
for (i = 0; i < compressed_run_lengths_data.size(); ++i)
{
cout << compressed_run_lengths_data.at(i) << compressed_characters_data.at(i);
}
}
else
{
data;
}
}
}
catch (runtime_error &e)
{
cout << e.what();
return 1;
}
return 0;
}
As requested, an elaboration on my comments:
while (i <= data.size()) // <- i runs up to and including data.size ()
{
if (data.at(i - 1) == data.at(i)) // data.at (i) is out of range when i == data.size ()
I have not analysed your algorithm, but you probably want:
while (i < data.size())
instead.

Remove only one element to make a string palindrome

I will be given string. I can remove only 1 element from it. After removing it if the new string becomes palindrome I have to print "Yes" otherwise "No".
For example, I am given a string "abdbca". Here I can remove 5th index 'c' and make it palindrome and i have to print "Yes". On the other hand if the string is something like "abcd" I can not make it palindrome by removing only one character. Hence I have to print "No".
I tried to do it but my code is not efficient enough. Can anybody please suggest me a efficient way to do it? I have to check strings of 10^5 length in less than 2.5 seconds.
the way I tried to do it is shown bellow :
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#define REP(i,n) for(int i=0;i<n;i++)
#define MAX 100010
using namespace std;
bool isPalindrome(char abc[]){
int len = strlen(abc), lem = len/2;
for(int i=0,n=len-1;i<=lem;i++,n--) if(abc[i]!=abc[n]) return false;
return true;
}
int main()
{
int tc;
char str[MAX];
scanf("%d",&tc);
while(tc--){
scanf("%s", str);
int length = strlen(str), len = length - 1, z = length % 2, res = 0, ans = 0, b=0,lem = length / 2;
for(int i = 0;i<length;i++){
int n=0, m=1;
for(int x = 0, y = len;x<i && y!=i;x++,y--){
n++;
if(str[x]!=str[y]){
m=0; ++res;
break;
}
}
if(i>lem) for(int x=n,y=len-n-1;x<y;x++,y--){
if(str[x]!=str[y]){
m=0; ++res;
break;
}
}
else for(int x=n+1,y=len-n;x<y;x++,y--){
if(str[x]!=str[y]){
m=0; ++res;
break;
}
}
if(m==1) {printf("YES\n");b++;break;}
}
//if(length <= res) printf("NO\n");
if(b==0) printf("NO\n");
}
return 0;
}
Since you you only need to remove one character, you can do so in linear time by modifying palindrome checking. The idea is that you compare characters from the beginning to characters from the end and stop at the first mismatch. If you remove one character from the mismatching pair and get a palindrome, then return true, otherwise return false. I implemented the idea in C++ below.
#include<iostream>
#include<string>
using namespace std;
bool palindromeExists(string s)
{
int i = 0;
int j = s.length()-1;
while(i < j)
{
if(s[i] != s[j]) //first mismatch
break;
i++;
j--;
}
int tempj = j-1; //remove s[j]
int tempi = i;
while(tempi < tempj)
{
if(s[tempi] != s[tempj])
break;
tempi++;
tempj--;
}
if(tempi >= tempj) //palindrome found?
return true;
tempi = i+1; //remove s[i]
tempj = j;
while(tempi < tempj)
{
if(s[tempi] != s[tempj])
return false;
tempi++;
tempj--;
}
return true;
}
int main()
{
string s = "abca";
if(palindromeExists(s))
cout << "YES" << endl;
else
cout << "NO" << endl;
return 0;
}
This should return true if the string is already a palindrome, or if it can be a palindrome after the removal of one character. I hope I didn't miss any corner cases.
You can refer complete program in c++ here. Input the string to get the index of character to be removed. String reversal is performed in palim() function. It returns -1 if string is already palindrome.
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
bool palim(string s)
{
string s2;
s2=string(s.rbegin(),s.rend());
if(s2==s)
{
return true;
}
else
{
return false;
}
}
int check(string s)
{
int x;
if(s.length()%2==0)
{
for(int i=0,j=s.length()-1;i<s.length()/2,j>=s.length()/2;i++,j--)
{
if(s[i]!=s[j])
{
string s1=s;
s1.erase(j,1);
if(palim(s1))
{
x=j;
break;
}
else
{
string s1=s;
s1.erase(i,1);
if(palim(s1))
{
x=i;
break;
}
}
}
}
}
else
{
for(int i=0,j=s.length()-1;i<s.length()/2,j>s.length()/2;i++,j--)
{
if(s[i]!=s[j])
{
string s1=s;
s1.erase(j,1);
if(palim(s1))
{
x=j;
break;
}
else
{
string s1=s;
s1.erase(i,1);
if(palim(s1))
{
x=i;
break;
}
}
}
}
}
return x;
}
int main()
{
string s;
cin>>s;
if(palim(s))
{
cout<<"-1"<<endl;
}
else
{
cout<<check(s)<<endl;
}
return 0;
}
Similar to turingcomplete, but with sub functions:
bool isPalindrome(std::string::const_iterator& start, std::string::const_iterator& end)
{
while (start < end) {
--end;
if (*start != *end) {
return false;
}
++start;
}
return true;
}
bool test(const std::string& s)
{
auto start = s.begin();
auto end = s.end();
if (isPalindrome(start, end)) {
// If we remove the middle character of a palindrome,
// We still have a palindrome.
return true;
}
// Now test if there is a palindrome
// if we skip the mismatch char from the start or from the end.
auto start2 = start;
auto end2 = end;
++start2;
--end;
return isPalindrome(start, end) || isPalindrome(start2, end2);
}
Live example

How to alphabetically sort strings?

I have been trying to use this c++ program to sort 5 names alphabetically:
#include <iostream>
#include <cstring>
#include <conio.h>
using namespace std;
int main()
{
char names[5][100];
int x,y,z;
char exchange[100];
cout << "Enter five names...\n";
for(x=1;x<=5;x++)
{
cout << x << ". ";
cin >> names[x-1];
}
getch();
for(x=0;x<=5-2;x++)
{
for(y=0;y<=5-2;y++)
{
for(z=0;z<=99;z++)
{
if(int(names[y][z])>int(names[y+1][z]))
{
strcpy(exchange,names[y]);
strcpy(names[y],names[y+1]);
strcpy(names[y+1],exchange);
break;
}
}
}
}
for(x=0;x<=5-1;x++)
cout << names[x];
return 0;
}
If I enter Earl, Don, Chris, Bill, and Andy respectively, I get this:
AndyEarlDonChrisBill
Could someone please tell me whats wrong with my program?
You could use std::set or std::multiset (if you will allow repeated items) of strings, and it will keep the items sorted automatically (you could even change the sorting criteria if you want).
#include <iostream>
#include <set>
#include <algorithm>
void print(const std::string& item)
{
std::cout << item << std::endl;
}
int main()
{
std::set<std::string> sortedItems;
for(int i = 1; i <= 5; ++i)
{
std::string name;
std::cout << i << ". ";
std::cin >> name;
sortedItems.insert(name);
}
std::for_each(sortedItems.begin(), sortedItems.end(), &print);
return 0;
}
input:
Gerardo
Carlos
Kamilo
Angel
Bosco
output:
Angel
Bosco
Carlos
Gerardo
Kamilo
You can use the sort function:
#include <algorithm>
#include <vector>
using namespace std;
...
vector<string> s;
sort(s.begin(),s.end());
You are using too much unnecessary loops. Try this simple and efficient one. You need to just swap when a string is alphabetically latter than other string.
Input
5
Ashadullah
Shawon
Shakib
Aaaakash
Ideone
Output
Aaaakash
Ashadullah
Ideone
Shakib
Shawon
#include <bits/stdc++.h>
using namespace std;
int main()
{
string s[200],x[200],ct,dt;
int i,j,n;
cin>>n;
for(i=0;i<n;i++)
{
cin>>s[i];
}
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(s[i]>s[j])
{
ct=s[i];
s[i]=s[j];
s[j]=ct;
}
}
}
cout<<"Sorted Name in Dictionary Order"<<endl;
for(i=0;i<n;i++)
{
cout<<s[i]<<endl;
}
return 0;
}
Your code implements a single-pass of bubble sort. Essentially missing the 'repeat until no changes are made to the array' loop around the outside.
The code does not take care when the names are already in order. Add the following
else if(int(names[y][z])<int(names[y+1][z]))
break;
To the if statement.
Putting this here in case someone needs a different solution.
/* sorting example */
#include <iostream>
using namespace std;
bool isSwap( string str1, string str2, int i)
{
if(str1[i] > str2[i])
return true;
if(str1[i] == str2[i])
return isSwap(str1,str2,i+1);
return false;
}
int main()
{
string str[7] = {"you","your","must","mike", "jack", "jesus","god"};
int strlen = 7;
string temp;
int i = 0;
int j = 0;
bool changed = false;
while(i < strlen-1)
{
changed = false;
j = i+1;
while(j < strlen)
{
if(isSwap(str[i],str[j],0))
{
temp = str[i];
str[i] = str[j];
str[j] = temp;
changed = true;
}
j++;
}
if(changed)
i = 0;
else
i++;
}
for(i = 0; i < strlen; i++)
cout << str[i] << endl;
return 0;
}