Updating code from one command line argument to two - c++

I have code which does the following :
const char* filename = argc >= 2 ? argv[1] : "stuff.jpg";
which reads in a photo as a command line argument and displays it.
I now want to take in two photo's, I tried this code :
const char* filename = argc >= 3 ? argv[1] : "stuff.jpg", argv[2] : "tester.jpg";
But I get an error like this :
error: expected initializer before ‘:’ token
Anybody know whats wrong? is there a similer way to do this input programmatically?

You're dealing with a ternary if-operator here. Have a look at this page. It's basically an inline if-statement.
Code that would do what you're looking for, looks something a little like this:
const char* filename1 = argc >= 2 ? argv[1] : "stuff.jpg";
const char* filename2 = argc >= 3 ? argv[2] : "tester.jpg";
That leaves you with two filename variables, storing either the supplied argument or the default values (stuff.jpg and tester.jpg, respectively).

To get all the arguments in an easy to use format I do:
int main(int argc, char* argv[])
{
std::vector<std::string> args(&argv[1], &argv[argc]);
// args.size() is the number of arguments.
// In your case the number of files.
// So now you can just loop over the file names and display each one.
// Note The above is guranteed to be OK
// As argv[] will always have a minimum of 2 members.
// argv[0] is the command name thus argc is always >= 1
// argv[argc] is always a NULL terminator.
}

What happens when you need 4, 5, or more photos?
Pseudo code:
vector<char *> photos;
if(argc > 1)
{
for i to argc-1
photos.push_back(argv[i]) ;
}

Related

What difference between argv[1]+1 and argv[2]

