Velocity Reviews > Using ternary and summing array

# Using ternary and summing array

flebber
Guest
Posts: n/a

 10-31-2011
Hi

I am learning C. I am trying to sum an array with the values returned
from a loop. Can I use the "?" operator as part of a loop; by
experimentation I know I can't put the increment in the loop.

doing ((i % 3 == 0)||(i % 5 == 0)) ? sum+=a[i] :i++ ; never actually
finished, I think I created an infinite loop.
PS I was following the example from here
http://www.tutorialspoint.com/ansi_c...r_examples.htm

So I have come to this this solution, I think the problem is that my
array a[] is assigned as a one element array and since the first value
returns false it gets 0 and exits. Is this right? If it is how do i
assign an array to have an unknown number of entries?

A kick in the right direction appreciated

#include <stdio.h>
int a[],i,sum=0;

int main()
{
while(i < 1000)
{
((i % 3 == 0)||(i % 5 == 0)) ? sum+=a[i] :0 ;
i++;
}
printf("The sum is %d\n",sum);
return 0;
}

Sayth

flebber
Guest
Posts: n/a

 10-31-2011
On Oct 31, 9:35*pm, flebber <(E-Mail Removed)> wrote:
> Hi
>
> I am learning C. I am trying to sum an array with the values returned
> from a loop. Can I use the "?" operator as part of a loop; by
> experimentation I know I can't put the increment in the loop.
>
> doing ((i % 3 == 0)||(i % 5 == 0)) ? sum+=a[i] :i++ ; never actually
> finished, I think I created an infinite loop.
> PS I was following the example from herehttp://www.tutorialspoint.com/ansi_c/ternary_operator_examples.htm
>
> So I have come to this this solution, I think the problem is that my
> array a[] is assigned as a one element array and since the first value
> returns false it gets 0 and exits. Is this right? If it is how do i
> assign an array to have an unknown number of entries?
>
> A kick in the right direction appreciated
>
> #include <stdio.h>
> int a[],i,sum=0;
>
> int main()
> {
> * while(i < 1000)
> * {
> * * ((i % 3 == 0)||(i % 5 == 0)) ? sum+=a[i] :0 ;
> * * i++;
> * }
> * printf("The sum is %d\n",sum);
> * return 0;
>
> }
>
> Sayth

Well I solved it using an if statement, but I would still love to know
if there is a way to do it with the "?".

Working Solution

#include <stdio.h>
int i,sum=0;
int total;

int main()
{
while(i < 1000)
{
if ((i % 3 == 0)||(i % 5 == 0)){
sum += i;
}
i++;
}
printf("The sum is %d\n",sum);
return 0;
}

Cheers

Sayth

flebber
Guest
Posts: n/a

 10-31-2011
On Oct 31, 9:35*pm, flebber <(E-Mail Removed)> wrote:
> Hi
>
> I am learning C. I am trying to sum an array with the values returned
> from a loop. Can I use the "?" operator as part of a loop; by
> experimentation I know I can't put the increment in the loop.
>
> doing ((i % 3 == 0)||(i % 5 == 0)) ? sum+=a[i] :i++ ; never actually
> finished, I think I created an infinite loop.
> PS I was following the example from herehttp://www.tutorialspoint.com/ansi_c/ternary_operator_examples.htm
>
> So I have come to this this solution, I think the problem is that my
> array a[] is assigned as a one element array and since the first value
> returns false it gets 0 and exits. Is this right? If it is how do i
> assign an array to have an unknown number of entries?
>
> A kick in the right direction appreciated
>
> #include <stdio.h>
> int a[],i,sum=0;
>
> int main()
> {
> * while(i < 1000)
> * {
> * * ((i % 3 == 0)||(i % 5 == 0)) ? sum+=a[i] :0 ;
> * * i++;
> * }
> * printf("The sum is %d\n",sum);
> * return 0;
>
> }
>
> Sayth

I created a working solution with an if statement but I would still
really love to know if I could use the "?" to acheive the same result.

Working solution

#include <stdio.h>
int i,sum=0;
int total;

int main()
{
while(i < 1000)
{
if ((i % 3 == 0)||(i % 5 == 0)){
sum += i;
}
i++;
}
printf("The sum is %d\n",sum);
return 0;
}

Sayth

Jean-Christophe
Guest
Posts: n/a

 10-31-2011
On 31 oct, 11:35, flebber

> #include <stdio.h>
> int a[],i,sum=0;

'a' size is undefined.

> int main()
> {
> while(i < 1000)

'i' is not initialized.

> {
> ((i % 3 == 0)||(i % 5 == 0)) ? sum+=a[i] :0 ;

1) You can't just write (a)?b:c;
2) 'a' is not initialized.

