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.
Related
I'm trying to implement a naive approach of the longest common subsequence algorithm. I'm using a recursive approach, passing two strings into the function lcs. I successfully counted the number of characters in the longest subsequence.
My problem is printing the characters of the lcs. I thought I could do this by storing matched characters in a string called sub and passing it as a parameter. However, I'm stuck on how to save the string. I've always struggled with recursion, and would appreciate any tips on approaching this problem the right way.
#include <iostream>
#include <string>
#include <math.h>
using namespace std;
int lcs(string a, string b,string sub){
int aLen = a.length();
int bLen = b.length();
if (aLen==0 || bLen==0){
return 0;
}
if(a.at(aLen-1)==b.at(bLen-1)){
return 1+lcs(a.substr(0,aLen-1),b.substr(0,bLen-1),a.at(aLen-1)+sub); // add letter to subsequence
}
else {
return max(lcs(a.substr(0,aLen-1),b.substr(0,bLen),sub),lcs(a.substr(0,aLen),b.substr(0,bLen-1),sub));
}
}
int main(int argc, const char * argv[])
{
char sub[]="";
int charsInLCS = lcs("sdmc","msdc",sub); //i want to output "sdc"
cout << charsInLCS << endl;
return 0;
}
Be careful, your base case is wrong as you never check a[0] against b[0]. Also, passing string copies is very expensive, much faster to pass just the indexes and work with that. We need to keep track of what characters we matched when a[idxa] == b[idxb]. Here is a solution using vectors:
#include <iostream>
#include <string>
#include <queue>
#include <math.h>
#include <algorithm> // std::reverse
using namespace std;
string s1, s2;
int lcs(int idx1, int idx2, vector<char> &v){
if (idx1 == -1 || idx2 == -1){
return 0;
}
if (s1[idx1] == s2[idx2]) {
v.push_back(s1[idx1]); // record that we used this char
return 1 + lcs(idx1 - 1, idx2 - 1, v);
} else {
vector<char> v1, v2;
int p1 = lcs(idx1 - 1, idx2, v1);
int p2 = lcs(idx1, idx2 - 1, v2);
if (p1 > p2) { // we used the chars we already had in v + the ones in v1
v.insert(v.end(), v1.begin(), v1.end());
return p1;
} else { // we used the chars we already had in v + the ones in v2
v.insert(v.end(), v2.begin(), v2.end());
return p2;
}
}
}
int main(int argc, const char * argv[])
{
s1 = "sdmc";
s2 = "msdc";
vector<char> v; // chars we used
int sol = lcs(s1.length() - 1, s2.length() - 1, v); //i want to output "sdc"
cout << sol << " ";
reverse(v.begin(), v.end());
for (auto num : v) {
cout << num;
}
return 0;
}
I've a program which is taking input from command-line and using them ahead. All this time the inputs were given separately after the invocation command eg ./a.out 1 2 3 4 5 and it was quite easy to use them (lets just sum them for the moment) -
#include <iostream>
#include <cstdlib>
int main(int argc, char **argv) {
int sum = 0;
for(int i = 1; i < argc; ++i) {
sum += std::atoi(argv[i]);
}
std::cout << sum << std::endl;
}
but now the input format has changed to ./a.out "1 2 3 4 5" and this method does not works correctly. I tried to take "1 2 3 4 5" to a string but then I cannot get the integers out of it. Nor can I think of any other solution at this moment. Is there any elegant method to take them out of argv without too much complexity?
You need to split the string. You can do this for example using string streams:
#include <iostream>
#include <sstream>
int main(int argc, char **argv) {
int sum = 0;
for(int i = 1; i < argc; ++i) {
std::istringstream iss(argv[i]);
for (int n; iss >> n;) sum += n;
}
std::cout << sum << std::endl;
}
I am new to C/C++ .I have 2 text files and need to combine two files contents
I executed like this g++ merge.cc -o merge and created two text files with content like this:
file1 : 1 3 5 7
file2 : 2 4 6 8
then excuted this command : ./merge 10 t1.txt t2.txt
Out came : 1 2 3 4 5 6 7 81 2 3 4 5 6 7 8
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
void combine(char s[], char t[], char result[]);
int main(int argc, char* argv[])
{
const int MAX = 20;
char inBuffer1[MAX];
char inBuffer2[MAX];
char outBuffer[MAX*2];
int max = atoi(argv[1]);
ifstream file1(argv[2]);
ifstream file2(argv[3]);
file1.getline(inBuffer1,max);
file2.getline(inBuffer2,max);
combine (inBuffer1, inBuffer2, outBuffer);
cout << outBuffer << endl;
}
void combine(char s[], char t[], char result[])
{
int i, j, k;
for (i = j = k = 0; s[i] && t[j]; k++)
{
if (s[i] <= t[j])
result[k] = s[i++];
else
result[k] = t[j++];
cout << result[k];
}
//tidy up
for (; s[i]; )
{
result[k] = s[i++];
cout << result[k++];
}
for (; t[j]; )
{
result[k] = t[j++];
cout << result[k++];
}
result[k] = 0;
}
Could you please anyone explain about this. I thave to sort files and reserve output using -c, -r commands
Thanks in advance
The c++ standard library has std::merge to do exactly what you seem to want here. Basically open the files, then do the merge from a couple of istream_iterators to an ostream_iterator.
Try the following C-program example (without combine function):
#include <stdio.h>
#include <stdlib.h>
// compare function to sort int values
int comparator(const void *p, const void *q)
{
int l = *(int*)p;
int r = *(int*)q;
return (l - r);
}
int main(int argc, char* argv[])
{
const int MAX = 20;
int buffer[MAX*2];
int cnt = 0; // numbers in buffer
// check arguments
if( argc < 3)
{
printf("Provide correct arguments: one number and two files with numbers\n");
return 1;
}
// reading from 2 files in series
FILE * f;
for(int i = 2; i <= 3; i++)
{
f = fopen(argv[i], "r");
if( f == NULL )
{
printf("File %s cannot be read!\n", argv[2]);
break;
}
while( !feof(f) && cnt < MAX*2 ) // while file is not finished and array is not full
{
if( fscanf(f, "%d", &buffer[cnt]) ) // read data
cnt++; // and if reading is successful count
}
fclose(f);
}
// sort the resulting array (instead of combine function)
qsort(buffer, cnt , sizeof(int), comparator);
// printing results
for( int i = 0; i < cnt; i++)
{
printf("%d ", buffer[i]);
}
}
This example is for cases when initial files can consist not ordered values, so all values from both files are read to memory and then sorted by standard function from stdlib.h (to use that qsort we need function comparator, read more in the references).
But for case when both input files are already arranged (sorted) program can be simpler, but you need open both files and compare values while reading to output the smallest value from two "current", and you do not need buffer array for that case (it is just a tip, try to write a program yourself).
EDIT:
It is C++ example with merge and sort from <algorithm>:
#include <iostream>
#include <fstream>
#include <algorithm>
#include <functional>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
int data; // buffer to read one value from file
ifstream file1(argv[1]);
ifstream file2(argv[2]);
vector<int> v1, v2; // vectors to store data
// reading initial data to vectors
while( !file1.eof() )
{
file1 >> data;
v1.push_back(data);
}
file1.close();
while( !file2.eof() )
{
file2 >> data;
v2.push_back(data);
}
file2.close();
// sorting (essential if files are not sorted)
sort(v1.begin(), v1.end(), less <int>());
sort(v2.begin(), v2.end(), less <int>());
// marging
vector<int> res(v1.size() + v2.size()); // vector to store result
merge(v1.begin(), v1.end(), v2.begin(), v2.end(), res.begin(), less <int>());
// printing result
for(vector<int>::iterator i = res.begin(); i != res.end(); i++)
{
cout << *i << " ";
}
}
NOTE: In this example you do not need to ask user about size of data sequence, so argv[1] is name of the first file, and argv[2] is name of the second one (add appropriate check by yourself).
The following C++ example shows usage of istream_iterator and ostream_iterator with merge method:
#include <iostream>
#include <fstream>
#include <algorithm>
#include <iterator>
using namespace std;
int main(int argc, char* argv[])
{
// open input files
ifstream file1(argv[1]);
ifstream file2(argv[2]);
// link input streams with files
istream_iterator<int> it1(file1);
istream_iterator<int> it2(file2);
istream_iterator<int> eos; // end-of-stream iterator
// link output stream to standard output
ostream_iterator<int> oit (cout," "); // " " = usage of space as separator
// marging to output stream
merge(it1, eos, it2, eos, oit);
file1.close();
file2.close();
return 0;
}
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;
}
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;
}