Find first no zero number in a string C++ - c++

Hello is there a way to find first number (from 1 to 9, no zero) in a string?
Is there a way with std::find or do I need other function to do this?

Hello is there a way to find first number (from 1 to 9, no zero) in a string?
You can use std::find_if to do so:
template< class InputIt, class UnaryPredicate >
InputIt find_if( InputIt first, InputIt last, UnaryPredicate p );
find_if searches for an element for which predicate p returns true
#include <string>
#include <algorithm>
#include <cctype>
#include <iostream>
int main()
{
auto const str = std::string{"hello user #0002654"};
auto const first_non_zero_it = std::find_if(begin(str), end(str), [](char c) {
return std::isdigit(c) && c != '0';
});
std::cout << *first_non_zero_it << '\n'; // prints 2
}
Demo: https://coliru.stacked-crooked.com/a/e3880961973ce038

You can traverse std::string as a char array with [] operator and size() function to get its length.
Then you can check for char values from 49 to 57 (in decimal, according to ASCII table).
EDIT
As mentioned in the comments below, it would be clearer to compare with the range from '1' to '9' than from 49 to 57. But it would be useful anyway to get familiar with different char representations.
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::string search_str = "abcd56";
for (int i = 0; i < search_str.size(); ++i) {
if (search_str[i] >= '1' && search_str[i] <= '9') {
std::cout << "found at " << i << "\n";
break;
}
}
}
As for std::find, I would better use std::find_first_of, which takes two pairs of iterators, one pointing to the range to be searched in and another to the range of elements to search for.
If the result of std::find_first_of is not equal to the end() of the searched range, then the first element index can be found with std::distance(search_range.begin(), result).
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::string search_str = "abcd56";
std::vector<char> find_range {'1','2','3','4','5','6','7','8','9'};
auto result = std::find_first_of(search_str.begin(), search_str.end(), find_range.begin(), find_range.end());
if (result == search_str.end()) {
std::cout << "no elements were found\n";
} else {
std::cout << "found match at "
<< std::distance(search_str.begin(), result) << "\n";
}
}

Related

C++ masking all characters of a string except for the last n characters with <algorithm>

In C++, how to mask all characters of string except last in character using <algorithm>?
ie;
I have a string
std::string barcode = "300001629197835714";
I would like to get output as
**************5714
This program can be easily done in a conventional way,
std::string barcode = "300001629197835714";
std::string out;
for (int i=0;i<barcode.length();i++)
{
if (i<barcode.length()-4)
{
out+="*";
}
else
{
out+=barcode[i];
}
}
std::cout<<out;
But can I do this with std::replace_if or with std::transform or any function from <algorithm> header?
Here's a solution using the algorithm library and iterators. I'm using std::prev to get an iterator 4 characters before end(), then std::fill to replace the digits in the range [begin, end - 4) with '*'.
#include <algorithm>
#include <string>
#include <iterator>
#include <iostream>
int main()
{
std::string barcode = "300001629197835714";
std::fill(barcode.begin(), std::prev(std::end(barcode), 4), '*');
std::cout << barcode;
}
Note that
std::prev(std::end(barcode), 4)
will cause undefined behavior if barcode is less than 4 characters.
Neither std::replace_if nor std::transform is necessary. The simple
barcode.replace(0, barcode.size() - 4, barcode.size() - 4, '*');
std::cout << barcode;
Make sure barcode.size() is greater than 4.
std::basic_string::replace (6).
For string manipulation I usually revert to regex instead of algorithm
#include <iostream>
#include <regex>
#include <string>
int main()
{
std::string barcode = "300001629197835714";
std::regex expression{ ".(?=.{4,}$)" };
auto secret = std::regex_replace(barcode, expression, "*");
std::cout << secret << std::endl;
}
You can use replace_if with a always true returning predicate and simply use the iterators from begin() to end()-4:
#include <string>
#include <algorithm>
#include <iostream>
int main()
{
std::string code = "1234564598745774";
int numVisibleDigits = 4;
std::replace_if(
code.begin(),
code.end()-numVisibleDigits,
[](char){return true;},
'*'
);
std::cout << code << std::endl;
}
it can be done with std::replace_if
std::string barcode = "300001629197835714";
int nonMasklenght = 4;
std::replace_if(barcode.begin(), barcode.end(), [&barcode, &nonMasklenght](const char &x)->bool {
size_t index = &x - &barcode[0];
return (index <( barcode.length() - nonMasklenght) );},
'*');
std::cout<<barcode;
ideone example
IfI look at the original code of the OP, then we can clearly see that the original string should not be modified.
Only masked output should be shown.
So, nearly all answers, except from Pepijn Kramer, are wrong.
And by the way. A Modification is not required and is not necessary. Simply show the masked output:
#include <iostream>
#include <string>
int main() {
// Our base data. It is const. It will not be modified
const std::string barcode = "300001629197835714";
// No algorithm and code
// - - -
// Just output
std::cout << std::string(14, '*') << barcode.substr(barcode.length() - 4) << '\n';
return 0;
}

