string uppercase function in c++ - 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);
}

Related

A better approach for keyword searching in c++

Can you help me with this aproach :
The thing is, we need to do a case-insensitive search for the keywords in a string (for a function which return true is if any of the keyword is found in the string, elsewise false)
So I am using this piece of code:
std::transform(string.begin(), string.end(), string.begin(), ::toupper);
std::transform(keywords.begin(), keywords.end(), keywords.begin(), ::toupper);
std::istringstream iss(keywords);
std::string word;
while(iss >> word) {
if(string.find(word) != std::string::npos)
return true;
}
return false;
The problem with this is that it creates unnecessary copies of the existing data. Can there be a better approach to it?
First of all for making this more reuseable creating an object responsible for holding the keyword data would be preferrable. You can use std::string_views, std::pair<std::string::const_iterator, std::string::const_iterator> or something similar to avoid making a copy of the string data for the keywords and using std::search to find the keywords allows you to prevent having to copy the string to convert it to upper case for a search while also keeping benefit of converting the keywords to upper case:
class KeywordSearch
{
std::vector<std::string_view> m_keywords;
std::string m_keywordData;
public:
KeywordSearch(std::string&& keywords)
: m_keywordData(std::move(keywords))
{
auto pos = m_keywordData.begin();
auto const end = m_keywordData.end();
std::for_each(pos, end, [](char& c) { c = std::toupper(c); });
pos = std::find_if(pos, end, [](unsigned char c) { return !std::isspace(c); });
while (pos != end)
{
auto keywordEnd = std::find_if(pos + 1, end, [](unsigned char c) { return std::isspace(c); });
m_keywords.emplace_back(pos, keywordEnd);
pos = std::find_if(keywordEnd, end, [](unsigned char c) { return !std::isspace(c); });
}
}
// allow only move for now; copy would require an update of m_keywords
KeywordSearch(KeywordSearch&&) noexcept = default;
KeywordSearch& operator=(KeywordSearch&&) noexcept = default;
bool operator()(std::string const& haysack) const
{
for (auto const& keyword : m_keywords)
{
if (std::search(haysack.begin(), haysack.end(), keyword.begin(), keyword.end(),
[](char haysackChar, char keywordChar)
{
return std::toupper(haysackChar) == keywordChar;
}) != haysack.end())
{
return true;
}
}
return false;
}
};
void Test(KeywordSearch const& search, std::string const& str)
{
std::cout << (search(str) ? " keyword found in '" : "keyword not found in '") << str << "'\n";
}
int main() {
KeywordSearch search("foo bar baz");
Test(search, "NoFoOB");
Test(search, "barblabla");
Test(search, "babbba");
Test(search, "hello world");
Test(search, "hello wobaz");
}
Yes, maybe. If you want to avoid copies, then you can use an iterator.
C++ offers a functionality to iterate over paterrns in a string. This is the std::sregex_token_iterator. You can read here about that. You can either define a "positive" pattern, so, what you are looking for. Example: "\w+" will look for words. Or, you do a "negative" search, meaning, specify the separator (e.g., ' ' as a std::regex) and add "-1" as fourth parameter.
Then you can iterate over all keywords.
As for the case insenitivity. Do the conversion one time. I will not even show it in my below example.
First I created a small demo, where I print out the keywords that have been found in the given std::string.
#include <iostream>
#include <regex>
#include <string>
#include <iterator>
#include <algorithm>
const std::regex re{ R"(\w+)" };
int main() {
// Keys
const std::string keys{ "abc def ghi jkl" };
// Search string
std::string s{ "abcxxxghixxx" };
std::copy_if(std::sregex_token_iterator(keys.begin(), keys.end(), re), {},
std::ostream_iterator<std::string>(std::cout,"\n"),
[&s](const std::string& k) {return s.find(k) != std::string::npos; });
}
This approach can be taken over to build your needed function.
One of many possible solutions:
#include <iostream>
#include <regex>
#include <string>
#include <iterator>
#include <algorithm>
const std::regex re{ R"(\w+)" };
bool isAnyKeyWordInString(const std::string& keys, const std::string& s) {
bool result{};
std::for_each(std::sregex_token_iterator(keys.begin(), keys.end(), re), {},
[&](const std::string& k) {result |= (s.find(k) != std::string::npos); });
return result;
}
int main() {
// Keys
const std::string keys{ "abc def ghi jkl" };
// Search string
std::string s{ "abcxxxghixxx" };
// Evaluate
if (isAnyKeyWordInString(keys, s))
std::cout << "At least one key-word found\n";
else
std::cout << "No Keyword found\n";
}
this is fast!!!
but you have to keep changing the parameters depending on your requirement, for example: const int keyword_len = (int)keyword.length(); here i'm casting the unsigned long int to int.
also i'm not converting my searchable string to upper case before my conditional statement because its faster this way instead of looping through the string when i need to search.
when it comes to complexity it's O(n)+k where k<<n, because i'm not comparing the entire keyword size to the searchable string.
P.s. sorry for not making this code ideally reusable, but it is intractable.
#include <cctype>
#include <iostream>
#include <string>
int main(){
std::string searchable_string;
std::string keyword;
std::cout<<"enter the searchable string : "<<std::endl;
std::getline(std::cin, searchable_string);
std::cout<<"enter the keyword you are looking for : "<<std::endl;
std::getline(std::cin, keyword);
const int keyword_len = (int)keyword.length();
const int searchable_string_len = (int)searchable_string.length();
int upper_keyword[keyword_len];
int i = 0;
for(;i<keyword_len;){
upper_keyword[i] = toupper(x);
i++;
}
i = 0;
int j;
keeplooking:
j = 0;
comparetokeyword:
if(upper_keyword[j]==toupper(searchable_string[i+j])){
j++;
if(j <= (keyword_len)-1) goto comparetokeyword;
else {
//'i' is the relative position of your keyword.
std::cout<<"found keyword at: "<<std::endl<<i<<std::endl;
std::cout<<"do you want to keep looking for more(enter '1' for Yes and '0' for No) :"<<std::endl;
bool x;
std::cin>>x;
if(x){
i++;
if(i<searchable_string_len) goto keeplooking;
else goto terminate;
}
}
}
else{
i++;
if(i<searchable_string_len){
goto keeplooking;
}
terminate:
std::cout<<"reached the end."<<std::endl;
}
}

