0
votes

I need to write a program which reads a list of integers using scanf() (no using arrays). The first number is the representative exchange rate, and all remaining numbers represents cash amounts in dollars. The program should print the cash amount in dollars in "$" column and print in the "IS" column the cash amounts in the other coin (dollar*rate). In addition, program should print the sum of each column.

#include <stdio.h> 

int main()
{
    float rate = 0;
    float numDollar = 0;
    float numShekel = 0;
    float sumDollar = 0;
    float sumShekel = 0;


    printf(" \nPlease enter the U.S Dollar Representative Exchange Rate \n ");
    scanf(" %f", &rate);

    printf(" \nPlease enter the numbers which represents cash amount in Dollars (and then press enter) \n ");

    printf("\n$\t\t\t\t\tIS\n");

    while (scanf(" %f", &numDollar) !=EOF && (numDollar!='\n'))
    {
      sumDollar = sumDollar + numDollar;
      numShekel = numDollar * rate;
      sumShekel = sumShekel + numShekel;

      printf("%3.2f\t\t\t\t\t%3.2f\n",numDollar,numShekel);
    }

     printf("%3.2f\t\t\t\t\t%3.2f\n",sumDollar,sumShekel);

    return 0;
}

I have some questions:

  1. Based on the above program:

    user enters "rate" -> press enter key -> "enter list of numbers" -> press enter key.

    The problem: I want to print the column headers ($ and IS) only AFTER the above flow (i.e only AFTER user entered a list of integers and pressed enter key).

    I can`t just do the printing after the while loop, because then the columns headers will be printed below the columns values which is wrong. This is because I am restricted to print the next integer during the while loop because scanf will lose the previous value once the next one is read (correct?!)...

    Is there any way to iterate through all the integers stored in scanf buffer? so I can print the headers and then the values in one shot?

  2. In the above program, it seems that after all the column values are printed, the sum of each column is not printed until CTRL+D is entered. How can I make the sum to be printed also with the column values in one shot? I tried to change the while condition to != '\n' but it does not work because I am dealing with float and not char.

you can assume the list of integers are entered in a single line.

Please assist.

Thanks


I did a few changes.

Now I am left only with the 2nd problem. How can I print the sum with the columns headers in 1 shot? I don`t want to press CTRL+D and only then have the sum printed. I want columns Headers + Column Values + Columns Sum to be printed in one shot.

#include <stdio.h> 

int main()
{
    float rate = 0;
    float numDollar = 0;
    float numShekel = 0;
    float sumDollar = 0;
    float sumShekel = 0;


    printf(" \nPlease enter the U.S Dollar Representative Exchange Rate, and a list of cash amounts in Dollars in a single line (CTRL+D to finish) \n ");
    scanf(" %f", &rate);

    printf("\n$\t\t\t\t\tIS\n");

    while (scanf("%f", &numDollar) != EOF)
    {
      sumDollar = sumDollar + numDollar;
      numShekel = numDollar * rate;
      sumShekel = sumShekel + numShekel;

      printf("%3.2f\t\t\t\t\t%3.2f\n",numDollar,numShekel);
    }

     printf("%3.2f\t\t\t\t\t%3.2f\n",sumDollar,sumShekel);

    return 0;
}
3
What do you expect numDollar!='\n' to do, given that numDollar is a float ?Paul R
(numDollar!='\n') is wrong but will compile because C will infer a cast from int (which is what '\n' is, like it or not) to float. So it'll be a check to see if numDollar is 10 or 13, depending on platform.Mike DeSimone
I don`t expect it. I was just thinking in loud. Is there anyway to iterate through all numbers stored in scanf buffer?qwerty
But why not use arrays? Why invent ridiculous mechanism to store list of values?Andrey
I agree, but this is what university wants. I was not asked to store the values, just to print them in a table with the columns headers. Is there anyway to print the header table AFTER the list of values are read by scanf?qwerty

3 Answers

2
votes

What you want to do isn't possible with just scanf and printf and without using arrays. You'd need to take over the character-by-character input system, using something like the readline library or the terminfo library.

The fundamental problem is that scanf(' %f', ...) will scan until it reads a floating point value, discarding all whitespace until then. "Whitespace" here not only means spaces and tabs but line ends as well! So the user can type RETURN a few times, the number, RETURN a few more, the second number, and RETURN before your code even gets to it. Your code would then need to obliterate all this malformatted input, work its way back up to the proper line, which may well have scrolled away by then, and print the properly formatted values.

Thus you need something better than scanf which will be able to block RETURN (and ENTER and long lines) from scrolling the screen, and you need terminfo or equivalent to get the control sequences needed to do things like "erase this line" and "move cursor to this point".

scanf is no substitute for a robust parser, unfortunately. It's designed around reading input files and isn't very smart about terminal input.

1
votes
  1. This will print the sum first as desired, but will print the entered Dollars in reverse order.
    So far, dollar input order and printing order not specified.

  2. A kludge to detect \n is far below.

Recommend double with money variables.

Always check scanf() results. E.g. EOF, 0, 1

Space not needed in scanf(" %f",...

#include <stdlib.h>
#include <stdio.h>

void GetMoney(double rate, double *sumDollar, double *sumShekel) {
  double numShekel, numDollar;
  int cnt = scanf("%lf", &numDollar);
  if (cnt == EOF) {
    printf("%3.2lf\t\t\t\t\t%3.2lf\n", *sumDollar, *sumShekel);
    return;
  }
  if (cnt != 1) Handle_NonNumericInput();  // e.g. do same as EOF
  numShekel = numDollar * rate;
  *sumDollar += numDollar;
  *sumShekel += numShekel;
  GetMoney(rate, sumDollar, sumShekel);
  printf("%3.2lf\t\t\t\t\t%3.2lf\n", numDollar, numShekel);
}

int main() {
  double sumDollar = 0.0;
  double sumShekel = 0.0;
  double rate;
  //...
  printf("\n$\t\t\t\t\tIS\n");
  GetMoney(rate, &sumDollar, &sumShekel);
  //...
}

--

Concerning money, values in this case, that have fractional parts like $0.005 cause issues. Various approaches, do everything is the lowest legal unit like $0.01 --> 1 and $1.00 --> 100 OR round computation:

 sumDollar = round((sumDollar + numDollar)*100)/100;
 numShekel = round((numDollar * rate)*100)/100;

The issue of how to best handle money is beyond the scope of this post. This is just an FYI that there exist special financial computation issues.


Reading a line of numbers spaced with white-space (except '\n') and then finally terminated with '\n' is possible with scanf() (and ungetc()), but not worthy of coding except as an exercise as using fgets() and sscanf()/strtod() is far better. But fgets() uses a char array, banned by the post.

The below somewhat works, but is not robust:

char ch == '\n'; 
int cnt = scanf("%f%c", &numDollar, &ch);
if (cnt == EOF) Handle_EOForIOError();
if (cnt == 0 || !isspace((unsigned char) ch)) Handle_BadInput();
Process(numDollar);
if (ch == '\n') Handle_ThisIsTheLastOne();
// Handle More

The above gets fooled if a space and \n follow a number.

0
votes

scanf() if successful returns the total number of characters read, otherwise a negative number is returned. so can check,

scanf(...)>0 or scanf(...)!=-1

condition.
scanf() needs cntrl+D, it treats '\n' as other white spaces so to end reading input on enter use fgets(). you can then convert the string to float using atof() or strtof()