Why is my "while" condition not being met? - c++

I have been running this and typing "12+" as the expression. When it gets to the while loop it gets stuck as if the condition is never met. I dont see why this is because right before the while loop "it" is equal to 2 so the loop should not even be used.
//array based stack implementation
class Stack
{
private:
int capacity; //max size of stack
int top; //index for top element
char *listArray; //array holding stack elements
public:
Stack (int size = 50){ //constructor
capacity = size;
top = 0;
listArray = new char[size];
}
~Stack() { delete [] listArray; } //destructor
void push(char it) { //Put "it" on stack
listArray[top++] = it;
}
char pop() { //pop top element
return listArray [--top];
}
char& topValue() const { //return top element
return listArray[top-1];
}
char& nextValue() const {//return second to top element
return listArray[top-2];
}
int length() const { return top; } //return length
};
int main()
{
string exp;
char it = ' ';
int count;
int push_length;
cout << "Enter an expression in postfix notation:\n";
cin >> exp;
cout << "The number of characters in your expression is " << exp.length() << ".\n";
Stack STK;
for(count= 0; count < exp.length() ;count++)
{
if (exp[count] == '+')
{
it = exp[count - 1];
cout << it << "\n";
while (it != 1 || it != 2 || it != 3 || it != 4 || it != 5 || it != 6 || it != 7 || it != 8 || it != 9 || it != 0)
{
cout << it << "\n";
it = exp[count--];
}
STK.push(it);
//cout << STK.topValue() << "\n";
it = exp[count --];
if (it == 1 || it == 2 || it == 3 || it == 4 || it == 5 || it == 6 || it == 7 || it == 8 || it == 9 || it == 0){
STK.push(it);
cout << it;
}
cout << STK.topValue() << "\n";
it = STK.topValue() + STK.nextValue();
STK.pop();
STK.pop();
STK.push(it);
cout << STK.topValue() << "\n";
}
}
cout << "The number of characters pushed into the stack is " << STK.length() << ".\n";
push_length = STK.length();
return(0);
}

As you mention, your while clause is always true.
while (it != 1 || it != 2 || it != 3 || it != 4 || it != 5 || it != 6 || it != 7 || it != 8 || it != 9 || it != 0)
it will always not be some of those numbers.
You could change every || to && in that statement, since that is likely what you meant.
And change 1 to '1', 2 to '2', and so on...
A clearer approach would be:
while ( !std::isdigit(it) )
http://en.cppreference.com/w/cpp/string/byte/isdigit

Related

Why aren't the words getting calculated properly in C++?

