This should be an easy one. I have a function that traverses a csv and tokenizes based on commas and does things with the tokens. One of these things is convert it into an int. Unfortunately, the first token may not always be an int, so when it is not, I'd like to set it to "5".
Currently:
t_tokenizer::iterator beg = tok.begin();
if(*beg! ) // something to check if it is an int...
{
number =5;
}
else
{
number = boost::lexical_cast<int>( *beg );
}
Seeing as lexical_cast throws on failure...
try {
number = boost::lexical_cast<int>(*beg);
}
catch(boost::bad_lexical_cast&) {
number = 5;
}
I don't normally like to use exceptions this way, but this has worked for me:
try {
number = boost::lexical_cast<int>(*beg);
} catch (boost::bad_lexical_cast) {
number = 5;
}
Related
Given an input string A, is there a concise way to generate a string B that is lexicographically larger than A, i.e. A < B == true?
My raw solution would be to say:
B = A;
++B.back();
but in general this won't work because:
A might be empty
The last character of A may be close to wraparound, in which case the resulting character will have a smaller value i.e. B < A.
Adding an extra character every time is wasteful and will quickly in unreasonably large strings.
So I was wondering whether there's a standard library function that can help me here, or if there's a strategy that scales nicely when I want to start from an arbitrary string.
You can duplicate A into B then look at the final character. If the final character isn't the final character in your range, then you can simply increment it by one.
Otherwise you can look at last-1, last-2, last-3. If you get to the front of the list of chars, then append to the length.
Here is my dummy solution:
std::string make_greater_string(std::string const &input)
{
std::string ret{std::numeric_limits<
std::string::value_type>::min()};
if (!input.empty())
{
if (std::numeric_limits<std::string::value_type>::max()
== input.back())
{
ret = input + ret;
}
else
{
ret = input;
++ret.back();
}
}
return ret;
}
Ideally I'd hope to avoid the explicit handling of all special cases, and use some facility that can more naturally handle them. Already looking at the answer by #JosephLarson I see that I could increment more that the last character which would improve the range achievable without adding more characters.
And here's the refinement after the suggestions in this post:
std::string make_greater_string(std::string const &input)
{
constexpr char minC = ' ', maxC = '~';
// Working with limits was a pain,
// using ASCII typical limit values instead.
std::string ret{minC};
auto rit = input.rbegin();
while (rit != input.rend())
{
if (maxC == *rit)
{
++rit;
if (rit == input.rend())
{
ret = input + ret;
break;
}
}
else
{
ret = input;
++(*(ret.rbegin() + std::distance(input.rbegin(), rit)));
break;
}
}
return ret;
}
Demo
You can copy the string and append some letters - this will produce a lexicographically larger result.
B = A + "a"
I'm trying to return the last word in a string but am having trouble with the for loops. When I try to test the function I am only getting empty strings. Not really sure what the problem is. Any help is much appreciated.
string getLastWord(string text)
{
string revLastWord = "";
string lastWord = "";
if(text == "")
{
return text;
}
for(size_t i = text.size()-1; i > -1; i--)
{
if((isalpha(text[i])))
{
revLastWord+=text[i];
}
if(revLastWord.size()>=1 && !isalpha(text[i-1]))
{
break;
}
}
for(size_t k = revLastWord.size()-1; k > -1; k--)
{
lastWord+=revLastWord[k];
}
return lastWord;
}
I was coding up another solution until I checked back and read the comments; they are extremely helpful. Moreover, the suggestion from #JustinRandall was incredibly helpful. I find that find_last_of()
and substr() better state the intent of the function--easier to write and easier to read. Thanks! Hope this helps! It helped me.
std::string get_last_word(std::string s) {
auto index = s.find_last_of(' ');
std::string last_word = s.substr(++index);
return last_word;
}
/**
* Here I have edited the above function IAW
* the recommendations.
* #param s is a const reference to a std::string
* #return the substring directly
*/
std::string get_last_word(const std::string& s) {
auto index = s.find_last_of(' ');
return s.substr(++index);
}
The other answers tell you what's wrong, though you should also know why it's wrong.
In general, you should be very careful about using unsigned value types in loop conditions. Comparing an unsigned type like std::size_t and a signed type, like your constant -1, will cause the signed to get converted into an unsigned type, so -1 becomes the largest possible std::size_t value.
If you put some print statements throughout your code, you'll notice that your loops are never actually entered, because the conditional is always false. Use an int when performing arithmetic and especially when signed numbers are compared with.
string Expression::addevaluate(string x){
stringrep = x; //Stringrep is the string that user typed in,
//it might be 5+6+7-8-9*3/(2+5)
int totalnum = stringrep.length();
for(int i=0;i < totalnum;i++){ //This for loop will seperate the
//string by "+" and output a vector
//with seperate string
int addop = stringrep.find("+");
addvector.push_back(stringrep.substr(0,addop));
string a =stringrep.substr(0,addop);
totalnum=totalnum-(a.length());
stringrep = stringrep.substr(addop+1,totalnum);
}
int vectorlength = addvector.size();
for(int i = 0;i<vectorlength;i++){
cout << i+1<<":"<<addvector[i]<<",";
}
subevaluate(addvector);
return stringrep;
}
string Expression::subevaluate(vector<string> &v){
int totalnum = v.size();
//This is the question, I have no idea how can i set the value totalnum
//If it's the size of vector,it's too small. If it's the last totalnum
//from last function. Then there is a error. In addition,I do not know
//what the error is.
for(int i=0;i < totalnum;i++){
int addop = v[i].find("-");
if(addop > 0){
subtvector.push_back(v[i].substr(0,addop));
string a =v[i].substr(0,addop);
totalnum=totalnum-a.length();
v[i] = v[i].substr(addop+1,totalnum);
}
}
int vectorlength = subtvector.size();
for(int i = 0;i<vectorlength;i++){
cout << i+1<<":"<<subtvector[i]<<",";
}
return stringrep;
}
I do not know why I did wrong for the second for loop. Please help me solve the for loop. In addition,how can i seperate all the string by."+","-","*","/". Then calculate the answer like a calculator. Thanks.
This implementation will not work... suppose you have
"1+2*(3+4)"
the first split (even when written correctly) will get
"1"
"2*(3"
"4)"
What are you going to do with "2*(3" ?
At the very minimum to write a calculator with this approach you need:
add "(" front and add ")" at the end (i.e. change to "(1+2*(3+4))"
look for last OPEN parenthesis
move from there to the first CLOSED parenthesis
process what is in-between (i.e. "3+4") and replace the whole parenthesized expression it in the original string with the result (i.e. get from "1+2*(3+4)" to "(1+2*7)")
repeat until there are no more parenthesis
For splitting a string on a given character you should write a dedicated function, for example:
std::vector<std::string> split(const std::string& text, char sep) {
std::vector<std::string> result;
size_t pos = text.find(sep);
while(pos != std::string::npos) {
result.push_back(text.substr(0, pos));
text = text.substr(pos + 1);
}
result.push_back(text);
return result;
}
then you can write
std::vector<std::string> res = split(text, '+');
to get from "1+2*3+4" to a vector containing "1", "2*3", "4".
PS: Note that this way of computing expression is not what normally is done, but it can be made working so you should in my opinion keep working on it until it's done.
I think it will be difficult to make the code work when you split the string into a vector. The operator precedence will be too hard to handle, I think.
How about a recursive process?
In this way you can simplify the original string step by step. You just keep calling the evaluate function with substrings until they are turned into simple expressions.
Example:
exp = 12/(5+1)
call 1: call f("12/(5+1)")
call 1: f identifies the substring "5+1" and call itself (recursive)
call 2: call f("5+1")
call 2: simple expression calculates into "6" which is returned
call 1: The substring "(5+1)" is replaced by the returned "6"
call 1: exp now looks "12/6"
call 1: simple expression calculates into "2" which is returned
More complex expressions like "48/(5 + (2*3/(3-1))) would just result in more calls so that the string is simplified step by step.
The code could look like the code below. Only the structure is include - it is for OP to fill in the actual code.
bool isSimpleExpression(string& s)
{
// Return true if s is simple, i.e. X+Y, X-Y, X*Y, X/Y
// Otherwise false
}
string evaluateString(string& exp)
{
while(!isSimpleExpression(exp))
{
// exp must be broken into smaller part as it isn't simple yet
if (ExpContainsParanthesis() )
{
// Example: exp is "12/(5+1)"
string s1 = FindSubstringInMostInnerMatchingParanthesis(exp);
// Example: s1 is "5+1"
// Example: call evaluateString("5+1")
strint s2 = evaluateString(s1); // Recursive call
// Example: s2 is 6
ReplaceS1WithS2(exp, s1, s2);
// Example: exp is "12/6"
}
else if (ExpContainsMultiplication())
{
// Find the substring with multiplication
// Call this function with the substring
// Replace the substring with the returned result
}
else if ....
{
// division
}
// ... and so on
}
// Calculate the simple expression
string result;
// ..
// ..
return result;
}
I wrote a program to find duplicate entry in a table. I am a beginner in C++, hence I don't know how this program is working efficient. Is there any other idea to write this program? Here I have 3 tables (2D Vector), that they are 1)aRecord_arr 2)mainTable and 3)idxTable. idxtable is use to identify the keys to check duplicate entry. aRecord_arr table to be add in maintable. If it is already exist in maintable, it will show the error "Duplicate Entry". So Check this program, and give your suggestions.
typedef vector<string> rec_t;
typedef vector<rec_t> tab_t;
typedef vector<int> cn_t;
int main()
{
tab_t aRecord_arr= { {"a","apple","fruit"},
{"b","banana","fruit"} };
tab_t mainTable = { {"o","orange","fruit"},
{"p","pineapple","fruit"},
{"b","banana","fruit"},
{"m","melon","fruit"},
{"a","apple","fruit"},
{"g","guava","fruit"} };
tab_t idxTable = { {"code","k"},
{"name","k"},
{"category","n"}};
size_t Num_aRecords = aRecord_arr.size();
int idxSize = idxTable.size();
int mainSize = mainTable.size();
rec_t r1;
rec_t r2;
tab_t t1,t2;
cn_t idx;
for(int i=0;i<idxSize;i++)
{
if(idxTable[i][1]=="k")
{
idx.push_back(i);
}
}
for(size_t j=0;j<Num_aRecords;j++)
{
for(unsigned int id=0;id<idx.size();id++)
{
r1.push_back(aRecord_arr[j][idx[id]]);
}
t1.push_back(std::move(r1));
}
for(int j=0;j<mainSize;j++)
{
for(unsigned int id=0;id<idx.size();id++)
{
r2.push_back(mainTable[j][idx[id]]);
}
t2.push_back(std::move(r2));
}
for(size_t i=0;i<t1.size();i++)
{
for(size_t j=0;j<t2.size();j++)
{
if(t1[i]==t2[j])
{
cout<<"Duplicate Entry"<<endl;
exit(0);
}
}
}
}
If you want to avoid duplicate entries in an array, you should consider using a std::setinstead.
What you want is probably a std::map or a std::set
Don't reinvent the wheel, the STL is full of goodies.
You seem to be rooted in a weakly typed language - but C++ is strongly typed.
You will 'pay' the disadvantage of strong typing almost no matter what you do, but you almost painstakingly avoid the advantage.
Let me start with the field that always says 'fruit' - my suggestion is to make this an enum, like:
enum PlantType { fruit, veggie };
Second, you have a vector that always contain 3 strings, all with the same meaning. this seems to be a job for a struct, like:
struct Post {
PlantType kind;
char firstchar;
string name;
// possibly other characteristics
};
the 'firstchar' is probably premature optimization, but lets keep that for now.
Now you want to add a new Post, to an existing vector of Posts, like:
vector<Post> mainDB;
bool AddOne( const Post& p )
{
for( auto& pp : mainDB )
if( pp.name == p.name )
return false;
mainDB.push_back(p);
return true;
}
Now you can use it like:
if( ! AddOne( Post{ fruit, 'b', "banana" } ) )
cerr << "duplicate entry";
If you need speed (at the cost of memory), switch your mainDB to map, like:
map<string,Post> mainDB;
bool AddOne( const Post& p )
{
if( mainDB.find(p.name) != mainDB.end() )
return false;
mainDB[p.name]=p;
return true;
}
this also makes it easier (and faster) to find and use a specific post, like
cout << "the fruit is called " << mainDB["banana"].name ;
beware that the above will cause a runtime error if the post dont exists
As you can see, firstchar was never used, and could be omitted. std::map
has a hash-function-specialization for string keys, and it will probably be
orders of magnitude faster than anything you or I could whip up by hand.
All of the above assumed inclusion of the correct headers, and
using namespace std;
if you dont like using namespace, prepend std:: to all the right places
hope it helps :)
I have a function where i want to be able return what is printed out so then i can print the output on the page. How will i return both of the string which are outputted within both of those if statements ?
std::vector<std::string> el;
split(el,message,boost::is_any_of("\n"));
std::string a ("");
for(int i = 0; i < el.size(); i++)
{
if(el[i].substr(0,3) == ".X/")
{
DCS_LOG_DEBUG("--------------- Validating .X/ ---------------")
std::string str = el[i].substr(3);
std::vector<std::string>st;
split(st,str,boost::is_any_of("/"));
boost::regex const string_matcher(splitMask[0]);
if(boost::regex_match(st[0],string_matcher))
{
a = "Correct Security Instruction";
}
else
{
a = "Incorrect Security Instruction"
}
boost::regex const string_matcher1(splitMask[1]);
if(boost::regex_match(st[1],string_matcher1))
{
a = "Correct Security screening result"
}
else
{
a = "Incorrect Security screening result"
}
return a;
}
}
Thankfull for any help :)
You can return an std::pair of strings, for instance.
Define a class with two appropriately-named string members and return an instance of that.
Then, start to think about what methods or other data would be useful to have on that class.
You can push the strings in a std::vector that is passed to the function as a reference and later iterate over the vector upon return.
I would return a std::pair of bool values (one to indicate if the instruction is correct, and one to indicate if the screening result is correct), and let the calling code interpret the results.