Is there a shorter solution ?

H

HumbleWorker

Count the number of a in cX below

#include <stdio.h>

int main()
{
char cX[] = "ababcabcdabcaba", * k = cX;
int numA = 0;

while (*k && ('a' == *k++ ? ++numA : 1));

printf ("Number of a's = %u\n", numA);

return 0;
}
 
I

Ike Naar

Count the number of a in cX below

#include <stdio.h>

int main()
{
char cX[] = "ababcabcdabcaba", * k = cX;
int numA = 0;

while (*k && ('a' == *k++ ? ++numA : 1));

printf ("Number of a's = %u\n", numA);

The ``%u'' format expects an unsigned int, you're supplying a signed int.
Don't do that.
Either use ``int numA'' with ``%d'', or ``unsigned int numA'' with ``%u''.
 
K

Keith Thompson

Kenneth Brody said:
Because he posted from Google Groups, thinks this is a "chat
room", and figured the only reason he didn't get a reply within
five minutes is because he didn't post it correctly the first time?

And apparently the Google Groups Usenet interface has been having
problems. See the recent announcements in news.announce.important.
(But that doesn't particularly explain two posts in five minutes.)
 
H

HumbleWorker

And apparently the Google Groups Usenet interface has been having
problems. See the recent announcements in news.announce.important.

Yes this was the reason. I could'nt see the listing immediately, so
thought something was wrong at my end.

By the way, why are people worring about two posts ? Have we stopped
discussing C here ?
 
T

tom st denis

Count the number of a in cX below

#include <stdio.h>

int main()
{
        char cX[] = "ababcabcdabcaba", * k = cX;
        int numA = 0;
        while (*k && ('a' == *k++ ? ++numA : 1));
        printf ("Number of a's = %u\n", numA);
        return 0;
}

Um shorter eh ...

int numA;
int main()
{
char *k = "abababababawhatever";
while(*k) numA += *k++ == 'a';
printf("Number of a's = %d\n", numA);
return 0;
}

:)
 
H

HumbleWorker

int main()
{
   char *k = "abababababawhatever";
   while(*k) numA += *k++ == 'a';
   printf("Number of a's = %d\n", numA);
   return 0;

}

:)

Thanks ! Is it guaranteed that a logical true returns 1 ?
 
H

HumbleWorker

All logical expressions in C indicate truth by having a result of 1.

As we have know that any non-zero int evaluates to logical true, so
vice-versa doesn't a compiler have the freedom to return anything non-
zero ? Is there some standard that enforces that it should be 1 only ?
 
B

Ben Pfaff

HumbleWorker said:
As we have know that any non-zero int evaluates to logical true, so
vice-versa doesn't a compiler have the freedom to return anything non-
zero ? Is there some standard that enforces that it should be 1 only ?

Yes, the C standard says so, e.g.:

6.5.13 Logical AND operator

The && operator shall yield 1 if both of its operands
compare unequal to 0; otherwise, it yields 0. The result has
type int.

....

6.5.14 Logical OR operator

The || operator shall yield 1 if either of its operands
compare unequal to 0; otherwise, it yields 0. The result has
type int.
 
H

HumbleWorker

Yes, the C standard says so, e.g.:

     6.5.13 Logical AND operator

     The && operator shall yield 1 if both of its operands
     compare unequal to 0; otherwise, it yields 0. The result has
     type int.

...
That's nice. I learnt a new thing today !
 
J

James Kuyper

As we have know that any non-zero int evaluates to logical true, so
vice-versa doesn't a compiler have the freedom to return anything non-
zero ? Is there some standard that enforces that it should be 1 only ?

It's not just "some" standard, it's specifically the C standard (ISO/IEC
9899:1999). There's no enforcement, just a mandate. It does indeed
mandate that the result is 1 for each logical expression. Citations:
6.5.3p5: !
6.5.8p6: < > <= >=
6.5.9p3: == !=
6.5.13p3: &&
6.5.14p3: ||

As shown above, this mandate allows logical expressions to be used in
numerical contexts in ways that could not be guaranteed to work if the
standard gave implementations more freedom in this matter.

Another common use of this feature is in the context of the comparison
functions used by the qsort() and bsearch() standard library functions;
when comparing ordinary numerical types, the body of that function can
be written quite simply as

return (*left > *right) - (*left < *right);

It's debatable whether this feature was a great idea; but it's been a
part of C from the very beginning, and a lot of existing code relies
upon this feature.
 
H

HumbleWorker

Count the number of a in cX below
#include <stdio.h>
int main()
{
        char cX[] = "ababcabcdabcaba", * k = cX;
        int numA = 0;
        while (*k && ('a' == *k++ ? ++numA : 1));
        printf ("Number of a's = %u\n", numA);
        return 0;
}

Um shorter eh ...

int numA;
int main()
{
   char *k = "abababababawhatever";
   while(*k) numA += *k++ == 'a';
   printf("Number of a's = %d\n", numA);
   return 0;

}

:)

I am curious about one more thing. What would be the considerations of
efficiency when we use a for loop like this instead of the while loop
above ?

int main()
{
int numA = 0;
char* k = "abababababawhatever";
for (; *k; numA += *k++ == 'a');
printf("Number of a's = %d\n", numA);
return 0;
}
 
T

tom st denis

That's nice. I learnt a new thing today !

