Counting occurence of character in a string

J

Jordan Abel

Jordan Abel has an intense desire
to find some context in which it is OK
to use reserved identifiers to name his functions.
I don't know why.

.....wtf? when did this become personal? What did i ever do to you?
 
P

Peter Nilsson

pete said:
I don't see the point in searching for values
outside the range of char, in an array of char,

The whole notion of plain char is flawed though.
and neither does strchr.
I think it's more better to compare *s against

more better? ;)
the value of c converted to type char,
as in the standard's description of strchr.

size_t str_ccnt(const char* s, int c)
{
size_t n = 0;

do {
if (*s == (char)c) {
n++;
}
} while(*s++ != '\0');

The null character is required to be all bits zero. This (non at all
uncommon
style) may stop short on implementations where plain char has
(non-trapping)
trap representations.
return n;
}

strcmp and strncmp are the only standard string functions
which are based on unsigned char interpretation of bytes.

You don't think strcpy uses bytes? The specifications say it copies
characters, not char.
All of the others, like strchr, are based on char values.

And strchr is flawed for that reason. Members of the extended character
set
may not have values representable as char.

[Aside, there is no requirement that CHAR_MAX == SCHAR_MAX
in the case that plain char is signed.]

Many of the functions in the C standard library are the way they are
because that's how they were implemented and used prior to
standardisation. C89 put greater emphasis on preserving backwards
compatibility, than it did on making the standard library consistent.
I think strccnt should be more like strchr, than like strcmp.

Fair enough. I disagree.

But then I think plain char should be unsigned on all implementations.
 
K

Keith Thompson

Peter Nilsson said:
[Aside, there is no requirement that CHAR_MAX == SCHAR_MAX
in the case that plain char is signed.]

Yes, there is.

C99 5.2.4.2.1p2 says:

If the value of an object of type char is treated as a signed
integer when used in an expression, the value of CHAR_MIN shall be
the same as that of SCHAR_MIN and the value of CHAR_MAX shall be
the same as that of SCHAR_MAX. Otherwise, the value of CHAR_MIN
shall be 0 and the value of CHAR_MAX shall be the same as that of
UCHAR_MAX.
 
P

Peter Nilsson

Keith said:
Peter Nilsson said:
[Aside, there is no requirement that CHAR_MAX == SCHAR_MAX
in the case that plain char is signed.]

Yes, there is.

C99 5.2.4.2.1p2 says:

Yes, I meant to say (but came nowhere near to writing), that SCHAR_MAX
may still be 127 even if CHAR_BIT > 8. In context, that means that a
plain
(signed) char may not be able to represent all possible character
values
beyond the basic execution character set.
 
S

Stan Milam

Michael said:
Hi,

Is there a standard library function that counts the number of
occurences of a character in a string?

Regards,

Michael

No, but like most string function not included in the standard you can
roll your own fairly easily:


#include <errno.h>
#include <stddef.h>
#include <string.h>

/**********************************************************************/
/* Name: */
/* chrcount(). */
/* */
/* Description: */
/* The chrcount() function counts the number of times a character */
/* value appears in a string and returns the count to the caller */
/* */
/* Arguments: */
/* const char *string - The string to search. */
/* int chr - The character value to search for. */
/* */
/* */
/* Return Value: */
/* The number of times the character value appeared in the string */
/* */
/**********************************************************************/

size_t
chrcount(char *s1, int ch)
{
size_t count = 0; /* The count to return */

if ( s1 == NULL )
errno = EINVAL;
else while ( *s1 )
if ( *s1++ == ch )
count++;

return count; /* Return the count */
}
 
Z

Zoran Cutura

