C++ command line argument for .exe program - c++

I have program.exe that is being created on my Windows machine. For some reason I am not able to pass in command line arguments properly.
int main(int argc, char *argv[]) {
///////testing
cout << "\n\n(int)ARGV[1]: " << (int)argv[1] << "\n\n";
return 0;
}
In terminal I run:
program.exe 4
I see (int)ARGV[1]: 15333464 printed to my console.
Why does this happen, and how I can modify the code? I should get the number 4 printed out.

When you cast from char* to int you get the pointer value bitpattern interpreted as an integer.
A good way to instead interpret the character string pointed to, as a specification of an integer, is to use std::stoi from the <string> header.
Thus:
#include <iostream>
#include <stdlib.h> // EXIT_FAILURE
#include <string> // std::stoi
using namespace std;
int main(int argc, char *argv[])
{
if( argc != 2 )
{
return EXIT_FAILURE;
}
cout << "ARGV[1]: " << stoi( argv[1] ) << "\n";
}
For the case where the argument isn't a valid specification of an integer, stoi will throw an exception, and in the code above that will cause the program to terminate with some message displayed – a crash. That's generally preferable to producing incorrect results. But if you want to handle it, read up on try and catch in your C++ textbook.
If you want filenames as command line arguments, and more generally filesystem paths, then do note that the Windows convention for encoding of char based strings is Windows ANSI, which has a very limited set of characters. Some filenames and paths on my Norwegian computer can't be represented in your Windows ANSI (yes, Windows ANSI is locale-specific). So for this the C and C++ main argument mechanism, is ungood.
The Windows API provides a pair of wchar_t based functions that can be used as a (working) alternative, namely GetCommandLine (retrieves the raw UTF-16-encoded command line) and CommandLineToArgvW (standard parsing to produce individual arguments).
Some Windows compilers also provide an alternative to standard main called wmain, where argv is declared as wchar_t* argv[]. These compilers include Visual C++ and the MinGW64 variant of g++.

Here argv[1] is a character pointer (char*) so you cant convert a character pointer to an integer by type casting. So to convert the character pointer to an integer use the atoi() function, which is available in the c standard library (include the cstdlib library).
#include <iostream>
#include <cstdlib>
using std::cout;
using std::endl;
using std::atoi;
int main(int argc, char *argv[])
{
cout << atoi(argv[1]) << " " << endl;
return 0;
}
Note that atoi() returns zero if the argument passed to it cannot be converted to an integer. So you could check the returned value and if it is zero then print the relevant message.
Thus:
#include <iostream>
#include <cstdlib>
#include <cstring>
using std::atoi;
using std::cout;
using std::endl;
using std::strcmp;
int main(int argc, char *argv[])
{
if(argc == 2)
{
if(atoi(argv[1]) == 0 && strcmp(argv[1], "0") != 0)
cout << "The argument supplied is not an integer" << endl;
else
cout << atoi(argv[1]) << " " << endl;
}
else if( argc > 2)
cout << "Too many arguements" << endl;
else
cout << "Insufficient arguements" << endl;
return 0;
}

Related

How to execute a C++ program while including variables from the function within the terminal

I wrote a simple program to calculate the hypotenuse length of a triangle. My question is, how can I give variables "side1" and "side2" values while executing the main function from the terminal? Code below:
#include <iostream>
#include <cmath>
int main(int side1, int side2) {
int c2 = (pow(side1, 2)) + (pow(side2, 2));
std::cout << sqrt(c2) << std::endl;
return 0;
}
The function compiles without error, so normally I would execute the function from terminal using "./main.exe", but is there a way to pass values to variables side1 & side2 while executing? (ex: ./main.exe "5" "5"). I don't want to go the std::cin route because I already know how to do that. For the same reason, I don't want to assign values to the variables within the function (ex: int side1 {5};).
I don't know if this is possible to do or not, but sites like Leetcode have their functions set up this way, and I have no clue how they input values for test cases.
The signature of the main function can be
int main(int argc, char *argv[])
so you get an argument count and a "string" array. Note that argv[0] is the executable name, so side1 would be argv[1] and side2 is argv[2].
You need to get the command line argument strings and convert them to integers. Alas, this does increase the complexity of your program a little if you want to catch errors.
#include <cmath>
#include <iostream>
#include <string>
int help()
{
std::cerr <<
"usage:\n"
" a.exe SIDE1 SIDE2\n\n"
"Where SIDE1 and SIDE2 are integers.\n";
return 1;
}
int main( int argc, char ** argv )
{
int side1, side2;
if (argc != 3) return help();
try {
side1 = std::stoi( argv[1] );
side2 = std::stoi( argv[2] );
}
catch (...)
{
return help();
}
int c2 = side1*side1 + side2*side2;
std::cout << std::sqrt( c2 ) << "\n";
}
You could leave a lot of that error checking out and just let the program crash without explanation, but IMHO it is always worth adding a usage clause to your program to help users (including yourself two months from now) figure out how to run the program.
As noted previously, your function signature for main is incorrect. The correct signature when you want to access command line arguments is:
int main(int argc, char **argv)
argc is the count of arguments, the first being the name of the executable. argv is an array of those arguments. We can:
Check that the right number of arguments have been passed in, and print an error if not.
Use std::atoi to convert those inputs into ints, at which point we can use them as we please.
#include <iostream>
#include <cstdlib>
int main(int argc, char **argv) {
if (argc != 3) {
std::cerr << "Usage: "<< argv[0]
<< " val1 val2" << std::endl;
return 1;
}
auto v1 = std::atoi(argv[1]);
auto v2 = std::atoi(argv[2]);
std::cout << v1 << ", " << v2 << std::endl;
return 0;
}
Your main signature is wrong. See https://en.cppreference.com/w/cpp/language/main_function.