That being said, if you wrote code like "a += b == 4;" for a project I
was working on I might have words with you. But yes, they eval to 1
or 0.

The ideal way to write that is something like

if (b == 4) ++a;

or if you must ...

a += (b == 4) ? 1 : 0;

Though it's redundant it's a heck of a lot quicker to read... I
suppose

a += (b == 4);

With the brackets is ok to read ... still not my preferred style and
most don't write like that either.

Tom
 
K

Keith Thompson

James Kuyper said:
All logical expressions in C indicate truth by having a result of 1.

For certain meanings of the phrase "logical expressions".

The <, <=, >, >=, ==, !=, !, &&, and || operators are all defined to
yield either 0 or 1. I believe that's an exhaustive list.

On the other hand, of course, a scalar expression used as a condition is
treated as false if it compares equal to 0, true otherwise.

The is*() functions declared in <ctype.h> are only defined to return 0
for false, and some unspecified non-zero value for true. The same can
potentially apply to any expression used as a condition, unless its
top-level operator is one of the 9 listed above *or* it's specifically
written to yield only 0 or 1.

So:

if (x < y) count ++; // ok
count += (x < y); // ok and equivalent to the above

if (isdigit(c)) count ++; // ok
count += !!isdigit(c); // ok and equivalent to the above
count += isdigit(c); // legal but *not* equivalent to the above

#define FALSE 0
#define TRUE 1 // useful if you don't have <stdbool.h>
int cond = isdigit(c);
if (cond == FALSE) ...; // works, but unnecessarily verbose
if (cond == TRUE) ...; // dangerous, fails if cond < 0 or cond > 1
if (cond) ...; // the best way

See also section section 9 of the comp.lang.c FAQ, <http://www.c-faq.com/>.
 
J

James Kuyper

For certain meanings of the phrase "logical expressions".

The <, <=, >, >=, ==, !=, !, &&, and || operators are all defined to
yield either 0 or 1. I believe that's an exhaustive list.

That's the meaning that I intended for "logical expressions".
On the other hand, of course, a scalar expression used as a condition is
treated as false if it compares equal to 0, true otherwise.

And that is not. I'd refer to those as conditions, not logical
expressions. It's a distinction between what the value of an expression
means (0: false, 1: true) and how the value of the expression is used
(0: false, non-0: true).

In a very different but somewhat C-like language, it would be
philosophically cleaner to have logical expressions give results of
boolean type; conditions constrained to take values of boolean type; and
no conversions (neither implicit nor explicit) to or from the boolean
type. The equivalent of C's implicit conversions could be done by
non-boolean_value != 0
boolean_value ? 1 : 0
It would break way too much existing code to make any such change to C
itself, of course.
 
J

James Kuyper

I am curious about one more thing. What would be the considerations of
efficiency when we use a for loop like this instead of the while loop
above ?

int main()
{
int numA = 0;
char* k = "abababababawhatever";
for (; *k; numA += *k++ == 'a');
printf("Number of a's = %d\n", numA);
return 0;
}

The while-for conversion has no efficiency implications. Those parts of
the two programs are precisely equivalent, and if you're using a
compiler that isn't smart enough to recognize that fact and optimize
them the same way, you've got much bigger problems than simple
optimization to worry about.
 
K

Keith Thompson

James Kuyper said:
That's the meaning that I intended for "logical expressions".

I assumed so, but it's not clear from the phrase itself just what it
means; someone else might easily think of ``isdigit(c)'' as a logical
expression. (The standard doesn't define the term.)
And that is not. I'd refer to those as conditions, not logical
expressions. It's a distinction between what the value of an expression
means (0: false, 1: true) and how the value of the expression is used
(0: false, non-0: true).

That's a useful distinction, and it would be nice to have universally
agreed terms make that distinction.
In a very different but somewhat C-like language, it would be
philosophically cleaner to have logical expressions give results of
boolean type; conditions constrained to take values of boolean type; and
no conversions (neither implicit nor explicit) to or from the boolean
type. The equivalent of C's implicit conversions could be done by
non-boolean_value != 0
boolean_value ? 1 : 0
It would break way too much existing code to make any such change to C
itself, of course.

Yes, and there are plenty of languages like that, though most of them
aren't particularly C-like (Pascal, Ada). To avoid triggering a
language war, I'll just mention that I do personally prefer one approach
over the other without saying which.
 
S

Seebs

As we have know that any non-zero int evaluates to logical true, so
vice-versa doesn't a compiler have the freedom to return anything non-
zero?
No.

Is there some standard that enforces that it should be 1 only ?

Yes. It is called the language specification. The logical operators are
defined as yielding 0 or 1.

-s
 
J

J. J. Farrell

tom said:
That being said, if you wrote code like "a += b == 4;" for a project I
was working on I might have words with you. But yes, they eval to 1
or 0.

The ideal way to write that is something like

if (b == 4) ++a;

or if you must ...

a += (b == 4) ? 1 : 0;

Though it's redundant it's a heck of a lot quicker to read...

Quicker to read? The exact opposite for me - this one is about the worst
of all the possibilities you give. I find the one below much clearer and
quicker and easier to read reliably than the one above. When looking at
the above I'd tend to assume the conditional expression was doing
something useful, requiring me to read it carefully to be sure of what
it did - and then check again even more carefully when the first reading
said it didn't do anything useful.
 

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,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top