# Issue

I'm having troubles with my program. The aim of it is to read an input of numbers from the user, and when they stop inputting numbers (ctrl-d) it collects the inputted numbers and prints out 'Odd numbers were: blah blah' and 'Even numbers were: blah blah'.

I'm having trouble with how to exit the program at EOF and when it feels like I have overcome that problem, another problem occurs which is my program doesn't print the numbers from the array. It only prints 'Odd numbers were:' and 'Even numbers were:'.

Any help is appreciated. Thanks

```
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int main(void) {
int n, i, array[1000];
i=0;
while (i = getchar() !=EOF) {
scanf("%d", &array[i]);
i++;
}
printf("Odd numbers were:");
i=0 ;
while(i = getchar() != EOF) {
if(array[i]%2!=0) {
printf(" %d", array[i]);
i++;
}
}
printf("\nEven numbers were:");
i=0 ;
while(i = getchar() !=EOF) {
if (array[i]%2==0) {
printf(" %d", array[i]);
i++;
}
}
printf("\n");
return 0;
}
```

# Solution

**Performing Single-Digit Conversion to** `int`

You may be making things a bit harder on yourself than it needs to be. While you can use `while (scanf ("%d", &array[i]) == 1)`

to read *whitespace separated integers* and avoid having to perform a manual conversion, if your intent is to read single-digits, then using `getchar()`

is fine. (for that matter, you can read any multi-digit integer with `getchar()`

, it is simply up to you to provide a conversion from the ASCII characters to final numeric value)

The *manual conversion* for single-digit characters is straight forward? When you read digits as characters, you are not reading the *integer value represented by the digit*, you are reading the *ASCII value for the character that represents each digit*. See **ASCII Table and Description**. In order to convert a single ASCII character digit to it's integer value, you must subtract the ASCII value of `'0'`

. (**note:** the single-quotes are significant)

For example if you read a digit with `int c = getchar();`

, then you need to subtract `'0'`

to obtain the single-digit integer value, e.g. `int n = c - '0';`

When filling an array, you must ALWAYS protect against writing beyond the bounds of your array. If you declare `int array[1000] = {0};`

(which has available zero-based array indexes of `0-999`

), then you must validate that you never write beyond index `999`

or *Undefined Behavior* results. To protect your array bounds, simply keep track of the number of indexes filled and test it is always below the number of array elements available, e.g.

```
while (n < MAX && (c = getchar()) != EOF) /* always protect array bounds */
if ('0' <= c && c <= '9') /* only handle digits */
array[n++] = c - '0'; /* convert ASCII to int */
```

Next, while you are free to test `n % 2`

(using the `modulo`

operator), there is no need (little endian). Since any odd number will have its `ones-bit`

set to `1`

, all you need is a simple bitwise comparison, e.g (`7`

in binary is `0111`

).

```
if (array[i] & 1) /* if ones-bit is 1, odd */
printf (" %d", array[i]);
```

Of course, for even numbers, the ones-bit will be `0`

(e.g. `8`

in binary is `1000`

), so the corresponding test can be:

```
if ((array[i] & 1) == 0) /* if ones-bit is 0, even */
printf (" %d", array[i]);
```

Putting all of the pieces together, you can store all single digits read in `array`

and then segregate the *even* and *odd* numbers for printing in a very simple manner (**note:** neither `stdlib.h`

or `math.h`

are required),

```
#include <stdio.h>
#define MAX 1000 /* define a constant rather than use 'magic' numbers in code */
int main (void)
{
int array[MAX] = {0},
c, i, n = 0;
while (n < MAX && (c = getchar()) != EOF) /* always protect array bounds */
if ('0' <= c && c <= '9') /* only handle digits */
array[n++] = c - '0'; /* convert ASCII to int */
printf ("\narray : "); /* output array contents */
for (i = 0; i < n; i++)
printf (" %d", array[i]);
printf ("\narray - odd : ");
for (i = 0; i < n; i++)
if (array[i] & 1) /* if ones-bit is 1, odd */
printf (" %d", array[i]);
printf ("\narray - even : ");
for (i = 0; i < n; i++)
if ((array[i] & 1) == 0) /* if ones-bit is 0, even */
printf (" %d", array[i]);
putchar ('\n'); /* tidy up w/newline */
return 0;
}
```