Passing bash parameters to c++

I tried passing two parameters from bash to c++ program to be used but cant seem to get it to work exactly right. I would use the command ./bash "Turtle" "Cat" in linux command line.
#!/bin/bash
./main.out $1 $2
But the C++ file would only read ./main.out from argv. The cout would just print cut off versions of ./main.out such as ./main.out then /main.out and then main.out. Am I incorrectly using the parameters in the placement of the bash file?
int main(int argc, char *argv[]) {
cout << argv+0 << endl;
cout << argv+1 << endl;
cout << argv+2 << endl;
return 0;
}
This is because you are not printing the arguments as strings, your printing their memory locations. In clang++-9 (what I tested it in) this is what happens when a pointer is passed to std::cout, in many compilers (MSVC, correct me if im wrong) this will simply print nothing.
What you need to do is reference it as an array index and print that
int main(int argc, char **argv) {
cout << argv[0] << endl;
cout << argv[1] << endl;
cout << argv[2] << endl;
return 0;
}
The above code works fine for me (passing arguments manually when executing) when compiled with clang++-9. If you are going to use this code you should also check that there are at least 3 arguments (value of argc) otherwise you may point at invalid memory when indexing argv
Also try and avoid std::endl and use "\n" instead, std::endl needlessly flushes the buffer and is not required 99% of the time
Your bash file is fine. The problem is in your C++. Try something like this:
#include <iostream>
int main(int argc, char **argv) {
std::cout << argv[1] << "\n";
std::cout << argv[2] << "\n";
}
[warning: this doesn't check for errors, so if you don't pass any parameters, it'll misbehave badly.]
char *argv[] is a pointer of pointers (same as char **argv), you need
cout << argv[1] << endl;

Passing parameters from command line to C++

Searching the net for examples how to pass command line parameters to a C++ code, I came up with an abandoned post where this process is being explained. This code was not working and after a few amendments I came up with the following (working) code:
#include <iostream>
#include <windows.h>
#include <fstream>
#include <string>
using namespace std;
// When passing char arrays as parameters they must be pointers
int main(int argc, char* argv[]) {
if (argc < 2) { // Check the value of argc. If not enough parameters have been passed, inform user and exit.
std::cout << "Usage is -i <index file name including path and drive letter>\n"; // Inform the user of how to use the program
std::cin.get();
exit(0);
} else { // if we got enough parameters...
char* indFile;
//std::cout << argv[0];
for (int i = 1; i < argc; i++) { /* We will iterate over argv[] to get the parameters stored inside.
* Note that we're starting on 1 because we don't need to know the
* path of the program, which is stored in argv[0] */
if (i + 1 != argc) {// Check that we haven't finished parsing already
if (strcmp(argv[i],"/x")==0) {
// We know the next argument *should* be the filename:
char indFile=*argv[i+1];
std::cout << "This is the value coming from std::cout << argv[i+1]: " << argv[i+1] <<"\n";
std::cout << "This is the value of indFile coming from char indFile=*argv[i+1]: " <<indFile <<"\n";
} else {
std::cout << argv[i];
std::cout << " Not enough or invalid arguments, please try again.\n";
Sleep(2000);
exit(0);
}
//std::cout << argv[i] << " ";
}
//... some more code
std::cin.get();
return 0;
}
}
}
Executing this code from the Windows command line using:
MyProgram.exe /x filename
returns the next output:
This is the attribute of parameter /x: filename
This is the value from *argv[i+1]: f
The original post from cplusplus.com did not compile; the code above does.
As you can see printing the argv[2] gives me the name of the file. When I try to capture the file name into another var so I can use it in the C++ program, I only get the first character (second response line).
Now for my question: How can I read the value from the command line parameter the pointer is pointing to?
Hope someone can help this newbie in C++ :-)
*argv[i+1]
Accesses the 1st char of the char* argv[] argument.
To get the whole value use something like
std::string filename(argv[i+1]);
instead.
You can't store a string in a single char.
Here's the once-an-idiom for copying the main arguments to more manageable objects:
#include <string>
#include <vector>
using namespace std;
void foo( vector<string> const& args )
{
// Whatever
(void) args;
}
auto main( int n, char* raw_args[] )
-> int
{
vector<string> const args{ raw_args, raw_args + n };
foo( args );
}
Do note that this code relies on an assumption that the encoding used for the main arguments can represent the actual command line arguments. That assumption holds in Unix-land, but not in Windows. In Windows, if you want to deal with non-ASCII text in command line arguments, you'd better use a third party solution or roll your own, e.g. using Windows' GetCommandLine API function.

