Checks if an input , a string, has Roman numerals - c++

A function that takes, as input, a string and returns true if that string contains only
Roman numerals and false otherwise. Recall, the Roman numerals are M, D, C, L,
X, V, and I.
this is what i have so far
bool isRoman(string str, char key)
{
assert(str.length() > 0)
if(length[i] == key)
{
return i;
}
}

A demo that uses no extra standard library.
#include <stdexcept>
#include <cctype>
#include <string>
using namespace std;
bool isRoman(string s){
if(s.empty()){
throw std::runtime_error("Got empty string");
}
bool isAllRoman = true;
for(const auto& c: s){
if(isspace(c)) //if you need to skip whitspace
continue;
if(!(c == 'M' || c == 'D' || c == 'C' ||
c == 'L' || c == 'X' || c == 'V' || c == 'I')){
isAllRoman = false;
break;
}
}
return isAllRoman;
}
Leave a comment if you have anything don't understand.

If you just want to know whether a std::string contains only values from a specific set of valid characters you can use std::string::find_first_not_of. That makes your function a one-liner:
bool isRoman(const std::string &str)
{
return !str.empty() && str.find_first_not_of("MDCLXVI") == std::string::npos;
}

#include <cctype>
#include <string>
#include <string_view>
using namespace std::string_literals;
bool is_roman(std::string_view sv)
{ // if the character is not found in the string
for(auto const &ch : sv) // containing roman numeric symbols, return false.
if ("MDCLXVI"s.find(std::toupper(static_cast<unsigned>(ch))) == std::string::npos)
return false;
return true;
}

Related

Detecting input white space to use in an if statement

I am trying to create a c++ program that detects when white space has been input to a cin line, and then detects what word comes after it.
I am only showing my function here:
int lineFunction (string line) {
if (/*whatever characters, then whitespace, and the letter ‘a’ is read*/) {
return 0;
}else if (/*whatever characters, then whitespace followed by the letter ‘b’*/) {
return 1;
}else {
return 2;
}
}
So if the input is, say: abc a then the output should be 0, and if the input is abc b then the output should be 1, otherwise it should be 2.
I would also like to know if this function could be ‘stacked’, like if I could have multiple white spaces and multiple words.
You can use std::find_if and std::isspace
#include <algorithm>
#include <cctype>
#include <iostream>
#include <string>
int lineFunction(std::string line) {
auto begin = std::find_if(std::begin(line), std::end(line), [](unsigned char c){ return std::isspace(c); });
if (begin == std::end(line) || ++begin == std::end(line)) return 2;
auto end = std::find_if(begin, std::end(line), [](unsigned char c){ return std::isspace(c); });
std::string word(begin, end);
if (word == "a") {
return 0;
} else if (word == "b") {
return 1;
} else {
return 2;
}
}
int main() {
std::string line = "abc a";
std::cout << lineFunction(line);
}

Shunting-Yard Algorithm C++ Not Passing Correctly Between Methods?

