Using ternary and summing array

F

flebber

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++ ; never actually
finished, I think I created an infinite loop.
PS I was following the example from here
http://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 :0 ;
i++;
}
printf("The sum is %d\n",sum);
return 0;
}


Sayth
 
F

flebber

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++ ; 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 :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
 
F

flebber

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++ ; 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 :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
 
J

Jean-Christophe

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

Anyway, what are the 1000 values of a ?
 
J

James Kuyper

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++ ; 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/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? ...

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
your program is not defined by the C standard. This is bad - very bad.
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 :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;

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 to sum; otherwise, it adds b
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++)
 
B

Ben Bacarisse

Jean-Christophe said:
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 :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.

<snip>
 
B

Ben Bacarisse

flebber said:
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'.
 
F

flebber

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 : 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
your program is not defined by the C standard. This is bad - very bad.
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 to sum; otherwise, it adds b
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.
 
J

James Kuyper

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, 128);

// 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 to sum; otherwise, it adds b
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;
else
total += b;

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.
 
K

Keith Thompson

pete said:
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;
}
 
K

Kaz Kylheku

Note that my compiler creates a[] with zero members.

However, my compiler acts "strange" on this point.

==========
#include <stdio.h>

int a[];

int main(void)
{
printf("%ld\n",(long)sizeof(a));
}
==========

Do you have some tools so you see what the size of a is in the translated
object file? (Is it in the object file?)

This might be a degenerate case which has no meaning due to a possible flaw in
the standard.

Under 6.9.2 we have this text:

A declaration of an identifier for an object that has file scope without an
initializer, and without a storage-class specifier or with the storage-class
specifier static, constitutes a tentative definition. If a translation unit
contains one or more tentative definitions for an identifier, and the
translation unit contains no external definition for that identifier, then the
behavior is exactly as if the translation unit contains a file scope
declaration of that identifier, with the composite type as of the end of the
translation unit, with an initializer equal to 0.

But an array cannot have an initializer equal to 0:

int a[] = 0; // invalid!

The second example for this section states the intent:

If at the end of the translation unit containing
int i[];
the array i still has incomplete type, the implicit initializer causes it to
have one element, which is set to zero on program startup.

This would be the case if the implicit initializer were { 0 }. The intent
is clear from the example, but for the text to bear it out, we have to
believe that "an initializer equal to zero" refers to a specific choice
of initializer such as { 0 }.
Further investigation shows that my compiler seems to treat "int a[];" the
same as "extern int a[];". Is that "legal"?

I would avoid this situation, since only a non-normative example gives it
a clear meaning.

Compiler writers, however, should pay careful attention to examples and
footnotes.

What does your compiler do if, at the end of the translation unit, you
add:

int a[] = { 0 };

?
 
D

David Thompson

On Mon, 31 Oct 2011 07:46:25 -0400, James Kuyper
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.
FWIW, I do the same when I get to choose the style.
Two is still far short of demonstrating wide use, though.

Further, if I can express simply enough the actual size expected or
used, I make it a comment:

void interdigitate_a_flooby (flooby * x);

void pair_items (left a [/*n*/], const right b [/*n*/], size_t n);
/* this one could be VLAs in C99 if change order */

void grommetize_blorbs (blorb b [/*g_min_blorb+tan(2pi)*/]);
/* ignore the global behind the curtain */
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top