> i++;
> }
> printf("The sum is %d\n",sum);
> return 0;
> }

----

If you really want to use (a)?b:c; I suggest

#define SIZE 1000
int main(void)
{
int a[SIZE], i, sum;

// here you must initialize 'a' values
// ...

// loop
for( sum=i=0; i < SIZE; ++i )
sum += ( !(i % 3) || !(i % 5) ) ? a[i] : 0;

printf("The sum is %d\n",sum);
return 0;
}

----

Now, since it's pointless adding sum+=0 you could

for( sum=i=0; i < SIZE; ++i )
if( !(i % 3) || !(i % 5) ) sum += a[i];

Anyway, what are the 1000 values of a[i] ?

James Kuyper
Guest
Posts: n/a

 10-31-2011
On 10/31/2011 06:35 AM, flebber wrote:
> Hi
>
> I am learning C. I am trying to sum an array with the values returned
> from a loop. Can I use the "?" operator as part of a loop; by
> experimentation I know I can't put the increment in the loop.
>
> doing ((i % 3 == 0)||(i % 5 == 0)) ? sum+=a[i] :i++ ; never actually
> finished, I think I created an infinite loop.

You can put the increment in the loop, and you did so in the code below.
What you shouldn't do is put it in a conditional part of the ternary
expression. Your loop's behavior depends only upon the value of 'i'. If,
during one pass though the loop, the value of i doesn't change, it will
go through the loop again, with the same value of i, and therefore
exactly the same behavior - which means it still won't change. Infinite
loop.

Now, with that in mind, take a look at the code above. If i has a value
which is a multiple of 3 or a multiple of 5, the value of i will not be
changed.

That's why you've got to move the i++ out of the ternary expression, as
you did in your code below.

> PS I was following the example from here
> http://www.tutorialspoint.com/ansi_c...r_examples.htm
>
> So I have come to this this solution, I think the problem is that my
> array a[] is assigned as a one element array and since the first value
> returns false it gets 0 and exits. Is this right? ...

No, the first value does not "return false". Your code attempts to read
the first 1000 elements of a[], regardless of whether or not it actually
has 1000 elements. So what happens is that it tries to read pieces of
memory that aren't actually part of a[]. As a result, the behavior of
Don't do that.

> ... If it is how do i
> assign an array to have an unknown number of entries?

You can never assign an array - what you actually mean, I think, is
either "define" or "declare".

You can't define an array to have an unknown number of entries. Defining
an object requires you to give the compiler all the information it needs
to set aside storage space for the object; if you don't tell it how long
the array is, the compiler can't do that. When you declared it as int
a[], and didn't provide an actual length anywhere else in your program,
it implicitly made the length 1. But that's something you should have
known; it doesn't count as defining an array of unknown length.

What you can do is declare an array to have a number of entries that is
not known within your code, but is known SOMEWHERE ELSE. For instance,
the simplest change to your code that would allow this is to declare

extern int a[];

In some other part of your program, you must provide a definition for a
that does have a specific length:

int a[1000];

However, using global variables is seldom the best solution. All of your
variables are global, and none of them should be. A more appropriate way
to do this would be to declare a function, which takes a pointer to the
first element of the array, and length:

int three_five_sum(
int a[],
int n
){
// body of function.
}

That looks like it defines a to be an array, but one of the confusing
features of C is that the declaration of an array as a parameter to a
function is automatically converted into a declaration of a pointer to
the element type of that array. It's exactly the same as if I had
written "int *a". Just as a matter of convention, I normally declare
parameters which are pointers to the first element of an array using
array[], while I write those which are pointers to a single object as
*single_object. As far as I can tell, this convention is my own
peculiarity, and not in wide use.

> A kick in the right direction appreciated
>
> #include <stdio.h>
> int a[],i,sum=0;
>
> int main()
> {
> while(i < 1000)
> {
> ((i % 3 == 0)||(i % 5 == 0)) ? sum+=a[i] :0 ;
> i++;
> }
> printf("The sum is %d\n",sum);
> return 0;
> }

There are many good uses of the ternary operator; I use it all the time.
This isn't one of them. An expression statement containing a ternary
expression can usually be re-written using if(). Unless you're using the
result of the ternary expression, it's generally better to use the if()
version:

if( i%3 == 0 || i%5 == 0)
sum += a[i];

