NO

Author Topic: Learning to write simple Math console programs. Best function to use for Input?  (Read 4719 times)

EdPellesC99

  • Guest

   I want to have the user input a double. I can do this using the scanf function:

   ....
   double num;
    .... etc
   scanf("%lf", &num);
   .... etc

   But this is not safe for buffer overruns ... is it?

   What other function is best to use? It might be possible to use fscanf with stdin as source (as you can use fgets with stdin as source), I could try that..... but at this point I would appreciate some advice.

   I could use fgets, but the decimal number would go into a char array. This may or not be smart, I am a bit confused.

Everything was fine for me using fgets and StringCbGets or StringCChGets ...... in earlier studying, as I was using text.

Now that I am trying to do math, I am confused.
 
  As soon as someone suggests something, I will post an example .c file using their suggestion. If no one posts a suggestion, I will post some code anyway.

  Tx, Ed



LW

  • Guest
scanf() is okay as long as you are not dealing with strings. One point to remember is to flush the input buffer after each call this way:

Code: [Select]
while (getchar() != '\n')
  continue;

EdPellesC99

  • Guest
   Thanks for the reply LW.

  I am reading that as long as you specify the input field width to be a given number of characters (bytes ?), you will be OK.

  I am not sure how to use your code suggestion.

  Here is a file that is working, I want the number input by the user to end up in the variable "num" as a double float type so I can take the square root.

  Note: I am commenting for a beginner. And thanks to
Timo's addin, I have color syntax for the forum !!!



Quote

#include <stdio.h>
#include <math.h>

int main ()
{
   double num;
   printf("Enter only positive numbers.");
/*
The %lf specifier indicates a data object of type double.
*/
   scanf("%10lf", &num); // // ~ Here I format the input as a type long float (=double) [l means double when specifier is f]. Accept no more than 10 characters (For Buffer overrun safety. But is it completely safe? Am I better off using fgets ? Is it 10 characters or 10 bytes?
   
   if (num < 0)
   {
      printf("Input Error: Number is NOT positive !.\n");
   }
   else
   {
   // // ~ Ednt: All math is done in double types accord to math.h
      printf("You entered: %.2lf\n", num); // // ~ Ednt: Here I print my input with two decimal points.
      printf("The square root is: %.2lf\n", sqrt(num));
   }
return (0);
}


// // ~ •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •  •
  I like this as the input is read into the declared double "num" variable as a double float. It seems to be safe.
I could read it in using fgets into a char buffer, but then I have to get it as a double into my variable "num".
And as I said before I am getting a bit confused !


LW,
  With the above file, would you still recommend your code snippet, and if so how/where would I use it?


  In a day or two, I might post an fgets version. I am looking for opinions as to a Best Way to use from now on that is definitely safe from a buffer over-run

  Tx, Ed


« Last Edit: June 08, 2010, 06:23:13 PM by EdPellesC99 »

LW

  • Guest
EdPellesC99
Of course, if you want to be totally sure, you could write your own routines for processing your particular input data using fgets() approach, and in fact, that's what is often done in production code, but it's not really necessary at this point. Frankly speaking, there is no "silver bullet" as you put it. Additionally, when one talks about buffer, it could be an internal buffer as one that is declared being a char array, or otherwise an external system buffer. When scanf() is called with an "%s" parameter it is about to write in an internal buffer you specify, and that's when a buffer overrun may occur. However, when you're reading a number with scanf() you are virtually safe from such an occasion (given proper matching argument). So, scanf with "%lf" may be considered safe, and "%10lf" even safer (I don't quite remember is result defined or not taking "666666666666666666666666666"-like input in the first case, but it surely shouldn't make any security vulnerabilities).

Talking about external buffer, that's where your data gets in the first place. scanf() will read your input from this buffer until approaching the first symbol that cannot be understood given this format specifier. For example, if you have the "%d" specifier, it would read first three symbols of "123fg" string, but leave the others ("fg") staying there in the buffer. When you try to use scanf() again for doing a similar task it'd be forever stuck unable to read anything further. So, for preventing such an occasions, code snippet suggested above by me may be used. As I said, it meant to go right after any call to scanf(). Its sole puprose is to read and discard any input items remaining in system buffer until encountering a newline.
« Last Edit: June 08, 2010, 07:07:06 PM by LW »

