1

This program is supposed to go through an array of zeros and ones and count how many zeros, ones and all the character combined are there. However, the print statement inside the loop prints bunch of "48"s and "49"s. Even though the number of characters is calculated properly, seems like it is not extracting values from pointers in the "if statements", but rather it gets memory addresses.

Code itself:

#include <stdio.h>      /* using printf, gets, BUFSIZ */

int main(int argc, char *argv[])
{
    char input[BUFSIZ];

    int n;
    char *labelPtr;
    int zeroCount=0;
    int oneCount=0;
    n=0;

    gets(input);

    while(input[n])
    {
        labelPtr=&input[n];
        printf("%d \n", *labelPtr);
        if (*labelPtr==0)
        {
            zeroCount++;
        }
        if(*labelPtr==1)
        {
            oneCount++;
        }
        n++;
    }
    printf("The number of characters is %d \n", n);
    printf("The number of zeros is %d \n", zeroCount);
    printf("The number of ones is %d \n", oneCount);
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270
Bek Akilov
  • 13
  • 2
  • There is no good reason to use `gets` in this century. It is a broken function. – John Coleman Apr 10 '18 at 03:43
  • 1
    [asciitable.com](http://www.asciitable.com/) -- All things will become clear... (e.g. decimal `48` is ASCII `'0'` - or - ASCII `'0'` is decimal `48` - take your pick), add 1 for `'1'`... (hint: you `printf ("%c", ...)` or `putchar()` to print a character, you use `"%d"` to output a "decimal".) – David C. Rankin Apr 10 '18 at 03:47
  • 1
    You need to burn your current C book/teacher with fire and get a modern one instead. – Lundin Apr 10 '18 at 11:36
  • Thank you guys, that helped. This is literally the first time I am programming in C. I know some of the aspects of this problem are very obsolete, but I think it was done on purpose by my prof to make us understand how pointers and chars work in C. Thanks a lot to everyone who helped!! – Bek Akilov Apr 10 '18 at 23:46

2 Answers2

2
  1. Don't use gets. It is a well known cause of security problems. Use fgets instead.

  2. There is no reason for you to use char* type for labelPtr. Use just char label;.

  3. Use of if (*labelPtr == 0) is not correct since *labelPtr is char and value of the character '0' is not equal to the integer constant 0. You need to compare it with '0'. if (*labelPtr == '0'). Similarly, use if (*labelPtr == '1')

  4. To print a char, use the format specifier %c, not %d.

    printf("%c \n", *labelPtr);
    

    If you use %d as the format specifier, you get the integer value use to encode the character as the output. For ASCII encoding, you get 48 for the character '0' and 49 for the character '1'.


Here's an updated version of your posted code.

#include <stdio.h>      /* using printf, gets, BUFSIZ */

int main(int argc, char *argv[])
{
    char input[BUFSIZ] = {};

    int n = 0;
    char label;
    int zeroCount=0;
    int oneCount=0;

    fgets(input, sizeof(input), stdin);

    while( input[n] )
    {
        label = input[n];
        printf("%c \n", label);
        if (label == '0')
        {
            zeroCount++;
        }
        if(label == '1')
        {
            oneCount++;
        }
        n++;
    }
    printf("The number of characters is %d \n", n);
    printf("The number of zeros is %d \n", zeroCount);
    printf("The number of ones is %d \n", oneCount);
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270
1

You are confusing reading a number with reading characters. When you read with fgets (or any other function) you read characters. The characters you read are ASCII characters that are represented by numeric values 0-127 (for the most part, there is wide-char support). See ASCII Table The first 31-chars (ASCII values 0-30) are your control and whitespace characters (e.g. nul-character, tab, newline, ...) 127 (del) is likewise a non-printing character. The remainder 31-126 make up the printable characters (including the printable characters 0-9)

(note: you never use gets which is so prone to exploit and buffer overrun it has been removed from the C11 library)

Do not confuse or equate the number 0 with the ASCII character '0' (note the single-quotes).

In your code when you attempt to print each character, e.g.

    printf("%d \n", *labelPtr);

You are printing the ASCII value (the decimal value) for the ASCII character. You are looking for '0' and '1' and getting 48 and 49. That is because the ASCII code for character '0' is 48 and for '1' is 49. If you wish to print the character, you would need:

    printf("%c\n", *labelPtr);

Further, your counts will never register anything. Why? You are testing for 0 and 1 instead of '0' and '1'. (and noting that 0 is the nul-character -- so you would be beyond the last character in the string before it ever tested true). Instead you need:

        if (*labelPtr == '0')
            zeroCount++;
        if(*labelPtr == '1')
            oneCount++;

Putting it altogether and cleaning up unneeded/unused variables, you could do something like the following:

#include <stdio.h>      /* using printf, gets, BUFSIZ */

int main (void)
{
    char input[BUFSIZ] = "",
        *labelPtr = input;
    int n = 0,
        zeroCount=0,
        oneCount=0;

    fgets (input, BUFSIZ, stdin);

    for (; *labelPtr; labelPtr++, n++)
    {
        printf ("read ASCII char '%c' (%3d - decimal)\n", 
                *labelPtr, *labelPtr);
        if (*labelPtr == '0')
            zeroCount++;
        if(*labelPtr == '1')
            oneCount++;
    }
    printf("characters: %d\nzeros     : %d \nones      : %d \n", 
            n, zeroCount, oneCount);
}

Example Use/Output

$ echo "my 10 dogs have 100 fleas" | ./bin/zeroonect
read ASCII char 'm' (109 - decimal)
read ASCII char 'y' (121 - decimal)
read ASCII char ' ' ( 32 - decimal)
read ASCII char '1' ( 49 - decimal)
read ASCII char '0' ( 48 - decimal)
read ASCII char ' ' ( 32 - decimal)
read ASCII char 'd' (100 - decimal)
read ASCII char 'o' (111 - decimal)
read ASCII char 'g' (103 - decimal)
read ASCII char 's' (115 - decimal)
read ASCII char ' ' ( 32 - decimal)
read ASCII char 'h' (104 - decimal)
read ASCII char 'a' ( 97 - decimal)
read ASCII char 'v' (118 - decimal)
read ASCII char 'e' (101 - decimal)
read ASCII char ' ' ( 32 - decimal)
read ASCII char '1' ( 49 - decimal)
read ASCII char '0' ( 48 - decimal)
read ASCII char '0' ( 48 - decimal)
read ASCII char ' ' ( 32 - decimal)
read ASCII char 'f' (102 - decimal)
read ASCII char 'l' (108 - decimal)
read ASCII char 'e' (101 - decimal)
read ASCII char 'a' ( 97 - decimal)
read ASCII char 's' (115 - decimal)
read ASCII char '
' ( 10 - decimal)
characters: 26
zeros     : 3
ones      : 2

(note: the ' and ' on the next line with ( 10 - decimal) is the '\n' character)

Look things over and let me know if you have further questions.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85