I know this question is basic, I also newbie, so plz help me clear this problem:
I have this code:
int wmain(int argc, wchar_t *argv[])
{
if (*argv[1] == L'-' && (!_wcsicmp(L"install", argv[1]+1)))
{
wprintf(L"You pressed: -install !");
}
else
{
wprintf(L"Unknown");
}
}
It work OK, but if I replace to:
int wmain(int argc, wchar_t *argv[])
{
if (*argv[1] == L'-' && (!_wcsicmp(L"install", argv[2])))
{
wprintf(L"You pressed: -install !");
}
else
{
wprintf(L"Unknown");
}
}
It's break when run.
I don't know
Why use argv[1]+1
What difference between argv[1]+1 and argv[2] (I've used above).
Anyone explain for me, and give me document about wchar_t ???
First,
Why use argv[1]+1:
--> _wcsicmp require POINTER, so you need pass: argv[1] + 1 or argv[2]
Second,
What difference between argv[1]+1 and argv[2] (I've used above). :
-->
Do you see second argument of wmain: wchar_t *argv[] ? - This is mean POINTER to ARRAY (same same POINTER to POINTER).
Each argument separate by space.
So, argv[1] is pointer point to second argument, argv[2] is pointer point to third argument.
And, argv[1]+1 increase address in pointer by 1 (mean, that pointer will point to second character in second argument string)
argv[1]+1 points to the second character in the argv[1] string, while argv[2] points to the next string.
argv[1] + 1 is a pointer to the second character in argv[1] while argv[2] is the third element (pointer to character) in argv.
argv[1] == *(argv + 1)
argv[2] == *(argv + 2)
argv[1] + 1 == *(argv + 1) + 1 != argv[2]

Remove leading % from integer

Just a simple problem here: I have a char** argv[] that holds all of my arguments...in one of these arguments, I get an integer proceeded by a %
For example:
bg %2
I really just want the integer....is there an easy way to get this?
This is for homework, so I am willing to do some more digging if anyone can prod me in the right direction.
Thanks
Here is a way to do it using c++ methods:
lets assume you have one of the char* in the list char** argv[]
std::string tempString(argv[the one with the %]);
int position = tempString.find_first_of('%');
int = atoi(tempString.substr(position, tempString.size()-position).c_str());
A quick explination, the first line converst the char* into a std::string, the second line gets the position of the %, the third line gets the sub-string of the number (assuming it ends at the end of the char*), converts it back to a char* and passes it through atoi to get the int.
Hope this helps.
Here is one way to do it using atoi:
for (int i = 0 ; i != argc ; i++) {
if (argv[i][0] == '%') {
int num = atoi(&argv[i][1]);
printf("Got a number: %d\n", num);
}
}

C/C++ Pointers and Arrays help

I have the following C++ code and I can't seem to get it working. What I am trying to do is read numerous entries from the command line, separated by ('|') pipe characters, and then splitting the resulting strings by spaces.
eg.
mkdir C:/unixcode/shells|cd D:/margins/code | pwd| finger kobojunkie | last -l kobojunkie
but so far, I get errors, something about declaring the size of the pointer:
Initializer fails to determine the size of argv2
cannot convert char** to char* for argument 1 to char strtok(char*, const char*)
int main(int argc, char *argv[])
{
char * pch;
pch = strtok (argv,"|");
//parse the contents of the generated arrays
while (pch != NULL)
{
printf ("%s\n",pch);
char * argv2[] = pch;
char * subpch = strtok(argv2," ");
while (subpch !=NULL)
{
printf ("%s\n",subpch);
subpch = strtok (NULL, " ");
}
pch = strtok (NULL, " ");
}
return 0;
}
the type of argv is char**, not char* hence you cannot pass it to strtok. Use argv[ 1 ] instead, but check that argc >= 2 first.
Or, since this is tagged c++, use stl to split the string, eg
void split( const std::string& s, char delim, std::vector<std::string>& elems )
{
std::stringstream ss( s );
std::string item;
while( std::getline( ss, item, delim ) )
if( !item.empty() )
elems.push_back( item );
}
int main( int argc, char *argv[] )
{
if( argc == 2 )
{
std::vector< std::string > elements;
split( argv[ 1 ], '|', elements );
//elements now contains all items..
}
}
The command-line is managed by a program: the shell (probably cmd.exe in Windows or bash in Linux). That shell gets all the stuff written in the command line and parses it and executes the commands specified.
Unless you are writing a shell, you cannot ever see the "|" of your example command-line inside the programs you write. They are effectively processed from the shell and removed from the parameters sent to the programs.
In
mkdir C:/unixcode/shells|cd D:/margins/code | pwd| finger kobojunkie | last -l kobojunkie
the shell calls the 5 following commands, each with the parameters specified
mkdir C:/unixcode/shells
cd D:/margins/code
pwd
finger kobojunkie
last -l kobojunkie
Note none of the programs receive a "|".
If you are indeed writing a shell, the command-line is not available in the argv array. It depends on the way you manage input inside your shell.
argv is an array of arrays pointers. You cannot pass it as is to strtok: you need to pass its elements in a loop
for (k = 1; k < argc; k++) {
pch = strtok(argv[k], "|");
/* ... */
}
Also: are you sure you want to delimit with "|"? That character has a special meaning to shells and, usually, does not make it to your program.
Unless you call your program with them escaped, eg
bash$ ./a.out 'one|two|three' 'four|five|six'
argv is not a string. argv is an array of strings. strtok takes a string, so you cannot pass it an array of strings and expect it to do something meaningful.
Each string element of the argv array is a separate command line parameter, except for the first which is the name of the executable. So what you should be doing is looking through each string entry for "|", and acting accordingly.

invalid conversion from ‘char*’ to ‘char’

I have a,
int main (int argc, char *argv[])
and one of the arguements im passing in is a char. It gives the error message in the title when i go to compile
How would i go about fixing this?
Regards
Paul
When you pass command line parameters, they are all passed as strings, regardless of what types they may represent. If you pass "10" on the command line, you are actually passing the character array
{ '1', '0', '\0' }
not the integer 10.
If the parameter you want consists of a single character, you can always just take the first character:
char timer_unit = argv[2][0];
If you only ever want the first character from the parameter the folowing will extract it from string:
char timer_unit = argv[2][0];
The issue is that argv[2] is a char* (C-string) not char.
You are probably not passing in what you think (though this should come from the command line). Please show the complete error message and code, but it looks like you need to deal with the second argument as char *argv[], instead of char argv[] -- that is, as a list of character arrays, as opposed to a single character array.
Everything stays strings when you pass them in to your program as arguments, even if they are single characters. For example, if your program was called "myprog" and you had this at the command line:
myprog arg1 53 c a "hey there!"
Then what you get in the program is the following:
printf("%d\n", argc);
for(int i = 0; i < argc; i++)
{
printf("%s\n", argv[0]);
}
The output of that would be:
6
myprog
arg1
53
c
a
hey there!
The point being that everything on the command line turns into null-terminated strings, even single characters. If you wanted to get the char 'c' from the command line, you'd need to do this:
char value = argv[3][0];
not
char value = argv[3]; // Error!
Even the value of "53" doesn't turn into an int. you can't do:
int number = argv[2]; // Error!
argv[2] is { '5', '2', '\0' }. You have to do this:
int number = atoi(argv[2]); // Converts from a string to an int
I hope this is clear.
Edit: btw, everything above is just as valid for C (hence the printf statements). It works EXACTLY the same in C++.

Processing command line argument

I've been working with OpenCV, and some of the example code I've seen uses the following to read in a filename. I understand that argc is the number of command line arguments that were passes, and argv is a vector of argument strings, but can someone clarify what each part of the following line does? I've tried searching this but haven't found many results. Thanks.
const char* imagename = argc > 1 ? argv[1] : "lena.jpg";
Thanks.
const char* imagename = // assign the string to the variable 'image_name'
argc > 1 // if there is more than one cmd line argument (the first is always the program name)
? argv[1] // use the first argument after the program name
: "lena.jpg"; // otherwise use the default name of "lena.jpg"
If argc is greater than 1, assigns to imagename the pointer held in argv[1] (i.e. the first argument given on the command line); otherwise (argc is not greater than 1), assigns a default value, "lena.jpg".
It uses the ternary operator ?:. This is used this way: CONDITION ? A : B and can be read as
if (CONDITION)
A
else
B
So that a = C ? A : B assigns A to a if C is true, otherwise assigns B to a. In this specific case, "A" and "B" are pointers to char (char *); the const attribute says we have "strings" that are "constant".
The example shows the use of the ternary operator.
const char* imagename = argc > 1 : argv[1] : "lana.jpg"
By ternary you can say that this expression has three members.
First member is a condition expression
Second member is the value that could be assigned to imagename if conditional expression is true.
Third member is the value that could be assigned to imagename if conditional expression is false.
This example can be translated to:
const char* imagename;
if(argc > 1)
imagename = argv[1];
else
imagename = "lana.jpg";
if (argc > 1) {
const char* imagename = argv[1];
} else {
const char* imagename = "lena.jpg";
}
(if we agree that imagename can go out of the brackets' scope)