Of course, the whole point of your exercise was to practice the use of
the ternary operator - but you should do that with a problem for which
that operator is a reasonable thing to use. Try the following: write a
function that takes two pointer arguments, a and b, and a count. For
each value of i from 0 to count-1, it adds something to sum. However, if
i is a multiple of 3 or 5, it adds a[i] to sum; otherwise, it adds b[i]
to sum.

You've got a variable named i, which is used only inside the loop, which
must be incremented during each step of the loop. When you've got that
combination, it's generally better to write it as a for() loop rather
than a while loop:

for(int i=0; i<1000; i++)

If your code has to be compatible with C90, you'll have to break that up
into two parts:

int i;
for(i=0; i<1000; i++)

--
James Kuyper

Ben Bacarisse
Guest
Posts: n/a

 10-31-2011
Jean-Christophe <(E-Mail Removed)> writes:

> On 31 oct, 11:35, flebber
>
>> #include <stdio.h>
>> int a[],i,sum=0;

>
> 'a' size is undefined.
>
>> int main()
>> {
>> while(i < 1000)

>
> 'i' is not initialized.

It is. It's got static storage duration and hence will be zero
initialised. It should not be "out there" and, if it were defined where
it should be, (in main) you'd be right.

>> {
>> ((i % 3 == 0)||(i % 5 == 0)) ? sum+=a[i] :0 ;

>
> 1) You can't just write (a)?b:c;

I know what you mean -- it's not a good idea -- but it's perfectly valid
C.

> 2) 'a' is not initialized.

It is. Both 'i' and 'a' are initialised in the op's code. That 'a' is
both defined and initialised is an odd quirk of C and that quirk should
definitely not be used by anyone.

>> i++;
>> }
>> printf("The sum is %d\n",sum);
>> return 0;
>> }

<snip>
--
Ben.

Ben Bacarisse
Guest
Posts: n/a

 10-31-2011
flebber <(E-Mail Removed)> writes:
<snip>
> On Oct 31, 9:35Â*pm, flebber <(E-Mail Removed)> wrote:
> I created a working solution with an if statement but I would still
> really love to know if I could use the "?" to acheive the same result.

Yes, but it won't be any clearer.

> Working solution
>
>
> #include <stdio.h>
> int i,sum=0;
> int total;

You don't use total. It will just confuse people.

> int main()
> {
> while(i < 1000)
> {
> if ((i % 3 == 0)||(i % 5 == 0)){
> sum += i;

You can write

sum += (i % 3 == 0 || i % 5 == 0) ? i : 0;

Since logical expressions are either 0 or 1, you can also write

sum += (i % 3 == 0 || i % 5 == 0) * i;

but both are, in my opinion, inferior to a simple 'if'.

What would make it clearer is to use a 'for' loop and to avoid having
"global" (technically file scope) variales. Simple counted loops are
best expressed using 'for'.

> }
> i++;
> }
> printf("The sum is %d\n",sum);
> return 0;
> }

--
Ben.

flebber
Guest
Posts: n/a

 10-31-2011

