Go Down

Topic: write a function to add numbers to a sum? (Read 348 times) previous topic - next topic

flyandance



The code below adds all the numbers in an array to a sum, but I don't really want to use an array here. I only want a simple function that can be used to add any amount of numbers to a sum.

such as this:
Code: [Select]
int total=add(num1, num2)
int total=add(num1, num2, num3)
int total=add(num1, num2, num3, num4.....)


here is my failed code:
Code: [Select]
byte love[]={1,2,3,4,5,6,8,9,10};


void setup() {
  Serial.begin(9600);     
}

void loop() {

  int buf= adding (love, sizeof(love));
  Serial.println(buf);
  delay(2000); 
}


int adding (byte *hate, byte len){
    int buf=0;
    for (byte i=0; i<len; i++){
    buf+= hate[i];
    }
  return buf; 
  }

el_supremo

#1
Mar 18, 2017, 09:47 pm Last Edit: Mar 18, 2017, 09:51 pm by el_supremo
In what way does it fail?

Oh, you mean it uses an array and you don't want to do that.
Hmmm. I think there is a way to specify a variable number of arguments but I forget, or never knew, how to do it :)

Pete
Don't send me technical questions via Private Message.


flyandance

Take a look:

https://www.tutorialspoint.com/cprogramming/c_variable_arguments.htm
http://www.cplusplus.com/reference/cstdarg/va_copy/

getting 2089 with this code. Should be 14.
Code: [Select]


#include <stdarg.h>
byte love[]={1,2,3,4,5,6,8,9,10};

void setup() {
  Serial.begin(9600);     
}

void loop() {

  int buf= adding (love, sizeof(love));
  Serial.println(buf);

  int buff= add (4,1,2,3,4);
  Serial.println(buff);
   
  delay(2000); 
}


int adding (byte *hate, byte len){
    int buf=0;
    for (byte i=0; i<len; i++){
    buf+= hate[i];
    }
  return buf; 
  }

int add (int n, ...){
  int buf=0;
  int val=n;
  int counter=0; 
 
  va_list adding, count;
  va_start (adding, n);
 
  va_copy (count, adding);
  while (val!=0){
    val=va_arg (count, int);
    ++counter;
  }
  va_end(count);
 
  for (; counter>0; counter--){
  buf+=va_arg (adding, int);
  }
  va_end(adding);
 
    return buf;
  }





econjack

This seems like using an H-bomb to kill an ant. Why do you want to do it this way?

flyandance

This seems like using an H-bomb to kill an ant. Why do you want to do it this way?
This is the part of a library that I am writing. I need to figure out a way to do it properly in its simplest form first.

user091ard

getting 2089 with this code. Should be 14.
Code: [Select]

void loop() {

  int buf= adding (love, sizeof(love));
  Serial.println(buf);

  int buff= add (4,1,2,3,4);
  Serial.println(buff);
   
  delay(2000); 
}

add(4, 1, 2, 3, 4) should be 1+2+3+4 = 10. The first argument is the number of arguments.


Try this solution (I don't have a board beside me, so I can't test this):

Code: [Select]

#include <stdarg.h>

int sum(int num,...)
{
   va_list valist;
   va_start(valist, num);

   int sum = 0;
   for (int i = 0; i < num; i++)
   {
      sum += va_arg(valist, int);
   }

   va_end(valist);

   return sum;
}

void setup()
{
   Serial.begin(9600);
}

void loop()
{
   int result = sum(4, 1, 1, 1, 1);
   Serial.println(result);

   delay(2000);
}



flyandance

add(4, 1, 2, 3, 4) should be 1+2+3+4 = 10. The first argument is the number of arguments.


Try this solution (I don't have a board beside me, so I can't test this):

Code: [Select]

#include <stdarg.h>

int sum(int num,...)
{
   va_list valist;
   va_start(valist, num);

   int sum = 0;
   for (int i = 0; i < num; i++)
   {
      sum += va_arg(valist, int);
   }

   va_end(valist);

   return sum;
}

void setup()
{
   Serial.begin(9600);
}

void loop()
{
   int result = sum(4, 1, 1, 1, 1);
   Serial.println(result);

   delay(2000);
}



