Related
so I'm currently working on a brute force attacker project in C++. I've managed to get it working, but one problem that I'm facing is that if the program actually managed to get a correct guess, the function still goes on. I think the problem is that the program fails to return a guess. Take a look at my code:
(Sorry for the mess, by the way, I'm not that experienced in C++ - I used to code in Python/JS.)
#include <iostream>
#include <cstdlib>
#include <string>
std::string chars = "abcdefghijklmnopqrstuvwxyz";
std::string iterateStr(std::string s, std::string guess, int pos);
std::string crack(std::string s);
std::string iterateChar(std::string s, std::string guess, int pos);
int main() {
crack("bb");
return EXIT_SUCCESS;
}
// this function iterates through the letters of the alphabet
std::string iterateChar(std::string s, std::string guess, int pos) {
for(int i = 0; i < chars.length(); i++) {
// sets the char to a certain letter from the chars variable
guess[pos] = chars[i];
// if the position reaches the end of the string
if(pos == s.length()) {
if(guess.compare(s) == 0) {
break;
}
} else {
// else, recursively call the function
std::cout << guess << " : " << s << std::endl;
iterateChar(s, guess, pos+1);
}
}
return guess;
}
// this function iterates through the characters in the string
std::string iterateStr(std::string s, std::string guess, int pos) {
for(int i = 0; i < s.length(); i++) {
guess = iterateChar(s, guess, i);
if(s.compare(guess) == 0) {
return guess;
}
}
return guess;
}
std::string crack(std::string s) {
int len = s.length();
std::string newS(len, 'a');
std::string newGuess;
newGuess = iterateStr(s, newS, 0);
return newGuess;
}
Edit : Updated code.
The main flaw in the posted code is that the recursive function returns a string (the guessed password) without a clear indication for the caller that the password was found.
Passing around all the strings by value, is also a potential efficiency problem, but the OP should be worried by snippets like this:
guess[pos] = chars[i]; // 'chars' contains the alphabet
if(pos == s.length()) {
if(guess.compare(s) == 0) {
break;
}
}
Where guess and s are strings of the same length. If that length is 2 (OP's last example), guess[2] is outside the bounds, but the successive call to guess.compare(s) will compare only the two chars "inside".
The loop inside iterateStr does nothing useful too, and the pos parameter is unused.
Rather than fixing this attempt, it may be better to rewrite it from scratch
#include <iostream>
#include <string>
#include <utility>
// Sets up the variable and start the brute force search
template <class Predicate>
auto crack(std::string const &src, size_t length, Predicate is_correct)
-> std::pair<bool, std::string>;
// Implements the brute force search in a single recursive function. It uses a
// lambda to check the password, instead of passing it directly
template <class Predicate>
bool recursive_search(std::string const &src, std::string &guess, size_t pos,
Predicate is_correct);
// Helper function, for testing purpouse
void test_cracker(std::string const &alphabet, std::string const &password);
int main()
{
test_cracker("abcdefghijklmnopqrstuvwxyz", "dance");
test_cracker("abcdefghijklmnopqrstuvwxyz ", "go on");
test_cracker("0123456789", "42");
test_cracker("0123456789", "one"); // <- 'Password not found.'
}
void test_cracker(std::string const &alphabet, std::string const &password)
{
auto [found, pwd] = crack(alphabet, password.length(),
[&password] (std::string const &guess) { return guess == password; });
std::cout << (found ? pwd : "Password not found.") << '\n';
}
// Brute force recursive search
template <class Predicate>
bool recursive_search(std::string const &src, std::string &guess, size_t pos,
Predicate is_correct)
{
if ( pos + 1 == guess.size() )
{
for (auto const ch : src)
{
guess[pos] = ch;
if ( is_correct(guess) )
return true;
}
}
else
{
for (auto const ch : src)
{
guess[pos] = ch;
if ( recursive_search(src, guess, pos + 1, is_correct) )
return true;
}
}
return false;
}
template <class Predicate>
auto crack(std::string const &src, size_t length, Predicate is_correct)
-> std::pair<bool, std::string>
{
if ( src.empty() )
return { length == 0 && is_correct(src), src };
std::string guess(length, src[0]);
return { recursive_search(src, guess, 0, is_correct), guess };
}
I've tried your code even with the modified version of your iterateStr() function. I used the word abduct as it is quicker to search for. When stepping through the debugger I noticed that your iterateChar() function was not returning when a match was found. Also I noticed that the length of string s being passed in was 6 however the guess string that is being updated on each iteration had a length of 7. You might want to step through your code and check this out.
For example at on specific iteration the s string contains: abduct but the guess string contains aaaabjz then on the next iteration the guess string contains aaaabkz. This might be your concerning issue of why the loop or function continues even when you think a match is found.
The difference in lengths here could be your culprit.
Also when stepping through your modified code:
for ( size_t i = 0; i < s.length(); i++ ) {
guess = iterCh( s, guess, i );
std::cout << "in the iterStr loop\n";
if ( guess.compare( s ) == 0 ) {
return guess;
}
}
return guess;
in your iterateStr() function the recursion always calls guess = iterCh( s, guess, i ); and the code never prints in the iterStr loop\n";. Your iterateChar function is completing through the entire string or sequence of characters never finding and return a match. I even tried the word abs as it is easier and quicker to step through the debugger and I'm getting the same kind of results.
I want to compare two strings in C++:
There is a function getName() that returns a string.
Now I can write Out << getName(); this will print the string.
However I want to print the string only if its value is arpit or arpit*N* where N is an integer. I don't want to print it if its value is arpita, arpitx, where N is something other than an integer or an empty string.
I know this can be easily done, but I want to do this in a minimal number of lines.
What I have done so far is:
char name1[] = getName();
char name2[] = "arpit";
for (int x = 0; x <= 4; x++){
if (name1[x] == name2[x]) continue;
else return ( Out << "not equal") ;
}
while(name1[x] ! = "\0"){
if(isdigit(name1[x])
x++;
else return (Out << "not equal") ;
}
Out << getName();
UPDATE 1
getName() returns a string until it encounters white space, and it will not return any line or 2 or more words.
If you have C++11:
static std::regex const matcher( "arpit\\d*" );
if ( regex_match( name, matcher ) ) {
// matches...
}
If you don't have C++11, boost::regex is practically identical.
If you don't have C++11, and you can't use boost:
if ( name1.size() >= name2.size()
&& std::equal( name2.begin(), name2.end(), name1.begin() )
&& std::find_if( name1.begin() + name2.size(),
name1.end(),
[]( unsigned char ch ) { return !isdigit( ch ); }
) == name1.end() )
// matches...
}
For the rest, your code has quite a few errors, and shouldn't
compile. In particular, there is nothing which getName()
could return which can be used to initialize a char []; the
type of a string in C++ is std::string, and your variables
should be:
std::string name1( getName() );
std::string name2( "arpit" );
(except that you need better names. The second might be
something like reference or header, for example.)
And of course, it's undefined behavior to call isdigit with
a char; you have to convert to unsigned char first.
auto s = getName();
if(s.size() >= 5 && s.substr(0,5) == "arpit")
Out << s;
std::set<std::string> m_allowed_strings;
std::string validate_string(const string & s)
{
if(m_allowed_strings.find(s) != m_allowed_strings.end())
return s;
return "";
}
cout << validate_string(getName());
I'm new to C++. I'm working on a project where I need to read mostly integers from the user through the console. In order to avoid someone entering non-digit characters I thought about reading the input as a string, checking there are only digits in it, and then converting it to an integer. I created a function since I need to check for integers several times:
bool isanInt(int *y){
string z;
int x;
getline(cin,z);
for (int n=0; n < z.length(); n++) {
if(!((z[n] >= '0' && z[n] <= '9') || z[n] == ' ') ){
cout << "That is not a valid input!" << endl;
return false;
}
}
istringstream convert(z); //converting the string to integer
convert >> x;
*y = x;
return true;
}
When I need the user to input an integer I'll call this function. But for some reason when I make a call tho this function the program doesn't wait for an input, it jumps immediately to the for-loop processing an empty string. Any thoughts? Thanks for your help.
There are many ways to test a string for only numeric characters. One is
bool is_digits(const std::string &str) {
return str.find_first_not_of("0123456789") == std::string::npos;
}
This would work:
#include <algorithm> // for std::all_of
#include <cctype> // for std::isdigit
bool all_digits(const std::string& s)
{
return std::all_of(s.begin(),
s.end(),
[](char c) { return std::isdigit(c); });
}
You can cast the string in a try/catch block so that if the cast fails you it would raise an exception and you can write whatever you want in the console.
For example:
try
{
int myNum = strtoint(myString);
}
catch (std::bad_cast& bc)
{
std::cerr << "Please insert only numbers "<< '\n';
}
Character-classification is a job typically delegated to the ctype facets of a locale. You're going to need a function that takes into account all 9 digits including the thousands separator and the radix point:
bool is_numeric_string(const std::string& str, std::locale loc = std::locale())
{
using ctype = std::ctype<char>;
using numpunct = std::numpunct<char>;
using traits_type = std::string::traits_type;
auto& ct_f = std::use_facet<ctype>(loc);
auto& np_f = std::use_facet<numpunct>(loc);
return std::all_of(str.begin(), str.end(), [&str, &ct_f, &np_f] (char c)
{
return ct_f.is(std::ctype_base::digit, c) || traits_type::eq(c, np_f.thousands_sep())
|| traits_type::eq(c, np_f.decimal_point());
});
}
Note that extra effort can go into making sure the thousands separator is not the first character.
try another way like cin.getline(str,sizeof(str)), and str here is char*. I think ur problem may be cause by other functions before calling this function. Maybe u can examine other parts of ur codes carefully. Breakpoints setting is recommended too.
Always use off-the-shelf functions. Never write alone.
I recommend
std::regex
Enjoy.
I'm very new to C++, boost etc.
I would like to know if there is already a function in boost or STL I can use to determine if a string is numeric.
Numeric strings may look like:
100
or
100.52
I know there are tons of examples how to write such a function but I would like to know if there is already a function I can use for this.
I'm looking for a pure C++-solution, not C.
[UPDATE:
I'm already using lexical_cast to convert my strings, I'm just wondering if there is a method like is_numeric I can use for this...]
No, there's not a ready-made way to do this directly.
You could use boost::lexical_cast<double>(your_string) or std::stod(your_string) and if it throws an exception then your string is not a double.
C++11:
bool is_a_number = false;
try
{
std::stod(your_string);
is_a_number = true;
}
catch(const std::exception &)
{
// if it throws, it's not a number.
}
Boost:
bool is_a_number = false;
try
{
lexical_cast<double>(your_string);
is_a_number = true;
}
catch(bad_lexical_cast &)
{
// if it throws, it's not a number.
}
boost::regex (or std::regex, if you have C++0x) can be used;
you can defined what you want to accept (e.g. in your context,
is "0x12E" a number or not?). For C++ integers:
"\\s*[+-]?([1-9][0-9]*|0[0-7]*|0[xX][0-9a-fA-F]+)"
For C++ floating point:
"\\s*[+-]?([0-9]+\\.[0-9]*([Ee][+-]?[0-9]+)?|\\.[0-9]+([Ee][+-]?[0-9]+)?|[0-9]+[Ee][+-]?[0-9]+)"
But depending on what you're doing, you might not need to
support things that complex. The two examples you cite would be
covered by
"[0-9]+(\\.[0-9]*)?"
for example.
If you're going to need the numeric value later, it may also be
just as easy to convert the string into an istringstream, and
do the convertion immediately. If there's no error, and you
extract all of the characters, the string was a number; if not,
it wasn't. This will give you less control over the exact
format you want to accept, however.
If performance is a concern at all, I would use boost.spirit.qi rather than std::stringstream:
#include <string>
#include <boost/spirit/include/qi_parse.hpp>
#include <boost/spirit/include/qi_numeric.hpp>
bool is_numeric(std::string const& str)
{
std::string::const_iterator first(str.begin()), last(str.end());
return boost::spirit::qi::parse(first, last, boost::spirit::double_)
&& first == last;
}
If you want to allow trailing whitespace then do the following instead:
#include <string>
#include <boost/spirit/include/qi_parse.hpp>
#include <boost/spirit/include/qi_numeric.hpp>
#include <boost/spirit/include/qi_char_class.hpp>
#include <boost/spirit/include/qi_operator.hpp>
bool is_numeric(std::string const& str)
{
std::string::const_iterator first(str.begin()), last(str.end());
return boost::spirit::qi::parse(first, last,
boost::spirit::double_ >> *boost::spirit::qi::space)
&& first == last;
}
Use a stringstream and return true if the convertion "ate" all the characters in the original string (=eof()).
bool is_numeric(const std::string& str) {
std::stringstream conv;
double tmp;
conv << str;
conv >> tmp;
return conv.eof();
}
bool is_numeric(std::string number)
{
char* end = 0;
std::strtod(number.c_str(), &end);
return end != 0 && *end == 0;
}
bool is_integer(std::string number)
{
return is_numeric(number.c_str()) && std::strchr(number.c_str(), '.') == 0;
}
Source
The following code
The following sentense, return true if "str" is composed of 0~9 only, otherwise, return false.
return str.find_first_not_of("0123456789") == std::string::npos
You could try a lexical_cast on the string.
From C++11, you can simply use one of std::stof, std::stod, std::stold for converting to float, double and long double, respectively. They convert a string to the numerical value or throw an exception, if there's a problem (see the reference). Here is an example with std::stod:
bool isNumeric(const std::string& str) {
try {
std::stod(str); // can safely ignore the return value, function is not [[nodiscard]]
return true;
}
catch (const std::exception&) {
return false;
}
}
Also have a look at the functions to convert a string to signed and unsigned integers.
There is no boost needed, only stl ...
A single char could be checked as an int (c >= '0' && c <= '9'), find_if_not will find the first char not matching the condition between [first] and [last]. If no match was found, it will return [last].
If additional chars like space,.- should be checked, add them.
#include <string>
#include <algorithm>
bool isNumeric(std::string strValue)
{
if (strValue.empty())
return false;
else
return (std::find_if_not( std::begin(strValue)
, std::end(strValue)
, [](char c)
{ return (c >= '0' && c <= '9'); }
) == std::end(strValue)
);
}
P.S.
#Jian Hu is an empty string numeric ?
When I use getline, I would input a bunch of strings or numbers, but I only want the while loop to output the "word" if it is not a number.
So is there any way to check if "word" is a number or not? I know I could use atoi() for
C-strings but how about for strings of the string class?
int main () {
stringstream ss (stringstream::in | stringstream::out);
string word;
string str;
getline(cin,str);
ss<<str;
while(ss>>word)
{
//if( )
cout<<word<<endl;
}
}
Another version...
Use strtol, wrapping it inside a simple function to hide its complexity :
inline bool isInteger(const std::string & s)
{
if(s.empty() || ((!isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) return false;
char * p;
strtol(s.c_str(), &p, 10);
return (*p == 0);
}
Why strtol ?
As far as I love C++, sometimes the C API is the best answer as far as I am concerned:
using exceptions is overkill for a test that is authorized to fail
the temporary stream object creation by the lexical cast is overkill and over-inefficient when the C standard library has a little known dedicated function that does the job.
How does it work ?
strtol seems quite raw at first glance, so an explanation will make the code simpler to read :
strtol will parse the string, stopping at the first character that cannot be considered part of an integer. If you provide p (as I did above), it sets p right at this first non-integer character.
My reasoning is that if p is not set to the end of the string (the 0 character), then there is a non-integer character in the string s, meaning s is not a correct integer.
The first tests are there to eliminate corner cases (leading spaces, empty string, etc.).
This function should be, of course, customized to your needs (are leading spaces an error? etc.).
Sources :
See the description of strtol at: http://en.cppreference.com/w/cpp/string/byte/strtol.
See, too, the description of strtol's sister functions (strtod, strtoul, etc.).
The accepted answer will give a false positive if the input is a number plus text, because "stol" will convert the firsts digits and ignore the rest.
I like the following version the most, since it's a nice one-liner that doesn't need to define a function and you can just copy and paste wherever you need it.
#include <string>
...
std::string s;
bool has_only_digits = (s.find_first_not_of( "0123456789" ) == std::string::npos);
EDIT: if you like this implementation but you do want to use it as a function, then this should do:
bool has_only_digits(const string s){
return s.find_first_not_of( "0123456789" ) == string::npos;
}
You might try boost::lexical_cast. It throws an bad_lexical_cast exception if it fails.
In your case:
int number;
try
{
number = boost::lexical_cast<int>(word);
}
catch(boost::bad_lexical_cast& e)
{
std::cout << word << "isn't a number" << std::endl;
}
If you're just checking if word is a number, that's not too hard:
#include <ctype.h>
...
string word;
bool isNumber = true;
for(string::const_iterator k = word.begin(); k != word.end(); ++k)
isNumber &&= isdigit(*k);
Optimize as desired.
Use the all-powerful C stdio/string functions:
int dummy_int;
int scan_value = std::sscanf( some_string.c_str(), "%d", &dummy_int);
if (scan_value == 0)
// does not start with integer
else
// starts with integer
You can use boost::lexical_cast, as suggested, but if you have any prior knowledge about the strings (i.e. that if a string contains an integer literal it won't have any leading space, or that integers are never written with exponents), then rolling your own function should be both more efficient, and not particularly difficult.
Ok, the way I see it you have 3 options.
1: If you simply wish to check whether the number is an integer, and don't care about converting it, but simply wish to keep it as a string and don't care about potential overflows, checking whether it matches a regex for an integer would be ideal here.
2: You can use boost::lexical_cast and then catch a potential boost::bad_lexical_cast exception to see if the conversion failed. This would work well if you can use boost and if failing the conversion is an exceptional condition.
3: Roll your own function similar to lexical_cast that checks the conversion and returns true/false depending on whether it's successful or not. This would work in case 1 & 2 doesn't fit your requirements.
Here is another solution.
try
{
(void) std::stoi(myString); //cast to void to ignore the return value
//Success! myString contained an integer
}
catch (const std::logic_error &e)
{
//Failure! myString did not contain an integer
}
Since C++11 you can make use of std::all_of and ::isdigit:
#include <algorithm>
#include <cctype>
#include <iostream>
#include <string_view>
int main([[maybe_unused]] int argc, [[maybe_unused]] char *argv[])
{
auto isInt = [](std::string_view str) -> bool {
return std::all_of(str.cbegin(), str.cend(), ::isdigit);
};
for(auto &test : {"abc", "123abc", "123.0", "+123", "-123", "123"}) {
std::cout << "Is '" << test << "' numeric? "
<< (isInt(test) ? "true" : "false") << std::endl;
}
return 0;
}
Check out the result with Godbolt.
template <typename T>
const T to(const string& sval)
{
T val;
stringstream ss;
ss << sval;
ss >> val;
if(ss.fail())
throw runtime_error((string)typeid(T).name() + " type wanted: " + sval);
return val;
}
And then you can use it like that:
double d = to<double>("4.3");
or
int i = to<int>("4123");
I have modified paercebal's method to meet my needs:
typedef std::string String;
bool isInt(const String& s, int base){
if(s.empty() || std::isspace(s[0])) return false ;
char * p ;
strtol(s.c_str(), &p, base) ;
return (*p == 0) ;
}
bool isPositiveInt(const String& s, int base){
if(s.empty() || std::isspace(s[0]) || s[0]=='-') return false ;
char * p ;
strtol(s.c_str(), &p, base) ;
return (*p == 0) ;
}
bool isNegativeInt(const String& s, int base){
if(s.empty() || std::isspace(s[0]) || s[0]!='-') return false ;
char * p ;
strtol(s.c_str(), &p, base) ;
return (*p == 0) ;
}
Note:
You can check for various bases (binary, oct, hex and others)
Make sure you don't pass 1, negative value or value >36 as base.
If you pass 0 as the base, it will auto detect the base i.e for a string starting with 0x will be treated as hex and string starting with 0 will be treated as oct. The characters are case-insensitive.
Any white space in string will make it return false.