Checks if an input , a string, has Roman numerals

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;
}

C++ Check if whole string is uppercase

I am trying to check if the whole word is upper case, if this is true it should return true, else return false.
My current code is:
#include "UpperCaseFilter.h"
#include "ReadFilteredWords.h"
#include "ReadWords.h"
#include <locale>
bool UpperCaseFilter::filter(string word) {
if(!word.empty()) {
for(int i = 0; i < word.length(); i++) {
if(isupper(word[i])) {
return true;
}
else {
return false;
}
}
}
}
The problem with this code is, if i have for example HeLLO, it will return true because my last character is true. How would I only return true if the whole string is true. I did it using a counter method but it is not the most efficient.
I also tried using the all_of method but I think I dont have the correct compiler version because it says all_of isn't defined (Even with correct imports).
I'm not sure what other approaches there are to this.
Alternatively utilize the std::all_of function in combination with std::isupper in predicate:
#include <iostream>
#include <string>
#include <algorithm>
int main() {
std::string s = "HELLo";
if (std::all_of(s.begin(), s.end(), [](unsigned char c){ return std::isupper(c); })) {
std::cout << "Is uppercase." << '\n';
} else {
std::cout << "Is not uppercase." << '\n';
}
}
Used as part of a function:
bool isUpper(const std::string& s) {
return std::all_of(s.begin(), s.end(), [](unsigned char c){ return std::isupper(c); });
}
bool is_all_upper(const std::string& word)
{
for(auto& c: word)
if(!std::isupper(static_cast<unsigned char>(c)))
return false;
return true;
}
I assume that, if the string is empty, it can be considered all-uppercase.
You shouldn't have two return conditions inside your loop. Rather, you can use the loop to find problems and, if there are no problems, you'll escape the loop and can tell the user that everything was alright at the end.
In the comments you say "i believe it doesn't need to return anything if the string is empty"; however, a function with a return type, such as this one always returns something. If you don't specify a return value it will give you one, whether you like it or not. Therefore, you must decide what the output should be for every conceivable input. Accordingly, I've added an if statement that emphasizes the special condition of an empty string.
#include "UpperCaseFilter.h"
#include "ReadFilteredWords.h"
#include "ReadWords.h"
#include <locale>
bool UpperCaseFilter::filter(const string &word) {
if(word.empty()) //You'll need to do the right thing here
return true;
//Even if the right thing to do were to return true, so that
//the check above would be redundant, you'd want to leave a
//comment here pointing out that you've handled the special case
for(size_t i = 0; i < word.length(); i++)
if(!isupper(static_cast<unsigned char>(word[i])))
return false;
return true;
}
Note that your previous function signature was:
bool UpperCaseFilter::filter(string word) {
I've changed this to:
bool UpperCaseFilter::filter(const string &word) {
The const guarantees that the function will not alter word and the & symbol passes the string to the function without copying it. This makes the function faster and saves memory.
#include "UpperCaseFilter.h"
#include "ReadFilteredWords.h"
#include "ReadWords.h"
#include <locale>
bool UpperCaseFilter::filter(string word)
{
int k=0;
if(!word.empty())
{
for(int i = 0; i < word.length(); i++)
{
if(isupper(word[i]))
k++;
}
}
if(k==word.length())
return true;
else
return false; //this will return false even when word length is 0
}
its more simple now provided if you have done other things right this would run.
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
string str;
cin >> str;
bool flag = false;
int i = 0;
while(str[i])
{
if(isupper(str[i]))
{
flag = true;
}
if(!(isupper(str[i])))
{
flag = false;
break;
}
i++;
}
if(flag == false)
cout << "false" << endl;
else
cout << "true" << endl;
}
#include <iostream>
#include <string>
#include <boost/algorithm/string.hpp>
bool IsAllUpperString(string str)
{
if(boost::to_upper_copy(str)== str) return true;
return false;
}

Can you specify what ISN'T a delimiter in std::getline?

I want it to consider anything that isn't an alphabet character to be a delimiter. How can I do this?
You can't. The default delimiter is \n:
while (std::getline (std::cin, str) // '\n' is implicit
For other delimiters, pass them:
while (std::getline (std::cin, str, ' ') // splits at a single whitespace
However, the delimiter is of type char, thus you can only use one "split-character", but not what not to match.
If your input already happens to be inside a container like std::string, you can use find_first_not_of or find_last_not_of.
In your other question, are you sure you have considered all answers? One uses istream::operator>>(std::istream&, <string>), which will match a sequence of non-whitespace characters.
You don't. getline is a simple tool for a simple job. If you need something more complex, then you need to use a more complex tool, like RegEx's or something.
You can't do what you want using std::getline(), but you can roll your own. Here's a getline variant that let's you specify a predicate (function, functor, lambda if it's C++11) to indicate if a character is a delimiter along with a couple overloads that let you pass in a string of delimiter characters (kind of like strtok()):
#include <functional>
#include <iostream>
#include <string>
using namespace std;
template <typename Predicate>
istream& getline_until( istream& is, string& str, Predicate pred)
{
bool changed = false;
istream::sentry k(is,true);
if (bool(k)) {
streambuf& rdbuf(*is.rdbuf());
str.erase();
istream::traits_type::int_type ch = rdbuf.sgetc(); // get next char, but don't move stream position
for (;;ch = rdbuf.sgetc()) {
if (istream::traits_type::eof() == ch) {
is.setstate(ios_base::eofbit);
break;
}
changed = true;
rdbuf.sbumpc(); // move stream position to consume char
if (pred(istream::traits_type::to_char_type(ch))) {
break;
}
str.append(1,istream::traits_type::to_char_type(ch));
if (str.size() == str.max_size()) {
is.setstate(ios_base::failbit);
break;
}
}
if (!changed) {
is.setstate(ios_base::failbit);
}
}
return is;
}
// a couple of overloads (along with a predicate) that allow you
// to pass in a string that contains a set of delimiter characters
struct in_delim_set : unary_function<char,bool>
{
in_delim_set( char const* delim_set) : delims(delim_set) {};
in_delim_set( string const& delim_set) : delims(delim_set) {};
bool operator()(char ch) {
return (delims.find(ch) != string::npos);
};
private:
string delims;
};
istream& getline_until( istream& is, string& str, char const* delim_set)
{
return getline_until( is, str, in_delim_set(delim_set));
}
istream& getline_until( istream& is, string& str, string const& delim_set)
{
return getline_until( is, str, in_delim_set(delim_set));
}
// a simple example predicate functor
struct is_digit : unary_function<char,bool>
{
public:
bool operator()(char c) const {
return ('0' <= c) && (c <= '9');
}
};
int main(int argc, char* argv[]) {
string test;
// treat anything that's not a digit as end-of-line
while (getline_until( cin, test, not1(is_digit()))) {
cout << test << endl;
}
return 0;
}

Comparing wstring with ignoring the case

I am sure this would have been asked before but couldn't find it. Is there any built in (i.e. either using std::wstring's methods or the algorithms) way to case insensitive comparison the two wstring objects?
If you don't mind being tied to Microsoft implementation you can use this function defined in <string.h>
int _wcsnicmp(
const wchar_t *string1,
const wchar_t *string2,
size_t count
);
But if you want best performance/compatibility/functionality ratio you will probably have to look at boost library (part of it is stl anyway). Simple example (taken from different answer to different question):
#include <boost/algorithm/string.hpp>
std::wstring wstr1 = L"hello, world!";
std::wstring wstr2 = L"HELLO, WORLD!";
if (boost::iequals(wstr1, wstr2))
{
// Strings are identical
}
Using the standard library:
bool comparei(wstring stringA , wstring stringB)
{
transform(stringA.begin(), stringA.end(), stringA.begin(), toupper);
transform(stringB.begin(), stringB.end(), stringB.begin(), toupper);
return (stringA == stringB);
}
wstring stringA = "foo";
wstring stringB = "FOO";
if(comparei(stringA , stringB))
{
// strings match
}
You can use std::tolower() to convert the strings to lowercase or use the function wcscasecmp to do a case insensitive compare on the c_str()'s.
Here is a comparison functor you can use directly as well:
struct ci_less_w
{
bool operator() (const std::wstring & s1, const std::wstring & s2) const
{
#ifndef _WIN32
return wcscasecmp(s1.c_str(), s2.c_str()) < 0;
#else
return _wcsicmp(s1.c_str(), s2.c_str()) < 0;
#endif
}
};
Talking about English right ?! though I would go with my lovely Boost :)
bool isequal(const std::wstring& first, const std::wstring& second)
{
if(first.size() != second.size())
return false;
for(std::wstring::size_type i = 0; i < first.size(); i++)
{
if(first[i] != second[i] && first[i] != (second[i] ^ 32))
return false;
}
return true;
}
You could use the boost string algorithms library. Its a header only library as long as you're not going to do regex. So you can do that very easily.
http://www.boost.org/doc/libs/1_39_0/doc/html/string_algo.html
#include <algorithm>
#include <string>
#include <cstdio>
bool icase_wchar_cmp(wchar_t a, wchar_t b)
{
return std::toupper(a) == std::toupper(b);
}
bool icase_cmp(std::wstring const& s1, std::wstring const& s2)
{
return (s1.size() == s2.size()) &&
std::equal(s1.begin(), s1.end(), s2.begin(),
icase_wchar_cmp);
}
int main(int argc, char** argv)
{
using namespace std;
wstring str1(L"Hello"), str2(L"hello");
wprintf(L"%S and %S are %S\n", str1.c_str(), str2.c_str(),
icase_cmp(str1,str2) ? L"equal" : L"not equal");
return 0;
}
If you need that the string will always make case insensitive comparation (when using operators == or !=), then a possible elegant solution is to redefine char_traits::compare method.
Define your own structure. Example
struct my_wchar_traits: public std::char_traits< wchar_t>
{
static int compare( const char_type* op1, const char_type* op2, std::size_t num)
{
// Implementation here... any of the previous responses might help...
}
};
Then, define your own case insensitive string:
typedef std::basic_string< wchar_t, my_wchar_traits> my_wstring;
You can use mismatch() or lexicographical_compare(). This is suggested by Scott Meyers in Effecitve STL, item 35.