I was creating the program for my friend who is interested in numerology and wants a way to calculate the value of words faster. But even though there are no errors and/or warnings, but the words' values aren't being calculated correctly. For example, "mark" has a value of 9, but the program shows 2. If you can figure out what the problem is, then pls help me. Thank you so much!
My Code:
#include <iostream>
#include <string>
int value{0};
void clear();
int main(void)
{
int number{0};
std::string response;
bool run = true;
while (run)
{
clear();
value = 0;
number = 1;
response = "";
std::cout << "How many words to evalute?:\n> ";
std::cin >> number;
std::cin.ignore();
clear();
std::string* pPhrase = new std::string[number];
int* pValue = new int[number];
for (int i = 0; i < number; ++i) // could replace "number" with "sizeof(pPhrase)/sizeof(pPhrase[0])"
{
std::cout << "Enter Word #" << i+1 << " (or type your full phrase):\n> ";
std::cin >> pPhrase[i];
for (char j : pPhrase[i])
{
value = 0;
j = std::tolower(j);
if (j == 'a' || j == 'i' || j == 'j'
|| j == 'q' || j == 'y')
value += 1;
if (j == 'b' || j == 'k' || j == 'r')
value += 2;
if (j == 'c' || j == 'g' || j == 'l'
|| j == 's')
value += 3;
if (j == 'd' || j == 'm' || j == 't')
value += 4;
if (j == 'e' || j == 'h' || j == 'n'
|| j == 'x')
value += 5;
if (j == 'u' || j == 'v' || j == 'w')
value += 6;
if (j == 'o' || j == 'z')
value += 7;
if (j == 'f' || j == 'p')
value += 8;
pValue[i] = value;
value = 0;
std::cout << '\n';
clear();
}
}
std::cin.ignore();
std::cin.clear();
std::cout << "\n\n";
for (int i = 0; i < number; ++i)
std::cout << "Value of \"" << pPhrase[i] << "\": " << pValue[i] << '\n';
//std::cin.ignore();
std::cin.clear();
std::cout << "Would you like to evaluate another phrase? (Y/n):\n> ";
std::getline(std::cin, response);
delete[] pPhrase;
delete[] pValue;
if (response[0] == 'y' || response[0] == 'Y'
|| response.empty() || response[0] == ' ')
{
std::cout << "\n\n";
continue;
}
break;
}
std::cout << "Exiting...";
system("killall Terminal");
std::cout << "\n\n\n";
return 0;
}
void clear()
{
system("clear");
}
You could make your program run faster by using a lookup table:
static const int table[26] = {
/* a */ 1, /* b */ 2, /* c */ 3, /* d */ 4, /* e */ 5,
/* f */ 8, /* g */ 3, /* h */ 5, /* i */ 1, /* j */ 1,
/* k */ 2, /* l */ 3, /* m */ 4, /* n */ 5, /* o */ 7,
/* p */ 8, /* q */ 1, /* r */ 2, /* s */ 3, /* t */ 4,
/* u */ 6, /* v */ 6, /* w */ 6, /* x */ 5, /* y */ 1,
/* z */ 7,
};
// ...
if (isalpha(j))
{
const int table_index = j - 'a';
const letter_value = table[table_index];
pValue[i] = letter_value;
//...
}
Print the assembly language for your code fragment, then print the assembly language for the above code fragment. Compare.
Look at all the places where you set value to zero. You do it before main() begins (which is not very useful, actually). Then, bizarrely, you set value to zero at both the start and end of your inner for loop, which means that all the value += statements in that for loop might as well be value = statements. You keep value from accumulating value.
How to solve this? First, get rid of all the value = 0 statements inside your inner for loop. Second, add int value = 0; before the inner for loop, like this:
int value = 0;
for (char j : pPhrase[i])
{
// ...
}
At this point, you might as well get rid of int value{0}; above main(). That step isn't absolutely necessary, but that declaration of value is totally unneeded.
Also, DO NOT put system("killall Terminal"); in your sample code. It's very unfriendly, since it kills the very command line on which you want others to run your sample code.
(In general, using system() at all is a bad idea, since it's unportable.)
There are several issues. The main issue is that on line 70, pValue[i] = value; is incorrectly positioned inside the for loop.
Here is a fixed version:
#include <iostream>
#include <string>
using namespace std;
int value{0};
void clear();
int main() {
int number{0};
string response;
while (true) {
clear();
value = 0;
number = 1;
response = "";
cout << "How many words to evaluate?:\n> ";
cin >> number;
cin.ignore();
clear();
auto *pPhrase = new string[number]{};
int *pValue = new int[number]{};
for (int i = 0; i < number; ++i) // could replace "number" with "sizeof(pPhrase)/sizeof(pPhrase[0])"
{
cout << "Enter Word #" << i + 1 << " (or type your full phrase):\n> ";
cin >> pPhrase[i];
for (char j: pPhrase[i]) {
j = tolower(j);
if (j == 'a' || j == 'i' || j == 'j'
|| j == 'q' || j == 'y')
value += 1;
if (j == 'b' || j == 'k' || j == 'r')
value += 2;
if (j == 'c' || j == 'g' || j == 'l'
|| j == 's')
value += 3;
if (j == 'd' || j == 'm' || j == 't')
value += 4;
if (j == 'e' || j == 'h' || j == 'n'
|| j == 'x')
value += 5;
if (j == 'u' || j == 'v' || j == 'w')
value += 6;
if (j == 'o' || j == 'z')
value += 7;
if (j == 'f' || j == 'p')
value += 8;
cout << '\n';
clear();
}
pValue[i] = value;
value = 0;
}
cin.ignore();
cin.clear();
cout << "\n\n";
for (int i = 0; i < number; ++i)
cout << "Value of \"" << pPhrase[i] << "\": " << pValue[i] << '\n';
cin.clear();
cout << "Would you like to evaluate another phrase? (Y/n):\n> ";
getline(cin, response);
delete[] pPhrase;
delete[] pValue;
if (response[0] == 'y' || response[0] == 'Y'
|| response.empty() || response[0] == ' ') {
cout << "\n\n";
continue;
}
break;
}
cout << "Exiting...";
system("killall Terminal");
cout << "\n\n\n";
return 0;
}
void clear() {
system("clear");
}

Why I am not getting desired output for my c++ problem

I am solving a question which states: to change every '?' with 'a' in a string if doesn't contain if won't form consecutive 'a' else substitute with 'b', eg. a?b will be abb and not aab because here 2 a's are consecutive.
My problem is for i = 3 my string should be over- written with 'b ' according to my code it is entering into the desired block but the string does n't gets written with b, but in all the other case where it should be witten with 'a' it get's written .Help me out with these.
You can refer the problem statement from here to for better understanding my problem :https://www.hackerearth.com/practice/algorithms/greedy/basics-of-greedy-algorithms/practice-problems/algorithm/exploring-ruins/
#include <iostream>
using namespace std;
int main() {
string str;
cin >> str;
int n = str.size();
for(int i = 0; i < str.size(); i++) {
if(str[i] == '?') {
if(i == 0) {
if(str[i + 1] == 'a')
str[i] = 'b';
else
str[i] = 'a';
cout << "I am in if" << endl;
} else if(i == n - 1) {
if(str[i - 1] == 'a')
str[i] == 'b';
else
str[i] == 'a';
cout << "I am in if of else if " << endl;
} else {
if(str[i + 1] == 'a' || str[i - 1] == 'a') {
str[i] == 'b';
cout << "I am in if of else " << endl;
} else {
str[i] = 'a';
cout << "I am in else of else " << endl;
}
}
cout << str[i] << endl;
} else
continue;
}
cout << str << endl;
return 0;
}
Given string : ?ba??b
desired output : ababab
my output : aba?ab
It will be a lot easier for you if you would use functions to solve this problem.
bool check_neighbors_for_a(const string &str, size_t place) {
bool result = false;
if (place > 0) { // If there is a char before the current char
result = str[place - 1] == 'a'; // If the previous char is 'a' result become true
}
if (place < str.size() - 1) { // If there is a char after the current char
result = result || str[place + 1] == 'a'; // If the result has become true before this line, result will stay true. Else, result will be true if the next char is equal to 'a'.
// For example: b?a => result = (false || 'a' == 'a')
// For example: a?b => result = (true || 'b' == 'a')
// For example: a?a => result = (true || 'a' == 'a')
}
return result;
}
void replace_questions_by_a(string &str) {
for (size_t i = 0; i < str.size(); i++) {
if (str[i] == '?') {
if (check_neighbors_for_a(str, i)) { // If one of the neighbors is equal to 'a'
str[i] = 'b'; // Place 'b' instead of '?'
} else {
str[i] = 'a'; // Place 'a' instead of '?'
}
}
}
}

Check if a string contains a valid postfix expression

I have a string that needs to be check for a valid postfix expression.
A valid postfix string is 1 2 + but not 1 2+ since each character needs a space. Also, since it's a string, you can enter words, but they should return -1 for this function.
I have tried using vector array with strings and checking for valid ints, but when the user enters letters this obviously creates a problem.
string postfix = "1 2 +"; // valid
string postfix = "soemthing"; // error
string postfix = "1 2+" ; // error since there is no space.
if (!isdigit(postfix[0]))
return -1;
int t;
string line = "55 124 4 5";
std::vector <int> ints;
std::istringstream iss ( line, std::istringstream::in);
int main() {
while (iss >> t )
{
ints.push_back(t);
}
if (!digit(ints[0]) || !digit(ints[0]))
return -1;
}
~
From this post you can get the algorithm to check. In c++:
int isValid(string postfix) {
int l = postfix.size();
char c;
bool numStarted = false;
int counter = 0;
for (int i = 0; i < l; i++) {
c = postfix.at(i);
if (numStarted == true && c == ' ') {
numStarted = false;
} else if (numStarted == false && c == ' ') {
return -1;
} else if (c == '-' || c == '+' || c == '*' || c == '/') {
if (counter < 2 || numStarted) {
return -1;
}
counter--;
numStarted = true;
} else if (!isdigit(c)) {
return -1;
} else if (!numStarted && isdigit(c)) {
counter++;
numStarted = true;
}
}
return (counter == 1 ? 1 : -1);
}
To test this:
int main(int argc, char** argv) {
string postfix1 = "1 2 +"; // valid
string postfix2 = "soemthing"; // error
string postfix3 = "1 2+"; // error since there is no space.
cout << isValid(postfix1) << endl;
cout << isValid(postfix2) << endl;
cout << isValid(postfix3) << endl;
return 0;
}
output:
1
-1
-1

Array access results in a null pointer dereference

I have the following for each loop which compares several guids with each other.
stringc flanking_id = *flanking_it;
if (abzug) {
if (AppFrame::isValidPointer(&flanking_id)) {
if (AppFrame::isValidPointer(&abzug->guid)) {
if (flanking_id.size() > 0 && abzug->guid.size() > 0) {
if (flanking_id.size() >= abzug->guid.size()) {
if (flanking_id.equalsn(abzug->guid, abzug->guid.size())) {
return bauteil;
}
}
}
}
}
}
abzug-guid is an core::stringw which is an Irrlicht-Engine datatype.
isValidPointer calls a method which is containing the following two lines
BOOL result = somePointer != 0 && somePointer != NULL && somePointer != nullptr && somePointer != nil;
return result;
So it shouldn't be possible, that one of my guids is broken. But Xcode says there is a possible null pointer dereference in this line.
if (flanking_id.equalsn(abzug->guid, abzug->guid.size())) {
This is the warning...
Array access (via field 'array') results in a null pointer dereference (within a call to 'equalsn')
How to solve this hint?
EDIT: equalsn() from irrString.h by Irrlicht-Engine
bool equalsn(const string<T,TAlloc>& other, u32 n) const
{
u32 i;
for(i=0; i < n && array[i] && other[i]; ++i)
if (array[i] != other[i])
return false;
// if one (or both) of the strings was smaller then they
// are only equal if they have the same length
return (i == n) || (used == other.used);
}
Example on Ideone.com
int * p1 = 0;
int p2 = *p1;
cout << "&p2 != 0: " << (&p2 != 0) << endl;
cout << "*p1 = 1 : " << flush;
*p1 = 1;
cout << "ok" << endl;
Output:
Runtime error time: 0 memory: 3096 signal:11
&p2 != 0: 1
*p1 = 1 :
So, the check for valid pointer after the last one was dereferenced is useless. It should be
if (abzug) {
if (AppFrame::isValidPointer(flanking_it)) {
stringc flanking_id = *flanking_it;
//...
Concerning warning, I'm not sure what Xcode dislikes, but I suspect this lines
for(i=0; i < n && array[i] && other[i]; ++i) // line 1
if (array[i] != other[i]) // line 2
There is should be check in line 1 that index i is less then size of array. In case of n greater than source string length there will be error.
BTW, instead of 7 enclosed if-statements you can use
if (!abzug ||
!AppFrame::isValidPointer(&flanking_id) ||
!AppFrame::isValidPointer(&abzug->guid) ||
... {
return ...;
}
if (flanking_id.equalsn(abzug->guid, abzug->guid.size())) {
return bauteil;
}
Or if a return statement can not be used then
do {
if (!abzug ||
!AppFrame::isValidPointer(&flanking_id) ||
!AppFrame::isValidPointer(&abzug->guid) ||
... {
break;
}
if (flanking_id.equalsn(abzug->guid, abzug->guid.size())) {
return bauteil;
}
} while (0);

Post fix calculator, returns wrong value

I'm Writing a program to implement postfix calculator, its giving me completely wrong answers.
Really appreciate the help
class stacks {
public:
typedef int List;
static const int size = 100;
stacks() {
use = 0;
}
void push(List entry) {
data[use] = entry;
++use;
}
List pop() {
if(!empty()) {
--use;
return data[use];
}
}
bool empty() const {
return use == 0;
}
int Size() const {
return use;
}
private:
List data[size];
int use;
};
int main() {
stacks s;
string input;
int final;
ifstream infile("foo.txt",ios::in);
while (getline(infile, input))
cout << "Expression: ";
for (int i = 0; i<input.length(); i++) {
cout << input[i];
auto oper1 = s.pop();
auto oper2 = s.pop();
if(input[i] == '1' || input[i] == '2' || input[i] == '3' || input[i] == '4' || nput[i] == '5' || input[i] == '6' || input[i] == '7' || input[i] == '8' || input[i] == '9')
s.push(input[i] - '0');
if(input[i] == '+')
s.push(oper1 + oper2);
if(input[i] == '-')
s.push(oper1 - oper2);
if(input[i] == '*')
s.push(oper1 * oper2);
if(input[i] == '/')
s.push(oper1 / oper2);
}
final = s.pop();
cout << endl << "Value = " << final << "." << endl << endl;
}
What do you recommend?
Thanks
You need to wait to pop() until you know you have an operator. You're popping stuff off the stack when you shouldn't be.