EdPellesC99

  • Guest
   Tx for the reply LW.

  I rewrote the file to do two square roots.

  I just want to verify this is what you are saying should be done.

Quote

#include <stdio.h>
#include <math.h>

int main ()
{
   static double num;
   printf("Enter only positive numbers.\n");
   scanf("%10lf", &num);
    // // ~ Here I format the input as a type long float (=double) [l means double when specifier is f]. Accept no more than 10 characters (For Buffer overrun safety. But is it completely safe? Am I better off using fgets ? Is it 10 characters or 10 bytes?
while (getchar() != '\n')
continue;

     if (num < 0)
   {
      printf("Input Error: Number is NOT positive !.\n");
   }
   else
   {
      printf("You entered: %.2lf\n", num);
      printf("The square root is: %.2lf\n\n\n", sqrt(num));
   }

   printf("Ok, Again enter a positive numbers.\n");
   scanf("%10lf", &num);
   
while (getchar() != '\n')
continue;

     if (num < 0)
   {
      printf("Input Error: Number is NOT positive !.\n");
   }
   else
   {
      printf("You entered: %.2lf\n", num);
      printf("The square root is: %.2lf\n", sqrt(num));
   }
return (0);

}

  Thanks again for the reply.

  I will post soon a version using fgets and sscanf.

... Ed

EdPellesC99

  • Guest

   Ok,
   Here is an alternate way using fgets and sscanf. Is there any advantage here over the scanf method above?


Is there a better way to use fgets other than writing to the variable using sscanf?

  Appreciate any comments !!!!!!!

  What do you think LW ?

Quote

#include <stdio.h>
#include <math.h>
#include <string.h> // needed for strchr
#include <stdlib.h>
#define arraysz 100

static char Note[arraysz];

int main ()
{
   static double num;
   printf("Enter a non-negative number:");
// // ~ •  •  •  •  •  •  •  •  •  •  •  • Acquire Input into char array, then remove the line feed that fgets gives you.

if (NULL != fgets(Note, sizeof(Note) -1, stdin))
   {
   char *lfptr = strchr(Note, '\n');
   if (lfptr) *lfptr = '\0';
   }
// // ~ •  •  •  •  •  •  •  •  •  •  •  •

  printf("You entered %s\n", Note);

sscanf (Note,"%10lf",&num); // // ~ Ednt: using sscanf write 10 characters to address of type double variable num. "lf" means use the l modifier before float, which means a double float type.

  printf("num is: %10.4lf\n", num); // // ~ Ednt: If input has greater than 10 digits before decimal, then write only first 10 .... and four digits after the decimal (there or not) to the address of my type double "num" variable.

   if (num < 0)
   {
      printf("Input Error: Number is negative.\n");
   }
   else
   {
      printf("The square root is: %f\n", sqrt(num));
   }
return (0);

}

 
// // ~ •  •  •  •  •  •  •  •  •  •  •  •

Tx for Input !,

 Ed
// // ~ •  •  •  •  •  •  •  •  •  •  •  •



EdPellesC99

  • Guest

   LW,

   I see exactly what you mean now, and I thank you for your input on clearing the system buffer.

I like the scanf way better, I have corrected my code for two square roots using your method to clear. It is below.

I would appreciate your thoughts as to when the fgets/sscanf method might be a more reliable way to go (if ever).

  Thanks again,
  Ed


Quote

#include <stdio.h>
#include <math.h>

int main ()
{
   static double num;
   printf("Enter only positive numbers.\n");
   scanf("%10lf", &num);

     if (num < 0)
   {
      printf("Input Error: Number is NOT positive !.\n");
   }
   else
   {
      printf("You entered: %.2lf\n", num);
      printf("The square root is: %.2lf\n\n\n", sqrt(num));
   }

while (getchar() != '\n')
continue;

   printf("Ok, Again enter a positive numbers.\n");
   scanf("%10lf", &num);
   
     if (num < 0)
   {
      printf("Input Error: Number is NOT positive !.\n");
   }
   else
   {
      printf("You entered: %.2lf\n", num);
      printf("The square root is: %.2lf\n", sqrt(num));
   }
return (0);

}