Using getopt when options have options C++ - c++

I am using getopt to parse command line arguments and my issue is that some of my options have options. My project is to test different backend implementations of maps and the -b flag specifies which implementation to use. Most of the options are straight forward but for the backends that use hash tables (chained and open) there is an additional -number that can be added to the end to specify the load factor. So it would be -b chained-0.75.
My idea is that I would take the substring from 8 to the end (or 5 for the "open" option) because that would ignore the "chained-" part of the string and then use atof() to convert it to a double and then declare my map. I believe optarg is a char array (?) and I keep running into type mismatch errors even though I have tried std::string str(optarg); I also don't know what to write in place of else if (strcasecmp(optarg, "chained") == 0) because there could be any number at the end of it. So right now when I do -b chained-0.75 it calls the usage function.
Here is what I have so far:
while ((c = getopt(argc, argv, "hb:n:p:")) != -1) {
switch (c) {
case 'b':
if (strcasecmp(optarg, "unsorted") == 0) {
map = new UnsortedMap();
} else if (strcasecmp(optarg, "sorted") == 0) {
map = new SortedMap();
} else if (strcasecmp(optarg, "bst") == 0) {
map = new BSTMap();
} else if (strcasecmp(optarg, "unordered") == 0) {
map = new UnorderedMap();
} else if (strcasecmp(optarg, "chained") == 0) {
double load_factor;
std::string str(optarg);
std::string ld_str = str.substr(8, str.length()-1);
load_factor = atof(ld_str);
map = new ChainedMap(load_factor);
} else if (strcasecmp(optarg, "open") == 0) {
map = new OpenMap();
} else {
usage(1);
}
break;
Any hints or ideas would be appreciated!

strcasecmp() is an exact match comparison function, this strcasecmp() will obviously not match "chained-0.75". The only thing that strcasecmp() will match against the string "chained" is "chained", not "chained-0.75", not "changed-foobar", not "chained-anything".
The right function is strncasecmp:
} else if (strncasecmp(optarg, "chained-", 8) == 0) {
Note that you're comparing against "chained-", and not just "chained". A few moments' of thinking should make it clear why.
The existing code also fails to take into account the possibility that the string after "chained-" is not a number, since atof() does not handle parsing errors. If you need to be able to detect and handle an error here, use strtod() instead of atof().

Related

How to run main statement and else statement only once, inside loop?

So I'm trying to add controller support to an old game, but am having some trouble with the logic. I need to execute a command once a trigger is pressed, one time. Otherwise I need to execute a command one time if the trigger is released. All inside a while loop, I know I'm missing something obvious. I'm having trouble only sending the -attack command once.
while (true) {
Sleep(100);
bool flag = false;
if ((gamepad.rightTrigger == 1) && (flag == false))
{
SendCommandToConsole(0, 0, "+attack");
flag = true;
}
else if ((gamepad.rightTrigger == 0) && (flag == true))
{
SendCommandToConsole(0, 0, "-attack");
}
}
Let me show you my proposal:
bool flag = false;
while (true) {
Sleep(100);
if ((gamepad.rightTrigger == 1) && (!flag))
{
SendCommandToConsole(0, 0, "+attack");
flag = true;
}
else if ((gamepad.rightTrigger == 0) && flag)
{
SendCommandToConsole(0, 0, "-attack");
}
}
You see three things:
flag is declared outside of the while-loop, which has been proposed before and which is the answer to your question.
Don't check for flag == true or flag == false, just for flag or !flag, this improves the readability of your code.
I removed some obsolete empty lines. It's ok to leave an empty line between different parts of your source code, but it's advised to keep if-, then-, else-loops together, also for readability purposes.

Testing multiple boolean values in a single IF statement

I a newbie C++ programmer trying to test aruments/parameters passed to a program.
Multiple arguments can be passed to the program, however I want to test that if certain arguments are passed then other arguments become invalid.
e.g. PGM accepts arg(1) arg(2) arg(3) arg(4) arg(5) etc...
if arg(1) and arg(2) are supplied then arg(3), arg(4) and arg(5) etc... are invalid and the program should terminate with an error message if they are also supplied along with arg(1) and arg(2).
I've thought that using boolean IF tests would be a good way to check if certain values are true/false.
I searched on stackoverflow but not found an answer that encompasses exactly what i'm trying to do. If someone can point me in the right direction or suggest a far more efficient way of doing this I would be very grateful.
My code currently looks like this:
bool opt1 = false;
bool opt2 = false;
bool opt3 = false;
bool opt4 = false;
bool opt5 = false;
for(int i=1; i<argc; i++) {
char *str = argv[i];
if (strcmp (str, "-opt1:")==0) {opt1 = true;}
else if (strcmp (str, "-opt2:")==0) {opt2 = true;}
else if (strcmp (str, "-opt3:")==0) {opt3 = true;}
else if (strcmp (str, "-opt4:")==0) {opt4 = true;}
else if (strcmp (str, "-opt5:")==0) {opt5 = true;}
}
if((opt1) && (opt2) && (~(opt3)) && (~(opt4)) && (~(opt5)) {
** DO SOMETHING **
} else {
** DISPLAY ERROR MESSAGE AND USAGE TEXT **
}
A good solution would be using operands ! and &&
! denotes "not" (or in such case "not true") while && combines two different logical comparisons (in such case, "logic test 1" and "logic test 2")
Here's an example to do it:
if((opt1 && opt2)&&(!(opt3||opt4||opt5))){
/*
Do something if opt1 and opt2 are true and others are false
*/
}
This is practically the same as #Fareanor's solution above (first solution)
A possible fix could be (if I have well understood your problem):
if(opt1 && opt2) // opt3, opt4 and opt5 are invalid
{
if(!(opt3 || opt4 || opt5))
{
// Do something
}
else
{
// Display error message because at least opt3 or opt4 or opt5 is provided and not requested
}
}
else // opt3, opt4 and opt5 are valid
{
// Do something
}
But I think it could be better to just ignore the obsolete parameters instead of display an error while you can still run your process with only opt1 and opt2. Which could lead us to the simpler code:
if(opt1 && opt2)
{
// Do something without using opt3, opt4 and opt5
}
else
{
// Do something taking into account opt3, opt4 and opt5
}
I hope it is what you was looking for.

Checking if given process is running

When I use the following function as isRunning("example.exe"); it always returns 0 no matter if the process is running or not.
I tried making it std::cout << pe.szExeFile; in the do-while loop and it outputs all the processes in the same format as I am trying to pass the function.
The project is multi-byte character set, in case that makes a difference.
bool isRunning(CHAR process_[])
{
HANDLE pss = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
PROCESSENTRY32 pe = { 0 };
pe.dwSize = sizeof(pe);
if (Process32First(pss, &pe))
{
do
{
if (pe.szExeFile == process_) // if(!strcmp(pe.szExeFile, process_)) is the correct line here
return true; // If you use this remember to close the handle here too with CloseHandle(pss);
} while (Process32Next(pss, &pe));
}
CloseHandle(pss);
return false;
}
Can't seem to find my mistake.
Thanks for your time.
You are using if (pe.szExeFile == process_) which compares the pointer values. You should be using something like strcmp or _stricmp to compare the actual string values instead.
e.g.
if(strcmp (pe.szExeFile, process_) == 0)
return true;

Conditional construction with shared_ptr?

I have:
Command *command;
if(commandType == "Start")
{
command = new StartCommand();
}
else if (commandType == "Stop")
{
command = new StopCommand();
}
Now suppose I want command to be a shared_ptr, how do I translate the code above to use a shared_ptr?
Skipping the obvious, if you want to properly initialise your variable, e.g. if it's const, you could do it like this
std::shared_ptr<Command> factoryCommand(std::string const& commandType) {
if(commandType == "Start")
return std::make_shared<StartCommand>();
if(commandType == "Stop")
return std::make_shared<StopCommand>();
return std::shared_ptr<Command>(nullptr);
}
std::shared_ptr<Command> const command {factoryCommand(commandType)};
As indicated in the comments, you can also violate the RAII guideline of C++ and separate definition and initialisation. I would still prefer to use std::shared_ptr<Command>::operator= over std::shared_ptr<Command>::reset though, as it is more intuitive and doesn't trick you into newing something you will never delete.
So, for the "Start" branch, for example, this would look like this:
std::shared_ptr<Command> command;
//...
// I would flag this in the review process as "you're doing it wrong"
command.reset(new StartCommand());
// This is what you should do if you *have* to separate definition and initialisation:
command = std::make_shared<StartCommand>();
Some very simple changes will do the job:
shared_ptr<Command> command;
if(commandType == "Start")
{
command = make_shared<StartCommand>();
}
else if (commandType == "Stop")
{
command = make_shared<StopCommand>();
}

Can you do optional parameters in a function thru cfscript?

I am finally getting around to writing stuff in cfscript, and so I am starting with writing some needed formatting functions. Here is an example:
Function FormatBoolean(MyBool, Format) {
Switch(Format){
Case "YES/NO":{
If (MyBool eq 1)
Return "YES";
Else
Return "NO";
Break;
}
Default:{
If (MyBool eq 1)
Return "Yes";
Else
Return "";
Break;
}
}
}
What I would like to do is make Format an optional argument. If you don't include the argument, the function will currently still run, but it won't find format, and it seems that cfparam did not get translated to cfscript.
Will I just have to check if Format is defined and give it a value? Or is there a nicer way of doing this?
Thanks
Personally I prefer to set defaults to this kind of arguments. Also I've refactored function a bit... But not tested :)
function FormatBoolean(required any MyBool, string Format = "") {
switch(arguments.Format) {
case "YES/NO":
return YesNoFormat(arguments.MyBool EQ 1);
default:
return (arguments.MyBool eq 1) ? "Yes" : "";
}
}
Please note that (arguments.MyBool EQ 1) may be replaced with (arguments.MyBool), so it covers all boolean values. You may be interested to make it more reliable, something like this (isValid("boolean", arguments.MyBool) AND arguments.MyBool) -- this should allow to check any value at all.
All variables passed into a function are available to access programmatically via the ARGUMENTS scope. You can refer to it as if it were an array (because it is), as well as standard struct key access (which I've done for you below for the MyBool parameter):
<cfscript>
Function FormatBoolean(MyBool) {
var theFormat = '';
if (ArrayLen(ARGUMENTS) GT 1)
theFormat = ARGUMENTS[2];
Switch(theFormat){
Case "YES/NO":{
If (ARGUMENTS.MyBool eq 1)
Return "YES";
Else
Return "NO";
Break;
}
Default:{
If (ARGUMENTS.MyBool eq 1)
Return "Yes";
Else
Return "";
Break;
}
}
}
</cfscript>
Add your preferred additional levels of data validation as necessary.