Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > passing array to isdigit()

Reply
Thread Tools

passing array to isdigit()

 
 
Carramba
Guest
Posts: n/a
 
      02-09-2005
hi!

I am trying to confirm if input is digit, so I thought it would by easy to
do it with with isdigit() funktion,
but how do I pass arrays to it if the imput is more then 1 sign?

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
int main(){
char a[3]; // enter 2 sign + \0

scanf("%c", &a);
if(isdigit(a[0]) && isdigit(a[1])) {printf("japp");
}
else{
printf("nopp");
}

printf("\n\na[0]=>%d a[1]=>%d", a[0], a[1]);
return 0;
}



getting output:
12
nopp

2359144


--
Thanx in advance!



______________________________________
I se the lightat the end, but every time I take a step it's get dim.
 
Reply With Quote
 
 
 
 
Eric Sosman
Guest
Posts: n/a
 
      02-09-2005


Carramba wrote:
> hi!
>
> I am trying to confirm if input is digit, so I thought it would by easy to
> do it with with isdigit() funktion,
> but how do I pass arrays to it if the imput is more then 1 sign?
>
> #include <stdio.h>
> #include <ctype.h>
> #include <stdlib.h>
> int main(){
> char a[3]; // enter 2 sign + \0
>
> scanf("%c", &a);


Here's the problem: "%c" reads only one character, so
only a[0] receives input. a[1] and a[2] remain unchanged,
containing "random garbage" (which may or may not include
the '\0' you mention). What you probably want is

scanf("%2s", a);

Note the change from "c" (read one character) to "s" (read
a string), the inclusion of "2" to limit the string length
to the amount the a[] array can hold, and the removal of
the `&' operator.

> if(isdigit(a[0]) && isdigit(a[1])) {printf("japp");


Here's another problem, probably not involved in your
trouble but a problem nonetheless. Write

if (isdigit( (unsigned char)a[0] ) && ...

to guard against character codes with negative values. All
of the digits 0-9 have positive codes, but characters like
'' and '' may be negative on some machines. If the user
enters such a character, you cannot safely use isdigit() on
it until you convert it to a non-negative value.

--
http://www.velocityreviews.com/forums/(E-Mail Removed)

 
Reply With Quote
 
 
 
 
Michael Mair
Guest
Posts: n/a
 
      02-09-2005


Carramba wrote:
> hi!
>
> I am trying to confirm if input is digit, so I thought it would by easy
> to do it with with isdigit() funktion,
> but how do I pass arrays to it if the imput is more then 1 sign?


You mean: more than one character.
There are several ways to go about this:
1) You have a string and pass it to a function which runs through the
whole string and checks every character (but not the string terminator)
with isdigit(). If you encounter non-digit, you return false.
2) You have an array of char and the number of potential digit
characters. Do as above and pass array and length but instead of
checking against the string terminator, run through all potential
digits using the length you got passed.
3) The strtol() function will convert a string into a long value.
Its interface provides the means to check whether the last digit
read was the last character before the string terminator.
Leading white spaces might be discarded -- just look it up.
4) Use sscanf() plus scanset restricted to the digits and get also
the number of read characters. If it equals the string length,
you know everything was a digit.

>
> #include <stdio.h>
> #include <ctype.h>
> #include <stdlib.h>
> int main(){
> char a[3]; // enter 2 sign + \0
>
> scanf("%c", &a);

You mean
int n, onlydigits;
if( 1 != scanf("%2s%n", a, &n))
{
/* Deal with error */
}
if (strlen(a)!=n) { /* We read more characters than expected */ }

> if(isdigit(a[0]) && isdigit(a[1]))


onlydigits = 1;
for (n=0; n<strlen(a); n++)
if (!isdigit(a[n]))
onlydigits = 0;
if(onlydigits)

> {printf("japp");
> }
> else{
> printf("nopp");
> }
>
> printf("\n\na[0]=>%d a[1]=>%d", a[0], a[1]);
> return 0;
> }
>
>
>
> getting output:
> 12
> nopp
>
> 2359144
>
>


-Michael
--
E-Mail: Mine is a gmx dot de address.

 
Reply With Quote
 
Luke Wu
Guest
Posts: n/a
 
      02-09-2005

Carramba wrote:
> hi!
>
> I am trying to confirm if input is digit, so I thought it would by

easy to
> do it with with isdigit() funktion,
>


I think you are trying to get either a 1 digit number or a 2 digit
number from the user (judging by your 3 element character array, where
1 of the elements would be for null).

>
> but how do I pass arrays to it if the imput is more then 1 sign?
>


By sign I assume you mean digit. You can't pass arrays to isdigit().

>
>
> #include <stdio.h>
> #include <ctype.h>
> #include <stdlib.h>
>


why did you add stdlib.h?

>
> int main(){
> char a[3]; // enter 2 sign + \0
>


Assuming you meant 2 digits and null.

>
>
> scanf("%c", &a);
>


You are sending scanf the address of the whole array, while it expects
the address of a single character only. This invokes UB (type
mismatch), but since the address of an array is equivalent(in value not
type) to the address of the first element of the array, your program
might just fill the first element of a (a[0]) with the charcter it gets
from stdin. a[1] and a[2] will definitely be untouched (and since your
array is automatic, most likely will contain garbage).

>
> if(isdigit(a[0]) && isdigit(a[1])) {printf("japp");
>


a[1] contains garbage, so dont' be suprised if the condition in the if
clause evaluates to false.

>
> }
> else{
> printf("nopp");
> }
>
> printf("\n\na[0]=>%d a[1]=>%d", a[0], a[1]);
> return 0;
> }
>



Hereis my version of a program that takes input and checks if the user
entered a 1 or 2 digit number (don't trust scanf or gets):



#include <stdio.h> /* for getchar(), printf() & puts() */
#include <string.h> /* for strchr() */
#include <stdlib.h> /* for abs(), strtol(), and exit() */

int main()
{
char c; /* for stdin consuming while loop */
char input[10]; /* holds user character input */
char *chptr; /* for error checks in fgets() & strtol() */
long number; /* number after conversion by strotol */

printf("Input a 1 or 2 digit number and hit enter: ");
fflush(stdout);

chptr = fgets(input, sizeof input, stdin); /* user input into
buffer */
if(chptr == NULL)
{
puts("ERROR: fgets failed, press Enter to exit");
getchar();
exit(EXIT_FAILURE);
}

/* following if-while eats all the leftover characters in stdin
upto and including the newline (which must be still in stdin
if it isn't inside our input buffer */
if(!strchr(input, '\n'))
while((c = getchar()) != '\n');


number = strtol(input, &chptr, 0); /* convert to long interger */


/* if absolute value of number is between 0 and 99, then the user
must have entered a 1 or 2 digit number; if the user entered
something weird, strtol can still return '0' but endptr will
point to first element of buffer if that is so; so we must
make sure that chptr != &input[0] or chptr != input in our if */

if( abs(number) >= 0 && abs(number) <= 99 && chptr != input)
{
/* user entered a 1 or 2 digit number */
printf("yapp, %ld is good input\n\n", number);
}
else if( chptr == input)
{
/* user entered weird input (not number) */
printf("nopp, that wasn't even a number!!\n\n");
}
else
{
/* user entered > 2 digit number */
printf("nopp, wasn't a 1 or 2 digit number\n\n");
}

puts("Program Finished: Press enter to exit");
getchar();
return EXIT_SUCCESS;
}


If the program above confuses you, good, because confusion is what
forces us to
investigate, and investigation brings enlightenment (last year I had no
clue why most experts used fgets, now I use it all the time).

Good luck.

 
Reply With Quote
 
Flash Gordon
Guest
Posts: n/a
 
      02-09-2005
Carramba wrote:
> hi!
>
> I am trying to confirm if input is digit, so I thought it would by easy
> to do it with with isdigit() funktion,
> but how do I pass arrays to it if the imput is more then 1 sign?


With isdigit you have to check characters 1 at a time.

> #include <stdio.h>
> #include <ctype.h>
> #include <stdlib.h>
> int main(){
> char a[3]; // enter 2 sign + \0
>
> scanf("%c", &a);


You are only reading 1 character here, however many the user enters. So
a[1] is still uninitialised in the line below.

> if(isdigit(a[0]) && isdigit(a[1])) {printf("japp");
> }
> else{
> printf("nopp");
> }
>
> printf("\n\na[0]=>%d a[1]=>%d", a[0], a[1]);


You need to terminate the last line with a line feed or it might not be
displayed.

> return 0;
> }
>
>
>
> getting output:
> 12
> nopp
>
> 2359144

--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
 
Reply With Quote
 
CBFalconer
Guest
Posts: n/a
 
      02-09-2005
Luke Wu wrote:
>

.... snip ...
>
> If the program above confuses you, good, because confusion is what
> forces us to investigate, and investigation brings enlightenment
> (last year I had no clue why most experts used fgets, now I use it
> all the time).


Now try out ggets (and fggets) which you can get at:

<http://cbfalconer.home.att.net/download/>

and maybe you won't want to bother with all those tests on the
results from fgets.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson


 
Reply With Quote
 
Michael Mair
Guest
Posts: n/a
 
      02-09-2005
Eric Sosman wrote:
>
> Carramba wrote:
>
>> if(isdigit(a[0]) && isdigit(a[1])) {printf("japp");

>
>
> Here's another problem, probably not involved in your
> trouble but a problem nonetheless. Write
>
> if (isdigit( (unsigned char)a[0] ) && ...
>
> to guard against character codes with negative values. All
> of the digits 0-9 have positive codes, but characters like
> '' and '' may be negative on some machines. If the user
> enters such a character, you cannot safely use isdigit() on
> it until you convert it to a non-negative value.


I have a question on this one: Does this follow from
C99, 7.4 Character handling
#1:
"The header <ctype.h> declares several functions useful for classifying
and mapping characters. In all cases the argument is an int, the value
of which shall be representable as an unsigned char or shall equal the
value of the macro EOF. If the argument has any other value, the
behavior is undefined."
or is there another source as well?
Accidentally, I just have got a request for a "ANSI C" program where
I have to use isalpha() extensively. Depending on the locale, the
above might be an issue, so I want to get that right and know why.
Essentially, I also would have to assert(UCHAR_MAX<=INT_MAX),
wouldn't I?

Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
 
Reply With Quote
 
Peter Nilsson
Guest
Posts: n/a
 
      02-10-2005
> Eric Sosman wrote:
> > Carramba wrote:
> >
> > > if(isdigit(a[0]) && isdigit(a[1])) {printf("japp");

> >
> > Here's another problem, probably not involved in your
> > trouble but a problem nonetheless. Write
> >
> > if (isdigit( (unsigned char)a[0] ) && ...
> >
> > to guard against character codes with negative values. All
> > of the digits 0-9 have positive codes, but characters like
> > '' and '' may be negative on some machines. If the user
> > enters such a character, you cannot safely use isdigit() on
> > it until you convert it to a non-negative value.


As I argued in a previous thread, it's more robust to use
aliasing, than conversion...

unsigned char *p = &a[0];

if (isdigit(p[0]) && ...

Michael Mair wrote:
>
> I have a question on this one: Does this follow from
> C99, 7.4 Character handling
> #1:
> "The header <ctype.h> declares several functions useful for
> classifying and mapping characters. In all cases the argument
> is an int, the value of which shall be representable as an
> unsigned char or shall equal the value of the macro EOF.
> If the argument has any other value, the behavior is undefined."


Yes.

> or is there another source as well?
> Accidentally, I just have got a request for a "ANSI C" program
> where I have to use isalpha() extensively. Depending on the
> locale, the above might be an issue, so I want to get that right
> and know why. Essentially, I also would have to assert
> (UCHAR_MAX<=INT_MAX), wouldn't I?


Depends how paranoid you are. It's arguable whether a hosted
implementation where UCHAR_MAX > INT_MAX can ever be conforming.

[For instance, (fputc)() would no longer guarantee that a rereading
a written byte would reproduce the original. But some argue
this is a QoI issue.]

--
Peter

 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      02-10-2005
Michael Mair wrote:
> Eric Sosman wrote:
>
>>
>> Carramba wrote:
>>
>>> if(isdigit(a[0]) && isdigit(a[1])) {printf("japp");

>>
>> Here's another problem, probably not involved in your
>> trouble but a problem nonetheless. Write
>>
>> if (isdigit( (unsigned char)a[0] ) && ...
>>
>> to guard against character codes with negative values. All
>> of the digits 0-9 have positive codes, but characters like
>> '' and '' may be negative on some machines. If the user
>> enters such a character, you cannot safely use isdigit() on
>> it until you convert it to a non-negative value.

>
> I have a question on this one: Does this follow from
> C99, 7.4 Character handling
> #1:
> "The header <ctype.h> declares several functions useful for classifying
> and mapping characters. In all cases the argument is an int, the value
> of which shall be representable as an unsigned char or shall equal the
> value of the macro EOF. If the argument has any other value, the
> behavior is undefined."
> or is there another source as well?


Yes, that's the crucial paragraph. You must guarantee
that the argument to isxxx() is either EOF or a non-negative
value, specifically, a non-negative value corresponding to
a character code represented as an unsigned char. Informally,
the isxxx() argument must be in { EOF, 0..UCHAR_MAX }.

For values returned by getc() and friends no special
precautions need be taken: the returned value is exactly what
isxxx() expects, and you can pass it directly without fuss.
The surprises occur when you store a character code in a `char',
because `char' is a signed type on some implementations. If a
particular `char' has a negative value, it will (usually) become
a negative-valued `int' upon promotion, and if so will not be
in the range { 0..UCHAR_MAX }. If you're lucky(?) the negative
`char' will just happen to have the same value as EOF and you'll
avoid undefined behavior -- but at the cost of massive confusion.

Peter Nilsson suggests processing a string by converting its
`char*' pointer to `unsigned char*':

char *string = ...;
unsigned char *safe = (unsigned char*)string;
if (isxxx(*safe)) ...

While this will work on Every Single C Implementation I Have
Ever Encountered, it is in fact "lying to the compiler," and
thus braving the compiler's revenge. The thing that `string'
points to is a plain `char', not an `unsigned char', and it is
(very mildly) risky to pretend that the one is the other. I am
too full of post-prandial Cognac at the moment to work out the
details, but I rather suspect that a system with signed `char'
and ones' complement representation for negatives might get into
some trouble with such a lie. Since the incorruptibly honest
convert-at-point-of-call idiom cannot fail while the pointer-
twiddling approach carries with it a faint whiff of impropriety,
I see no reason to use the latter.

> Accidentally, I just have got a request for a "ANSI C" program where
> I have to use isalpha() extensively. Depending on the locale, the
> above might be an issue, so I want to get that right and know why.
> Essentially, I also would have to assert(UCHAR_MAX<=INT_MAX),
> wouldn't I?


The characteristics of getc() and isxxx() seem to rule out
some "exotic" architectures, or at least to constrain them. If
If UCHAR_MAX <= INT_MAX all's well, but if UCHAR_MAX > INT_MAX
there are some `unsigned char' values that cannot be returned from
getc() or passed to isxxx(). The only way out of this predicament,
I think, is to say that such values do not correspond to legitimate
character codes for the implementation at hand. You might have
INT_MAX == 32767 and UCHAR_MAX == 65535, but if getc() can only
return values in the set { EOF, 0..511 }, say, all will still be
well.

Incidentally, note that a system with signed `char' must
either limit itself to non-negative codes for actual characters
or must provide a useful definition for the conversion of out-
of-range `unsigned char' values to plain signed `char'. It
would be unconscionable if

int ch;
char c;
if ((ch = getchar()) != EOF)
c = ch;

.... were to raise a signal or do "something weird" if `ch'
happened to exceed CHAR_MAX. The library was born as the servant
of the language, but now and then becomes its master.

With 20-20 hindsight one can opine that the original decision
to leave the signedness of `char' unspecified was unfortunate.
However, one can't lay the blame on Ritchie; he observed that
different machines took different positions on the matter and
decided not to make implementing his new language difficult for
half of them. So many of his other decisions turned out well that
it's hard to chastise him -- indeed, it's hard to do other than
admire him. "Too bad," nonetheless.

--
Eric Sosman
(E-Mail Removed)lid
 
Reply With Quote
 
Peter Nilsson
Guest
Posts: n/a
 
      02-10-2005
Eric Sosman wrote:
>
> Peter Nilsson suggests processing a string by converting its
> `char*' pointer to `unsigned char*':
>
> char *string = ...;
> unsigned char *safe = (unsigned char*)string;
> if (isxxx(*safe)) ...
>
> While this will work on Every Single C Implementation I Have
> Ever Encountered, it is in fact "lying to the compiler," and
> thus braving the compiler's revenge.


No. The way I see it, it's countering a lie from the implementation.

Ordinary character strings should really be stored as unsigned char,
non-negative codings. This is how they're written and read by
implementations.

Suppose I have an input sequence along the lines of...

char blah[42];
fgets(blah, sizeof blah, stdin);

Suppose the user enters "Caf", and suppose we have an 8-bit
implementation where 's character code is 233. How is this stored
in blah?

The standard requires that 233 is stored as a 'byte', as in...

* (unsigned char *) &blah[3] = 233;

Subsequent examination of blah[3] via a char lvalue will _not_
yield the original character coding. Converting the plain char
value to unsigned char, may also fail to yield the original
character coding. Since isxxxx operates on the original character
coding, then it seems obvious sense to use an unsigned char
lvalue, rather than conversion of a plain char to unsigned char.

> The thing that `string' points to is a plain `char', not an
> `unsigned char', and it is (very mildly) risky to pretend that
> the one is the other.


Unfortunately, that is what the standard tells implementations
to do!

> I am too full of post-prandial Cognac at the moment to work
> out the details, but I rather suspect that a system with
> signed `char' and ones' complement representation for negatives
> might get into some trouble with such a lie.


I agree. And I think the standard should explicitly require
plain char to be unsigned on 1c or sm machines, or 2c C99
implementations where CHAR_MIN might be a 'non-value'.

> Since the incorruptibly honest convert-at-point-of-call idiom
> cannot fail


I've demonstrated above that it can.

> while the pointer-twiddling approach carries with it a faint
> whiff of impropriety, I see no reason to use the latter.


I've demonstrated that consistent use of unsigned char lvalues
_can't_ fail!

> ...
> Incidentally, note that a system with signed `char' must
> either limit itself to non-negative codes for actual characters
> or must provide a useful definition for the conversion of out-
> of-range `unsigned char' values to plain signed `char'. It
> would be unconscionable if
>
> int ch;
> char c;
> if ((ch = getchar()) != EOF)
> c = ch;
>
> ... were to raise a signal or do "something weird" if `ch'
> happened to exceed CHAR_MAX. The library was born as the servant
> of the language, but now and then becomes its master.


For consistency with other aspects of implementation requirements,
this should really be written as...

int ch;
unsigned char c;
if ((ch = getchar()) != EOF)
c = ch;

> With 20-20 hindsight


It's wonderful, isn't it!

> one can opine that the original decision to leave the
> signedness of `char' unspecified was unfortunate.


That character types have duplicate roles of byte and
character stores was also unfortunate.

--
Peter

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Passing an array from FORTRAN to C then passing it within C andReturning it to FORTRAN deadpickle C Programming 1 11-07-2010 02:38 PM
Passing derived class object array in place of base class object array justanotherguy63@yahoo.com C++ 9 12-03-2004 10:57 PM
Passing a contiguously allocated 2D array to a function expecting a 1 dimesnional array Jonathan Underwood C Programming 2 08-13-2003 04:21 PM
Re: Passing pointer to array from C to Python..and modifying same array in python? J W Python 0 07-14-2003 02:59 PM
Passing pointer to array from C to Python..and modifying same array in python? JW Python 1 07-12-2003 10:45 PM



Advertisments