So i am writing a program that takes in an int, and returns something to do with the bits that represent the int. However, when I put an int in the command line and immediately print it out it, it prints 2.
Why is this happening, and how can I fix it?
~ ./a.out 8
I can only take in one parameter for main:
#include<iostream>
#include<cstdlib>
using namespace std;
void foo (int ii, int x){
static int p;
k= x<<ii;
.
.
}
int main(int x) {
cout << x << endl;
.
.
.
return 0
}
Parameter passing does not work the way you appear to believe it does.
There are precisely two signatures for main that are guaranteed to work:
int main()
and
int main(int argc, char *argv[])
The latter is the one you use when you want to parse command line arguments. Here argc is the argument count, i.e. the number of passed arguments (including the name of the command itself) and the length of argv. argv is an array of C-style strings that holds the arguments.
So, when you call
./a.out 8
then argc is 2, argv[0] is "./a.out", argv[1] is "8", and argv[2] is a null pointer. If you want to use the first command line argument as a number, you have to parse argv[1] with std::istringstream or atoi or similar, as in
#include <iostream>
#include <sstream>
int main(int argc, char *argv[]) {
if(argc < 2) {
std::cerr << "No argument was given.\n";
return -1;
}
std::istringstream parser(argv[1]);
int x;
if(parser >> x) {
std::cout << x << " * 2 = " << x * 2 << '\n';
} else {
std::cerr << "The argument was not a number.\n";
return -2;
}
}
As a side note, because this is not something you can depend upon, this also explains why you get the output 2. When you write
int main(int x) {
x takes the value of argc, and what would have been argv is ignored, for low-level reasons that have to do with the way the arguments are laid out in memory before the jump to main. When you call the program with ./a.out 8, that value is 2, and so x is 2 in your code. This is not guaranteed to work by the C++ standard, but it is likely to happen on all platforms as it did on yours.
Related
This question already has answers here:
What does int argc, char *argv[] mean?
(12 answers)
Closed 7 years ago.
I wrote this simple code to understand how the argument system works. I dragged a textfile to the .exe file, and get 2 as output instead of 1 as i expected.
Why 2? Is Arg 1 the .exe itself? How can i find out the filenames of the arguments?
#include<iostream>
using namespace std;
int main(int argc, char* argv[])
{
int i = 0;
const int max = 100000;
if (argc > 0)
{
cout<< argc <<endl;
}
cin.get(); cin.get();
return 0;
}
And an additional question. Where can i inform on how to access each argument and use the informations. My goal is to open all files passed as arguments to the .exe.
This is not a duplicate question, i asked why 2 is returned when you pass 1 argument. The question in the Link is another...
argv[0] is normally the name of the program being run, and is counted in argc. If argc >= 2, the first of your text-file names should be in argv[1]. You can simply loop over them...
for (size_t i = 1; i < argc; ++i)
if (std::ifstream infile(argv[i]))
...use infile...
else
std::cerr << "ERROR - unable to open " << argv[i] << '\n';
For more complex requirements, you may want to use getopt() et al if your system provides it, or the boost library equivalents.
According to the C++ Standard (3.6.1 Main function)
...If argc is nonzero these arguments shall be supplied in argv[0]
through argv[argc-1] as pointers to the initial characters of
null-terminated multibyte strings (ntmbs s) (17.5.2.1.4.2) and argv[0]
shall be the pointer to the initial character of a ntmbs that
represents the name used to invoke the program or "".
To output all arguments you can use various approaches as for example
for ( char **s = argv; *s; ++s ) std::cout << *s << std::endl;
for ( int i = 0; i < argc; i++ ) std::cout << argv[i] << std::endl;
#include <algorithm>
#include <iterator>
//...
std::copy( argv, argv + argc, std::ostream_iterator<char *>( std::cout, "\n" ) );
first argument for main is always name of execution file(means .exe file name)
that is why the value of argc is 2 ( 1 for program name and other for your .txt file)
you can check it by printing argv[0]
I'm writing a very basic command line C++ application that takes arguments on execution.
I just started C++ today, and it seems apparent that you can only take char** as the data type for arguments. I want to take two floats as parameters (to add them together later), but I can't seem to cast the character arrays as floats.
I have tried static_cast<float>(argv[0]) and stof(argv[0]) to cast the values, and both give compiler errors (unable to cast and not defined in scope, respectively).
I'm using the Code::Blocks IDE if that answers any questions.
My code:
#include <iostream>
#include <string>
/**
* author: 2mac
*
*/
using namespace std;
void derp();
float getSum(float num1, float num2);
int main(int argc, char** argv)
{
float num1 = static_cast<float>(argv[0]);
float num2 = static_cast<float>(argv[1]);
if (argc != 0 || argc != 2)
cout << "Usage: hello-world [args]\nargs: none OR <num1> <num2> to be added together" << endl;
else
{
switch (argc)
{
case 0:
derp();
break;
case 2:
derp();
cout << num1 << " + " << num2 << " equals " << getSum(num1,num2) << endl;
break;
}
}
return 0;
}
void derp()
{
cout << "Hello, world!\n";
cout << "It's time to lern some C++!" << endl;
}
float getSum(float num1, float num2)
{
return num1 + num2;
}
Using this to convert your input to float number,
double f1, f2;
if (argc == 2)
{
f1 = atof (argv[0]);
f2 = atof (argv[1]);
}
A char** in C++ is just that, an pointer to a pointer to a character, thus not convertable to a float (Or any numeric value for that matter) directly Thus your first example will fail. You can use the intermediary functions atof or strtof (note strtof, not stof, why your second example fails) to convert these values, assuming you are sure they are actually in float form.
You are just converting a char * variable to float by typecasting. It will typecast value of the pointer to float, not the string to float.
You need to use functions such as atof, strtof to convert string to float. Or you can write your own function to to convert string to float.
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I made a simple test program to play around with C++11 threads.
#include <iostream>
#include <stdlib.h>
#include <thread>
using namespace std;
void tee(int civ)
{
for(int loop=0; loop<19; loop++, civ++)
{
civ = civ%19;
cout << loop << "\t" << civ << endl;
this_thread::sleep_for(chrono::milliseconds(300));
}
}
void koot()
{
while(true)
{
cout << ":) ";
this_thread::sleep_for(chrono::milliseconds(300));
}
}
int main(int argc, char *argv[])
{
thread saie(tee, atoi(argv[1])),
kamaa(koot);
saie.join();
kamaa.join();
return 0;
}
It works fine as long as I supply command line arguments, but if I don't, it crashes.
How can this be solved?
I tried checking the argument count, and if they existed, to no avail.
EDIT: I had to add this line:
if(argc < 2) return 1;
It crashes because you are accessing
argv[1]
which would hold a command line argument (other than the program's name) if there was one. You should check whether argc is greater than 1. Why greater than 1? Because the first command line argument is the name of the program itself. So argc is always greater than 0. And indexing starts at 0. So if argc == 1, only argv[0] is valid.
#include <iostream>
int main(int argc, char* argv[])
{
// no need to check argc for argv[0]
std::cout << argc << " " << argv[0] << "\n";
}
argv[1] is null, causing a crash in the call to atoi(). Note that array indices in C++ are zero-based!
because you don't check if argc > 1 and you try to access argv[1]
way to solve this is first check if argc > 1 and then access argv[1].
int main(int argc, char *argv[])
{
if(argc > 1){
thread saie(tee, atoi(argv[1])),
kamaa(koot);
saie.join();
kamaa.join();
}
return 0;
}
Points to remember:
argc is by default 1. This is the argument counter that holds the no. of arguments passed to the program. By default, its 1 because the program gets the executable's name(and path)
argv holds the array of NULL terminated character arrays(or strings). argv[0] will always hold the name of the executable.
never assume user will always enter the arguments. and always do a bounds check while accessing argv or any array in the future.
Try the following code instead:
int main(int argc, char *argv[])
{
if(argc < 2) { cout<<"No command line arguments found\n Aborting!\n"; return 1;}
else { thread saie(tee, atoi(argv[1])),kamaa(koot);}
saie.join();
kamaa.join();
return 0;
}
You are trying to access a command line argument argv[1] which is not present. It is always better to check if the command line argument exists or not.
How would you use an if/then statement using argv[], upon the option/parameter entered?
For example, a.out -d 1 sample.txt versus a.out -e 1 sample.txt.
int main (int argc, char *argv[])
{
ifstream infile(argv[3]);
int c;
int number = 0;
int count = 0;
while ( infile.good() ) {
if (argv[1] == "-d")
{
c = infile.get();
number = atoi(argv[2]);
if (number == count)
{
cout.put(c);
count = 0;
}
else
count++;
}
if (argv[1] == "-e")
{
cout << "entered -e" << endl; //testing code
}
}//end while
}//end main
You can't use the equality operator to compare C-style strings, you have to use std::strcmp:
if (std::strcmp(argv[1], "-d") == 0)
The reason behind that is that the == operator compares the pointers not what they point to.
I hope you want to check the input parameter -d or -e, right?
if that is the case please use strcmp()
if (!strcmp(argv[1],"-d"))
{
count++;
printf("\ncount=%d",count);
}
if (!strcmp(argv[1],"-e"))
{
printf("entered -e"); //testing code
}
The first error is in the very first line of main:
ifstream infile(argv[3]);
You cannot write that because there is no third argument. When you invoke your program like this:
a.out -d 1 < sample.txt
then the command line that the program sees looks like this:
argv[0] = "a.out"
argv[1] = "-d"
argv[2] = "1"
The < sample.txt, by contrast, is interpreted by the shell directly, and the file is streamed to the standard input of your program – and there’s nothing you can do to change that, inside your program.
As for the parsing itself, don’t do it inside the loop which reads the file, do it before and set appropriate flags.
For the actual parsing I’d suggest using a library to spare you a lot of pain. The standard Unix tool is getopt but that’s only got a C interface. There are several C++ libraries, amongst them Boost.Program_Options which is a tad too complex for my taste, though.
The argc/argv comes from C and is rather cumbersome to use, so when more than basic argument passing is done, you can transform the arguments to a vector of strings and work in a C++ style:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
main(int argc, char* argv[])
{
std::vector<std::string> args;
std::transform(argv+1, argv+argc, std::back_inserter(args), [](char* arg){ return std::string(arg); });
if (args.at(1) == "-d") { std::cout << "Arg 1 = -d" << "\n"; }
for (auto& arg: args) { std::cout << "arg: " << arg << "\n"; }
}
Still, you need to check that the argument is present. If this is a basic tool and it is acceptable that the tool aborts when the parameter is not present, then you can access args elements with args.at(x) instead of args[x]
Or check this SO question for an argument parser.
char argv[] is an array of char *
so
if (string(argv[1]) == "-d")
I have a sort of calculator in C++ that should accept arguments when executed. However, when I enter 7 as an argument, it might come out to be 10354 when put into a variable. Here is my code:
#include "stdafx.h"
#include <iostream>
int main(int argc, int argv[])
{
using namespace std;
int a;
int b;
if(argc==3){
a=argv[1];
b=argv[2];
}
else{
cout << "Please enter a number:";
cin >> a;
cout << "Please enter another number:";
cin >> b;
}
cout << "Addition:" << a+b << endl;
cout << "Subtaction:" << a-b << endl;
cout << "Multiplycation:" << a*b << endl;
cout << "Division:" << static_cast<long double>(a)/b << endl;
system("pause");
return 0;
}
Wherever did you get int argv[]? The second argument to main is char* argv[].
You can convert these command line arguments from string to integer using strtol or to floating-point using strtod.
For example:
a=strtol(argv[1], nullptr, 0);
b=strtol(argv[2], nullptr, 0);
But you can't just change the parameter type, because the operating system is going to give you your command-line arguments in string form whether you like it or not.
NOTE: You must #include <stdlib.h> (or #include <cstdlib> and using std::strtol;) to use the strtol function.
If you want error-checking, use strtol instead of atoi. Using it is almost as easy, and it also gives you a pointer to the location in the string where parsing terminated. If that points to the terminating NUL, parsing was successful. And of course it is good that you verify argc to make sure the user provided enough parameters, and avoid trying to read missing parameters from argv.
Example of error checking:
char* endp;
a = strtol(argv[1], &endp, 0);
if (endp == argv[1] || *endp) { /* failed, handle error */ }
The function signature is int main(int argc, char *argv[]). argv is an array of string pointers.
If the argument is 7, it will be in the form of a string ("7"). Use atoi() to convert it to the number 7.
Second argument in the main should either either be char* argv[] or char** argv. Then you have to have convert them to int.