Как сделать проверку на то чтобы в веденной строке была лишь одна запятая/точка?
Имею вот подобный код, который запускает цикл чтобы проверить введенные в строку числа, в дальнейшем строка преобразуется в double через atof если числа в строке подойдут под условия. Я написал замену запятых на точку и выдачу ошибки если больше двух точек подряд, но столкнулся с непониманием того как мне написать адекватное условие для проверки есть ли в числе есть еще точки(кроме как написать одну длинную строку где будет провекра от stra[a]=='.'
до stra[a+15]=='.'
) и если есть то уже выдать опять же ошибку. Помогите пожалуйста:(
#include < stdlib.h >
#include <math.h>
int main() {
char stra[15];
double numbera = 0;
int a = 0;
int error1=0;
do {
error1 = 0;
printf("Enter a(maximum 15 - digit number) : \n");
gets(stra);
while (stra[a] != '\0') {
if (stra[a] == ',' && a <= 15) {
stra[a] = '.';
}
else if (stra[a] == '.' && stra[a + 1] == '.' && stra[a+2] != '\0' ||) {
printf("Error, not correct number \n");
error1 = 1;
a1 = 0;
break;
}
else if (a > 15) {
printf("The number is too large(more than 15 digits) \n");
error1 = 1;
a = 0;
break;
}
++a;
}
if (atof(stra) <= 0) {
printf("The number is negative \n");
error1 = 1;
}
} while (error1 > 0);```
numbera = atof(stra);
}
Ответы (1 шт):
Интерактивный ввод, даже из консоли, не большое удовольствие. Задача разбита на части.
int read_double(FILE *f, double *d)
читает вещественное число из файла. Она возвращает код ошибки:
RD_OK
- всё в порядке, число в*d
;RD_ERROR_FILE_FAILURE
- чтение из файла не удалось. Обычно это фатальная ошибка;RD_ERROR_WORD_TOO_LONG
- слишком длинный ввод. Его можно было бы объединить со следующим, но сделано так как было в вопросе;RD_ERROR_INVALID_FORMAT
- непонятный формат. Функция попыталась прочитать с точкой, с запятой, ничего не получилось.
read_double
пропускает пробелы и читает слово длиной до 98 символов. Слова длиннее считаются ошибкой. Если слово слишком длинное, его хвост пропускается до следующего пробела. Иначе оставшийся мусор может вызвать ложное срабатывание следующего ввода.
Функция main
запускает read_double
в цикле до первого успеха. Кроме ошибок выше, она ещё проверяет что число ≥ 0. Это не та ошибка, которую следует тащить в read_double
, которая занимается только чтением и форматами.
#include <ctype.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define RD_OK 0
#define RD_ERROR_FILE_FAILURE 1
#define RD_ERROR_WORD_TOO_LONG 2
#define RD_ERROR_INVALID_FORMAT 3
int read_double(FILE *f, double *d) {
// read word from file
char buffer[100];
if (fscanf(f, "%99s", buffer) != 1) {
return RD_ERROR_FILE_FAILURE;
}
// check word length
if (strlen(buffer) == 99) {
// word is too long to be actual double literal
// skip until next whitespace
while (true) {
int c = fgetc(f);
if (c == EOF) {
break;
}
if (isspace(c)) {
ungetc(c, f);
break;
}
}
return RD_ERROR_WORD_TOO_LONG;
}
double dd;
int n;
// try to scan as it is
if (sscanf(buffer, "%lf%n", &dd, &n) == 1 && n == (int)strlen(buffer)) {
*d = dd;
return RD_OK;
}
// replace comma with point
char *p = strchr(buffer, ',');
if (p == NULL) {
return RD_ERROR_INVALID_FORMAT;
}
*p = '.';
// try to scan modified string
if (sscanf(buffer, "%lf%n", &dd, &n) == 1 && n == (int)strlen(buffer)) {
*d = dd;
return RD_OK;
}
return RD_ERROR_INVALID_FORMAT;
}
int main() {
bool ok = false;
double d;
while (!ok) {
printf("enter double: ");
switch (read_double(stdin, &d)) {
case RD_OK:
if (d < 0) {
fprintf(stderr, "ERROR: negative value. Try again.\n");
} else {
ok = true;
}
break;
case RD_ERROR_FILE_FAILURE:
fprintf(stderr, "FATAL: input stream is broken.\n");
exit(1);
break;
case RD_ERROR_WORD_TOO_LONG:
fprintf(stderr, "ERROR: value is too long. Try again.\n");
break;
case RD_ERROR_INVALID_FORMAT:
fprintf(stderr, "ERROR: invalid format. Try again.\n");
break;
default:
fprintf(stderr, "ERROR: unknown error. Try again.\n");
break;
}
}
printf("entered %lf\n", d);
}
Компилируем:
$ gcc temp.c
Запускаю и сразу закрываю входной поток чтобы получить ошибку файла:
$ ./a.out enter double: FATAL: input stream is broken.
Все ошибки кроме ERROR: unknown error.
:
$ ./a.out enter double: 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 ERROR: value is too long. Try again. enter double: 1.2.3 ERROR: invalid format. Try again. enter double: -123 ERROR: negative value. Try again. enter double: 123 entered 123.000000
Разные запятые:
$ ./a.out enter double: 12.3 entered 12.300000 $ ./a.out enter double: 12,3 entered 12.300000