**Example Compilation with Warnings Enabled**

```
$ gcc -Wall -Wextra -pedantic-std=gnu11 -Ofast -o bin/arrayevenodd arrayevenodd.c
```

**Example Use/Output**

```
$ echo "01234567890123456789" | ./bin/arrayevenodd
array : 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
array - odd : 1 3 5 7 9 1 3 5 7 9
array - even : 0 2 4 6 8 0 2 4 6 8
```

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

**Performing Manual Multi-Digit Conversion to** `int`

If you are needing to convert multi-digit integers from characters, the easy way is to use a function that provides the conversion for you (e.g. the `scanf`

family of functions or by using line oriented with `fgets`

or `getline`

and parsing and converting the strings of digits with `strtok`

and then `strtol`

, or parsing with `sscanf`

, etc.)

However, performing a manual conversion of individual characters read by `getchar()`

into a multi-digit integers is straight forward. You simply check for a valid character than can begin an integer (including the prefixes of `+/-`

) and sum each digit providing a proper offset for the place of the digit by increasingly multiplying the sum by `10`

before adding (or actually subtracting if building a the sum as a *negative* sum for coding efficiency purposes) each digit until you reach the next non-digit and then you add the final sum to your array and advance the array index.

While building the sum, it is up to you to check for *integer Overflow* before adding the final sum to your array. (you can handle the overflow condition however you like, the example below just throws the error and exits)

The manual conversion probably adds about 20 lines of code, e.g.

```
#include <stdio.h>
#include <stdint.h> /* exact length types */
#include <limits.h> /* INT_X constants */
#define MAX 1000 /* define constant rather than use 'magic' number in code */
int main (void)
{
int array[MAX] = {0},
c, i, start = 0, sign = 1, n = 0;
int64_t sum = 0;
while (n < MAX && (c = getchar()) != EOF) { /* always protect array bounds */
if (!start) { /* flag to start building int */
start = 1; /* flag - working on int */
if (c == '+') /* handle leading '+' sign */
continue;
else if (c == '-') /* handle leading '-' sign */
sign = -1;
else if ('0' <= c && c <= '9') /* handle digits */
sum = sum * 10 - (c - '0'); /* note: sum always computed */
else /* as negative value */
start = 0; /* reset - char not handled */
}
else if ('0' <= c && c <= '9') { /* handle digits */
sum = sum * 10 - (c - '0'); /* convert ASCII to int */
if (sum < INT_MIN || (sign != -1 && -sum > INT_MAX))
goto err; /* check for overflow, handle error */
}
else { /* non-digit ends conversion */
if (sum) /* if sum has value, add to array */
array[n++] = sign != -1 ? -sum : sum;
sign = 1; /* reset values for next conversion */
start = 0;
sum = 0;
}
}
if (sum) /* add last element to array on EOF */
array[n++] = sign != -1 ? -sum : sum;
printf ("\narray : "); /* output array contents */
for (i = 0; i < n; i++)
printf (" %d", array[i]);
printf ("\narray - odd : ");
for (i = 0; i < n; i++)
if (array[i] & 1) /* if ones-bit is 1, odd */
printf (" %d", array[i]);
printf ("\narray - even : ");
for (i = 0; i < n; i++)
if ((array[i] & 1) == 0) /* if ones-bit is 0, even */
printf (" %d", array[i]);
putchar ('\n'); /* tidy up w/newline */
return 0;
err:
fprintf (stderr, "error: overflow detected - array[%d]\n", n);
return 1;
}
```

**Example Use/Output**

```
$ echo "1,2,3,5,76,435" | ./bin/arrayevenodd2
array : 1 2 3 5 76 435
array - odd : 1 3 5 435
array - even : 2 76
```

**Example with '+/-' Prefixes**

```
$ echo "1,2,-3,+5,-76,435" | ./bin/arrayevenodd2
array : 1 2 -3 5 -76 435
array - odd : 1 -3 5 435
array - even : 2 -76
```

Look over the new example and let me know if you have any more questions.

Answered By - David C. Rankin Answer Checked By - Timothy Miller (PHPFixing Admin)

## 0 Comments:

## Post a Comment

Note: Only a member of this blog may post a comment.