Search code examples
arrayscfloating-pointmultiplicationgetchar

Reading float numbers using getchar() and printing the float number and it's double


I'm having trouble in converting numbers to float using getchar() method to solve my problem. For my problem I need to store characters in an array of fixed size = 50. Also, storing in an array only happens when there is a space ' ' or a newline \n read using getchar(). This happens until EOF is read. At last, the float number and it's double (with a tab space) is returned and printed using printf.

As per instructions, only getchar() is allowed. Functions like scanf(), fgets(), atoi(), atol(), atof(), strtol(), strtoul() or an extra array can not be used.

Here is what I've come up with till now. ( see sample input and output at bottom )

#include <stdio.h>
#define SIZE 50    // assume no more than 50 literals in input
int main(){
 
  float c;
  float u;
  float value = 0.0;
  float resu[SIZE];
  int index = 0;
  int i;
  char sub = '0';

  value = 0;
  c = getchar();
  while ( c != EOF){ 
    if(c == '.'){
      u = 0.1;
    }

    else if (c == ' ' || c == '\n'){ 
      if(u == 0.1){
        value = value * 0.1;
    } 
      resu[index] = value;
      index++;
      value = 0;
    }

    if( c >= '0' && c <= '9'){
        value = value * 10 + (c-sub);
    }
    c = getchar(); // read next
  }
 
  //printing the result
  for(i=0; i < index; i++)
    printf("%.4lf \t %.4lf\n", resu[i],resu[i] *2.0);
 
  return 0;
}

(Note- There is a tab between the original number and it's double)

Sample Input: 
2.3 4.56
43.3 43 5.3
.3 1.2

Sample Output: 
2.3000    4.6000
45.6000    91.2000 //ERROR
43.3000    86.6000
4.3000    8.6000   //ERROR
5.3000    10.6000
0.3000    0.6000
1.2000    2.4000

Solution

  • Two things you don't do is initialize u or reset u for each word.

    float u = 0;
    ....
        else if (c == ' ' || c == '\n') { 
            if (u == 0.1){
                value = value * 0.1;
            } 
            resu[index] = value;
            index++;
            value = 0;
            u = 0;       // Reset it for next number
        }
    

    Also, you hard-code u = 0.1, but that only works when there is only 1 decimal place. That may be ok for this assignment, but a better option would be to count the digits after the decimal.

    #include <stdbool.h>
    #include <math.h>
    #include <ctype.h>
    ...
    int digits_after_decimal = 0;
    bool have_decimal_point = false;
    int value = 0;
    int c;
    while ((c = getchar()) != EOF) {
        // Decimal point found?
        if ('.' == c) {
            have_decimal_point = true;
        }
        else if (isdigit(c)) {
            // Add this digit to integer value
            // Parentheses not required but added for clarity
            value = (value * 10) + (c - '0');
            // If decimal point already found, increment count
            if (have_decimal_point) digits_after_decimal += 1;
        }
        // Complete word. Save and reset
        // TODO: Multiple spaces between words?
        else if (' ' == c || '\n' == c) {
            // Divide by the correct power of 10 based on
            // the number of digits after the decimal point
            resu[index++] = value / pow(10, digits_after_decimal);
            if (index == SIZE) break;  // Avoid overflow
            // Reset for next number
            digits_after_decimal = 0;
            have_decimal_point = false;
            value = 0;
        }
        // TODO: Negative numbers?
    }