0

How can I assign a integer and float values given by user to a variable or array without using scanf()?

Like we have getchar,fgetc,fgets...etc for char and string, Is there any function for floats and integers ?

7
  • 3
    man strtol, man strtof. Make sure to look at the "See also" section. Commented Aug 4, 2017 at 17:12
  • there are no specific input functions for numbers. Commented Aug 4, 2017 at 17:14
  • what actually your purpose for looking such thing might help us to direct you in right way. Commented Aug 4, 2017 at 17:20
  • I recommend reading the guide to scanf written by @FelixPalmen especially section "4. How would I get numbers without scanf()?" Commented Aug 4, 2017 at 17:33
  • This is an challenging goal if the input must stop once the end of the number occurs. IOWs, "123 456\n" must stop after the 3 to simulate scanf("%d", ...) and not read in the whole line. Not easy, especially with FP. I suspect reading a line will satisfy OP. Commented Aug 4, 2017 at 18:23

3 Answers 3

1

There aren't functions to read integers and floats but you can use fgets with strtol for integers and strtof for floats:

// floats:
char str_f[20];
float f;

fgets (str_f, 20, stdin);
f = strtof(str_f, NULL);

// integers:
char str_i[20];
int i;

fgets(str_i, 20, stdin);
i = strtol(str_i, NULL, 0);

You can also use atoi for integers but it's not recommended because atoi doesn't detect errors and it's considered obsolete.

If you want to detect errors you can use the following code:

// floats:
char *endptr_f;
char str_f[20];
float f;

fgets (str_f, 20, stdin);
f = strtof(str_f, &endptr_f);

if (*endptr_f != '\n' || str_f[0] == '\n' || endptr_f == str_f)
{
    printf("ERROR: \"%s\" is an invalid float!\n", str_f);
}

// integers:
char *endptr_i;
char str_i[20];
int i;

fgets(str_i, 20, stdin);
i = strtol(str_i, &endptr_i, 0);

if (*endptr_i != '\n' || str_i[0] == '\n' || endptr_i == str_i)
{
    printf("ERROR: \"%s\" is an invalid integer!\n", str_i);
}
Sign up to request clarification or add additional context in comments.

10 Comments

"atoi doesn't detect errors" and neither does your answer. Any possible error is completely overlooked.
atoi() is obsolete? Any reference on that or is it just not recommended?
@WeatherVane ok, sorry, I added the code to detect errors
No sorry, your error checking for strtof will not pick up on the bad input "1a.2" nor when there is an overflow. You have not checked the return value from fgets. It is essential to thoroughly check all user input, whether they are malicious or just careless.
And this illustrates the point with why we used canned input functions. So easy to screw up and cause hard to find errors.
|
0

Years ago I wrote this, Tested in VS2017 and still works. Very simple, Not very good but maybe you can use it for something

#define INT_CONVERTED       (1 << 0)
#define FLOAT_CONVERTED     (1 << 1)

char *strlwr(char *str)
{
    char *ptr = str;

    while (*ptr)
    {
        *ptr = tolower(*ptr);
        ptr++;
    }
    return str;
}


int NumberOfDots(char *s)
{
    int dots = 0;
    while (*s)
        dots += *s++ == '.';
    return dots;
}

int NOTstrcasechr(char *str, int ch)
{
    return strchr(str, ch) == NULL && strchr(str, toupper(ch)) == NULL;
}

int ReadNumber(double *db, int *in)
{
    int result = 0;

    do
    {
        char str[100];
        int dots;

        result = 0;
        printf("Enter number: ");
        fgets(str, 100, stdin);
        if ((dots = NumberOfDots(str)) > 1) str[0] = '\0';

        if (sscanf(str, "%lf", db) == 1)
        {
            result |= FLOAT_CONVERTED;
        }
        if (!result || (!dots && NOTstrcasechr(str, 'e')))
            if (NOTstrcasechr(str, 'x'))
            {
                if (sscanf(str, "%d", in) == 1)
                {
                    result |= INT_CONVERTED;
                }
            }
            else 
                if(result)
                {
                    result |= INT_CONVERTED;
                    *in = (int)*db;
                }
        if (strstr(strlwr(str), "exit") != NULL) result = -1;

    } while (!result);
    return result;
}


int main(int argc, char **argv)
{
    double db;
    int in;
    int result;

    while ((result = ReadNumber(&db, &in)) != -1)
    {

        if (result & FLOAT_CONVERTED) printf("Float = %lf ", db);
        if (result & INT_CONVERTED) printf("Integer = %d ", in);
        printf("\n\r");

    }
    return 0;
}

Enter number: xfdsfdsfdsf
Enter number: rthdgfhghg
Enter number: 0x4567
Float = 17767.000000 Integer = 17767
Enter number: 3e67
Float = 30000000000000000978680950144401383192292617328216608963406365458432.000000
Enter number: 54567
Float = 54567.000000 Integer = 54567
Enter number: dfgdfgdfgdfgdgg
Enter number: 3456
Float = 3456.000000 Integer = 3456
Enter number: 12354654465454654654565567567576
Float = 12354654465454653961713368432640.000000 Integer = -1
Enter number: exit

Comments

-2

Is there any function for floats and integers ?

Yes, it is scanf(), yet OP does not want to use that.

How to get Integer and float input without scanf()?

This is not a trivial task to do just like scanf("%d", &some_int), scanf("%f", &some_float).

The primary problem is to stop reading characters once the longest valid input is consumed - this could be in the middle of a line of user input. I did not find a terse robust solution.

Instead, talcked the problem of reading a line of user input for one integer long. Reading a float is similar. Changes needed near *** lines

Still the problem of finite text length occurs. The below code assumes valid input is made of up to 2x the maximum needed to print a long.

Overflow is an issue somewhat addressed here. Recall with scanf(), OF/UF is undefined behavior.

The central idea is to read a line by skipping whitespace, reading N characters and then looking for any non-white space after that. Then parse the buffer.


#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

// character array size needed to represent all `long`
#define INT_STR_SIZE (sizeof(long)*CHAR_BIT/3 + 3)
#define INT_BUF_SIZE (INT_STR_SIZE*2)

int readline_long(long *dest) {                        // ***
  int ch;
  while (isspace(ch = getchar()) && ch != '\n') {
    ;
  }
  if (ch == EOF) return EOF;
  ungetc(ch, stdin);

  char buf[INT_BUF_SIZE];                                 // ***
  if (fgets(buf, sizeof buf, stdin) == NULL) return EOF;
  if (strchr(buf, '\n') == NULL) {
    // Get rest of line
    bool only_white_space = true;
    while ((ch = getchar()) != '\n' && ch != EOF) {
      if (!isspace(ch)) only_white_space = false; // consume rest of line
    }
    if (!only_white_space) return 0;  // extra junk
  }
  char *endptr;
  errno = 0;
  long y = strtol(buf, &endptr, 10);                    // ***
  if (buf == endptr) return false;  // no conversion
  while (isspace((unsigned char) *endptr)) {
    endptr++;
  }
  if (*endptr) return 0; // extra junk
  *dest = y;
  return 1;
}

Test code

int main(void) {
  long lg;
  int retval;
  while ((retval = readline_long(&lg)) != EOF) {
    printf("retval = %d", retval);
    if (retval > 0) printf(" val = %ld", lg);
    if (errno) printf(" errno = %d", errno);
    putchar('\n');
    fflush(stdout);
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.