Curfew
Curfew

Reputation: 3

Facing problems with the atoi function if used repeatedly

I have to find the frequency of digits {0,1,2,3,4,5,6,7,8,9} in a given string, I'm using atoi function to convert the character to an integer and I'm having problems with the atoi function when the input string is large (tried this with different test cases of varying length),

for example if the input string is

1v88886l256338ar0ekk

my code works properly and the answer is

1 1 1 2 0 1 2 0 5 0

where the 1st digit indicates the frequency of 0 and so on upto 9,

but if the input string is

9139f793308o0lo66h6vc13lgc697h0f6c32lu84445972k0o0l033od17c083yn5051d6j319hyo8j939n28d913015ns6zx5653x01211x12ch2526o65sg7xw6302141q9203s22l336319ll9yx4b597mr318a7943906750j4u152067nq83ne9f24thu96yd05173l47c803roxci45615f0w53i1sz913jj6za733l73tw6r66mq6p44sfhjr26h8e801z8zlcx2l1e65r2879xj3w3acv216196uq158o663y7oz2i5378v0v5w17762451t424352m23026r9o202i9785382o159e4gu1c8561157z5f1vqs5755465b8u728u956434mv944885li456628a994u7j5278m269n1pk8e46940q834h06il6h447888tr7ig72z10fe09k5g98h9bgt6z40v42s16pt6k3l3v45i83i01b9448g554741w766f2q7v31i085488h060e710p53076c6nm98pi946g8j2n6j8x29qa1ad48172y0u4818121p686bud89741201p54087u56g8scerv9pvhuo09re477zfb224i2c1325bj58jx4bk7b009f6446j5i95474p266i503r670n631x6940gwl71ejbx47imx576129248901765rnpu6l80084t0j1839f5y3409w2n403fu6ogw1170jmb6o5l520vg0703e0

upon reaching the end of the string the atoi function returns wrong values

for example,

my code uses atoi to convert char text to an integer and stores it into int num

at the beginning the function works fine,

text is 9 num is 9 
text is 1 num is 1 
text is 3 num is 3 
text is 9 num is 9 
text is 7 num is 7 
text is 9 num is 9 
text is 3 num is 3 
text is 3 num is 3 
text is 0 num is 0 
text is 8 num is 8 
text is 0 num is 0 
.
.
.

and upon nearing the very end of the string the function returns

.
.
. 
text is 2 num is 2 
text is 4 num is 4 
text is 0 num is 0 
text is 3 num is 30 
text is 6 num is 60 
text is 1 num is 10 
text is 1 num is 10 
text is 7 num is 70 
text is 0 num is 0 
text is 6 num is 61 
text is 5 num is 51 
text is 5 num is 51 
text is 2 num is 21 
text is 0 num is 1
text is 7 num is 71  
text is 0 num is 1 
text is 0 num is 1 
text is 3 num is 31 

If I replace int num = atoi(&text) with int num = text - '0' my program works perfectly for all test cases,

so can someone please tell me what went wrong and whether I have used the function incorrectly. Please keep in mind I just want to know why atoi didn't work, hence I'm not looking for replacements for the function.

I've included the snippet of my code below

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

int main() {
    int arr[10] = {0};
    char text;
   text = getchar();
   while(text != EOF)
   {
       if(isdigit(text))
       {
           printf("text is %c ",text);
           int num = atoi(&text);
           printf("num is %d\n ",num);
           for(int i =0; i<10;i++)
           {
               if(num==i)
               {
                   arr[i]++;
                   //printf("arr[%d] is %d\n", i,arr[i]);
                   break;
               }
           }
       }
       text = getchar();
   }
for(int i=0; i<10;i++)
{
    printf("%d ",arr[i]);
}  
    return 0;
}

Thanks in advance for taking the time to read and answer my question

Upvotes: 0

Views: 532

Answers (2)

wildplasser
wildplasser

Reputation: 44240

  • you don't need atoi() since you are dealing with single characters, not with strings
  • getc()returns an int [0 .. 255 for actual characters, -1 for EOF]
  • you can avoid a lot of {} braces by using break and continue

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

int main() {
    int arr[10] = {0};
    int text, num;
   while(1) {
        text = getchar();
        if (text == EOF) break;
        if (!isdigit(text)) continue;
        printf("text is %c ", text);
        num = text - '0'
        printf("num is %d\n ",num);
        arr[num]++;
        //printf("arr[%d] is %d\n", num, arr[num]);
    }
    for(int i=0; i<10;i++)
    {
        printf("%d ",arr[i]);
    }

    return 0;
}

Upvotes: 1

Andrew Henle
Andrew Henle

Reputation: 1

Per the atoi() documentation in the C standard:

The atoi, atol, and atoll functions convert the initial portion of the string pointed to by nptr to int, long int, and long long int representation, respectively.

Note the bolded part.

Given

char text;

this code invokes undefined behavior because the address passed to atoi() is not that of a string:

int num = atoi(&text);

One fix would be:

char text[2];
text[1] = '\0';

// getchar() returns int, not char, in order
// to handle EOF properly
int input = getchar();
while(input != EOF)
{
    text[0] = input;
    if(isdigit(text[0]))
    {
        printf("text is %s ",text);
        int num = atoi(text);

That ensures that a string (a nul-terminated series of char) is passed to atoi().

Upvotes: 1

Related Questions