This should work, but I don't want to enter the "first argument as the number of arguments". I want every argument to be added to the sum, so sum(4, 1, 1, 1, 1) = 8, not 4;

The va_copy should do the trick, but It doesn't work for me.

user091ard

#8
Mar 19, 2017, 09:30 pm Last Edit: Mar 19, 2017, 09:49 pm by user091ard
Try this code (the only restriction is that your last argument has to be 0):

Code: [Select]

#include <stdarg.h>

int add(int num, ...)
{
int total = num;
int counter = 0;
int val = num;

va_list adding, count;
va_start (adding, num);

va_copy(count, adding);
while (val != 0)
{
val = va_arg(count, int);
++counter;
}
va_end(count);

for (int i = 0; i < counter - 1; ++i)
{
total += va_arg (adding, int);
}
va_end(adding);

return total;
}

void setup()
{
Serial.begin(9600);
}

void loop()
{
int buff = add(1, 2, 3, 4, 0);
Serial.println(buff);
delay(2000);
}


Or this solution (with INT_MAX):

Code: [Select]

#include <stdarg.h>
#include <limits.h>

int add(int num, ...)
{
int total = num;
int counter = 0;
int val = num;

va_list adding, count;
va_start (adding, num);

va_copy(count, adding);
while (val != INT_MAX)
{
val = va_arg(count, int);
++counter;
}
va_end(count);

for (int i = 0; i < counter - 1; ++i)
{
total += va_arg (adding, int);
}
va_end(adding);

return total;
}

void setup()
{
Serial.begin(9600);
}

void loop()
{
int buff = add(1, 2, 3, 4, 5, 1, INT_MAX);
Serial.println(buff);
delay(2000);
}

flyandance

Try this code (the only restriction is that your last argument has to be 0):

Code: [Select]

#include <stdarg.h>

int add(int num, ...)
{
int total = num;
int counter = 0;
int val = num;

va_list adding, count;
va_start (adding, num);

va_copy(count, adding);
while (val != 0)
{
val = va_arg(count, int);
++counter;
}
va_end(count);

for (int i = 0; i < counter - 1; ++i)
{
total += va_arg (adding, int);
}
va_end(adding);

return total;
}

void setup()
{
Serial.begin(9600);
}

void loop()
{
int buff = add(1, 2, 3, 4, 0);
Serial.println(buff);
delay(2000);
}


Or this solution (with INT_MAX):

Code: [Select]

#include <stdarg.h>
#include <limits.h>

int add(int num, ...)
{
int total = num;
int counter = 0;
int val = num;

va_list adding, count;
va_start (adding, num);

va_copy(count, adding);
while (val != INT_MAX)
{
val = va_arg(count, int);
++counter;
}
va_end(count);

for (int i = 0; i < counter - 1; ++i)
{
total += va_arg (adding, int);
}
va_end(adding);

return total;
}

void setup()
{
Serial.begin(9600);
}

void loop()
{
int buff = add(1, 2, 3, 4, 5, 1, INT_MAX);
Serial.println(buff);
delay(2000);
}

ok, thanks a lot. so using va_copy really doesn't work. It can't exit the arguments counting while loop by itself. while for a summing function, adding a zero to the end is okay, but it really doesn't work for me here, as I am not necessarily write a summing function. I will figure it out.

boolrules


GoForSmoke

If you check AVR-LibC where Arduino gets its standard C libraries

http://www.nongnu.org/avr-libc/user-manual/modules.html

you may notice that there is no stdarg.h.

With more checking you can find that the AVR-LibC stdio.h does use va_list.

So just on instinct and a whim I decided to see if AVR-LibC in Arduino IDE has stdarg by default. It does.

sketch:
Code: [Select]

int x, y, z;

int addEmUp( int n, ... )
{
  x = n;
  y = 0;

  va_list vList;
  va_start( vList, n );
  
  for ( int i = 0; i < n; i++ )
  {
    z = va_arg( vList, int );
    y += z;
    Serial.println( z );
  }
  return y;
}

void setup()
{
  Serial.begin( 250000 );
  z = addEmUp( 5, 1,2,3,4,5 );
    Serial.println();
    Serial.println( z );
}

void loop()
{

}


output:
Quote
1
2
3
4
5

15
Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

Go Up