Printing parameters in win32 console application

Here's my code:
int _tmain(int argc, _TCHAR* argv[])
{
for (int i = 1;i<argc;i++) printf("Argument %d:%s\n",i,argv[i]);
// output = Argument 1:param
for (int k = 1; k < argc; k++) cout << "Argument " << k << ": " << argv[k];
// output = Argument 1: 00BF5878
return(0);
}
My question is: why do I see different outputs on cout and printf?
You see an address in the output from cout because you have built the program with UNICODE or _UNICODE defined. Probably by way of a setting in a Visual Studio project. Then _tmain expands to MIcrosoft's non-standard wmain, and _TCHAR expands to wchar_t.
And cout doesn't know how that a pointer to wchar_t is supposed to point to a null-terminated string of wide characters.
I am not sure why that doesn't happen with printf. Lemme check.
OK I have checked and your printf is not printing "param" as you indicate it does.
Here's the corrected code I checked with:
#include <iostream>
#include <stdio.h>
#include <tchar.h>
using namespace std;
int _tmain( int argc, _TCHAR* argv[] )
{
for( int i = 0;i < argc; ++i )
{
printf("printf Argument %d:%s\n",i,argv[i]);
}
for( int i = 0; i < argc; ++i )
{
cout << "cout Argument " << i << ": " << argv[i] << endl;
}
}
And here's the result:
[D:\dev\test]
> cl foo.cpp /D _UNICODE
foo.cpp
[D:\dev\test]
> foo param
printf Argument 0:f
printf Argument 1:p
cout Argument 0: 004F9A9C
cout Argument 1: 004F9AA4
[D:\dev\test]
> _
In other words, the apparent conundrum is entirely caused by your inaccurate reporting of results.
Solution: instead of using Microsoft's non-standard wmain, and in particular instead of using the now totally meaningless Windows 9x support macros!, use a standard C++ main.
The difference is that printf takes the contents of the parameters and forces the data to match the format specifier. The content of argv[i] will be treated as a nul terminated string because of the %s format specifier.
The cout in conjunction with the stream insertion operator will output based on the type of the parameter. The compiler will search all the operator<<() methods for cout and choose the one the best matches the parameter.
In your case, the compiler is looking for the method operator<<(TCHAR *) and didn't find an exact match. Instead, the compiler recognized that the parameter was a pointer and chose operator<<(void *) which prints out a pointer.
Try defining operator<<(TCHAR*) and see what happens.

What is the difference between _tmain() and main() in C++?

