c++ char comparison to see if a string is fits our needs - c++

i want to do my work if chars of the string variable tablolar does not contain any char but small letters between a-z and ','. what do you suggest?
if string tablolar is;
"tablo"->it is ok
"tablo,tablobir,tabloiki,tablouc"->it is ok
"ta"->it is ok
but if it is;
"tablo2"->not ok
"ta546465"->not ok
"Tablo"->not ok
"tablo,234,tablobir"->not ok
"tablo^%&!)=(,tablouc"-> not ok
what i tried was wrog;
for(int z=0;z<tablolar.size();z++){
if ((tablolar[z] == ',') || (tablolar[z] >= 'a' && tablolar[z] <= 'z'))
{//do your work here}}

tablolar.find_first_not_of("abcdefghijknmopqrstuvwxyz,") will return the position of the first invalid character, or std::string::npos if the string is OK.

bool fitsOurNeeds(const std::string &tablolar) {
for (int z=0; z < tablolar.size(); z++)
if (!((tablolar[z] == ',') || (tablolar[z] >= 'a' && tablolar[z] <= 'z')))
return false;
return true;
}

The c function islower tests for lowercase. So you probably want something along these lines:
#include <algorithm>
#include <cctype> // for islower
bool fitsOurNeeds(std::string const& tabular)
{
return std::all_of(tabular.begin(), tabular.end(),
[](char ch)
{
return islower(ch) || ch == ',';
});
}

Related

Is this good enough to check an ascii string?

bool is_ascii(const string &word) {
if((unsigned char)(*word.c_str()) < 128){
return true
}
return false
}
I want to check whether a string is ascii string. I also saw such a function to detect whether a string is ascii chars or not:
bool is_ascii(const string &str){
std::locale loc;
for(size_t i = 0; i < str.size(); i++)
if( !isalpha(str[i], loc) && !isspace(str[i], loc))
return false;
return true;
}
Which one is better or more reliable?
Other answers get the is-char-ASCII part already. I’m assuming it’s right. Putting it together I’d recommend:
#include <algorithm>
bool is_ascii_char(unsigned char c) {
return (c & 0x80) == 0;
}
bool is_ascii(std::string_view s) {
return std::ranges::all_of(s, is_ascii_char);
}
https://godbolt.org/z/nKb673vaM
Or before C++20, that could be return std::all_of(s.begin(), s.end(), is_ascii_char);.
ASCII is a lot more than just alpha characters and spaces. If you want to accept all ASCII, just use your second example and change the if:
if(str[i] < 0 || str[i] > 0x7f)
return false;

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?

booleans with constraints

How do I write a boolean that checks if a string has only letters, numbers and an underscore?
Assuming String supports iterators, use all_of:
using std::begin;
using std::end;
return std::all_of(begin(String), end(String),
[](char c) { return isalnum(c) || c == '_'; });
In an easier way, run a loop and check all the characters holding the property you mentioned, and if not, just return false.
Code:
bool stringHasOnlyLettersNumbsandUndrscore(std::string const& str)
{
for(int i = 0; i < str.length(); ++i)
{
//Your character in the string does not fulfill the property.
if (!isalnum(str[i]) && str[i] != '_')
{
return false;
}
}
//The whole string fulfills the condition.
return true;
}
bool stringHasOnlyLettersNumbsandUndrscore(std::string const& str)
{
return ( std::all_of(str.begin(), str.end(),
[](char c) { return isalnum(c) || c == '_'; }) &&
(std::count_if(str.begin(), str.end(),
[](char c) { return (c == '_'); }) < 2));
}
Check if each character is a letter, number or underscore.
for c and c++ , this should do.
if(!isalnum(a[i]) && a[i]!='_')
cout<<"No";
You will have to add < ctype > for this code to work.
This is just the quickest way that comes to mind, there might be other more complex and faster ways.

C++ function to remove parenthesis from string doesn't catch them all

I wrote a function in c++ to remove parenthesis from a string, but it doesn't always catch them all for some reason that I'm sure is really simple.
string sanitize(string word)
{
int i = 0;
while(i < word.size())
{
if(word[i] == '(' || word[i] == ')')
{
word.erase(i,1);
}
i++;
}
return word;
}
Sample result:
Input: ((3)8)8)8)8))7
Output: (38888)7
Why is this? I can get around the problem by calling the function on the output (so running the string through twice), but that is clearly not "good" programming. Thanks!
if(word[i] == '(' || word[i] == ')')
{
word.erase(i,1);
}
i++;
If you erase a parenthesis, the next character moves to the index previously occupied by the parenthesis, so it is not checked. Use an else.
if(word[i] == '(' || word[i] == ')')
{
word.erase(i,1);
} else {
i++;
}
while(i < word.size())
{
if(word[i] == '(' || word[i] == ')')
{
word.erase(i,1);
}
i++;
}
When you remove an element the next element is moved to that location. If you want to test it, you will have to avoid incrementing the counter:
while (i < word.size()) {
if (word[i] == '(' || word[i] == ')' ) {
word.erase(i,1);
} else {
++i;
}
}
That can also be done with iterators, but either option is bad. For each parenthesis in the string, all elements that are after it will be copied, which means that your function has quadratic complexity: O(N^2). A much better solution is use the erase-remove idiom:
s.erase( std::remove_if(s.begin(), s.end(),
[](char ch){ return ch==`(` || ch ==`)`; })
s.end() );
If your compiler does not have support for lambdas you can implement the check as a function object (functor). This algorithm has linear complexity O(N) as the elements that are not removed are copied only once to the final location.
It's failing because your incrementing the index in all cases. You should only do that if you're not deleting the character, since the deletion shifts all the characters beyond that point back by one.
In other words, you'll have this problem wherever you have two or more consecutive characters to delete. Rather than deleting them both, it "collapses" the two into one.
Running it through your function twice will work on that particular input string but you'll still get into trouble with something like "((((pax))))" since the first call will collapse it to "((pax))" and the second will give you "(pax)".
One solution is to not advance the index when deleting a character:
std::string sanitize (std::string word) {
int i = 0;
while (i < word.size()) {
if(word[i] == '(' || word[i] == ')') {
word.erase(i,1);
continue;
}
i++;
}
return word;
}
However, I'd be using the facilities of the language a little more intelligently. C++ strings already have the capability to search for a selection of characters, one that's possibly far more optimised than a user loop. So you can use a much simpler approach:
std::string sanitize (std::string word) {
int spos = 0;
while ((spos = word.find_first_of ("()", spos)) != std::string::npos)
word.erase (spos, 1);
return word;
}
You can see this in action in the following complete program:
#include <iostream>
#include <string>
std::string sanitize (std::string word) {
int i = 0;
while ((i = word.find_first_of ("()", i)) != std::string::npos)
word.erase (i, 1);
return word;
}
int main (void) {
std::string s = "((3)8)8)8)8))7 ((((pax))))";
s = sanitize (s);
std::cout << s << '\n';
return 0;
}
which outputs:
388887 pax
Why not just use strtok and a temporary string?
string sanitize(string word)
{
int i = 0;
string rVal;
char * temp;
strtok(word.c_str(), "()"); //I make the assumption that your values should always start with a (
do
{
temp = strtok(0, "()");
if(temp == 0)
{
break;
}
else { rVal += temp;}
}while(1);
return rVal;
}

