C++ Bug fixing: Hawaiian Pronunciation Program - c++

I am writing a C++ program that will show you how to pronounce a Hawaiian word.
Rules:
p, k, h, l, m, n (Pronounced like the english versions.)
w -start of word (Either pronounced as a w or a v sound. We shall pronounce it as a w sound.)
w -after the letter ‘a’ (Either pronounced as a w or a v sound. We shall pronounce it as a w sound.)
w -after ‘i’ or ‘e’ (Pronounced as a v sound.)
w -after ‘u’ or o (Pronounced as a w sound.)
My progress: My program works, but there's a couple of bugs.
When I type "iwa", the pronunciation must be "ee-vah" but I'm
getting "ee-wah".
My code is not ignoring whitespaces. So when I type "e komo mai", I want "eh koh-moh meye" but instead, I get "e komo mai is pronounced eh-eh-koh-moh-oh-meye".
Here is my code:
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
string convertToHawaiian(string input);
bool vowelGroup(char first, char next, string& replacement);
bool consonantGroup(char prevchar, char currchar, string& replacement);
bool singleVowel(char current, string& replacement);
int main() {
// Declare my variables
string userInput;
string replacement;
//cout << "Enter a hawaiian word to pronounce ==>";
getline(cin,userInput);
// For loop that will call my Consonant function
// Call my Hawaiian function and put it
// into pronunciation
replacement = convertToHawaiian(userInput);
// if My initial input has a capital, the replacement
// will keep the capital letter at the beginning
if (isupper(userInput.at(0))) {
replacement.at(0) = toupper(replacement.at(0));
}
// Get rid of the '-' character at the end of the string
if (replacement.at(replacement.size() - 1) == '-') {
replacement.pop_back();
}
cout << userInput << " is pronounced " << replacement << endl;
return 0;
}
// My main function that will convert my input
// into the hawaiian pronunciation
string convertToHawaiian(string input) {
char nextChar;
string replacement = "";
string result = "";
// Iterate through my string to check for vowels,
// vowelgroups and consonants.
for (unsigned int i = 0; i < input.size(); i++) {
char character = input.at(i);
character = tolower(character);
if (i != input.size() - 1) {
nextChar = input.at(i + 1);
nextChar = tolower(nextChar);
}
if ((i != input.size() - 1) && (vowelGroup(character, nextChar, replacement))) {
i++;
result = result + replacement;
}
else if (singleVowel(character, replacement)) {
result = result + replacement;
}
else {
consonantGroup(character, nextChar, replacement);
result = result + replacement;
}
}
return result;
}
bool vowelGroup (char first, char nextChar, string& result) {
bool isVowel = true;
if (first == 'a') {
nextChar = tolower(nextChar);
if ((nextChar == 'i') || (nextChar == 'e')) {
result = "eye-";
}
else if ((nextChar == 'o') || (nextChar == 'u')) {
result = "ow-";
}
else {
return false;
}
}
else if (first == 'e') {
nextChar = tolower(nextChar);
if (nextChar == 'i') {
result = "ay-";
}
else if (nextChar == 'u') {
result = "eh-oo-";
}
else {
return false;
}
}
else if (first == 'i') {
nextChar = tolower(nextChar);
if (nextChar == 'u') {
result = "ew-";
}
else {
return false;
}
}
else if (first == 'o') {
nextChar = tolower(nextChar);
if (nextChar == 'i') {
result = "oy-";
}
else if (nextChar == 'u') {
result = "ow-";
}
else {
return false;
}
}
else if (first == 'u') {
nextChar = tolower(nextChar);
if (nextChar == 'i') {
result = "ooey-";
}
else {
return false;
}
}
else {
isVowel = false;
return isVowel;
}
return isVowel;
}
// Check to verify consonants
bool consonantGroup(char character, char nextChar, string& replacement) {
bool isConson = true;
if ((character == 'p') || (character == 'k') || (character == 'h') || (character == 'l') || (character == 'm') || (character == 'n')){
replacement = character;
return isConson;
}
if ((character == 'w') && (nextChar == 'a')) {
replacement = 'w';
return isConson;
}
else if (((character == 'u') || (character == 'o')) && (nextChar == 'w')) {
replacement = 'w';
cout << "Not replacing w" << endl;
return isConson;
}
else if (((character == 'i') || (character == 'e')) && (nextChar == 'w')) {
replacement = 'v';
return isConson;
}
else {
isConson = false;
return isConson;
}
}
bool singleVowel(char current, string& result) {
bool isVowel = true;
if (current == 'a') {
result = "ah-";
return isVowel;
}
else if (current == 'e') {
result = "eh-";
return isVowel;
}
else if (current == 'i') {
result = "ee-";
return isVowel;
}
else if (current == 'o') {
result = "oh-";
return isVowel;
}
else if (current == 'u') {
result = "oo-";
return isVowel;
}
else {
isVowel = false;
return isVowel;
}
}