Stan Milam said:
size_t
chrcount(char *s1, int ch)
{
size_t count = 0; /* The count to return */

if ( s1 == NULL )
errno = EINVAL;


Hm, I can see that testing the input for usability can be of help. But
we all know that this function could be passed any pointer valid
or not and I hardly undesrtand why one would get meaningfull error
messages for a pretty simple (but IMO very unlikly) case that there
is a NULL pointer passed but not if the passed pointer points to
other not usable locations.
 
B

Barry Schwarz

Hm, I can see that testing the input for usability can be of help. But
we all know that this function could be passed any pointer valid
or not and I hardly undesrtand why one would get meaningfull error
messages for a pretty simple (but IMO very unlikly) case that there
is a NULL pointer passed but not if the passed pointer points to
other not usable locations.

One does what one can within the scope of the language. You can test
for NULL. You cannot portably test for most other kinds of "invalid"
pointers, such as one pointing to a freed area or one that has not yet
been initialized. Whether testing for this one case is worth the
effort is a quality of implementation issue.


<<Remove the del for email>>
 
Z

Zoran Cutura

Barry Schwarz said:
One does what one can within the scope of the language. You can test
for NULL. You cannot portably test for most other kinds of "invalid"
pointers, such as one pointing to a freed area or one that has not yet
been initialized. Whether testing for this one case is worth the
effort is a quality of implementation issue.

So would you think that a implementation like the above has a high or
low qoi? Others?
 
K

Keith Thompson

Zoran Cutura said:
So would you think that a implementation like the above has a high or
low qoi? Others?

Both. It's high because it catches certain errors that might
otherwise lead to undefined behavior, and low because by doing so it
can lead the user to assume it will catch more errors than it actually
does. Quality is not a linear measurement. If it were, a simple

while (1) {
quality ++;
}

would put us all out of business. (Well, not really; implemeting the
"++" operator would still be non-trivial.)
 
M

Michael Wojcik

Hm, I can see that testing the input for usability can be of help. But
we all know that this function could be passed any pointer valid
or not and I hardly undesrtand why one would get meaningfull error
messages for a pretty simple (but IMO very unlikly) case that there
is a NULL pointer passed but not if the passed pointer points to
other not usable locations.

A helmet doesn't protect against all types of injuries, so why use
one at all?

In my opinion - based on many years of experience with C code, my own
and others', a null (not "NULL") pointer is a common error case. Even
if it weren't, however, it's simple to check for, and the check is
almost free. (In any code path where its cost is significant, using
a function like this would be absurd anyway.)
 
P

pete

Peter said:
The whole notion of plain char is flawed though.
But then I think plain char should be unsigned on all implementations.


If you're really intending strccnt to be used on arrays
of any byte type,
then it would have been more better for you to have written

size_t strccnt(const void *s, int c)

instead of

size_t strccnt(const char *s, int c)
 
P

pete

Jordan said:
....wtf? when did this become personal? What did i ever do to you?

I was guessing that you had no intention of backing up your
bogus claim about freestanding implementations.
 
J

Jordan Abel

I was guessing that you had no intention of backing up your bogus
claim about freestanding implementations.

Your wording suggested some intense personal hatred towards me which
cannot be accounted for by this explanation [unless you are heavily
emotionally invested in your interpretation of what is and is not
allowed for freestanding implementations]

It's reserved for the library. Freestanding implementations provide
only a very restricted subset of the library, which does not include
either of the headers these are reserved for. Many of the
requirements in the standard implicitly only apply to hosted
implementations, and it's reasonable to suppose that the 'reserved
as external identifiers in all contexts' for functions which can
only appear in two headers that are not present on freestanding
implementations is one of those, given that it is a library issue.
You are the one who needs to back up your claim.
 
P

pete

Jordan said:
I was guessing that you had no intention of backing up your bogus
claim about freestanding implementations.

Your wording suggested some intense personal hatred towards me which
cannot be accounted for by this explanation [unless you are heavily
emotionally invested in your interpretation of what is and is not
allowed for freestanding implementations]

It's reserved for the library. Freestanding implementations provide
only a very restricted subset of the library, which does not include
either of the headers these are reserved for. Many of the
requirements in the standard implicitly only apply to hosted
implementations, and it's reasonable to suppose that the 'reserved
as external identifiers in all contexts' for functions which can
only appear in two headers that are not present on freestanding
implementations is one of those, given that it is a library issue.
You are the one who needs to back up your claim.

I was hoping that you wouldn't need to be told again
that it doen't matter which headers are included.
 
J

Jordan Abel

Jordan said:
Jordan Abel wrote:

Peter Nilsson wrote:

Jordan Abel wrote:
On 2005-11-22, Randy Howard
Bjørn Augestad wrote
(in article <[email protected]>):

size_t strccnt(const char* s, int c)

Apart from namespace problems? Not much. :)

It's fine on a freestanding implementation

Do you have chapter and verse on that?

Jordan Abel has an intense desire
to find some context in which it is OK
to use reserved identifiers to name his functions.
I don't know why.

....wtf? when did this become personal? What did i ever do to you?

I was guessing that you had no intention of backing up your bogus
claim about freestanding implementations.

Your wording suggested some intense personal hatred towards me which
cannot be accounted for by this explanation [unless you are heavily
emotionally invested in your interpretation of what is and is not
allowed for freestanding implementations]

It's reserved for the library. Freestanding implementations provide
only a very restricted subset of the library, which does not include
either of the headers these are reserved for. Many of the
requirements in the standard implicitly only apply to hosted
implementations, and it's reasonable to suppose that the 'reserved
as external identifiers in all contexts' for functions which can
only appear in two headers that are not present on freestanding
implementations is one of those, given that it is a library issue.
You are the one who needs to back up your claim.

I was hoping that you wouldn't need to be told again
that it doen't matter which headers are included.

That wasn't what i said, if you'd bother actually reading for
comprehension - the fact that the headers _exist_ or not [in a
freestanding impementaton, they do not] would seem a bit more relevant
than whether they're included - at least, that's my understanding of
'freestanding implementation'