Finding item in string and say WHEN it was found - c++

I have a string of items (see code). I want to say when a specific item from that list is found. In my example I want the output to be 3 since the item is found after the first two items. I can print out the separate items to the console but I cannot figure out how to do a count on these two items. I think it is because of the while loop... I always get numbers like 11 instead of two separate 1s. Any tips? :)
#include <iostream>
#include <string>
using namespace std;
int main() {
string items = "box,cat,dog,cat";
string delim = ",";
size_t pos = 0;
string token;
string item1 = "dog";
int count = 0;
`;
while ((pos = items.find(delim)) != string::npos)
{
token = items.substr(0, pos);
if (token != item1)
{
cout << token << endl; //here I would like to increment count for every
//item before item1 (dog) is found
items.erase(0, pos + 1);
}
else if (token == item1)
return 0;
}
return 0; //output: box cat
}
I replaced your search algorithm with the method explode, that separates your string by a delimiter and returns a vector, which is better suited for searching and getting the element count:
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <algorithm>
std::vector<std::string> explode(const std::string& s, char delim)
{
std::vector<std::string> result;
std::istringstream iss(s);
for (std::string token; std::getline(iss, token, delim); )
{
result.push_back(std::move(token));
}
return result;
}
int main()
{
std::string items = "box,cat,dog,cat";
std::string item1 = "dog";
char delim = ',';
auto resultVec = explode(items, delim);
auto itResult = std::find_if(resultVec.begin(), resultVec.end()
, [&item1](const auto& resultString)
{
return item1 == resultString;
});
if (itResult != resultVec.end())
{
auto index(std::distance(resultVec.begin(), itResult) + 1); // index is zero based
std::cout << index;
}
return 0;
}
By using std::find_if you can get the position of item1 by iterator, which you can use with std::distance to get the count of elements that are in front of it.
Credits for the explode method go to this post: Is there an equivalent in C++ of PHP's explode() function?
There are many ways to Rome. Here an additional solution using a std::regex.
But main approach is the same as the accepted answer. Using modern C++17 language elements, it is a little bit more compact.
#include <iostream>
#include <string>
#include <regex>
#include <iterator>
#include <vector>
const std::regex re{ "," };
int main() {
std::string items{ "box,cat,dog,cat" };
// Split String and put all sub-items in a vector
std::vector subItems(std::sregex_token_iterator(items.begin(), items.end(), re, -1), {});
// Search and check if found and show result
if (auto it = std::find(subItems.begin(), subItems.end(), "dog"); it != subItems.end())
std::cout << "Found at position: " << std::distance(subItems.begin(), it) + 1 << '\n';
else
std::cout << "Not found.\n";
return 0;
}

How to compare strings that shows number of differences

I'm new to programming so I'm sorry if my question is hard to understand.
I have a string modelAnswer as such
string modelAnswer = "ABABACDA";
So it's supposed to be the answers to a quiz and I'm trying to make it so that if user's input is
string studentAnswer = "ABADBDBB"; for example the program will show that I have gotten 3 points as the first three letters of the studentAnswer string matches the modelAnswer.
You can use standard algorithm std::inner_product as for example
#include <iostream>
#include <string>
#include <numeric>
#include <functional>
int main()
{
std::string modelAnswer( "ABABACDA" );
std::string studentAnswer( "ABADBDBB" );
auto n = std::inner_product( modelAnswer.begin(), modelAnswer.end(),
studentAnswer.begin(), size_t( 0 ),
std::plus<size_t>(), std::equal_to<char>() );
std::cout << n << std::endl;
return 0;
}
The program output is
3
It is assumed that the strings have the same length. Otherwise you should use the less string as the first pair of arguments.
For example
#include <iostream>
#include <string>
#include <numeric>
#include <algorithm>
#include <functional>
#include <iterator>
int main()
{
std::string modelAnswer( "ABABACDA" );
std::string studentAnswer( "ABADBDBB" );
auto n = std::inner_product( modelAnswer.begin(),
std::next( modelAnswer.begin(), std::min( modelAnswer.size(), studentAnswer.size() ) ),
studentAnswer.begin(), size_t( 0 ),
std::plus<size_t>(), std::equal_to<char>() );
std::cout << n << std::endl;
return 0;
}
If you are using standard strings, with the proper includes (Mainly #include <string>), you can write a simple for loop to iterate over each character, comparing them.
std::string answer = "ABABACDA";
std::string stringToCompare = "ABADBDBB";
int score = 0;
for (unsigned int i = 0; (i < answer.size()) && (i < stringToCompare.size()); ++i)
{
if (answer[i] == stringToCompare[i])
{
++score;
}
}
printf("Compare string gets a score of %d.\n", score);
The above code works for me, printing the following result:
Compare string gets a score of 3.
Using a stringstream, you can push one character at a time into temporary variables and test for equivalence in a loop.
#include <iostream>
#include <string>
#include <sstream>
int main() {
std::istringstream model("ABABACDA");
std::istringstream student("ABADBDBB");
int diff = 0;
char m, s;
while ((model >> m) && (student >> s))
if (m != s) diff++;
std::cout << diff << std::endl; // 5
return 0;
}

How to find an element in a container before a given starting position?

I would like to find the last occurrence of an element in a container before some given starting position.
For instance, if I'm trying to find the last space before a given character in a string 's', I believe the obvious approach would be something like:
string::const_iterator b;
b = i; // <-- 'i' specifies where to start looking
while ((b != s.begin()) && (b[-1] != ' '))
b--;
Is there a better way to do this using STL algorithms?
I've tried:
b = find(string::const_reverse_iterator(i),
string::const_reverse_iterator(s.begin()), " ").base();
But I'm not sure if this works as intended.
You can use std::string::find_last_of and specify where it should search no farther than. The following will find the position of the first space before the word test.
#include <iostream>
#include <string>
int main()
{
std::string foo = "this is a test string";
auto pos = foo.find_last_of(" ", foo.find("test", 0));
std::cout << pos;
std::cin.get();
return 0;
}
Output:
9
For generic purposes, I think I would use std::find_end with an adequate lambda function. The example on the page illustrates well the function's behavior.
The reverse iterator solution will work:
#include <iostream>
#include <algorithm>
int main()
{
using std::string;
using const_iterator = string::const_iterator;
using const_reverse_iterator = string::const_reverse_iterator;
string s("This is an sample");
const_iterator pos = s.begin() + s.find("sample");
const_reverse_iterator result = std::find(const_reverse_iterator(pos), s.crend(), 's');
std::cout << string(s.cbegin(), result.base()) << '\n';
}
However, you might prefer the solution of #NathanOliver.

Find string with the most different characters

I have an array of strings,
sparnus , sapnus , lol , noon ...
As you can see they both start and end with the same character.
What can i do to compare, let's say "sparnus" with "sapnus" and find out which string has more different characters?
sparnus has s p a r n u s (6 different characters)
sapnus has s a p n u s (5 different characters)
(note: s repeats itself, so it's not a different character)
is there a function? algorithm? tips and advice are welcome.
Standard container std::set itself is in fact an algorithm.:)
For example
#include <iostream>
#include <string>
#include <set>
int main()
{
std::string s1( "sparnus" ), s2( "sapnus" );
std::cout << std::set<char>( s1.begin(), s1.end() ).size() << std::endl;
std::cout << std::set<char>( s2.begin(), s2.end() ).size() << std::endl;
return 0;
}
The output is
6
5
So you can use standard algorithm std::max_element with a predicat that compares sizes of two sets built from strings.
Here is an example
#include <iostream>
#include <string>
#include <set>
#include <algorithm>
#include <cstring>
#include <iterator>
int main()
{
const size_t N = 10;
char s[][N] = { "lol" , "noon", "sparnus", "sapnus" };
auto it = std::max_element( std::begin( s ), std::end( s ),
[]( const char *a, const char *b )
{
return std::set<char>( a, a + std::strlen( a ) ).size() <
std::set<char>( b, b + std::strlen( b ) ).size();
} );
std::cout << *it<< std::endl;
return 0;
}
The output is
sparnus
Or you can use the approach that was shown in one post here that was deleted by unknown reason. For example You can sort all words by using standard algorithm std::sort then apply standard algorithm std::unique and standard C function std::strlen will give you the number of unique characters in each string.
template <typename InputIterator>
std::size_t countDiffChars( InputIterator first,
InputIterator last )
{
bool lookup[1 << CHAR_BIT] {};
std::size_t count = 0;
while (first != last)
{
auto&& val = lookup[(unsigned char)*first++];
count += !val;
val = true;
}
return count;
}
Usage:
char const str[] = "Hello";
auto c = countDiffChars(std::begin(s), std::end(s));
Demo.
use a boolean array of 256 entries and loop on the string and set each flag of the array to true indexing by the letter of the string. At the end you may count the number of trues in the array and found how many different characters are there.
If instead of a boolean array you use an int array you may also count how many times a letter is found if that serves somehow! ( that may be done if you don't want to use sets as a previous answer points ).
#include <iostream>
#include <string>
int cnt(std::string s){
bool b[0x100]={false};int r=0;
for(int i:s) b[i]=true;for(int i:b) r+=i;
return r;
}
int main(int argc, char **argv)
{ std::cout<<cnt("sparnus")<<" "<<cnt("sapnus")<<std::endl;
return 0;
}