One of the more common sources of bugs is shared mutable state.
In your case, it is state shared between loop iterations.
The whitespace case is handled here:
else {
consonantGroup(character, nextChar, replacement);
result = result + replacement;
}
and in that case, replacement will be string "spilled over" from the previous iteration.
The remedy is very simple: declare replacement inside the loop instead.
You can solve the "iwa" problem if you stare at these lines until you spot the bug:
if ((character == 'w') && (nextChar == 'a')) {
replacement = 'w';

Related

Unexpected answer for a simple stack problem in C++

class Solution {
public:
bool isValid(string s) {
map<char , char> m;
m[')'] = '(';
m['}'] = '{';
m[']'] = '[';
stack<char> st;
if(s[0] != '(' || s[0] != '{' || s[0] != '[')
return "false";
for(int i = 0; i<s.length(); i++)
{
if(s[i] == '(' || s[i]== '{' || s[i]== '[')
{
st.push(s[i]);
}
else if(st.top() == m[s[i]])
{
st.pop();
}
else if(st.top() != m[s[i]])
{
return "false";
}
}
if(st.empty())
return "true";
else
return "false";
}
};
The code fails for a basic example such as "(]". I don't understand how this is possible.
( first goes in the stack
( is not the map for ]
So it should return "false". But it returns true.
Regarding your expression:
(s[0] != '(' || s[0] != '{' || s[0] != '[')
For a start, unless s[0] is some weird quantum variable that can be three things at once, that expression will never be false. Think about some possibilities:
Character != '(' != '{' != '[' || all
--------- ------ ------ ------ ------
( false true true true
{ true false true true
[ true true false true
x true true true true
As you can see, every character will have that expression evaluating as true. You probably should be using && rather than ||.
In addition, you return a C-style string from your function which, being a non-zero pointer, will translate to true in a boolean context, as evidenced by:
#include <iostream>
bool returnT() { return "true"; }
bool returnF() { return "false"; }
int main() {
std::cout << returnT() << '\n';
std::cout << returnF() << '\n';
}
which outputs:
1
1
So I would be more inclined to start with something like this:
class Solution {
public:
bool isValid(string s) {
stack<char> st;
map<char, char> m;
m[')'] = '('; m['}'] = '{'; m[']'] = '[';
if (s[0] != '(' && s[0] != '{' && s[0] != '[') {
return false;
}
for (int i = 0; i < s.length(); ++i) {
if (s[i] == '(' || s[i]== '{' || s[i]== '[') {
st.push(s[i]);
} else if (st.top() == m[s[i]]) {
st.pop();
} else if (st.top() != m[s[i]]) {
return false;
}
}
return st.empty();
}
};
But do watch out for one thing. If your valid input characters are limited to the six brackets, you should be okay.
But if you want to allow for other characters that don't affect the stack, such as with:
[14^{6+(2x3)}]
then your code will not work because the first 1 character will be considered a mismatch. To handle that, you'll need to modify it to take them into account.
For example:
for (int i = 0; i < s.length(); ++i) {
if (s[i] == '(' || s[i]== '{' || s[i]== '[') {
// Handle open brackets: store.
st.push(s[i]);
} else if (s[i] == ')' || s[i]== '}' || s[i]== ']') {
// Handle close brackets: check.
if (st.top() == m[s[i]]) {
st.pop();
} else {
return false;
}
}
// Anything else is just a "noise" character, ignore.
}
Apparently, a ')' must be close to '(' in ascii code.
class Solution {
public:
bool isValid(string s) {
stack<char> st; st.push('\0');
for (auto c : s) {
if (isalpha(c)) continue;
else if (c - st.top() <= 3 && c - st.top() > 0)
st.pop();
else
st.push(c);
}
return st.size() == 1;
}
};
int main() {
Solution solu;
cout << solu.isValid("[](){}") << endl;
cout << solu.isValid(")(") << endl;
}

How to fix runtime error in Shunting Yard algorithm

I have implemented Shunting yard algorithm using stack in c++.
Well it is working quite well on inputs from SPOJ example inputs but when I input:
1
(((a+b) * (c+r)^(t+b)-n)^(c-(d * e))-b)+(c+(e-(d^r)))
I get a runtime error.
Note: I only get a runtime error when I call infixToPostfix() and use the above input and not when I comment it out.
Submission to SPOJ and running on ideone(with input above) results in a runtime error.
I really can't understand this behaviour of my program, so any help is welcomed.
I have tried some random inputs and it seems to work fine on them.
Even though they had spaces around operators.
#include<iostream>
#include<vector>
#include<math.h>
#include<stack>
#include<strings.h>
using namespace std;
void infixToPostfix(string st);
int pr(char s);
int main() {
int t;
scanf("%d",&t);
cin.ignore();
string st; // input string
while(t--)
{
getline(cin,st);
cin.sync();
cout<<st<<endl;
infixToPostfix(st);
}
return 0;
}
int pr(char s) // to check precedence
{
if(s == '^')
{
return 4;
}
else if(s == '*')
{
return 3;
}
else if(s == '/')
{
return 3;
}
else if(s == '+')
{
return 2;
}
else if(s == '-')
{
return 2;
}
else {
return 0;
}
}
void infixToPostfix(string st)
{
stack<char>op; //stack to hold operators and bracket
st += 'n';
int l = st.size();
op.push('0');
string fst; //final string
for(int x = 0;x<l;x++)
{
if(st[x] == '(')
{
op.push(st[x]);
}
else if(st[x] == ')')
{
while(op.top() != '(' && !op.empty())
{
fst +=op.top();
op.pop();
}
op.pop();
}
else if(st[x] == '+' || st[x] == '-' || st[x] == '*' ||st[x] == '/' ||st[x] == '^')
{
if(pr(st[x]) <= pr(op.top()))
{
fst += op.top();
op.pop();
op.push(st[x]);
}
else{
op.push(st[x]);
}
}
else if(st[x] == 'n'){
while(op.size() != 0)
{
if(op.top() != '0')
{fst += op.top();}
op.pop();
}
}
else if((st[x] >= 'a' || st[x] <= 'z' )&& st[x] != ' ')
{
fst += st[x];
}
}
printf("%s\n",fst.c_str());
}

Input operator Polynomial

I am trying to create an input operator for a Polynomial class. However, my input operator is not reading my first coefficients and everything after the first exponent. It is basically reading the first term without coefficients. Here is my code:
std::istream & operator>> (std::istream & in,
Polynomial & aPoly)
{
double tempCoefficient; // temporary storage for coefficient
char ch; // variable that contains results from peek()
char dum; // removes useless symbols like '+' and 'x'
int tempExponent; // contains current exponent for coefficient
bool moreTerms = true; // variable that tells when the terms run out
bool negativeCoefficient = false; // tells when coefficient is negative
aPoly.coefficients.resize(0); // Clears aPoly before inserting user input
in >> ch ;
if (ch == '-')
{
negativeCoefficient = true;
ch = in.peek();
}
else
{
in.putback(ch);
}
if (ch >= '0' && ch <= '9')
{
in >> tempCoefficient;
if (negativeCoefficient)
{
tempCoefficient *= -1;
negativeCoefficient = false;
}
ch = in.peek();
}
if (ch == 'x')
{
tempCoefficient = 1.0;
in >> dum;
if (in.peek() == '^')
{
in >> dum;
in >> tempExponent;
}
else
{
tempExponent = 1;
}
}
else
{
tempExponent = 0;
moreTerms = false;
}
aPoly.coefficients.resize(tempExponent + 1);
aPoly.coefficients[tempExponent] = tempCoefficient;
if ((in.peek() != '+') || (in.peek() != '-'))
{
moreTerms = false;
}
while (moreTerms)
{
ch = in.peek();
if (ch == '+')
{
in >> dum; // '+'
}
else
{
negativeCoefficient = true;
in >> dum; // '-'
}
ch = in.peek();
if ( (ch >= '0') && (ch <= '9') )
{
in >> tempCoefficient;
if (negativeCoefficient)
{
tempCoefficient *= -1;
negativeCoefficient = false;
}
ch = in.peek();
}
else
{
if (negativeCoefficient)
{
tempCoefficient = -1.0;
negativeCoefficient = false;
}
else
{
tempCoefficient = 1.0;
}
}
if (ch == 'x')
{
in >> dum;
if (in.peek() == '^')
{
in >> dum;
in >> tempExponent;
}
else
{
tempExponent = 1;
}
}
else
{
tempExponent = 0;
moreTerms = false;
}
if ((in.peek() != '+') && (in.peek() != '-'))
{
moreTerms = false;
}
aPoly.coefficients[tempExponent] = tempCoefficient;
}
return in;
}
You have a problem here
if ((in.peek() != '+') || (in.peek() != '-'))
where the condition is always true.
Further down in the code you use && which works better.

Fast way to determine if string is a JSON number

The check must not user C++11 features or additional libraries e.g. Boost, Regex etc. I came up with the following solution. No pretty but working. Does it get more elegant and/or faster from here?
bool isJsonNumber(const std::string& text)
{
if(text.empty()) return false;
bool foundE = false;
bool foundESign = false;
bool leadingZero = false;
bool lastIsDigit = false;
bool foundDot = false;
for(uint32_t i=0; i < text.length(); ++i)
{
const unsigned char c = text[i];
lastIsDigit = false;
const bool currIsNoDigit = (c < '0' || c > '9');
if(i == 0)
{
if(currIsNoDigit && c != '-' ) return false;
if(c == '0') leadingZero = true;
if(c != '-') lastIsDigit = true;
}
else
{
if(leadingZero)
{
leadingZero = false;
if(c != '.') return false;
foundDot = true;
}
else if(c == '.')
{
if(foundDot) return false;
foundDot = true;
}
else if(c == 'e' || c == 'E')
{
if(foundE) return false;
foundE = true;
}
else if(foundE && !foundESign)
{
if(currIsNoDigit && c != '-' && c != '+') return false;
if(c == '+' || c == '-')
{
foundESign = true;
}
else
{
lastIsDigit = true;
}
}
else
{
foundESign = false;
if(currIsNoDigit) return false;
lastIsDigit = true;
}
}
}
if(lastIsDigit == false) return false;
return true;
}
The use case is a small embedded server that recieves huge CSV files and anwsers clients with portions in JSON.
It would probably be easier to use std::stod:
size_t endpos;
std::stod(text, &endpos);
if (endpos != text.length())
{
// Not a number
}
else
{
// A number
}
If you don't have std::stod, as it's a C++11 feature, you could do something similar with std::strtod.
If you want to disallow INFINITY or NAN or hexadecimal floating point values, it's as easy as checking that the second or third character in the string is not a letter:
if ((text.length() > 2 && std::isalpha(text[1])) ||
(text.length() > 3 && std::isalpha(text[2])))
{
// Not a number
}
For "larger" numnbers there always std::stold or std::strtold. However if you want arbitrarily sized numbers then either do as you do now or use a library such as GMP (mpf_set_str seems like a good function for this).

C++ program for checking a string for balanced ()s, {}s and []s

So here's my problem:
I'm supposed to write a c++ program that checks a string to be balanced. So far I have the code working to make sure that it has the same number of ('s and )'s (the same with ['s and {'s). The problem is that this works for almost everything, but it doesn't work for strings where the {'s, ('s and ['s all get mixed up.
For example: "{ { [ ( ) ] } ( ) }" comes back as balanced (true) as it should. However, "{ ( [ ] } )" comes back true, but it shouldn't.
What are some ideas in the logic and/or code that would check for when they're out of order?
Thanks for any help!
In case it helps, my code follows:
bool ExpressionManager::isBalanced(string expression)
{
//remove whitespace
string edited;
for(int i = 0; i < expression.length(); i++)
{
if(expression[i] == ' ')
{
continue;
}
else
{
edited += expression[i];
}
}
expression = edited;
//set up brckets
string brackets;
for(int i = 0; i < expression.length(); i++)
{
if (expression.at(i)=='(')
{
brackets += expression.at(i);
}
if (expression.at(i)=='[')
{
brackets += expression.at(i);
}
if (expression.at(i)=='{')
{
brackets += expression.at(i);
}
if (expression.at(i)=='}')
{
brackets += expression.at(i);
}
if (expression.at(i)==']')
{
brackets += expression.at(i);
}
if (expression.at(i)==')')
{
brackets += expression.at(i);
}
}
int parenbal = 0;
int brackbal = 0;
int mustachebal = 0;
for (int i = 0; i<(brackets.size());i++)
{
if(brackets[i]=='(')
parenbal++;
if(brackets[i]=='[')
brackbal++;
if(brackets[i]=='{')
mustachebal++;
if(brackets[i]==')')
parenbal--;
if(brackets[i]==']')
brackbal--;
if(brackets[i]=='}')
mustachebal--;
}
bool isbalanced = false;
if ((mustachebal==0)&&(brackbal==0)&&(parenbal==0))
{
isbalanced = true;
}
//check for brackets mixed up with other stuff.
return isbalanced;
}
If you employ a Stack to store those tokens, then you are always looking for the closing-counterpart corresponding to the one on the top of the stack or an open-token.
The flow would be
If the token is an open token, push it onto the stack.
If the token is a close token, check if the top of the stack is the corresponding open-token. If it is, then pop the stack as you found them balanced. If it is not, then it's an error.
Seems more like a homework assignment. So I would comment accordingly and allow you to learn a few things.
Always initialize your variables. strings are not initialized in your code.
You do not iterate over the string three time, you can check the string only once.
Use if-else if-else structure instead of if-if-if structure.
Always use brackets braces
Be consistent with your usage, either use at() or [], but dont mix them in code.
//this code may help you check string for balanced brackets with no
//repeated brackets,paranthesis or braces (e.g. [2*{3/(1+2)}].Note: no repeatance of
//brackets
#include <iostream.h>
#include <conio.h>
#include "IntStack.h"
#include <stdio.h>
void main(void)
{
char bracket[20];
gets (bracket);
char arr[6];
int i=0;
while(i<20)
{
switch(bracket[i])
{
case '[':
{
arr[0]=1;
break;
}
case '{':
{
arr[1]=2;
break;
}
case '(':
{
arr[2]=3;
break;
}
case ')':
{
arr[3]=3;
break;
}
case '}':
{
arr[4]=2;
break;
}
case ']':
{
arr[5]=1;
break;
}
default:
cout<<"";
}
i++;
}
if(arr[3]==arr[2])
cout<<"";
else
cout<<" ) or ( is missing "<<endl;
if(arr[1]==arr[4])
cout<<"";
else
cout<<" } or { is missing "<<endl;
if(arr[5]==arr[0])
cout<<"";
else
cout<<" ] or [ is missing"<<endl;
}
void check_brackets (string bituy)
{
int flag = 1
int count[6] = {0, 0, 0, 0, 0, 0};
stack<char> barstack;
for (int i = 0; i < bituy.length(); i++)
{
if (bituy[i] == '{')
count[0]++;
else if (bituy[i] == '}')
count[1]++;
else if (bituy[i] == '(')
count[2]++;
else if (bituy[i] == ')')
count[3]++;
else if (bituy[i] == '[')
count[4]++;
else if (bituy[i] == ']')
count[5]++;
}
for (int i = 0; i < 6; i += 2)
{
if (count[i] != count[i+1])
{
cout << "Wrong Syntax!" << endl;
flag = 0;
break;
}
}
if (flag)
{
for (int i = 0; i < bituy.length(); i++)
{
if (bituy[i] == '{' || bituy[i] == '(' || bituy[i] == '[')
barstack.push(bituy[i]);
else
{
if ((barstack.top() == '{' && bituy[i] == '}') || (barstack.top() == '(' && bituy[i] == ')') || (barstack.top() == '[' && bituy[i] == ']'))
barstack.pop();
else
{
cout << "Wrong Syntax!" << endl;
flag = 0;
break;
}
}
}
}
if (flag)
cout << "No Errors!" << endl;
}
#include<bits/stdc++.h>
using namespace std;
bool isBalance(char n[],int size){
int i,count=0;
//int size=strlen(n);
for(i=0;i<size;i++){
if(n[i]=='{'||n[i]=='['||n[i]=='('){
count ++;
}
else if(n[i]=='}'||n[i]==']'||n[i]==')'){
count --;
}
else return -1;
}
if(count==0)
return true;
else
return false;
}
int main(){
char n[1000];
gets(n);
int size=strlen(n);
bool result=isBalance(n,size);
if(result==true)
cout<<"Balance";
else
cout<<"Not Balance";
return 0;
}
//bracket Chaecker program
void bracket_checker()
{
int i=0;
char d;
char ch;
int count=0;
char *s = new char[21];
fstream out;
out.open("brace.txt",ios::in);
while(out>>d)
{
if(d =='}'|| d ==')' || d == '{' || d =='(')
{
s[i]=d;
i++;
}
}
if (i % 2 != 0)
cout <<"\ninvalid braces";
else if (( s[0] == '}' || s[0]==')' || s[0]==']') || (s[i]=='{' || s[i]=='(' || s[i]=='[' ))
cout <<"\n invalid braces";
else
{
for(int a=0; a<i; a++)
{
if (s[a] == '(' || s[a] == '{' || s[a] =='[' )
push1(s[a]);
if((s[a]=='(' && (s[a+1]=='{' || s[a+1]=='}')) || (s[a]=='[' && (s[a+1]=='{' || s[a+1]=='}')))
break;
else
if (s[a] == ')' || s[a] == '}' )
{
if (head != NULL)
{
ch = pop1();
if( ch == '{' && s[a] == '}' || ch == '(' && s[a] == ')' || ch=='[' && s[a]==']')
cout <<" ";
else
break;
}
else
break;
}
}
if(head==NULL)
cout <<" valid";
else
cout <<"In Valid";
}
}