> If you really want to use (a)?b:c; I suggest
>
> #define SIZE 1000
> int main(void)
> {
> int a[SIZE], *i, *sum;
>
> // here you must initialize 'a' values
> // ...
>
> // loop
> *for( sum=i=0; *i < SIZE; *++i )
> * sum += ( !(i % 3) || !(i % 5) ) ? a[i] : 0;
>
> *printf("The sum is %d\n",sum);
> *return 0;

Thank You Jean-Christophe, I like the way you use the define as I
think it makes it clear and readable.

> No, the first value does not "return false". Your code attempts to read
> the first 1000 elements of a[], regardless of whether or not it actually
> has 1000 elements. So what happens is that it tries to read pieces of
> memory that aren't actually part of a[]. As a result, the behavior of
> Don't do that.

James thanks for explaining that. I had the feeling I was doing it
wrong but wasn't quite sure where it was going wrong.

> extern int a[];

So this declares my array as a global value. I can then assign a
value(size of array) to it locally. This would then mean that if I had
5 different functions they could all have their own size declared of
array a[] locally? May not be the best idea but I could do this?

> int three_five_sum(
> int a[],
> int n
> ){
> // body of function.
> }

With this skeleton shouldn't I declare int a[1000], ?

> Try the following: write a
> function that takes two pointer arguments, a and b, and a count. For
> each value of i from 0 to count-1, it adds something to sum. However, if
> i is a multiple of 3 or 5, it adds a[i] to sum; otherwise, it adds b[i]
> to sum.

Working on it... not close yet but will get there, having issues with
local variables.

#include <stdio.h>
#define limit 1000;

int two_pointer_args(int, int); /* function using two ints */
int main()

{
two_pointer_args(int i, int j);
i, j = 0;
int i_total=0;
int j_total=0;
{
while (i < limit)
{
if ((i % 3 == 0)|| (i % 5 == 0))
{
i_total+=i;
}
else
{
j_total = i + j;
}
i++;
}
printf(" The sum of i was %d and the sum of j was %d\n", i_total,
j_total);
}
return 0;
}

Thanks for all the help Sayth.

James Kuyper
Guest
Posts: n/a

 11-01-2011
On 10/31/2011 07:11 PM, flebber wrote:
....
>> extern int a[];

>
> So this declares my array as a global value. I can then assign a
> value(size of array) to it locally.

No, that declaration REQUIRES that 'a' be a global variable. You can
define it as a global variable in some other module, but you can never
assign it; C doesn't allow assignment of arrays. Once you've defined the
array, you can then assign values to each element of the array, separately.

> ... This would then mean that if I had
> 5 different functions they could all have their own size declared of
> array a[] locally? May not be the best idea but I could do this?

No, only the definition of 'a' can give it a size, and the size that it
is given by the definition is the one and only correct size for that
array. You can declare 'a' in multiple different modules, none of which
know the size, but you need to make sure that none of those modules try
to use a part of the array that doesn't exist.

>> int three_five_sum(
>> int a[],
>> int n
>> ){
>> // body of function.
>> }

>
> With this skeleton shouldn't I declare int a[1000], ?

You need to either define or dynamically allocate an array of at least n
ints, somewhere, but that array doesn't need to be defined with a name
of 'a'. 'a' is simply the name of a local pointer variable that is
initialized with a copy of the pointer value passed to three_five_sum()
as it's first argument. Example:

int main(void)
{
int bunny[256];

// Fill in values for bunny

// Calculate the sum for the middle 128 elements of bunny:
int sum = three_five_sum(bunny+64, 12;

// rest of program
}

>> Try the following: write a
>> function that takes two pointer arguments, a and b, and a count. For
>> each value of i from 0 to count-1, it adds something to sum. However, if
>> i is a multiple of 3 or 5, it adds a[i] to sum; otherwise, it adds b[i]
>> to sum.

>
> Working on it... not close yet but will get there, having issues with
> local variables.
>
> #include <stdio.h>
> #define limit 1000;
>
> int two_pointer_args(int, int); /* function using two ints */
> int main()
>
> {
> two_pointer_args(int i, int j);

This declares a function named two_pointer_args which takes two
arguments, both of which are integers, not pointers.

Contrary to what I think you were trying to do, the lines after this are
NOT interpreted as a definition of that function. First of all, the ';'
terminates the declaration, so everything after this point is part of
the main() function body, and has nothing to do with two_pointer_args().
Secondly, even if you had left out the ';', it wouldn't have worked. You
can declare the function within main() (though I think it's better to
declare it outside of main()), and you can call it from main(), but you
cannot define it inside main(); you have to define it somewhere else.

> i, j = 0;

That line does not do what you think it does. It retrieves the value of
'i', and then discards it. Then it sets j to 0. Read up on the comma
operator.

> int i_total=0;
> int j_total=0;

You're calculating two different totals. I was talking about calculating
a single total.

> {
> while (i < limit)
> {
> if ((i % 3 == 0)|| (i % 5 == 0))
> {
> i_total+=i;
> }
> else
> {
> j_total = i + j;
> }

The whole point of my suggestion was to create an example where it would
be natural to use the ?: ternary operator. If you had only one variable,
named 'total', and if you had declared the arguments as pointers named a
and b, then you could have written:

if( i%3 == 0 || i%5 == 0)
total += a[i];
else
total += b[i];

Now, that code can be re-written to use the ?: operator, and it's a very
natural thing to do. Figure out how, and you'll have a much better
understanding of what that operator is all about.

--
James Kuyper

Keith Thompson
Guest
Posts: n/a

 11-01-2011
pete <(E-Mail Removed)> writes:
> flebber wrote:
>> I created a working solution with an if statement but I would still
>> really love to know if I could use the "?" to acheive the same result.

>
>> if ((i % 3 == 0)||(i % 5 == 0)){
>> sum += i;
>> }

>
> If that is truly your goal:
>
> sum += ((i % 3 == 0)||(i % 5 == 0)) ? i : 0;

Yes, but frankly it's a foolish goal. The "if" form is easier to
read -- though personally I'd find it even easier with more whitespace
and fewer parentheses:

if (i % 3 == 0 || i % 5 == 0) {
sum += i;
}

--
Keith Thompson (The_Other_Keith) http://www.velocityreviews.com/forums/(E-Mail Removed) <http://www.ghoti.net/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"