I'm working on an app with a map and do not want a person to be able to enter an invalid point on the map (think Latitude and longitude).
Say you have a panel that looks something like this. Note not codewise how it looks, just how it would look like if you looked at the application:
[My great application]
Textbox1 [XX:XX:XX]
Textbox2 [XX:XX:XX]
Textbox3 [XX:XX:XX]
Pushbutton [APPLY]
My main problem
I have no way of knowing if what someone enters is right in the text boxes. My TextBox is expecting 3 sets integers [XX:XX:XX]. Nothing below 00, and nothing above 99 (strictly 2 digits). For this example I will only show on int to keep it short:
int myInt = NULL; //Don't want garbage data here
bool isValid = false;
//Gets input and sets textbox to myInt
std::string myString = std::to_string(myInt); //Cast int to a string
If(myString.length() - 1 == 0) //NULL intToString.length() == 1?
{
std::cout << "Incorrect, please try again" << std::endl;
}
else
{
isValid = true;
}
if(isValid)
{
//applyChanges(); <-- MY INTS WOULD GO INTO THIS
}
then I quickly realized that 0-9 are totally valid. (00, 01, ..., 09). So this wouldn't work.
My question
How am I able to test if what a user inputs is correct? It's not quite making sense to me. I'm not sure what else I can do besides test the length.
All in all I want to find a way to get a condition so that when all is well THEN isValid = true;
Notes
I can directly access all the data in the textboxes
I have the ability to check for gaining or loss of focus
Here's a solution I came up with. Let me know if I misunderstood your problem.
The algorithm is simple:
Splits the input into 3 parts;
Make sure each is 2 digits long;
Convert to an integer and make sure its within range;
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
// Simple string split algorithm
std::vector<std::string> string_split(
std::string const& str,
char delimiter)
{
std::istringstream ss{str};
std::vector<std::string> result;
std::string line;
while(std::getline(ss, line, delimiter)) {
result.emplace_back(std::move(line));
}
return result;
}
// Validates the input
bool isValid(std::string const& input) {
// Split string on each ':'
// 00:00:00
// ^ ^
auto substr = string_split(input, ':');
// If there are not 3 parts, its malformed
if(substr.size() != 3)
return false;
// For reach result...
for(auto const& str : substr) {
// If it is not 2 digits long, error.
if(str.size() != 2)
return false;
try {
// Try converting it to an integer
// This throws on failure
auto value = std::stoi(str);
// make sure its within range
return value >= 0 && value <= 99;
} catch(...) {
// Failed to convert
return false;
}
}
return true;
}
int main()
{
// Some tests
std::vector<std::string> inputs{
"00:00:00",
"99:99:99",
"1:00:00",
"AA:00:00",
"0B:0000",
"0B:00c00",
};
// Run tests and print result
for(auto& input : inputs) {
if(isValid(input)) {
std::cout << input << " - Valid!"<< std::endl;
} else {
std::cout << input << " - Invalid!"<< std::endl;
}
}
}
Results:
$g++ -o main *.cpp
$main
00:00:00 - Valid!
99:99:99 - Valid!
1:00:00 - Invalid!
AA:00:00 - Invalid!
0B:0000 - Invalid!
0B:00c00 - Invalid!
Hope this helps,
Cheers.
I agree with markhc but you might also like using a regular expression way of doing things. The advantage is that the same code can be used to validate other type of input also and of course is much shorter.
Here is the code (parts stolen from markhc!):
#include <regex>
#include <string>
#include <iostream>
using namespace std;
int main()
{
string regx = R"([0-9]{2}:[0-9]{2}:[0-9]{2})";
smatch matches;
// some test data
std::vector<std::string> inputs{
"00:00:00",
"99:99:99",
"1:00:00",
"AA:00:00",
"0B:0000",
"0B:00c00",
};
// Run tests and print result
for (auto& input : inputs) {
if (regex_search(input, matches, regex(regx)))
{
std::cout << input << " - Valid!" << std::endl;
}
else {
std::cout << input << " - Invalid!" << std::endl;
}
}
}
This also produces as output:
00:00:00 - Valid!
99:99:99 - Valid!
1:00:00 - Invalid!
AA:00:00 - Invalid!
0B:0000 - Invalid!
0B:00c00 - Invalid!
The regular expression [0-9]{2}:[0-9]{2}:[0-9]{2} is explained below.
[0-9] means digit 0-9
{2} means 2 times
: means the separator you need
To show how flexible the regular expressions are:
..If you wanted a different format like 000:0000 for example you just have to change the regex to
[0-9]{3}:[0-9]{4} and the code remains the same.
I'm trying to make a program that contiues to randomly generate a string of letters, but stop when it has generated a word the user have entered.
I have made it generate the letters but I don't know how to make it recognize a word from it.
for (int i = 1; i < 1000; i++) {
int n = rand() % 26;
char c = (char)(n + 65);
cout << c;
}
return 0;
I'm gonna change the for loop to a while loop when I know how to make it find the users input.
I'm very new to programming so the solution is most likely obvious.
As one of the comments suggests, you need to create a string from your chars. After that, I would suggest looking at:
http://www.cplusplus.com/reference/string/string/find/
its a search function for strings used on other strings... which is exactly what you're looking for.
One of the comments also suggest using == to compare the string you created from chars and the user input string, but there isn't much use in doing it this way when the string::find function does the exact same thing but more efficently
A Modern C++ solution.
The interesting part in the main function which is below.
#include <random>
#include <iostream>
#include <algorithm>
#include <list>
#include <sstream>
void NotFoundMessage(std::list<char>& randomSequence);
void FoundMessage(long long iterationCount);
// Seed with a real random value, if available
std::random_device r;
std::default_random_engine e1(r());
// A random character between 'A' and 'Z'
std::uniform_int_distribution<int> uniform_dist('A', 'Z');
char nextRandomCharacter()
{
return static_cast<char>(uniform_dist(e1));
}
int main()
{
std::string input;
std::cin >> input;
// <--- NEEDS CHECKS IF INPUT IS CORRECT!!!!
std::list< char > randomSequence;
// Fill randomSequence with initial data
for ( const auto& c : input )
{
randomSequence.push_back( nextRandomCharacter() );
}
long long iterationCount = 1;
while ( !std::equal( input.begin(), input.end(),
randomSequence.begin() ) )
{
NotFoundMessage( randomSequence );
// remove character from front and add random char at end.
randomSequence.pop_front();
randomSequence.push_back( nextRandomCharacter() );
iterationCount++;
}
FoundMessage(iterationCount);
}
void NotFoundMessage(std::list<char>& randomSequence)
{
std::cout << "Not found in: ";
for ( const auto& c : randomSequence )
std::cout << c << ' ';
std::cout << '\n';
}
void FoundMessage(long long iterationCount)
{
std::cout << "Found after "
<< iterationCount
<< " iterations."
<< std::endl;
}
I need to get all regex matches and their positions.
For example, I have this regex:
std::regex r("(a)|(b)|(c)");
And this input text:
std::string text("abcab");
Now I want to loop the matches there in every loop I can access all occurrences from one match. So in first loop I could get "a" at position 0 and "a" at position 3. In second loop it'd be "b" at 1 and "b" at 4. And in third loop it'd be "c" at position 2. How can I do this?
Currently I have every regex part separately (regex for (a), (b) and (c)) and go through them one by one. But there are quite many of them so I'm looking for better/faster solution.
You can declare string vectors to store the captured values in, and then check which alternative branch matched, and add it to the corresponding vector.
Here is a C++ demo:
#include <string>
#include <iostream>
#include <regex>
using namespace std;
int main() {
std::regex r("(a)|(b)|(c)");
std::string s = "abcab";
std::vector<std::string> astrings; // Declare the vectors to
std::vector<std::string> bstrings; // populate with the contents
std::vector<std::string> cstrings; // of capturing groups
for(std::sregex_iterator i = std::sregex_iterator(s.begin(), s.end(), r);
i != std::sregex_iterator();
++i)
{
std::smatch m = *i;
if (m[1].matched) { // Check if Group 1 matched and
astrings.push_back(m[1].str()); // Put a value into a string vector
}
else if (m[2].matched) { // Check if Group 2 matched and
bstrings.push_back(m[2].str()); // Put a value into b string vector
}
else if (m[3].matched) { // Check if Group 3 matched and
cstrings.push_back(m[3].str()); // Put a value into c string vector
}
}
// Printing vectors - DEMO
for (auto i: astrings)
std::cout << i << ' ';
std::cout << "\n";
for (auto i: bstrings)
std::cout << i << ' ';
std::cout << "\n";
for (auto i: cstrings)
std::cout << i << ' ';
return 0;
}
You may also consider using std::regex_constants::optimize flag when declaring the regexp (see Galik's comment).
I would like to parse through two vectors of strings and find the strings that match each other and the ones that do not.
Example of what I want get:
input vector 1 would look like: [string1, string2, string3]
input vector 2 would look like: [string2, string3, string4]
Ideal output:
string1: No Match
string2: Match
string3: Match
string4: No Match
At the moment I use this code:
vector<string> function(vector<string> sequences, vector<string> second_sequences){
for(vector<string>::size_type i = 0; i != sequences.size(); i++) {
for(vector<string>::size_type j = 0; j != second_sequences.size(); j++){
if (sequences[i] == second_sequences[j]){
cout << "Match: " << sequences[i];
}else{
cout << "No Match: " << sequences[i];
cout << "No Match: " << second_sequences[j];
}
}
}
}
It works great for the ones that match, but iterates over everything so many times,
and the ones that do not match get printed a large number of times.
How can I improve this?
The best code is the code that you did not have to write.
If you take a (STL) map container it will take care for you of sorting and memorizing the different strings you encounter.
So let the container works for us.
I propose a small code quickly written. You need for this syntax to enable at least the C++ 2011 option of your compiler ( -std=c++11 on gcc for example ). The syntax that should be used before C++11 is much more verbose (but should be known from a scholar point of view ).
You have only a single loop.
This is only a hint for you ( my code does not take into account that in the second vector string4 could be present more than once, but I let you arrange it to your exact needs)
#include <iostream>
#include <vector>
#include <string>
#include <map>
using namespace std;
vector<string> v1 { "string1","string2","string3"};
vector<string> v2 { "string2","string3","string4"};
//ordered map will take care of "alphabetical" ordering
//The key are the strings
//the value is a counter ( or could be any object of your own
//containing more information )
map<string,int> my_map;
int main()
{
cout << "Hello world!" << endl;
//The first vector feeds the map before comparison with
//The second vector
for ( const auto & cstr_ref:v1)
my_map[cstr_ref] = 0;
//We will look into the second vector ( it could also be the third,
//the fourth... )
for ( const auto & cstr_ref:v2)
{
auto iterpair = my_map.equal_range(cstr_ref);
if ( my_map.end() != iterpair.first )
{
//if the element already exist we increment the counter
iterpair.first->second += 1;
}
else
{
//otherwise we put the string inside the map
my_map[cstr_ref] = 0;
}
}
for ( const auto & map_iter: my_map)
{
if ( 0 < map_iter.second )
{
cout << "Match :";
}
else
{
cout << "No Match :" ;
}
cout << map_iter.first << endl;
}
return 0;
}
Output:
No Match :string1
Match :string2
Match :string3
No Match :string4
std::sort(std::begin(v1), std::end(v1));
std::sort(std::begin(v2), std::end(v2));
std::vector<std::string> common_elements;
std::set_intersection(std::begin(v1), std::end(v1)
, std::begin(v2), std::end(v2)
, std::back_inserter(common_elements));
for(auto const& s : common_elements)
{
std::cout<<s<<std::endl;
}
I have a string as "1.0.0" and I want to extract the "1", "0", and "0". If the last zero is not present, the string must store 0 by default:
verstr.substr(0,verstr.find(".");
The above statement can find the first digit that is "1", however, I am not able to think of a solution for extracting the remainder of the string.
After this i convert it to a long as:
va = atol(verstr.substr(0,verstr.find(".")).c_str());
so i want the "1" in va , 0 in "vb" and so on
Thanks.
C++11 solution:
#include <iostream>
#include <string>
#include <regex>
using namespace std;
int main(int, char **) {
string version("1.2.3");
match_results<string::const_iterator> m;
regex re("([0-9]+)\\.([0-9]+)(\\.([0-9]+))?");
if (regex_match(version, m, re)) {
int major = stoi(m[1].str()),
minor = stoi(m[2].str()),
rev = stoi(m[4].str().length() == 0 ? 0 : m[4].str());
cout << "major: " << major << endl;
cout << "minor: " << minor << endl;
cout << "rev: " << rev << endl;
} else {
cout << "no match\n";
}
}
The regular expression used is ([0-9]+)\.([0-9]+)(\.([0-9]+))? and breaks down as follows:
[0-9]+ matches one or more digits
\. matches a literal dot.
? following the last expression indicates that it is optional
Expressions wrapped in ( and ) are capture groups. There are five capture groups in this expression:
0 - always matches the entire string - we don't use this.
1 - matches the major version number.
2 - matches the minor version number.
3 - matches a dot followed by the revision number - we don't use this but it is necessary because we use the parentheses followed by a ? to make this whole group optional.
4 - matches the revision number.
Not sure if I understand what you need, if you want to retrieve the digits as strings, with a minimum of x digits, you can do something like this.
vector<string> GetVersion(const string &strInput, int iMinSize)
{
vector<string> vRetValue;
std::stringstream ss(strInput);
string strItem;
while(std::getline(ss, strItem, '.'))
vRetValue.push_back(strItem);
while(vRetValue.size() < iMinSize)
vRetValue.push_back("0");
return vRetValue;
}
int _tmain(int argc, _TCHAR* argv[])
{
vector<string> vRetValue = GetVersion("1.0", 3);
return 0;
}
A possibility would to use std::sscanf(). It is simple to use and provides a level of error checking with relatively few lines of code:
#include <iostream>
#include <string>
#include <cstdio>
int main()
{
std::string input[] = { "1.0.7", "1.0.", "1.0", "1.", "1" };
for (size_t i = 0; i < sizeof(input)/sizeof(input[0]); i++)
{
std::cout << input[i] << ": ";
// Init to zero.
int parts[3] = { 0 };
// sscanf() returns number of assignments made.
if (std::sscanf(input[i].c_str(),
"%d.%d.%d",
&parts[0],
&parts[1],
&parts[2]) >= 2)
{
// OK, the string contained at least two digits.
std::cout << parts[0]
<< ","
<< parts[1]
<< ","
<< parts[2]
<< "\n";
}
else
{
std::cout << "bad format\n";
}
}
return 0;
}
Output:
1.0.7: 1,0,7
1.0.: 1,0,0
1.0: 1,0,0
1.: bad format
1: bad format
See online demo: http://ideone.com/0Ox9b .
find and substr are two really nice family of function overloads that are pretty well suited to many simple parsing problems, especially when your syntax checking only needs to be loose.
To extract multiple scalars out of your version vector, store the found index somewhere:
const auto a = verstr.find('.');
const std::string major = verstr.substr(0, a);
Then re-use it with one of the overloads of string::find, saying start searching at one after a:
const auto b = verstr.find ('.', a+1);
const std::string minor = verstr.substr(a+1, b);
And so forth.
If you need a syntax check, compare the returned indices against string::npos:
const auto a = verstr.find('.');
if (std::string::npos == a)
.... bad syntax ....
Pastebin style version of this answer:
#include <string>
#include <stdexcept>
#include <iostream>
struct Version
{
std::string Major, Minor, Patch;
Version(std::string const &Major)
: Major(Major), Minor("0"), Patch("0")
{}
Version(std::string const &Major, std::string const &Minor)
: Major(Major), Minor(Minor), Patch("0")
{}
Version(std::string const &Major, std::string const &Minor, std::string const &Patch)
: Major(Major), Minor(Minor), Patch(Patch)
{}
};
std::ostream& operator<< (std::ostream &os, Version const &v)
{
return os << v.Major << '.' << v.Minor << '.' << v.Patch;
}
Version parse (std::string const &verstr) {
if (verstr.empty()) throw std::invalid_argument("bad syntax");
const auto first_dot = verstr.find('.');
if (first_dot == std::string::npos)
return Version(verstr);
const auto second_dot = verstr.find('.', first_dot+1);
if (second_dot == std::string::npos)
return Version(verstr.substr(0, first_dot),
verstr.substr(first_dot+1, second_dot));
return Version(verstr.substr(0, first_dot),
verstr.substr(first_dot+1, second_dot),
verstr.substr(second_dot+1));
}
and then
int main () {
std::cout << parse("1.0") << '\n'
<< parse("1.0.4+Patches(55,322)") << '\n'
<< parse("1") << '\n';
parse(""); // expected to throw
}
try something like this instead of solution below the line
string s = "1.0.0";
string delimiters = ".";
size_t current;
size_t next = -1;
do
{
current = next + 1;
next = s.find_first_of( delimiters, current );
string current_substring = s.substr( current, next - current ); // here you have the substring
}
while (next != string::npos);
Ok, please don't use this solution below, if you really don't know what you're doing, according to discussion below this answer with #DavidSchwartz
Take a look at function strtok http://www.cplusplus.com/reference/clibrary/cstring/strtok/
char str[] = "1.0.0";
char * pch;
pch = strtok (str,".");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, ".");
}
Take a look at Boost libraries, specifically String Algo.
Standard library support for string manipulation is somewhat limited in C++. And reinventing the wheel is just plain bad.
Update:
I was asked in comments why I consider all find/substr based solutions bad style.
I'll try my best.
As questions does not states otherwise, performance is not a question here. Maintainability and readability are much more important. All solutions proposed here tightly tie split algorithm semantics with a specific version parsing algorithm semantics. This hurts both.
This hurts maintainability, because when you will need to change version format, it will involve changing the very same block of code that implements splitting, making it more error-prone. Same applies to unit-tests.
This hurts readability, because due to mixed semantics I can't at once guess an intent behind this block of code. For example, when I am looking up parse algorithm to check how missing 3d version argument is handled, I'd better not waste my time digging through split implementation details.
If parsing pattern would have been slightly more difficult, I'd have advised regular expressions. But in this case splitting string by a delimiter is an action generic and often used enough to justify having it as a separate function.
if it's only simple char comparison in a small string...
char[] should not be so bad... and c functions should work... (EDIT: for some, its a blasphemy... a lot of C++ method use char* whether it's const or not).
why use an object if it's to has the same functionality with more memory to be used, and more time for the process to spend?
EDIT:
I saw that some answer suppose to create a lot of string object... i don't khnow if it's really the best way...
a little 2 line recursive C like function can do that without gasping a lot.
In c++ code I probably would do that with string object, as it's negligible gasp... but just to say it so.
In string object i would use the length property to get the last char first (with [] operator, or appropriate method).
then just need to get the two elements (in a loop, or with 2 back reference in an object accepting regex (which is less efficient))