virtualghost
virtualghost

Reputation: 33

My program doesn't manipulate a string's values correctly

I need to code a program that gets input values for a string, then it ignores the characters that are not digits and it uses the digits from the string to create an integer and display it. here are some strings turned into integers as stated in the exercise.

I wanted to go through the string as through a vector, then test if the each position is a digit using isdigit(s[i]), then put these values in another vector which creates a number using the digits. At the end it's supposed to output the number. I can't for the life of it figure what's wrong, please help.

#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main()
{
    char *s;
    scanf("%s", s);
    printf("%s\n", s);

    int i, n=0, v[100], nr=0;
    for(i=0; i<strlen(s); i++)
    {
        if (isdigit(s[i]) == 1)
        {
            v[i] = s[i];
            n++;
        }
    }
    for(i=0;i<n;i++)
    {
        printf("%c\n", v[i]);
    }

    for(i=0; i<n; i++)
    {
        nr = nr * 10;
        nr = nr + v[i];
    }
    printf("%d", nr);
    return 0;
}

Upvotes: 0

Views: 90

Answers (4)

P.P
P.P

Reputation: 121397

The pointer s is unintialized which is your major problem. But there are other problems too.

  • isdigit() is documented to return a non-zero return code which is not necessarily 1.

  • The argument to isdigit() needs to be cast to unsigned char to avoid potential undefined behaviour.

  • Your array v is also using the same index variable i - which is not right. Use a different variable to index v when you store the digits.

  • You need to subtract '0' to get the each digits integer equivalent.

  • scanf()'s format %s can't handle inputs with space (among other problems). So, use fgets().


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

int main(void)
{
char s[256];
fgets(s, sizeof s, stdin);
s[strcspn(s, "\n")] = 0; /* remove trailing newline if present */
printf("%s\n", s);

int i, n = 0, v[100], nr = 0;
size_t j = 0;
for(i = 0; i < s[i]; i++)
{
    if (isdigit((unsigned char)s[i]))
    {
        v[j++] = s[i];
        n++;
    }
}
for(i = 0;i < j; i++)
{
    printf("%c\n", v[i]);
}

if (j) { /* No digit was seen */
    int multiply = 1;
    for(i= j-1 ; i >= 0; i--) {
        nr = nr + (v[i] - '0') * multiply;
        multiply *= 10;
    }
}

printf("%d", nr);
return 0;
}

In addition be aware of integer overflow of nr (and/or multiply) can't hold if your input contains too many digits.

Another potential source of issue is that if you input over 100 digits then it'll overflow the array v, leading to undefined behaviour.

Upvotes: 2

Luis Colorado
Luis Colorado

Reputation: 12668

Just use this

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

int main()
{
    int c;
    while ((c = getchar()) != EOF) {
        switch (c) {
        case '0': case '1': case '2': case '3': case '4':
        case '5': case '6': case '7': case '8': case '9':
        case '\n':
            putchar(c); break;
        }
    }
    return 0;
} /* main */

This is a sample execution:

$ pru_$$
aspj pjsd psajf pasdjfpaojfdapsjd 2 4 1
241
1089u 0u 309u1309u98u 093u82 40981u2 982u4 09832u4901u 409u 019u019u 0u3 0ue 
10890309130998093824098129824098324901409019019030

Very elegant! :)

Upvotes: 0

Weather Vane
Weather Vane

Reputation: 34585

Firstly, you did not allocate any memory, I changed that to a fixed array.

Your use of scanf will stop at the first space (as in the first example input).

Next, you don't use the right array index when writing digits int v[]. However I have removed all that and simply used any digit that occurs.

You did not read the man page for isdigit. It does not return 1 for a digit. It returns a nonzero value so I removed the explicit test and left it as implicit for non-0 result.

I changed the string length and loop types to size_t, moving the multiple strlen calls ouside of the loop.

You have also not seen that digits' character values are not integer values, so I have subtracted '0' to make them so.

Lastly I changed the target type to unsigned since you will ignore any minus sign.

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

int main(void)
{
    char s[100];                              // allocate memory
    unsigned nr = 0;                          // you never check a `-` sign
    size_t i, len;                            // correct types
    if(fgets(s, sizeof s, stdin) != NULL) {   // scanf stops at `space` in you example
        len = strlen(s);                      // outside of the loop
        for(i=0; i<len; i++) {
            if(isdigit(s[i])) {               // do not test specifically == 1 
                nr = nr * 10;
                nr = nr + s[i] - '0';         // character adjustment
            }
        }
        printf("%u\n", nr);                 // unsigned
    }
    return 0;
}

Program session:

a2c3   8*5+=
2385

Upvotes: 0

virtualghost
virtualghost

Reputation: 33

Thanks a lot for your help, i followed someone's advice and replaced
v[i] = s[i] -> v[n] = s[i] and changed char *s with char s[100] now it works perfectly, i got rid of the variable nr and just output the numbers without separating them through \n . Thanks for the debugger comment too, I didn't know I can use that effectively.

Upvotes: 0

Related Questions