Есть ли функция для чисел с плавающей запятой и целых чисел?
Да, это scanf()
, но OP не хочет его использовать.
Как получить целочисленный и плавающий ввод без scanf()
?
Это не тривиальная задача, как scanf("%d", &some_int)
, scanf("%f", &some_float)
.
Основная проблема заключается в том, чтобы прекратить чтение символов после того, как будет использован самый длинный допустимый ввод — это может быть в середине строки пользовательского ввода. Я не нашел краткого надежного решения.
Вместо этого обсуждалась проблема чтения строки пользовательского ввода для одного целого числа long
. Чтение float
аналогично. Необходимы изменения возле строк ***
Тем не менее возникает проблема конечной длины текста. В приведенном ниже коде предполагается, что допустимый ввод сделан в 2 раза больше, чем требуется для печати long
.
Переполнение — это проблема, которая в некоторой степени рассматривается здесь. Напомним, что с scanf()
поведение OF/UF не определено.
Основная идея состоит в том, чтобы прочитать строку, пропустив пробелы, прочитав N символов, а затем отыскав после этого любое небелое пространство. Затем проанализируйте буфер.
#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;
}
Тестовый код
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);
}
}
04.08.2017
atoi
не обнаруживает ошибок, как и ваш ответ. Любая возможная ошибка полностью игнорируется. 04.08.2017atoi()
устарел? Любая ссылка на это или это просто не рекомендуется? 04.08.2017strtof
не будет обнаружена при неправильном вводе"1a.2"
или при переполнении. Вы не проверили возвращаемое значение изfgets
. Необходимо тщательно проверять все действия пользователя, независимо от того, являются ли они злонамеренными или просто неосторожными. 04.08.2017"\n"
этот код не сообщает об ошибке.char str_f[20]
довольно маленький дляfloat
. Кстати, проверка переполнения FP сложна, если вы хотите это сделать. Даже ОФ дляfloat
- это боль. 04.08.2017\n
. Я знаю, что 20 мало для чисел с плавающей запятой, но я думаю, что это легко изменить и понять, как работает код, и что, если вы хотите больше чисел с плавающей запятой, вы можете увеличить число 04.08.2017if (endptr_f == str_f)
, чтобы определить, не произошло ли преобразование. 04.08.2017