I am tasked with writing a Shunting-Yard algorithm for use in my final project (a calculator). I have written the program the way that makes sense to me, however, I am not getting any output when calling the main algorithm function (toRPN). I believe this is an issue with passing the values between parse and toRPN because I have tested parse directly within main and it works fine, but when I try to do a print test in the toRPN function, it prints nothing. Could someone point me in the right direction?
Header:
#include <iostream>
#include <math.h>
#include <vector>
#include <stack>
#include <queue>
using namespace std;
#ifndef SHUNTING_YARD_ALGORITHM_SHUNTINGYARD_H
#define SHUNTING_YARD_ALGORITHM_SHUNTINGYARD_H
class ShuntingYard {
public:
stack <string> stack;
vector <string> tokens;
queue <string> outputList;
vector <char> operators;
vector <int> precedence;
vector <char> associativity;
ShuntingYard ();
bool hasOnlyDigits(const string s);
int getPrecedence(const string s);
int getAssociativity(const char c);
vector<string> parse(const string input) const;
string mainAlgorithm(const string);
};
#endif //SHUNTING_YARD_ALGORITHM_SHUNTINGYARD_H
cpp:
#include "ShuntingYard.h"
#include <iostream>
#include <math.h>
#include <vector>
#include <stack>
#include <queue>
#include <sstream>
#include <numeric>
using namespace std;
stack <string> stack1;
queue <string> outputList;
vector <string> operators;
vector <int> precedence;
vector <char> associativity;
ShuntingYard::ShuntingYard () = default;
bool hasOnlyDigits(const string s){
return s.find_first_not_of( "0123456789" ) == string::npos;
}
int getPrecedence(const string s) {
for(int i = 0; i < operators.size(); i++) {
if (s == operators[i])
return precedence[i];
}
}
char getAssociativity(const string s) {
for(int i = 0; i < operators.size(); i++) {
if (s == operators[i])
return associativity[i];
}
}
vector<string> parse(const string input) {
// Parses the string by white space
istringstream ss(input);
vector <string> tokenVector;
// Fill vector with ss
for (string input; ss >> input;) {
tokenVector.push_back(input);
}
return tokenVector;
}
string toRPN(const string s) {
// Delimit string by white space and store in vector
vector <string> tokens = parse(s);
// Test print
for (int i = 0; i < tokens.size(); i ++)
cout << tokens[i];
//Change "rt" to "$" to be easily accessed
for (int i = 0; i < tokens.size(); i ++) {
if (tokens[i] == "rt")
tokens[i] = "$";
}
// Stores operators and their precedence/associativity to vectors using same index
operators.push_back("+"); precedence.push_back(2); associativity.push_back('L');
operators.push_back("-"); precedence.push_back(2); associativity.push_back('L');
operators.push_back("/"); precedence.push_back(3); associativity.push_back('L');
operators.push_back("*"); precedence.push_back(3); associativity.push_back('L');
operators.push_back("^"); precedence.push_back(4); associativity.push_back('R');
operators.push_back("$"); precedence.push_back(4); associativity.push_back('R');
// Shunting-Yard logic
while (tokens.size() != 0) {
for (int i = 0; i < tokens.size(); i++) {
if (hasOnlyDigits(tokens[i]))
outputList.push(tokens[i]);
if ( find(operators.begin(), operators.end(), tokens[i]) != operators.end()) {
while (getPrecedence(stack1.top()) > getPrecedence(tokens[i]) || (getPrecedence(stack1.top()) == getPrecedence(tokens[i]) &&
getAssociativity(tokens[i]) == 'L') && stack1.top() != "(") {
outputList.push(stack1.top());
stack1.pop();
stack1.push(tokens[i]);
}
}
if (tokens[i] == "(")
stack1.push(tokens[i]);
if (tokens[i] == ")")
while(!stack1.empty() && stack1.top() != "(") {
outputList.push(stack1.top());
stack1.pop();
}
stack1.pop();
}
if (tokens.size() == 0) {
while(!stack1.empty()) {
outputList.push(stack1.top());
stack1.pop();
}
}
}
// Replaces values with "$" back to "rt"
string str;
while (!outputList.empty()) {
if (outputList.front() == "$") {
str.insert(0,"rt");
outputList.pop();
}
else {
str.insert(0, (outputList.front()));
outputList.pop();
}
}
return str;
}
int main() {
string s1 = "3 + 4";
cout << toRPN(s1);
}
Update:
I have narrowed the issue down to the following while loop:
while (getPrecedence(stack1.top()) > getPrecedence(tokens[i]) || (getPrecedence(stack1.top()) == getPrecedence(tokens[i]) &&
getAssociativity(tokens[i]) == 'L') && stack1.top() != "(") {
outputList.push(stack1.top());
stack1.pop();
stack1.push(tokens[i]);
}
The line getPrecedence(stack1.top() > getPrecedence(tokens[I]) is the issue. In particular, running getPrecedence on the stack1.top(). This function basically takes in a string and compares it to the vector holding all of the operators that are stored. When it finds the index, it returns the precedence at that index (they are set up with all the indices in order). I don't see why I can't call this function in this way. The stack1.top() will just give a string which would be passed through and compared. Any thoughts?
Figured it out. There were a few things going one, but the main one which was haunting the program was that I was popping things off the stack when I shouldn't, resulting in the stack being empty, so it would never get into
while (getPrecedence(stack1.top()) > getPrecedence(tokens[i]) || (getPrecedence(stack1.top()) == getPrecedence(tokens[i]) &&
getAssociativity(tokens[i]) == 'L') && stack1.top() != "(")

C++ - Counting the number of vowels from a file

I'm having trouble implementing a feature that counts and displays the number of vowels from a file.
Here is the code I have so far.
#include <iostream>
#include <fstream>
#include <string>
#include <cassert>
#include <cstdio>
using namespace std;
int main(void)
{int i;
string inputFileName;
string s;
ifstream fileIn;
char ch;
cout<<"Enter name of file of characters :";
cin>>inputFileName;
fileIn.open(inputFileName.data());
assert(fileIn.is_open() );
i=0;
while (!(fileIn.eof()))
{
????????????
}
cout<<s;
cout<<"The number of vowels in the string is "<<s.?()<<endl;
return 0;
}
Note the question marks in the code.
Questions: How should I go about counting the vowels? Do I have to convert the text to lowercase and invoke system controls (if possible)?
Also, as for printing the number of vowels in the end, which string variable should I use, (see s.?)?
Thanks
auto isvowel = [](char c){ return c == 'A' || c == 'a' ||
c == 'E' || c == 'e' ||
c == 'I' || c == 'i' ||
c == 'O' || c == 'o' ||
c == 'U' || c == 'u'; };
std::ifstream f("file.txt");
auto numVowels = std::count_if(std::istreambuf_iterator<char>(f),
std::istreambuf_iterator<char>(),
isvowel);
You can using <algorithm>'s std::count_if to achieve this :
std::string vowels = "AEIOUaeiou";
size_t count = std::count_if
(
std::istreambuf_iterator<char>(in),
std::istreambuf_iterator<char>(),
[=]( char x)
{
return vowels.find(x) != std::string::npos ;
}
);
Or
size_t count = 0;
std::string vowels = "AEIOUaeiou";
char x ;
while ( in >> x )
{
count += vowels.find(x) != std::string::npos ;
}
Also read Why is iostream::eof inside a loop condition considered wrong?

C++ writing a function that extracts words from a paragraph

The program I am writing reads a text file, breaks the paragraph into individual words, compares them to a list of "sensitive words" and if a word from the text file matches a word from the Sensitive word list, it is censored. I have wrote functions that find the beginning of each word, and a function that will censor or replace words on the Sensitive word list with "#####" (which I left out of this post). A word in this case is any string that contains alphanumeric characters.
The function I am having trouble with is the function that will "extract" or return the individual words to compare to the sensitive word list (extractWord). At the moment it just returns the first letter of the last word in the sentence. So right now all the function does is return "w". I need all the individual words.
Here is what I have so far ...
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
bool wordBeginsAt (const std::string& message, int pos);
bool isAlphanumeric (char c); //
std::string extractWord (const std::string& fromMessage, int beginningAt);
int main()
{
string word = "I need to break these words up individually. 12345 count as words";
string newWord;
for (int i = 0; i < word.length(); ++i)
{
if (wordBeginsAt(word, i))
{
newWord = extractWord(word, i);
}
}
//cout << newWord; // testing output
return 0;
}
bool wordBeginsAt (const std::string& message, int pos)
{
if(pos==0)
{return true;}
else
if (isAlphanumeric(message[pos])==true && isAlphanumeric(message[pos- 1])==false)
{
return true;
}
else
return false;
}
bool isAlphanumeric (char c)
{
return (c >= 'A' && c <= 'Z')
|| (c >= 'a' && c <= 'z')
|| (c >= '0' && c <= '9');
}
std::string extractWord (const std::string& fromMessage, int beginningAt)
{
string targetWord= "";
targetWord = targetWord + fromMessage[beginningAt];
return targetWord;
}
edit: after trying to use targetWord as an array (which I couldn't define the size) and using several different for and while loops within extractWord I found a solution:
std::string extractWord (const std::string& fromMessage, int beginningAt)
{
string targetWord= "";
while (isAlphanumeric(fromMessage[beginningAt++]))
{
targetWord = targetWord + fromMessage[beginningAt-1];
}
return targetWord;
Since this is a C++ question, how about using modern C++, instead of using dressed-up C code? The modern C++ library has all the algorithms and functions needed to implement all of this work for you:
#include <algorithm>
#include <cctype>
std::string paragraph;
// Somehow, figure out how to get your paragraph into this std::string, then:
auto b=paragraph.begin(), e=paragraph.end();
while (b != e)
{
// Find first alphanumeric character, using POSIX isalnum()
auto p=std::find_if(b, e, [](char c) { return isalnum(c); });
// Find the next non-alphanumeric chararacter
b=std::find_if(p, e, [](char c) { return !isalnum(c); });
if (isbadword(std::string(p, b)))
std::fill(p, b, '#');
}
This does pretty much what you asked, in a fraction of the size of all that manual code that manually searches this stuff. All you have to do is to figure out what...
bool isbadword(const std::string &s)
...needs to do.
Your homework assignment is how to slightly tweak this code to avoid, in certain specific situations, calling isbadword() with an empty string.

string uppercase function in c++

I need to do 2 basic functions in c++
bool validMeno(const string& text){
if ()
return DUMMY_BOOL;
}
bool validPriezvisko(const string& text){
return DUMMY_BOOL;
}
first one returns true if the input is string with first letter uppercase
second one is true when all string is uppercase
plese help me i am noob in c++
Use header cctype and this should work.
bool validMeno(const string& text){
if (text.size() == 0)
return false;
return isupper(text[0]);
}
bool validPriezvisko(const string& text){
if (text.size() == 0)
return false;
for (std::string::size_type i=0; i<text.size(); ++i)
{
if (islower(text[i]))
return false;
}
return true;
}
EDIT:
Since you also want to check for strings that only stores alphabetic characters, you can use isalpha from cctype to check for that.
The relational operator == is defined for the C++ class std::string. The best touppercase implementation seems to come from the Boost String Algorithms library (see here), so I'll use that in my example. Something like this should work:
#include <boost/algorithm/string.hpp>
#include <string>
bool first_n_upper(const std::string & text, size_t n)
{
if (text.empty())
return false;
std::string upper = boost::to_upper_copy(text);
return text.substr(0, n) == upper.substr(0, n);
}
bool validMeno(const std::string & text)
{
return first_n_upper(text, 1);
}
bool validPriezvisko(const std::string & text)
{
return first_n_upper(text, std::string::npos);
}
Your problem is not completely specified. Should non-alpha characters be treated as lower-case or upper case? If they should be considered uppercase you could use:
#include <string>
#include <algorithm>
using namespace std;
bool validMeno(const string& text) {
return !text.empty() && isupper(text[0]);
}
bool validPriezvisko(const string& text) {
return !any_of(begin(text), end(text), islower);
}
On the other hand if non-alpha characters should be considered lower-case:
#include <string>
#include <algorithm>
using namespace std;
bool validMeno(const string& text) {
return !text.empty() && !islower(text[0]);
}
bool validPriezvisko(const string& text) {
return all_of(begin(text), end(text), isupper);
}