command line argument in c++ segmentation fault - c++

i am trying to use command line argument in Linux(Ubuntu) in c++ . but it generates run time error : segmentation fault.this program runs with no error in windows .here is my code
#include<iostream>
using namespace std;
int main(int argc , char **argv){
char **ss;
for(int i=0;i<argc;i++){
ss[i] = argv[i];
}
for(int i=0;i<argc ;i++)
cout<<ss[i];
return 0;
}
what is wrong with this code. please help me . thanks in advance.

Your program has undefined behaviour because you did not initialize pointer ss and allocate memory where you are going to copy elements pointed by argv
char **ss; // What value does it have?
for(int i=0;i<argc;i++){
ss[i] = argv[i];
You could do the following way
char **ss = new char *[argc];
for(int i=0;i<argc;i++){
ss[i] = argv[i];
The better way is to use std::vector<std::string>. In this case you could also copy not only pointers to arguments but and also the arguments. For example
#include<iostream>
#include <vector>
#include <string>
int main(int argc , char **argv)
{
std::vector<std::string> v( argv, argv + argc );
for ( const std::string &s : v ) std::cout << s << std::endl;
return 0;
}
If your compiler does not support the range based for statement then you can substitute it for
for ( std::vector<std::string>::size_type i = 0; i < v.size(); i++ )
{
std::cout << v[i] << std::endl;
}

As already answered, you haven't allocated any memory for ss.
Since you're using c++ and not c, you should have the c++ standard library at your disposal:
std::vector<std::string> ss;
ss.reserve(argc); // not necessary
for(int i=0;i<argc;i++)
ss.push_back(argv[i]);

Use the following declaration for ss
#include<iostream>
using namespace std;
int main(int argc , char **argv){
char *ss[argc]; // <--allocate argc count of pointers
for(int i=0;i<argc;i++){
ss[i] = argv[i];
}
for(int i=0;i<argc ;i++)
cout<<ss[i];
return 0;
}

Related

How do I read a stringstream into a char *[40] / char ** array?

I am working on creating a UNIX shell for a lab assignment. Part of this involves storing a history of the past 10 commands, including the arguments passed. I'm storing each command as a C++ string, but the parts of the program that actually matter, and that I had no input in designing (such as execve) use char * and char ** arrays exclusively.
I can get the whole command from history, and then read the program to be invoked quite easily, but I'm having a hard time reading into an arguments array, which is a char *[40] array.
Below is the code for a program I wrote to simulate this behavior on a test string:
#include <sstream>
#include <iostream>
#include <string>
using namespace std;
int main()
{
char *chars[40];
string test = "Hi how are you";
stringstream testStream;
testStream << test;
int i = 0;
while (true)
{
string test_2;
testStream >> test_2;
if (testStream.fail())
{
break;
};
chars[i] = (char *)test_2.c_str();
i++;
}
for (int i=0; i < 4; i++)
{
cout << chars[i];
}
cout << "\n";
}
I get the feeling it has something to do with the array being declared as an array of pointers, rather than a multi-dimensional array. Am I correct?
This line:
chars[i] = (char *)test_2.c_str();
leaves chars[i] 'dangling' when you go back round the loop or fall off the end. This is because test_2.c_str() is only valid while test_2 is in scope.
You'd do better to do something like this:
#include <sstream>
#include <iostream>
#include <string>
#include <vector>
#include <memory>
int main()
{
std::vector <std::string> args;
std::string test = "Hi how are you";
std::stringstream testStream;
testStream << test;
int i = 0;
while (true)
{
std::string test_2;
testStream >> test_2;
if (testStream.fail())
break;
args.push_back (test_2);
i++;
}
auto char_args = std::make_unique <const char * []> (i);
for (int j = 0; j < i; ++j)
char_args [j] = args [j].c_str ();
for (int j = 0; j < i; ++j)
std::cout << char_args [j] << "\n";
}
Now your vector of strings remains in scope while you are building and using char_args.
Live demo

Sort command line args in C++

I wanna sort an array of command line arguments. All arguments are integer.
Here is my code, but it does not work.
#include <iostream>
using namespace std;
int main (int argc, char *argv[]) {
for (int i=0; i<argc-1; ++i) {
int pos = i;
for (int j=i+1; j<argc; ++j) {
if (argv[j] - '0' < argv[pos] - '0') {
pos = j;
}
}
char *tempt = argv[i];
argv[i] = argv[pos];
argv[pos] = tempt;
}
for (int i=0; i<argc; ++i) {
cout << argv[i] <<endl;
}
}
After compiling, when I called ./a.out 4 3 2 1, it still printed 4 3 2 1 to the screen instead of 1 2 3 4.
What's wrong?
Thanks in advance.
Try std::sort from <algorithm> with a custom comparator
std::sort(argv, argv + argc, [](char * const & a, char * const & b) {
return atoi(a) < atoi(b);
});
In modern c++ you can use auto types for lambdas. For string to int convertion I would prefer stoi function over atoi (you can look for differences here). Also worth noting that first argument (argv[0]) is a program name, e.g. ./a.out, so you need to skip it from sorting. Final result could be looks like this:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
int main (int argc, char *argv[]) {
std::sort(argv + 1, argv + argc, [](auto l, auto r){ return std::stoi(l) < std::stoi(r); } );
std::copy(argv + 1, argv + argc, std::ostream_iterator<const char*>(std::cout, " "));
}
If all of command line arguments a unsigned number with fixed digits count you could also sort them like string, i.e. without explicit converting to numbers via std::stoi. In this case std::vector<std::string> could be used:
std::vector<std::string> v(argv + 1, argv + argc);
std::sort(v.begin(), v.end());
There is no need to use lambda or another custom comparator for std::sort.

How to sort command-line arguments in c++

All I want to do for right now is sort command-line arguments, but I keep getting a segmentation fault (core dumped) error, which I think means I have a pointer pointing at an imaginary place.
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<vector>
using namespace std;
int main (int argc, char* argv[]) {
vector<int> the_args;
vector<int>::iterator it;
it = the_args.begin(); //this seems logical to me.
int i = 1; //so I'll skip over argv[0]
while (i < argc)
{
the_args.insert (it, atoi(argv[i]));
i++;
it++;//this is probably the perpetrator.
}
sort (the_args.begin(), the_args.end());
for (it = the_args.begin(); it < the_args.end(); it++) //or else it's this
{
cout << *it << " ";
}
return 0;
}
I eventually want to program games. I've got enough experience in Java that I figured I could start trying to screw around in C++ and figure it out... but maybe not? Please be nice in your answers, I'm really discouraged that I even have to ask a question on here about sorting something.
Here:
vector<string> the_args( argv + 1, argv + argc );
Or:
vector<int> the_args;
for( int i = 1; i < argc; ++i )
{
the_args.push_back( atoi( argv[i] ) );
}
Then just sort it with std::sort as you’re doing.
the_args.insert (it, atoi(argv[i]));
This invalidates it. Scrap the iterator, and just use push_back.
the_args.push_back(atoi(argv[i]));
Alternatively, insert returns a valid iterator to the object that was just inserted, so you could also do this:
it = the_args.insert (it, atoi(argv[i]));
But that's unnecessarily complicated if you are just inserting at the end of the vector. Here's an option which replaces your entire loop, if you're a fan of one-liners:
std::transform(argv + 1, argv + argc, std::back_inserter(the_args), std::atoi);
Try the following
#include<iostream>
#include<cstdlib>
#include<vector>
int main (int argc, char* argv[])
{
vector<int> the_args
if ( argc > 1 ) the_args.reserve( argc - 1 );
for ( int i = 1; i < argc; i++ ) the_args.push_back( std::atoi( argv[i] ) );
std::sort( the_args.begin(), the_args.end() );
for ( int x : the_args )
{
std::cout << x << " ";
}
std::cout << std::endl;
return 0;
}

C++ the dynamic array and file reading don't work together

Such a code:
int _tmain(int argc, _TCHAR* argv[])
{
int *test = new int[];
ifstream f("ofile.txt");
for (int i=0,v; i<10; i++)
{
f>>v;
test[i]=1;
cout<<"\nv = "<<v<<", i = "<<i<<endl;
}
return 0;
}
caused of this message after compiling:
I guess (correct me if I'm wrong) here is some error about memory, but details are unknown for me. If I remove one of them (file reading or array) it works.
So it will be great to hear an explanation of the problem.
You're thinking java. To allocate an array like that you need to give a size.
e.g.
int *test = new int[20];
However a better scheme would be to use a vector of integers.
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm> // for sort()
int main(int argc, char *argv[])
{
std::vector<int> data;
std::ifstream fsin("ofile.txt");
int count = 0;
while (fsin.good())
{
int v;
fsin >> v;
if (fsin.good())
{
data.push_back(v);
std::cout << "\nv = " << v << ", i = " << count++ << std::endl;
}
}
std::sort(data.begin(), data.end());
for (size_t i=0; i<data.size(); i++)
std::cout << i << '\t' << data[i] << std::endl;
return 0;
}
You have to allocate a fixed size array, int *test = new int[]; shouldn't even work.
If the size is known, use int *test = new int[size];, otherwise try using a std::vector or std:array.

Calculating two numbers from command line c++

This is my code :
#include <iostream>
using namespace std;
int main (int argc, char* argv[])
{
int frstNumb = atoi (argv[1]);
int scndNumb = atoi (argv[2]);
int sum = 0;
sum = frstNumb + scndNumb;
}
Okay, now its working for integers. What do I must do so I can put e.g. "2.5 and 1.2" in my parameters? This program won't calculate that kind of numbers. Help?
Thanks
The arguments are always passed as strings. First of all, change the main function declaration to
int main (int argc, char* argv[])
Note that the return value of main MUST be int, otherwise it is nonstandard.
Second convert argv[1] and argv[2] to integers with either atoi , which, to my taste, is a bit C-ish, although the simplest, or by boost::lexical_cast
e.g.
int i1 = atoi(argv[1]); //#include <cstdlib>
int i1 = boost::lexical_cast<int>(argv[1]); //#include <boost/lexical_cast.hpp>
Yep-- you want atoi().
int frstNumb = atoi(argv[1]);
int scndNumb = atoi(argv[2]);
I'd suggest googling atoi() to see how it works, it will probably help you in the future.
argv[1] and argv[2] are strings. When you do the sum, wrap them with atoi() calls so they are parsed and converted to integers.
Thanks to Mark Loeser and walkingTarget
Your declaration of main() should be:
int main(int argc, char **argv)
or
int main(int argc, char *argv[])
main() should always return an int, and argv should always be an array of strings.
As suggested in other answers, you first need to change declaration of function main - argc represents total number of arguments passed to it and argv is an array of arguments themselves (each argument is an element in array; first element - argv[0] - is path to this executing binary! argv[1] is actually first argument from a command line).
Both in C and C++ you can use atoi or sscanf functions but in C++ you should take advantage of STL stringstream's conversion capabilities:
#include <iostream>
#include <sstream>
using namespace std;
int main(int argc, char* argv[])
{
if(argc != 3)
{
cerr << "Invalid number of operands" << endl;
return 1;
}
int n1 = 0;
int n2 = 0;
stringstream ss;
ss << argv[1];
ss >> n1;
ss.clear();
ss << argv[2];
ss >> n2;
int sum = n1 + n2;
return 0;
}