string to integers from argv - c++

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;
}

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.

C++ combine two files output

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;
}

c++ simple pointer program [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
Here is a simple program where it sums all of the numbers sent in on the command line. It should take an arbitrary number of values.
It keeps giving me a 0 for each line. I've tired to make several changes but it continues to give the same output
#include <iostream>
#include <cstdlib>
using namespace std;
int main(int argc, char *argv[])
{
for (int i = 0; i < argc; i++)
{
int sum=0;
sum+=atoi("argc[i]");
cout << sum << endl;
}
return 0;
}
"argc[i]" is a literal string so when converted by atoi gives 0! sum should be initialized before the loop :
int main(int argc, char *argv[]) {
int sum=0;
for (int i = 1; i < argc; i++) {
sum += atoi(argv[i]);
}
cout << sum << endl;
return 0;
}
Conventionally argv[0] is the name of the program (or at least the name used in the command line to invoke the program), so better start at index 1.
You need to spend dozen of hours reading more your books and experimenting on your computer. Asking here such a basic question don't help you at all (and is considered as rude...).
Don't forget to enable debugging info and all warnings when compiling (e.g. with g++ -Wall -g if using GCC). Then, learn how to use the debugger (e.g. gdb).
Your basics are not clear, I suggest you to read the book.
Program should be like this:
#include <iostream>
#include <cstdlib>
using namespace std;
int main(int argc, char *argv[])
{
int sum=0;
for (int i = 0; i < argc; i++)
{
sum+=atoi(argv[i]);
}
cout << sum << endl;
return 0;
}
move parameter sum outside loop!!
#include <iostream>
#include <cstdlib>
using namespace std;
int main(int argc, char *argv[])
{
int sum=0;
for (int i = 0; i < argc; i++)
{
sum+=atoi(argv[i]);
cout << sum << endl;
}
return 0;
}

Comparing two arrays and creating third array with common elements

I need to compare two arrays and output another array that shows common elements.
The output I'm expecting with my code is: 0000056789.
Help will be appreciated.
#include <iostream>
using namespace std;
const int CE = 10;
const int TOP = CE-1;
int iArr1[CE]={0,1,2,3,4,5,6,7,8,9};
int iArr2[CE]={5,6,7,8,9,10,11,12,13,14};
int iArr3[CE]={0,0,0,0,0,0,0,0,0,0};
void main()
{
int i;
int j;
int iCarr3 = 0;
for(i=0; i<=TOP; i++)
{
for (j=0; j<=TOP; j++)
{
if (iArr1[i]==iArr2[j])
{
iCarr3++;
iArr3[iCarr3]=iArr2[j];
}
}
}
cout << iCarr3 << endl;
cout << iArr3;
getchar();
}
you are printing the address of your array
to print the elements of an array
for (int i = 0; i < size; i++) // keep track of the size some how
cout<<iArr3[i]<<" ";
P.S: consider sorting the arrays first, and ckecking if iArr1[i] > iArr2[j]that way you won't need to scan all the elements on eavh pass
C++ has a set_intersection algorithm in the Standard Library:
#include <iostream>
#include <algorithm>
int main()
{
const int CE = 10;
int iArr1[CE] = {0,1,2,3,4,5,6,7,8,9};
int iArr2[CE] = {5,6,7,8,9,10,11,12,13,14};
int iArr3[CE] = {0,0,0,0,0,0,0,0,0,0};
std::set_intersection(std::begin(iArr1), std::end(iArr1),
std::begin(iArr2), std::end(iArr2),
std::begin(iArr3));
std::copy(std::begin(iArr3), std::end(iArr3), std::ostream_iterator<int>(std::cout, " "));
}
Output
5 6 7 8 9 0 0 0 0 0
Note
If your arrays aren't already sorted, you could put the data into a std::set first, since std::set_intersection() requires the inputs to be sorted.
Ok I hope this is not homework. The way you have it, the output will be 5678900000. For the output to be as you want change your code to be as such:
for(i=0; i<=TOP; i++)
{
for (j=0; j<=TOP; j++)
{
if (iArr1[i]==iArr2[j])
{
iArr3[iCarr3]=iArr2[j];
}
}
iCarr3++;
}
Then for the output do this:
for(int k = 0; k <= iCarr3; k++)
std::cout << iArr3[iCarr3] << " ";
As your array are sorted, use std::set_intersection. Otherwise you just have to std::sort them before.
But never forget to use the STD library, the code is a lot more compact and readable... And most of the time less buggy and faster that what you'll come with.
http://ideone.com/c3xE3m
#include <algorithm>
#include <iostream>
#include <iterator>
const size_t CE = 10;
int iArr1[CE]={0,1,2,3,4,5,6,7,8,9};
int iArr2[CE]={5,6,7,8,9,10,11,12,13,14};
int iArr3[CE]={0,0,0,0,0,0,0,0,0,0};
int main(int argc, char const *argv[])
{
auto end_elemnt =
std::set_intersection(iArr1, iArr1 + CE,
iArr2, iArr2 + CE,
iArr3);
std::copy(iArr3, end_elemnt, std::ostream_iterator<int>(std::cout, ", "));
return 0;
}
Here is the output:
$ ./a.exe
5, 6, 7, 8, 9,