I have a problem with variable number of arguments in C++. I write my code using Xcode.
Here is my code:
#include <iostream>
int sum(int n, ...)
{
int *p = &n;
p++;
int res = 0;
for(int i=0; i<n; i++){
res+=(*p);
p++;
}
return res;
}
int main(int argc, const char * argv[]) {
std::cout << sum(4, 1, 2, 3, 4);
return 0;
}
sum(4, 1, 2, 3, 4) should return a value of 10, but it returns 1606452732.
In C++ you use a template metafunction to do that. It's pretty straight forward:
int sum(int u)
{return u;} // Recursion-End
template<typename... Args>
int sum(int u, Args... rest)
{
return u + sum(rest...);
}
Try it online!
However there is a, as I consider it, depreciated C-way using va_start and va_end. You need to include cstdarg and on function call you need to provide the total parameter count. It would look like this:
int sum(int argnum, ...)
{
va_list arguments;
int i;
int sum = 0;
va_start(arguments, argnum); /* Needs last known character to calculate
the address of the other parameters */
for(i = 0; i < argnum; ++i)
sum += va_arg(arguments, int); /* use next argument */
va_end(arguments);
return sum;
}
Try it online!
From: http://en.cppreference.com/w/cpp/utility/variadic/va_start
#include <iostream>
#include <cstdarg>
int add_nums(int count, ...)
{
int result = 0;
va_list args;
va_start(args, count);
for (int i = 0; i < count; ++i) {
result += va_arg(args, int);
}
va_end(args);
return result;
}
int main()
{
std::cout << add_nums(4, 25, 25, 50, 50) << '\n';
return 0;
}
Related
Hello guys my program is not printing the maximum value it is printing some garbage value or address.
#include <iostream>
#include <cstdarg>
int findmax(int, ...);
int main(int argc, char *argv[]) {
std::cout << findmax(9, 255, 86, 4, 89, 6, 1, 422, 5, 29);
}
int findmax(int count, ...) {
int max, val;
va_list list;
va_start(list, count);
for (int i = 0; i < count; ++i) {
max = va_arg(list, int);
val = va_arg(list, int);
if (max < val) max = val;
}
va_end(list);
return max;
}
for (int i = 0; i < count; ++i) {
max = va_arg(list, int);
val = va_arg(list, int);
if (max < val) max = val;
}
In this code you take two arguments but iterate the index by one. va_arg always takes the next element, so you end up with taking values beyond the variadic function argument list.
You may iterate by two elements, but this would require you to have even number of arguments, thus just declare a separate variable to store the max element:
// std::numeric_limits is defined in <limits> header
auto max = std::numeric_limits<int>::min();
for (decltype(count) i = 0; i < count; ++i) {
auto val = va_arg(list, int);
if (max < val)
max = val;
}
Here is my program
#include <bits/stdc++.h>
using namespace std;
// Function to return gcd of a and b
int gcd(int a, int b)
{
if (a == 0)
return b;
return gcd(b % a, a);
}
// Function to find gcd of input2ay of
// numbers
int findGCD(int input2[], int n)
{
int result = input2[0];
for (int i = 1; i < n; i++)
{
result = gcd(input2[i], result);
if(result == 1)
{
return 1;
}
}
return result;
}
// Driver code
int main(int input1,int input2[40])
{
int n = sizeof(input2) / sizeof(input2[0]);
cout << findGCD(input2, n) << endl;
return 0;
}
The input has to go in following format
3 2 4 8
where 3 is size of array and 2 4 8 are elements of array.
Now I am getting following errors
main.cpp:40:5: warning: second argument of ‘int main(int, int*)’ should be ‘char **’ [-Wmain]
int main(int input1,int input2[40])
^~~~
main.cpp: In function ‘int main(int, int*)’:
main.cpp:43:23: warning: ‘sizeof’ on array function parameter ‘input2’ will return size of ‘int*’ [-Wsizeof-array-argument]
int n = sizeof(input2) / sizeof(input2[0]);
^
main.cpp:40:34: note: declared here
int main(int input1,int input2[40])
^
What is the problem here?
my question is mostly code adding more details.
edit
based on suggestions I came up with using atoi.
#include <stdio.h>
unsigned gcd(unsigned x, unsigned y){
unsigned wk;
if(x<y){ wk=x;x=y;y=wk; }
while(y){
wk = x%y;
x=y;
y=wk;
}
return x;
}
int gcd_a(int n, int a[n]){
if(n==1) return a[0];
if(n==2) return gcd(a[0], a[1]);
int h = n / 2;
return gcd(gcd_a(h, &a[0]), gcd_a(n - h, &a[h]));
}
int main(int argc ,char *argv[]){
// argc is number of arguments given including a.out in command line
// argv is a list of string containing command line arguments
int total = 0;
int i,input1;
int *value;
for(i = 1; i < argc; i++)
{
// The integers given is read as (char *)
value[i] = atoi(argv[i]);
total++;
}
input1 = total;
int gcd = gcd_a(input1, value);
printf("%d\n", gcd);
return 0;
}
But still this is not giving me desired result.
I compiled it online but it did not give any error but it did not took any arguments also.
The post can not be submitted because it looks mostly code java script programming error in SO.
The main method declaration must be int main(int ,char**);
Here you will get array of c-strings. i.e (["10","20","40"....]).
So you need to convert char* to integer using below methods
using atoi() method ==> read this
sscanf() method ==> read this
see the below code
int findGCD(char* input2[], int n)
{
int result = atoi(input2[1]); /*Here first argument is fileName itself ,so we are taking from second.i.e input2[1]*/
for (int i = 2; i < n; i++)
{
int a = atoi(input2[i]);
result = gcd(a, result);
if(result == 1)
{
return 1;
}
}
return result;
}
// Driver code
int main(int args,char** argv)
{
// for(int i = 0;i < args;i++)
// {
// cout <<"argv["<<i<<"] = "<<argv[i]<<endl;
// }
cout << "GCD::"<<findGCD(argv, args) << endl;
return 0;
}
I have a Matrix template class and I need a function to set it's elements with variable number of args.
I should be able to call it like this:
aghMatrix<string> matrix;
matrix.setItems(2, 3, "torzmiae", "jestdnaci", "tablickore", "wyrazobed", "oelmntai", "rozmiaecy");
Where first integer is rows number, second is columns and rest (R * C) arguments are elements that I should put into matrix.
It should work with any data types, not only primitive ones.
For now, my function looks like this:
template<typename T>
template<typename... ARGS>
void aghMatrix<T>::setItems(const int rows, const int cols, ARGS... args) {
array<T, sizeof...(args)>unpacked_args {args...};
int row = 0;
int col = 0;
for (T arg : unpacked_args)
{
this->matrixPtr[row][col] = arg;
col++;
if (col == this->cols) {
row++;
col = 0;
}
}
return;
}
I assumed my matrix object is able to hold all elements. It does compile with many warnings about casting everything to unsigned int, but the program doesn't work anyway (it freezes on start).
Class declaration:
template<typename T>
class aghMatrix {
public:
[...]
template<typename... ARGS> void setItems(const int rows, const int cols, ARGS... args);
[...]
private:
T **matrixPtr;
int rows;
int cols;
void createMatrix(const int row, const int col);
bool checkRowCol(const int row, const int col) const;
};
Github project
EDIT: Oops! I just noticed you said "non recursive," so I presume the following pattern doesn't work for you. I'll still leave it hanging here for now, but I have provided also a non recursive solution below (which is based on va_list and hence only works with POD types)
If I understand correctly what you want to do, then you probably want the recursive variadic argument unpacking pattern; something like this seems to do the trick...
#include <iostream>
using namespace std;
// Helper for build_matrix, taking zero variadic arguments.
// This serves as the termination in the recursive unpacking of the args.
template<typename T>
void build_matrix_helper(T**, size_t, size_t, size_t, size_t) { return; }
// Helper for build_matrix, taking at least one variadic argument.
template <typename T, typename ...ARGS>
void build_matrix_helper(T** matrix, size_t curr_row, size_t curr_col,
size_t row, size_t col, const T& first, ARGS...rest) {
if (curr_col < col) {
matrix[curr_row][curr_col] = first;
++curr_col;
return build_matrix_helper<T>(matrix, curr_row, curr_col, row, col, rest...);
}
else {
++curr_row;
curr_col = 0;
return build_matrix_helper<T>(matrix, curr_row, curr_col, row, col, first, rest...);
}
return;
}
// Bare bones implementation.
template<typename T, typename ...ARGS>
T **build_matrix(size_t row, size_t col, ARGS...elements) {
T **new_mat = new T*[row];
for (size_t j = 0; j < row; ++j)
new_mat[j] = new T[col];
build_matrix_helper<T>(new_mat, 0, 0, row, col, elements...);
return new_mat;
}
int main() {
int **nm = build_matrix<int>(2, 3, 1, 2, 3, 4, 5, 6);
for (size_t i = 0; i < 2; ++i) {
cout << "[" << i + 1 << "]: ";
for (size_t j = 0; j < 3; ++j)
cout << nm[i][j] << " ";
cout << endl;
}
delete[] nm;
return 0;
}
In general, you want to avoid any direct manipulation of memory as much as possible. Also avoid as much as possible any casting voodoo unless you absolutely need it (which also ties in with direct memory manipulation).
Anyway, can use a non recursive solution below, using std::va_list.
NOTE Since this uses va_list, it does not work with non POD types.
#include <iostream>
#include <cstdarg>
using namespace std;
template <typename T>
T **build_matrix(size_t row, size_t col, ...) {
va_list args;
T **matrix = new T*[row];
va_start(args, col);
for (size_t i = 0; i < row; ++i) {
matrix[i] = new T[col];
for (size_t j = 0; j < col; ++j)
matrix[i][j] = va_arg(args, T);
}
va_end(args);
return matrix;
}
int main() {
int **nm = build_matrix<int>(2, 3, 1, 2, 3, 4, 5, 6);
for (size_t i = 0; i < 2; ++i) {
cout << "[" << i + 1 << "]: ";
for (size_t j = 0; j < 3; ++j)
cout << nm[i][j] << " ";
cout << endl;
}
delete[] nm;
return 0;
}
EDIT Initializer lists
As has been suggested in the comments to your OP, it is better to use initializer lists. I know this isn't what you asked for originally, but maybe it's worth considering:
#include <iostream>
#include <stdexcept>
using namespace std;
template <typename T>
T **build_matrix(size_t row, size_t col, initializer_list<T> il) {
if (il.size() != row*col)
throw out_of_range("Number of elements does not match matrix dimensions!");
size_t curr_row = 0;
size_t curr_col = 0;
T **nm = new T*[row];
nm[0] = new T[col];
for (T elm : il) {
if (curr_col == col) {
++curr_row;
nm[curr_row] = new T[col];
curr_col = 0;
}
nm[curr_row][curr_col] = elm;
++curr_col;
}
return nm;
}
int main() {
int **nm = build_matrix<int>(2, 3, {1, 2, 3, 4, 5, 6});
for (size_t i = 0; i < 2; ++i) {
cout << "[" << i + 1 << "]: ";
for (size_t j = 0; j < 3; ++j)
cout << nm[i][j] << " ";
cout << endl;
}
delete[] nm;
return 0;
}
For a class assignment I am required to create 4 functions to test in a program. I must use the copyArray function, PrintArray function and InputArray function. The problem that I am having the most trouble with is the copyArray portion. I have completed most of the code on my own but I need to know if I am close to the solution or not close at all.The code, I'm sure, is a mess. If someone could help me get in the right direction of how to finish this I will be very grateful.
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
using std::istream;
using std::ostream;
void inputArray(istream &, int[], int*);
void printArray(ostream &, const int[], int);
float a[4] = { 0, 1, 2, 3 };
float b[4];
void copyArray(const int orig[], int dup[], int);
void main()
{
int a[4] = { 7, 14, 9, 10 };
int b[4];
cout << "The input data : " << endl;
inputArray(cin, a, b);
cout << "The printArray data : " << endl;
printArray(cout, b, 4);
}
//----------------------------------------------------------------------------
void inputArray(istream & in, int t[], int howMany)
{
for (int i = 0; i < howMany; i++)
in >> t[i];
return;
}
//-----------------------------------------------------------------------------
void printArray(ostream & out, const int r[], int cnt)
{
for (int i = 0; i< cnt; i++)
out << r[i] << endl;
return;
}
void copyArray(const int orig [], int dup [], int);
for (int i = 0; i < 4; i++){
b[i] = a[i];
}
}
Of course it would be better to define function copyArray as a template function. For example
template <typename T, size_t N>
void copyArray( T ( &dst )[N], const T ( &src )[N] )
{
for ( size_t i = 0; i < N; i++ ) dst[i] = src[i];
}
As for your function declaration then its definition can look like
void copyArray( int dst[], const int src[], size_t n )
for ( size_t i = 0; i < n; i++ ) dst[i] = src[i];
}
In the function definition shown by you you have to remove the semicolon after the closing parenthesis and to use function parameters instead of the global variables.
Take into account that there are standard algorithms std::copy, std::copy_n, std::copy_if, std::copy_backward declared in header <algorithm> that can be used for coping arrays.
I am almost done with my code; however, one part is not working well. Simply, reading from a file that contains only numbers(ex. cars sold). by using an array, trying to get the total of those numbers, max, and the number of the max index. My question is: how can I return the two values from my MaxSold function? it returns only the max added to the index which is not correct. the result should point to the employee number then the max.
This is my code so far:
#include <iostream>
#include <fstream>
/*#include <vector>
#include <iomanip>*/
void Read(int arryList[], int size);
void Print(int arryList[], int size);
int total(int arryList[], int size);
int MaxSold(int arryList[], int size, int& number);
using namespace std;
ifstream inFile("C:\\cars.dat");
int main()
{
int cars[7];
int i;
Read(cars,7);
Print(cars,7);
cout<<"The total of sold cars is: "<<total(cars, 7)<< "\n";
cout<<"The Max "<< MaxSold(cars, 7, i);
}
void Read(int arryList[], int size){
for(int i = 0; i < 7; i++)
{
inFile >> arryList[i];
}
return;
}
void Print(int arryList[], int size){
for (int i = 0; i < 7; i++){
cout << i + 1 << "-"<< arryList[i] << "\n";
}
return ;
}
int total(int arryList[], int size){
int sum = 0;
for (int i = 0; i < size; i++){
sum +=arryList[i];
}
return sum;
}
int MaxSold(int arryList[], int size, int& number){
int Maximum= 0;
int relate=0;
for( int i=0 ; i<7 ; i++){
if (arryList[i] > Maximum){
Maximum = arryList[i];
relate = i+1;
}
}
return Maximum, relate;
}
Use std::pair
#include<utility>
//..
std::pair<int,int> MaxSold(int arryList[], int size, int& number)
{
//...
return std::make_pair( Maximum, relate );
}
Then,
std::pair<int,int> p = MaxSold(cars, 7, i) ;
std::cout<< p.first ; //maximum
std::cout<< p.second ; //relate
You cannot return more than one value from a function. Of course, that value can be a container for multiple values. It can be your own custom type, but the simplest way would be to return a std::pair<int,int>.
std::pair<int, int> MaxSold(int arryList[], int size, int& number)
{
// ...
return std::make_pair(Maximum, relate);
}