Reputation: 33
I have to write a code that will convert the ASCII digit characters I enter into integers. This first code has been revised and given a thumbs up by the professor:
#include <stdio.h>
#include <stddef.h>
char * ASCIItoInt(char inputString[], int *integerPtr);
int main() {
char inputBuffer[1024];
char *ptr = NULL;
int integer = 8888;
while(fgets(inputBuffer, sizeof(inputBuffer), stdin)) {
ptr = inputBuffer;
int done = 0;
while(!done) {
char *newPtr = ASCIItoInt(ptr, &integer);
if(newPtr == NULL) {
if(*ptr != '\0')
++ptr; // Skip over offending character
else
done = 1;
} else {
printf("%d\n", integer);
ptr = newPtr;
}
}
}
return 0;
}
This code will test the function within the next code provided by reading a standard input until it has read all the lines and skipping any error causing (NULL) characters for ASCIItoInt.
This is ASCIItoInt:
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
char *ASCIItoInt(char *inputString, int *integerPtr) {
*integerPtr = 0;
while (*inputString) {
printf("%d\n", *integerPtr);
printf("%c\n", *inputString);
if (*inputString >= '0' && *inputString <= '9') {
*integerPtr *= 10;
*integerPtr += (*inputString - '0');
inputString++;
}
else
inputString++;
}
return inputString - *integerPtr;
}
We were instructed to compile as such:
gcc -Wall ASCIItoInt.c MainASCIItoInt.c -o ASCIItoInt
I don't know if it makes a difference. I just included it, because the MainASCIItoInt (the first code) calls for the second code. With all that being said, I compile and run, but get the same output nonstop. Could this be a return error, or something else? What would be the best way to fix it? This code isn't very good, but I'm trying to work at it little by little. Any help would be appreciated.
Upvotes: 3
Views: 73
Reputation: 33631
You were pretty close. Some tweaking only. Here's the corrected code with most of your original logic. Note the addition of an extra boolean inside your parsing function as well as a reversal of the if
sense. [please pardon the gratuitous style cleanup]:
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
char *
ASCIItoInt(char *str, int *integerPtr)
{
int chr;
char *cp;
int valid;
//printf("ASCIItoInt: ENTER str=%s",str);
*integerPtr = 0;
valid = 0;
cp = str;
for (chr = *cp; chr != 0; chr = *++cp) {
//printf("ASCIItoInt: chr=%2.2X\n",chr);
// is char a digit? bug out if not
if (! ((chr >= '0') && (chr <= '9')))
break;
*integerPtr *= 10;
*integerPtr += (chr - '0');
//printf("ASCIItoInt: %d\n",*integerPtr);
// say we found a valid digit
valid = 1;
}
if (! valid)
cp = NULL;
//printf("ASCIItoInt: EXIT cp='%s'\n",cp);
return cp;
}
int
main(int argc,char **argv)
{
char inputBuffer[1024];
char *ptr = NULL;
int integer = 8888;
FILE *xfin;
--argc;
++argv;
// need the argv for convenience if using gdb
if (argc > 0)
xfin = fopen(*argv,"r");
else
xfin = stdin;
while (fgets(inputBuffer, sizeof(inputBuffer), xfin)) {
ptr = inputBuffer;
int done = 0;
while (!done) {
char *newPtr = ASCIItoInt(ptr,&integer);
if (newPtr == NULL) {
if (*ptr != '\0')
++ptr; // Skip over offending character
else
done = 1;
}
else {
printf("%d\n", integer);
ptr = newPtr;
}
}
}
if (argc > 0)
fclose(xfin);
return 0;
}
Here's a way to do it with atoi
(using strtol
instead because of error checking):
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int
main(int argc,char **argv)
{
char inputBuffer[1024];
char *bp;
char *cp;
int integer = 8888;
FILE *xfin;
--argc;
++argv;
// need the argv for convenience if using gdb
if (argc > 0)
xfin = fopen(*argv,"r");
else
xfin = stdin;
while (fgets(inputBuffer, sizeof(inputBuffer), xfin)) {
bp = inputBuffer;
while (1) {
cp = strtok(bp," \n");
bp = NULL;
// nothing more
if (cp == NULL)
break;
integer = strtol(cp,&cp,10);
if (*cp != 0) {
printf("syntax error\n");
continue;
}
printf("%d\n",integer);
}
}
if (argc > 0)
fclose(xfin);
return 0;
}
UPDATE:
Per your request, here's the meaning of %2.2X
. Note that the actual interpretation can vary with the conversion specifier [the X
], so the authoritative reference is man 3 printf
Because the character being tested could be any [8 bit] value [notably newline], we don't want to output with %c
as we might get semi-unprintable output, so %2.2X
will output a "zero filled" 2 digit hexadecimal representation. Note: See below for a better way to output the trace printf
So, a space is 20
, a q
is 61
, a 0
is 30
and newline is 0A
.
In general, for a format of %w.pX
:
w
is the "field width" [the minimum number of characters that the field should occupy]
p
is the "precision". For the X
conversion [and d
], this is the minimum number of digits. For newline, since it's a value of 0x0A
[decimal 10], with a field width of 2
, it must be zero padded [on the left].
For hex, we could have %2.2X
or %2.2x
. This controls uppercase/lowercase [respectively] for our output.
Here are some formats and their outputs. The quotes are added to make it easy to see how much space the format is actually using. I've added some decimal formats for comparison
%X --> 'A'
%2X --> ' A'
%2.2X --> '0A'
%02X --> '0A'
%2.2x --> '0a'
%d --> '1'
%10d --> ' 1'
%10.10d --> '0000000001'
%10.9d --> ' 000000001'
%10.7d --> ' 0000001'
%d --> '37'
%10d --> ' 37'
%10.10d --> '0000000037'
%10.9d --> ' 000000037'
%10.7d --> ' 0000037'
%d --> '289'
%10d --> ' 289'
%10.10d --> '0000000289'
%10.9d --> ' 000000289'
%10.7d --> ' 0000289'
%d --> '1096'
%10d --> ' 1096'
%10.10d --> '0000001096'
%10.9d --> ' 000001096'
%10.7d --> ' 0001096'
%d --> '28492'
%10d --> ' 28492'
%10.10d --> '0000028492'
%10.9d --> ' 000028492'
%10.7d --> ' 0028492'
%d --> '137862923653'
%10d --> '137862923653'
%10.10d --> '137862923653'
%10.9d --> '137862923653'
%10.7d --> '137862923653'
I would be remiss if I didn't include a better way to output the debugging printf
:
int
isprintable(int chr)
{
return (chr >= 0x20) && (chr <= 0x7E);
}
printf("DEBUG: chr=%2.2X/'%c'\n",chr,isprintable(chr) ? chr : '.');
Upvotes: 1
Reputation: 2544
You should change your question to match the question you are asking in the comments
Answering your question in the comment:
You use atoi()
like this:
int main ()
{
int i;
char buffer[256];
printf ("Enter a number: ");
fgets (buffer, 256, stdin);
i = atoi (buffer);
printf ("The value entered is %d. Its double is %d.\n",i,i*2);
return 0;
}
The code will output:
Enter a number: 73
The value entered is 73. Its double is 146
Another solution is this:
char myarray[5] = {'-', '1', '2', '3', '\0'};
int i;
sscanf(myarray, "%d", &i);
i
will equal to -123
.
Upvotes: 1