Jimmy
Jimmy

Reputation: 33

Why do I get the same readout on my ASCII to number program?

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

Answers (2)

Craig Estey
Craig Estey

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

SegFault
SegFault

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

Related Questions