Checking for puncuation - c++

So, the goal is to check to see if the C style string ends with a period or exclamation mark. However, for some reason, i keep getting false.
bool isItSentence(const char* s)
{
int x = strlen(s);
for (int c = 0; s[c] != '\0'; c++)
{
if (!isupper(s[0])) return false;
if (isupper(s[c]) && c > 0) return false;
if (s[x-1] != '.') return false;
if (s[x-1] != '!') return false;
}
return true;
}
int main()
{
std::string str = "Smelly.";
reverse(str.c_str());
std::cout << isItSentence(str.c_str()) << std::endl;
std::cout << strlen(str.c_str()) << std::endl;
system("pause");
Heres what I have so far. But when I add the last if statement to handle exclamation marks, it returns zero. Any suggestions?

First, note s[x-1] is a loop invariant, so you'd rather move it out of the for loop
if (s[x-1] != '.') return false;
if (s[x-1] != '!') return false;
this is always false (a char cannot be both a dot and an explanation mark).
the test should rather be
if (s[x-1] != '.' && s[x-1] != '!') return false;

Related

String and character comparison

I am new to programming and I need to search any string to see if it includes only the letters a,b,c,d,e or f. The minute the program finds a letter that is not one of those the program should return false. Here is my function
bool is_favorite(string word){
int length = word.length(); // "word" is the string.
int index = 0;
while (index < length) {
if ((word[index] == 'a') || (word[index] == 'b') || (word[index] == 'c')||
(word[index] == 'd')|| (word[index] == 'e')|| (word[index] == 'f')) {
return true;
}
else {
return false;
}
index++;
}
}
Thank you very much for nay help! :)
The moment the return statement is encountered, the function is exited. This means that the moment any of the characters 'a', 'b', 'c', 'd', 'e', 'f' is encountered while iterating, due to the return statement the function will be exited immediately.
You can use std::string::find_first_not_of as shown below:
std::string input = "somearbitrarystring";
std::string validChars = "abcdef";
std::size_t found = input.find_first_not_of(validChars);
if(found != std::string::npos)
std::cout << "Found nonfavorite character " <<input[found]<<" at position "<<found<< std::endl;
else
{
std::cout<<"Only favorite characters found"<<std::endl;
}
If you unroll the loop by hand, you will spot the problem immediately:
if ((word[0] == 'a') || (word[0] == 'b') || (word[0] == 'c')||
(word[0] == 'd')|| (word[0] == 'e')|| (word[0] == 'f')) {
return true;
}
else {
return false;
}
if ((word[1] == 'a') || (word[1] == 'b') || (word[1] == 'c')||
(word[1] == 'd')|| (word[1] == 'e')|| (word[1] == 'f')) {
return true;
}
else {
return false;
}
//...
That is, the return value depends only on the first element.
"The minute the program finds a letter that is not one of those the program should return false" means
if ((word[0] != 'a') || (word[0] != 'b') || (word[0] != 'c')||
(word[0] != 'd')|| (word[0] != 'e')|| (word[0] != 'f')) {
return false;
}
if ((word[1] != 'a') || (word[1] != 'b') || (word[1] != 'c')||
(word[1] != 'd')|| (word[1] != 'e')|| (word[1] != 'f')) {
return false;
}
// ...
// After checking all the characters, you know what all them were in
// your desired set, so you can return unconditionally.
return true;
or, with a loop:
while (index < length) {
if ((word[index] != 'a') || (word[index] != 'b') || (word[index] != 'c')||
(word[index] != 'd')|| (word[index] != 'e')|| (word[index] != 'f')) {
return false;
}
index++;
}
return true;
bool is_favorite(string word){
return ( word.find_first_not_of( "abcdef" ) == std::string::npos );
}
It returns true if, and only if, there are only the characters 'a' through 'f' in the string. Any other character ends the search immediately.
And if you exchange string word with const string & word, your function will not have to create a copy of each word you pass to it, but work on a read-only reference to it, improving efficiency.
bool is_favorite(string word){
int length = word.length(); // "word" is the string.
int index = 0;
while (index < length) {
if (word[index] > 'f' || word[index] < 'a')
return false;
index++;
}
return true;
}
The return true is logically in the wrong place in your code.
Your version returns true as soon as it finds one letter that is a through f. It's premature to conclude that the whole string is valid at that point, because there may yet be an invalid character later in the string.
bool is_favorite(string word){
int length = word.length(); // "word" is the string.
int index = 0;
while (index < length) {
if ((word[index] == 'a') || (word[index] == 'b') || (word[index] == 'c')||
(word[index] == 'd')|| (word[index] == 'e')|| (word[index] == 'f')) {
return true; // This is premature.
}
else {
return false;
}
index++;
}
}
Minimal change that illustrates where the return true should be: after the loop. The return true is reached only if and only if we did not detect any invalid characters in the loop.
bool is_favorite(string word){
int length = word.length(); // "word" is the string.
int index = 0;
while (index < length) {
if ((word[index] == 'a') || (word[index] == 'b') || (word[index] == 'c')||
(word[index] == 'd')|| (word[index] == 'e')|| (word[index] == 'f')) {
// Do nothing here
}
else {
return false;
}
index++;
}
return true;
}
Obviously now that the affirmative block of the if is empty, you could refactor a little and only check for the negative condition. The logic of it should read closely to the way you described the problem in words:
"The minute the program finds a letter that is not one of those the program should return false."
bool is_favorite(string word){
int length = word.length(); // "word" is the string.
int index = 0;
while (index < length) {
if (!is_letter_a_through_f((word[index])
return false;
index++;
}
return true;
}
I replaced your large logical check against many characters with a function in the above code to make it more readable. I trust you do that without difficulty. My own preference is to keep statements short so that they are readable, and so that when you read the code, you can hold in your short-term memory the logic of what you are saying about control flow without being overloaded by the mechanics of your letter comparison.

String Comparison without compare()

I'm currently doing an assignment that requires us to create our own library for string comparison without using compare(), etc.
I got it to work, but during my research I created a bool function for character compare and return values.
It needs to work as if it returns like compare(), where 0 = strings are equal and 0 > or 0 < for not equal instead of true or false like I currently set it up to be.
I tried to change the bool functions to int but now when I run the program that was correctly returning strings are equal, it's showing not equal.
Header code:
bool compare_char(char &c1, char &c2)
{
if (c1 == c2)
return true;
else if (toupper(c1) == toupper(c2))
return true;
else
return false;
}
bool insensitive_string_comparision(string &string_one, string &string_two)
{
return ((string_one.size() == string_two.size()) &&
equal(string_one.begin(), string_one.end(), string_two.begin(), &compare_char));
}
string remove_spaces(string string)
{
string.erase(remove(string.begin(), string.end(), ' '), string.end());
return string;
}
string remove_punctuation(string string)
{
for (size_t i = 0, len = string.size(); i < len; ++i)
{
if (ispunct(string[i]))
{
string.erase(i--, 1);
len = string.size();
}
}
return string;
Int header changes
int compare_char(char &c1, char &c2)
{
if (c1 == c2)
return 0;
else if (toupper(c1) == toupper(c2))
return 0;
else if (toupper(c1) > toupper(c2))
return -1;
else if (toupper(c1) < toupper(c2))
return 1;
}
int insensitive_string_comparision(string &string_one, string &string_two)
{
return ((string_one.size() == string_two.size()) &&
equal(string_one.begin(), string_one.end(), string_two.begin(), &compare_char));
}
Int main changes
int result = insensitive_string_comparision(string_one, string_two);
if (result == 0)
cout << "Both Strings are equal." << endl;
else (result == 1 || result == -1)
cout << "Both Strings are not equal." << endl;
return 0;
I feel like I'm going to have to redesign the entire function to return the value that is similar to compare().
I'm assuming bool was the wrong decision to begin with? Where should I go moving forward to return a correct value?
In your question you are not entirely clear about how you want to compare the strings, but I made some assumptions based on your example code. You can fix your problem by writing insensitive_string_comparision like:
int insensitive_string_comparision(string &string_one, string &string_two) {
int len_one = string_one.length();
int len_two = string_two.length();
int len_comparison = 0;
if (len_one > len_two) {
len_comparison = -1;
} else if (len_one < len_two) {
len_comparison = 1;
}
int minlen = (len_comparison == -1) ? len_one : len_two;
for (int i = 0; i < minlen; i++) {
int order = compare_char(string_one[i], string_two[i]);
if (order != 0) {
return order;
}
}
return len_comparison;
}
I'd also recommend turning on warnings on your compiler. You don't need to put some of your return statements in else blocks.

Checking if argv[i] is a valid integer, passing arguments in main

I'm trying to make sure all arguments passed to main are valid integers, and if not, I'll print an error. For example, if I have an executable named total, I would enter total 1 2 3 4.
I want to print an error if there's an invalid integer, so if I enter total 1 2 3zy it will print an error message. My code is as follows.
#include <iostream>
#include<stdlib.h>
using namespace std;
bool legal_int(char *str);
int main(int argc, char *argv[])
{
//int total = 0;
for(int i = 1; i < argc; i++)
{
if( (legal_int(argv[i]) == true) )
{
cout << "Good to go" << endl;
}
else
{
cerr << "Error: illegal integer." << endl;
return 1;
}
}
// int value = atoi(argv[i]);
//cout << value << endl;
}
bool legal_int(char *str)
{
while(str != 0) // need to
if( (isdigit(str)) )// do something here
{
return true;
}
else
{
return false;
}
}
What I need to know is how can I index through all the characters in the string and make sure they are digits with the legal_int function?
When comparing every character, the logic should be if it's not legal, return false, otherwise continue:
bool legal_int(char *str)
{
while (str != 0)
{
if (!isdigit(*str))
{
return false;
}
str++;
}
return true;
}
What about:
bool legal_int(char *str) {
while (*str)
if (!isdigit(*str++))
return false;
return true;
}
It is not the best function but it should serve the purpose. The isdigit function needs a character to look at so pass in *str. The other key point is that you need to advance the pointer inside of the loop.
bool legal_int(char *str)
{
while(str != 0) // need to
if( (isdigit(str)) )// do something here
{
return true;
}
else
{
return false;
}
}
You have three mistakes:
while (str != 0) should be while (*str != 0). You want to continue until you encounter a zero in the string, not until the string itself goes away.
if( (isdigit(str)) ) should be if( (isdigit(*str++)) ). You want to look at what str points to and see if that's a digit, and you need to point to the next digit.
return true; That should not be there. You don't want to return just because you found a single digit.

Parsing Parenthesis using stack template class in C++

I have a homework and its just bugging for the last 2 days, I've been doing exactly what the pseudo code and still haven't got it right yet.
For example, if I put in "mike]" or "mike]123", my program will crash, due to the stack is empty...From what I observe, the program will crash when:
- The stack is empty
- And there is a close parenthesis
PS: with the help of us2012, I can fix the crash problem. However, the result is not right.
Instead of printing out "invalid", it outputs "valid"
:(
Here is the pseudo code from my professor:
def parse_parenthesis(str):
stack = create a new empty stack of OpenParen objects
for i from 0 to str.size() - 1:
if str[i] is an open parenthesis
stack.push(new OpenParen(str[i]))
else if str[i] is not a close parenthesis:
# str[i] is not a parenthesis of any kind, so ignore it
continue
# otherwise str[i] must be a close parenthesis, try to
# match it with the most recent open paren, on the top
# of the stack
else if stack is empty
return false;
else if stack.peek() is of the same type as str[i]:
# close properly
stack.pop()
else
return false;
if stack is not empty
return false;
else
return true
and here is what I have so far:
.cpp file
bool ParenMatching(const string& s, unique_ptr<string>& output)
{
unique_ptr<OpenParen> stack(new OpenParen);
bool validOpen, validClose, valid;
bool match; //haveCloseParen;
/*string unMatch = "Unmatch";
string unExpected = "Unexpected close paren";
string noError = "No Error";*/
for (size_t i = 0; i < s.length(); i++)
{
// check if its open parenthesis
validOpen = stack->IsOpenParen(s[i]);
// check if its close parenthesis
validClose = stack->IsCloseParen(s[i]);
// if there is open paren, push into the stack
if(validOpen)
stack->PushObj(s[i]);
else if(!validClose)
{
continue;
}
else if(stack->GetObj().IsEmpty())
valid = false;
else if(match = IsMatchParen(s[i], stack))
stack->PopObj();
else
valid = false;
}
if(!stack->GetObj().IsEmpty())
valid = false;
else
valid = true;
return valid;
}
bool IsMatchParen(const char c, const unique_ptr<OpenParen>& stack)
{
bool valid;
if(c == ')' && stack->PeekObj() == '(')
valid = true;
else if (c == ']' && stack->PeekObj() == '[')
valid = true;
else if (c == '}' && stack->PeekObj() == '{')
valid = true;
else if (c == '>' && stack->PeekObj() == '<')
valid = true;
else
valid = false;
return valid;
}
OpenParen.cpp
// Check if its open paren
bool OpenParen::IsOpenParen(const char c)
{
bool isOpen;
if(c == '(' || c == '[' || c == '{' || c == '<')
isOpen = true;
else
isOpen = false;
return isOpen;
}
// check if its close paren
bool OpenParen::IsCloseParen(const char c)
{
bool isClose;
if(c == ')' || c == ']' || c == '}' || c == '>')
isClose = true;
else
isClose = false;
return isClose;
}
gcc 4.7.3: g++ -Wall -Wextra -std=c++0x parens.cpp
#include <iostream>
#include <stack>
#include <string>
#include <vector>
bool isOpen(char c) {
return c == '(' || c == '[' || c == '{' || c == '<'; }
bool isClose(char c) {
return c == ')' || c == ']' || c == '}' || c == '>'; }
bool isMatch(char c1, char c2) {
return (c1 == '(' && c2 == ')')
|| (c1 == '[' && c2 == ']')
|| (c1 == '{' && c2 == '}')
|| (c1 == '<' && c2 == '>'); }
bool parse(const std::string& s) {
std::stack<std::string::value_type> stk;
for (std::string::size_type i = 0; i < s.size(); ++i) {
if (isOpen(s[i])) { stk.push(s[i]); }
else if (isClose(s[i])) {
if (!stk.empty() && isMatch(stk.top(), s[i])) { stk.pop(); }
else { return false; } } }
return stk.empty(); }
int main() {
std::vector<std::string> ptests = {
"", "()", "()()", "(())", "a(a)a" };
std::vector<std::string> ftests = {
"(", ")", ")(", ")()(", "))((" };
for (const auto& t : ptests) {
if (!parse(t)) { std::cout << "fail: " << t << std::endl; } }
for (const auto& t : ftests) {
if (parse(t)) { std::cout << "fail: " << t << std::endl; } }
}
One important thing you should keep in mind about C++ : Multiple else ifs do not live at the same level. That's because else if is not a single entity, it's an else that belongs to the preceding statement and an ifthat begins a new statement, so
if (cond1)
a();
else if (cond 2)
b();
else if (cond 3)
c();
else
d();
is actually
if (cond1)
a();
else {
if (cond 2)
b();
else {
if (cond 3)
c();
else
d();
}
}
Therefore, your check whether the stack is empty needs to be before the check whether the current close parens matches the top of the stack. Otherwise, your program will try to examine the top of the stack when it's empty, and that results in a crash.
Also, setting valid = false is not the right thing to do when you find a condition that indicates a non-match. The loop will still continue and can reset valid to true in a later iteration. You need to immediately return false, as you can already see in your pseudocode.

c++ checking if braces match

I've been asked as a bonus programming challenge to see if braces match in a random string or char like this: {1+1} this would return 1, while {1+1}) would return 0.
This is what I have so far but it doesn't seem to do anything. Any help would be great? thanks
//bonus.cpp
#include <iostream>
#include <string>
#include <queue>
#include <stack>
using namespace std;
int checkBraces (string s)
{
//int myLength = s.length();
std::stack<int> stack;
char d;
for (int i = 0; i < s.length(); i++)
{
char c = s[i];
if (c == '(')
{
stack.push(c);
}
else if (c == '[')
{
stack.push(c);
}
else if (c == '{')
{
stack.push(c);
}
else if (c == ')')
{
if (stack.empty())
{
return false;
}
else
{
d = stack.top();
stack.pop();
if (d != '(')
{
return false;
}
}
}
else if (c == ']')
{
if (stack.empty())
{
return false;
}
else
{
d = stack.top();
stack.pop();
if (d != '[')
{
return false;
}
}
}
else if (c == '}')
{
if (stack.empty())
{
return false;
}
else
{
d = stack.top();
stack.pop();
if (d != '{')
{
return false;
}
}
}
}
if (stack.empty()) return true;
else return false;
}
int main()
{
cout << "This program checks brace ([{}]) matching in a string." << endl;
checkBraces ("{1+1}");
}
What makes you think it doesn't do anything? It does. It checks for braces, but you're not doing anything with the return of checkBraces, which, btw, should return a bool, not an int.
Did you perhaps meant something like:
if (checkBraces ("{1+1}"))
cout << "matching";
else
cout << "not matching";
Pro-tip: learn how to use a debugger. You should learn how to debug before you start coding anything more than a "hello world".
As an addition to what have already been said, I would say that you could reduce the amount of code. As anyway you put chars into your stack, why not having a std::stack<char>?
You could save the braces into another string, to automatically compare it using one of the std::algorithms
const std::string openingBraces("{[(");
const std::string closingBraces("}])");
if (std::find(openingBraces.begin(), openingBraces.end(), currentChar) != openingBraces.end())
yourStack.push(currentChar);
else if (std::find(closingBraces.begin(), closingBraces.end(), currentChar) != closingBraces.end())
{
// check if currentChar is matching the one on top of your stack
}
I haven't written everything as it's always better to find answers by yourself.
Minimum you should do is to print the outcome of checkBraces.
but it doesn't seem to do anything
It does do something. It prints This program checks brace ([{}]) matching in a string..
You are calling checkBraces ("{1+1}") but you aren't doing anything with the returned value. Since this call can be optimized away, you are in a sense correct that your program doesn't seem to do anything.
So make it do something. Print the string that is to be tested, then print the result of the test. Once you have done that, you should test, and when you're done with that, you should test some more. Don't just test easy cases such as {i+1}. Test convoluted cases that should pass, and also test cases that should fail.
Learning how to test and learning how to debug are just as important skills (if not more important skills) as is learning how to write code.