I am running a C++ program from the command line on Bash, which is in a Linux environment. I am curious how you pass in a parameter from the command line. Here is my program:
#include <iostream>
using namespace std;
int large_pow2( int n );
int main()
{
int value = 15;
int largest_power = large_pow2(value);
cout << "The highest power of 2 in " << value << " is " << large_power << "." << endl;
return 0;
}
int large_pow2( int n )
{
int i = n
int j = i & (i - 1);
while( j != 0)
{
i = j;
j = i & (i - 1);
}
return j;
}
After I compile the program I want to be able to use the command line to pass in a number to use for value. For instance, to run the program you type ./"program_name" where "program_name" is the name of my program without quotes. Is there a way to set value = n or something? When I run the program let's say I want n to be 20 so on the command line I type something like ./"program_name" 20. Then the program would run with n = 20. Is there a way to do that? I am completely new to a Linux environment and Bash so don't quite know how to do things in it yet.
Use argc and argv in int main(int argc, char *argv[]) and modify your code accordingly.
The argc arguments tracks the number of arguments passed to your program from CLI and is always >=1. When 1 it is it name of program. So argc[0] is program name.
argv holds the command line arguments, other than program name and is always char string. Hence we need to use appropriate converter like atoi, if you don't want string.
So your code will look like, error checking not done for simplicity
int main(int argc, char *argv[])
{
//Now we expect argc ==2, program value, This will when argc != 2
// We should use if in real scenario
assert(argc == 2);
int value = atoi(argv[1])
int largest_power = large_pow2(value);
cout << "The highest power of 2 in " << value << " is " << large_power << "." << endl;
return 0;
}
Your main method can take (int argc, char** argv) which are the count of arguments and the NUL terminated args. The program path is argv[0] so atoi(argv[1]) is probably what you want. Check argc ==2.
Related
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.
Program in c++.
My goal for this assignment is to make sure the user enter only one argument in command line and that argument has to contain digits only and greater than 3. Otherwise, print error.
For example:
$ ./a.out 4
Successful!
$ ./a.out abc
Must be a numeric string grater than 3
$ ./a.out 4 abc
Must be one argument only
$ ./a.out 2
Must be a numeric string greater than 3
$ ./a.out 2ab
Must be a numeric string
This is my code so far to handle accepting one argument and greater than 3. I don't know to handle the numeric string part.
int main(int argc, char **argv){
if (argc == 2){
int num = atoi(argv[1];
if (num >3){
cout << "Successful" << endl;
else{
cout <<"Must be a numeric string greater than 3"<< endl;
}
else{
cout << "Must be one argument" << endl;
}
return 0;
}
I have tried this and got segmentation error.
int main(int argv, char **argv){
if (argc == 2){
int num = atoi(argv[1];
int i;
if (num >=3 && isdigit(argv[1][i]){
cout << "Successful" << endl;
else{
cout << "Must be a numeric string greater than 3"<<endl;
}
else{
cout << "Must be one argument" << endl;
}
return 0;
}
You could use std::strtol instead of atoi; this way you can check that the parsing stopped at the end of that string.
here is code that compiles and does not crash but doesn't produce the right answer. It doesn't work because you are only looking at the first char of argv[1]. Why did it crash, becuase you indexed using i which was untitialized
#include <iostream>
#include<ctype.h>
int main(int argc, char** argv) {
if (argc == 2) {
int num = atoi(argv[1]);
int i = 0;// <<<<========================================
if (num >= 3 && isdigit(argv[1][i])) {
std::cout << "Successful" << std::endl;
}
else {
std::cout << "Invalid" << std::endl;
}
}
else {
std::cout << "Must be one argument" << std::endl;
}
return 0;
}
to make it do the right thing you need to loop over all argv and inside that loop you must loop over all chars in argv[i]
note that I removed the using namespace - see here Why is "using namespace std;" considered bad practice?
Your text and your code are at odds with each other. Is 3 acceptable or not? My code below assumes it is not based on what you wrote.
The big thing here is that atoi() lacks the ability to tell you if the whole string was processed or not. You want to use what C++ provides from <string>, std::stoi() or the long or long long variations depending on what you expect a reasonable range of inputs to be.
std::stoi() has a second output parameter that tells you how many characters were processed. What you then need to check is if the number of characters processed is the length of the string. If not, some non-numeric charcters were entered.
Example code below.
#include <cstring>
#include <iostream>
#include <string>
int main(int argc, char* argv[]) {
if (argc != 2) {
std::cerr << "USAGE: ./a.out ARG\n";
return 1;
}
std::size_t loc;
int val;
// The try block is necessary because std::stoi() throws if the resulting
// number cannot be contained in the type, and if processing fails on the
// first character.
try {
val = std::stoi(argv[1], &loc);
} catch (...) {
std::cerr << "INVALID PARAMETER\n";
return 2;
}
if (loc != std::strlen(argv[1])) {
std::cerr << "INPUT MUST BE FULLY NUMERIC\n";
return 3;
}
if (val <= 3) {
std::cerr << "Parameter must be > 3\n";
return 4;
}
std::cout << "Parameter: " << val << '\n';
}
Test runs:
~/tmp
❯ ./a.out
USAGE: ./a.out ARG
~/tmp
❯ ./a.out 1
Parameter must be > 3
~/tmp
❯ ./a.out 4
Parameter: 4
~/tmp
❯ ./a.out 2ab
INPUT MUST BE FULLY NUMERIC
~/tmp
❯ ./a.out ab
INVALID PARAMETER
Other answers are good and correct. My goto for stuff like this is to use a stringstream.
#include <optional>
#include <sstream>
#include <string>
template <typename T>
auto string_to( const std::string & s )
{
T value;
return (std::istringstream( s ) >> value >> std::ws).eof()
? value
: std::optional <T> {};
}
It is easy enough to use:
#include <iostream>
int error( const char * message )
{
std::cerr << message << "\n";
return 1;
}
int main( int argc, char ** argv )
{
if (argc != 2) return error( "Must be one argument only" );
auto n = string_to<int>( argv[1] );
if (!n) return error( "Must be a numeric string" );
if (n <= 3) then error( "Must be a numeric string grater than 3" );
std::cout << "Successful!\n";
}
The basic principle behind all these answers is you must try to convert it to an integer to see if it is, in fact, an integer.
I like my little utility function (string_to<type>()) because it does all the dirty work correctly: it attempts to convert the value, meaning there may be whitespace before the value but nothing else. It then reads any remaining whitespace and checks for EOF (meaning nothing but whitespace may follow the value). Only if all the checks pass do you get a value back.
I like std::optional because it is exactly for these kinds of things — either you have a value or you do not. You could throw instead, or return a default value, or whatever works. Heck, you could inline it in your main function:
int main(...)
{
...
int value;
if (!(std::istringstream( argv[1] ) >> value >> std::ws).eof())
error( ... );
That’s ugly though, and not very descriptive. I prefer to put things in little helper functions (which the compiler may very well inline) with nice, descriptive names. Like that error function I used there: it tells you exactly what is going on just by reading the code.
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.
TL;DR: Why do my char* variables have the same value, even though I input different ones?
Consider this very short program:
char *GetCompleteString ()
{
char *completeString;
std::cout << "Please enter the complete string.\n";
std::cin.getline(completeString,100);
return completeString;
}
char *GetSubstring ()
{
char* substring;
std::cout << "Please enter the substring for which to search.\n";
std::cin.getline(substring,100);
return substring;
}
//////////////////////////////////////////////////
int main(int argc, const char * argv[])
{
char *complete, *sub;
complete = GetCompleteString();
sub = GetSubstring();
//diagnostic
std::cout << "Complete is " << complete << " and sub is " << sub;
//diagnostic
return 0;
}
Now, I enter "foo" for the first string, and "bar" for the second. But the output tells me that both variables are the same.
The Xcode debugger shows that both variables have the same address, so when I assign a value to bar, the previously-entered foo (which lives at the same address) takes the same value. Here's what the debugger pane is showing just before the program exits:
argv const char ** 0x00007fff5fbff928
argc int 1
complete char * 0x00007fff5fbff928
*complete char 'b'
sub char * 0x00007fff5fbff928
*sub char 'b'
&complete char ** 0x00007fff5fbff8e8
&sub char ** 0x00007fff5fbff8e0
Why are these two variables being assigned the same address? What am I missing here? (And why are they retaining the same address as argv, which I think is just for interfacing with the CLI?)
And are they even retaining the same addresses? (I added the last two (&) lines to the debugger, myself. And those show different addresses...)
What you are doing there is undefined behaviour since neither completeString nor substring point to actual allocated memory. Anything can happen ;)
To be more precise: It is very likely that since you don't assign a value to the local variables they just get the first value lying on the stack which could be random or something the initialisation of your libc left there.
You can use following updated code
char *GetCompleteString ()
{
char *completeString = (char*)malloc(sizeof(char)*numberofchars);
std::cout << "Please enter the complete string.\n";
std::cin.getline(completeString,100);
return completeString;
}
char *GetSubstring ()
{
char* substring = (char*)malloc(sizeof(char)*numberofchars);
std::cout << "Please enter the substring for which to search.\n";
std::cin.getline(substring,100);
return substring;
}
//////////////////////////////////////////////////
int main(int argc, const char * argv[])
{
char *complete, *sub;
complete = GetCompleteString();
sub = GetSubstring();
//diagnostic
std::cout << "Complete is " << complete << " and sub is " << sub;
//diagnostic
return 0;
}
I have added memory allocation calls in your functions. numberofchars is numbers of chars you expect in that char *, or you can give some more thought to make it dynamic
There are a few problems with your code. I will list them here -
The statement char *completeString; defines completeString to be a pointer to a character. What you need is a character array to store the string entered by the user.
The variable completeString and subString are local to the functions GetCompleteString and GetSubstring respectively. They are allocated on the stack and go out of scope when the function returns. If you try to access them in main, then this invokes undefined behaviour. You need to allocate space to store strings on the heap using new operator. This allocates memory on the heap. You should free this memory using the delete[] operator after you are done with it.
The signature of main as per the standard should be one of the following -
int main(); or int main(int argc, char *argv[]);
Applying these changes to your code, it is
#include <iostream>
#define MAX_LEN 100
char *GetCompleteString()
{
char *completeString = new char[MAX_LEN];
std::cout << "Please enter the complete string.\n";
std::cin.getline(completeString, MAX_LEN);
return completeString;
}
char *GetSubstring()
{
char* substring = new char[MAX_LEN];
std::cout << "Please enter the substring for which to search.\n";
std::cin.getline(substring, MAX_LEN);
return substring;
}
int main()
{
char *complete, *sub;
complete = GetCompleteString();
sub = GetSubstring();
std::cout << "Complete is " << complete << " and sub is " << sub;
delete[] sub;
delete[] complete;
return 0;
}
I'm trying to create an application that can receive some data on launch from another program.
For example:
Start_App.exe calls Main_App.exe and gives it the current date, all at the same time
(while launching it)
Main_App.exe outputs the date on its console
Without the data passed by Start_App the other program can't work correctly or will do something else.
I've been searching for a while but it seems like I'm missing the
technical names...
You'll probably want to use command-line arguments.
They are passed by writing them out, separated by spaces, directly after the program name.
Like so:
#include <iostream>
int main(int argc, char *argv[])
{
using namespace std;
cout << "There are " << argc << " arguments:" << endl;
// Loop through each argument and print its number and value
for (int nArg=0; nArg < argc; nArg++)
cout << nArg << " " << argv[nArg] << endl;
return 0;
}
argc is the number of arguments the program received.
*argv[] is an array of strings, one for each argument.
If you call the program like this:
Program.exe arg1 arg2 arg3
It gives you:
There are 3 arguments:
0 arg1
1 arg2
2 arg3