the fact that you turned this into some kind of personal attack against
me is at this point more of an issue than whether i was right or not.
 
R

Richard Heathfield

Jordan Abel said:
That wasn't what i said, if you'd bother actually reading for
comprehension -

Could you guys knock it off, please? Clearly you both know what you're
talking about, so you ought to be able to arrive at a correct conclusion
amicably - or at least without bloodshed.

It can sometimes be difficult for bright people to remember that other
people can be bright too - especially when they are disagreeing. Billy
Chambless famously said: "The way I see it, an intelligent person who
disagrees with me is probably the most important person I'll interact with
on any given day."

Come on lads - make friends, eh? :)
 
F

Flash Gordon

Jordan said:
I was hoping that you wouldn't need to be told again
that it doen't matter which headers are included.

That wasn't what i said, if you'd bother actually reading for
comprehension - the fact that the headers _exist_ or not [in a
freestanding impementaton, they do not] would seem a bit more relevant
than whether they're included - at least, that's my understanding of
'freestanding implementation'

My understanding is that although the free standing implementation is
not required to provide them, it is allowed to provide them, and since a
freestanding implementation is allowed to provide the headers and
functions they declare the comment about the identifiers being reserved
must still hold.

In n1134, section 5.1.2, it says:
| In a freestanding environment (in which C program execution may take
| place without any benefit of an operating system), the name and type
| of the function called at program startup are implementation-defined.
| Any library facilities available to a freestanding program, other than
| the minimal set required by clause 4, are implementation-defined.

Which clearly allows the other headers and corresponding functions to be
defined not as an extension (and certainly not one that breaks
conformance), but as an implementation defined feature. So any program
attempting to declare such an identifier clearly (IMHO) invokes
undefined behaviour on an implementation defining those facilities as
being provided.

Also, I can find nowhere the standard provides an exception to the
identifiers being reserved for freestanding environments.
the fact that you turned this into some kind of personal attack against
me is at this point more of an issue than whether i was right or not.

I agree that this should not be personal. It's about the C language (or
should be) not about the people.
 
K

Keith Thompson

Jordan Abel said:
[snip]
It's reserved for the library. Freestanding implementations provide
only a very restricted subset of the library, which does not include
either of the headers these are reserved for. Many of the
requirements in the standard implicitly only apply to hosted
implementations, and it's reasonable to suppose that the 'reserved
as external identifiers in all contexts' for functions which can
only appear in two headers that are not present on freestanding
implementations is one of those, given that it is a library issue.

It's an interesting question. I *think* that names starting with
"str" are reserved for use as identifiers with external linkage on
both hosted and freestanding implementations.

C99 7.1.3 says:

If the program declares or defines an identifier in a context in
which it is reserved (other than as allowed by 7.1.4), or defines
a reserved identifier as a macro name, the behavior is undefined.

so a program that uses "strccnt" as an identifier with external linkage
cannot be strictly conforming.

C99 4p6 says:

A _conforming freestanding implementation_ shall accept any
strictly conforming program that does not use complex types and in
which the use of the features specified in the library clause
(clause 7) is confined to the contents of the standard headers
<float.h>, <iso646.h>, <limits.h>, <stdarg.h>, <stdbool.h>,
<stddef.h>, and <stdint.h>. A conforming implementation may have
extensions (including additional library functions), provided they
do not alter the behavior of any strictly conforming program.

Since parts of clause 7 do apply to freestanding implementations, it's
reasonable to assume that 7.1.3, which is part of the introduction
applies to freestanding implementations.

Note that, as far as I can tell, a conforming hosted implementation
also qualifies as a conforming freestanding implementation, and
freestanding implementations can provide subsets of the standard
library. It seems reasonable to avoid using reserved identifiers
anyway.

(Of course, this is a fairly minor technical dispute on which people
can reasonable disagree; pete, you're taking this way too personally.)
 
P

pete

There is no "the headers these are reserved for"

7.26 Future library directions
[#1] The following names are grouped under individual
headers for convenience. All external names described below
are reserved no matter what headers are included by the
program.
the fact that you turned this into some
kind of personal attack against
me is at this point more of an issue than whether i was right or not.

The last time that I quoted you
that same part of the C99 last public draft,
the stupidest response that you were able to conjure up
was that that C99 wasn't the standard that you were interested in.
The C89 standard said exactly the same thing.
 
P

pete

Michael said:
A helmet doesn't protect against all types of injuries, so why use
one at all?

In my opinion - based on many years of experience with C code, my own
and others', a null (not "NULL") pointer is a common error case. Even
if it weren't, however, it's simple to check for, and the check is
almost free. (In any code path where its cost is significant, using
a function like this would be absurd anyway.)

Writing code to check errno after the return,
isn't any simpler than checking the input for NULL
prior to the function call.
 

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

Forum statistics

Threads
473,771
Messages
2,569,587
Members
45,097
Latest member
RayE496148
Top