If I run my C++ application with the following main() method everything is OK:
int main(int argc, char *argv[])
{
cout << "There are " << argc << " arguments:" << endl;
// Loop through each argument and print its number and value
for (int i=0; i<argc; i++)
cout << i << " " << argv[i] << endl;
return 0;
}
I get what I expect and my arguments are printed out.
However, if I use _tmain:
int _tmain(int argc, char *argv[])
{
cout << "There are " << argc << " arguments:" << endl;
// Loop through each argument and print its number and value
for (int i=0; i<argc; i++)
cout << i << " " << argv[i] << endl;
return 0;
}
It just displays the first character of each argument.
What is the difference causing this?
_tmain does not exist in C++. main does.
_tmain is a Microsoft extension.
main is, according to the C++ standard, the program's entry point.
It has one of these two signatures:
int main();
int main(int argc, char* argv[]);
Microsoft has added a wmain which replaces the second signature with this:
int wmain(int argc, wchar_t* argv[]);
And then, to make it easier to switch between Unicode (UTF-16) and their multibyte character set, they've defined _tmain which, if Unicode is enabled, is compiled as wmain, and otherwise as main.
As for the second part of your question, the first part of the puzzle is that your main function is wrong. wmain should take a wchar_t argument, not char. Since the compiler doesn't enforce this for the main function, you get a program where an array of wchar_t strings are passed to the main function, which interprets them as char strings.
Now, in UTF-16, the character set used by Windows when Unicode is enabled, all the ASCII characters are represented as the pair of bytes \0 followed by the ASCII value.
And since the x86 CPU is little-endian, the order of these bytes are swapped, so that the ASCII value comes first, then followed by a null byte.
And in a char string, how is the string usually terminated? Yep, by a null byte. So your program sees a bunch of strings, each one byte long.
In general, you have three options when doing Windows programming:
Explicitly use Unicode (call wmain, and for every Windows API function which takes char-related arguments, call the -W version of the function. Instead of CreateWindow, call CreateWindowW). And instead of using char use wchar_t, and so on
Explicitly disable Unicode. Call main, and CreateWindowA, and use char for strings.
Allow both. (call _tmain, and CreateWindow, which resolve to main/_tmain and CreateWindowA/CreateWindowW), and use TCHAR instead of char/wchar_t.
The same applies to the string types defined by windows.h:
LPCTSTR resolves to either LPCSTR or LPCWSTR, and for every other type that includes char or wchar_t, a -T- version always exists which can be used instead.
Note that all of this is Microsoft specific. TCHAR is not a standard C++ type, it is a macro defined in windows.h. wmain and _tmain are also defined by Microsoft only.
_tmain is a macro that gets redefined depending on whether or not you compile with Unicode or ASCII. It is a Microsoft extension and isn't guaranteed to work on any other compilers.
The correct declaration is
int _tmain(int argc, _TCHAR *argv[])
If the macro UNICODE is defined, that expands to
int wmain(int argc, wchar_t *argv[])
Otherwise it expands to
int main(int argc, char *argv[])
Your definition goes for a bit of each, and (if you have UNICODE defined) will expand to
int wmain(int argc, char *argv[])
which is just plain wrong.
std::cout works with ASCII characters. You need std::wcout if you are using wide characters.
try something like this
#include <iostream>
#include <tchar.h>
#if defined(UNICODE)
#define _tcout std::wcout
#else
#define _tcout std::cout
#endif
int _tmain(int argc, _TCHAR *argv[])
{
_tcout << _T("There are ") << argc << _T(" arguments:") << std::endl;
// Loop through each argument and print its number and value
for (int i=0; i<argc; i++)
_tcout << i << _T(" ") << argv[i] << std::endl;
return 0;
}
Or you could just decide in advance whether to use wide or narrow characters. :-)
Updated 12 Nov 2013:
Changed the traditional "TCHAR" to "_TCHAR" which seems to be the latest fashion. Both work fine.
End Update
the _T convention is used to indicate the program should use the character set defined for the application (Unicode, ASCII, MBCS, etc.). You can surround your strings with _T( ) to have them stored in the correct format.
cout << _T( "There are " ) << argc << _T( " arguments:" ) << endl;
Ok, the question seems to have been answered fairly well, the UNICODE overload should take a wide character array as its second parameter. So if the command line parameter is "Hello" that would probably end up as "H\0e\0l\0l\0o\0\0\0" and your program would only print the 'H' before it sees what it thinks is a null terminator.
So now you may wonder why it even compiles and links.
Well it compiles because you are allowed to define an overload to a function.
Linking is a slightly more complex issue. In C, there is no decorated symbol information so it just finds a function called main. The argc and argv are probably always there as call-stack parameters just in case even if your function is defined with that signature, even if your function happens to ignore them.
Even though C++ does have decorated symbols, it almost certainly uses C-linkage for main, rather than a clever linker that looks for each one in turn. So it found your wmain and put the parameters onto the call-stack in case it is the int wmain(int, wchar_t*[]) version.
With a little effort of templatizing this, it wold work with any list of objects.
#include <iostream>
#include <string>
#include <vector>
char non_repeating_char(std::string str){
while(str.size() >= 2){
std::vector<size_t> rmlist;
for(size_t i = 1; i < str.size(); i++){
if(str[0] == str[i]) {
rmlist.push_back(i);
}
}
if(rmlist.size()){
size_t s = 0; // Need for terator position adjustment
str.erase(str.begin() + 0);
++s;
for (size_t j : rmlist){
str.erase(str.begin() + (j-s));
++s;
}
continue;
}
return str[0];
}
if(str.size() == 1) return str[0];
else return -1;
}
int main(int argc, char ** args)
{
std::string test = "FabaccdbefafFG";
test = args[1];
char non_repeating = non_repeating_char(test);
Std::cout << non_repeating << '\n';
}