Determine if a string contains only alphanumeric characters (or a space)

I am writing a function that determines whether a string contains only alphanumeric characters and spaces. I am effectively testing whether it matches the regular expression ^[[:alnum:] ]+$ but without using regular expressions. This is what I have so far:
#include <algorithm>
static inline bool is_not_alnum_space(char c)
{
return !(isalpha(c) || isdigit(c) || (c == ' '));
}
bool string_is_valid(const std::string &str)
{
return find_if(str.begin(), str.end(), is_not_alnum_space) == str.end();
}
Is there a better solution, or a “more C++” way to do this?
Looks good to me, but you can use isalnum(c) instead of isalpha and isdigit.
And looking forward to C++0x, you'll be able to use lambda functions (you can try this out with gcc 4.5 or VS2010):
bool string_is_valid(const std::string &str)
{
return find_if(str.begin(), str.end(),
[](char c) { return !(isalnum(c) || (c == ' ')); }) == str.end();
}
You can also do this with binders so you can drop the helper function. I'd recommend Boost Binders as they are much easier to use then the standard library binders:
bool string_is_valid(const std::string &str)
{
return find_if(str.begin(), str.end(),
!boost::bind(isalnum, _1) || boost::bind(std::not_equal_to<char>, _1, ' ')) == str.end();
}
Minor points, but if you want is_not_alnum_space() to be a helper function that is only visible in that particular compilation unit, you should put it in an anonymous namespace instead of making it static:
namespace {
bool is_not_alnum_space(char c)
{
return !(isalpha(c) || isdigit(c) || (c == ' '));
}
}
...etc
In case dont want to use stl function then this can be used:
// function for checking char is alphnumeric
bool checkAlphaNumeric(char s){
if(((s - 'a' >= 0) && (s - 'a' < 26)) ||((s - 'A' >= 0) && (s - 'A' < 26)) || ((s- '0' >= 0) &&(s - '0' < 10)))
return true;
return false;
}
//main
String s = "ab cd : 456";
for(int i = 0; i < s.length(); i++){
if(!checkAlphaNumeric(s[i])) return false;
}