当输入为浮点时,如何阻止scanf解析整数部分
所以这个程序是一个简单的十进制到二进制的转换器 我希望代码重复,直到用户按下当输入为浮点时,如何阻止scanf解析整数部分,c,floating-point,integer,C,Floating Point,Integer,所以这个程序是一个简单的十进制到二进制的转换器 我希望代码重复,直到用户按下ctrl+D。我还想让用户知道,如果他们输入像-2或1.1这样的数字,那么输入的数字不是正整数 问题是当他们输入一个floatmy code时,我的代码只是无限地打印我的第一个print语句 这是我的代码: void DecToBin(int userInput){ int binary[32]; int i = 0; while (userInput > 0) { binary[i
ctrl+D
。我还想让用户知道,如果他们输入像-2
或1.1
这样的数字,那么输入的数字不是正整数
问题是当他们输入一个float
my code时,我的代码只是无限地打印我的第一个print语句
这是我的代码:
void DecToBin(int userInput){
int binary[32];
int i = 0;
while (userInput > 0) {
binary[i] = userInput % 2;
userInput /= 2;
i++;
}
for (int j = i - 1; j >= 0; --j) {
printf("%d", binary[j]);
}
}
因此,当我输入像11.1
或负值之类的内容时,它不应该接受它,并在终端中打印“请输入一个正整数(或EOF退出)”
应接受11.0
等输入
所以,我想问的是,我的代码有什么问题使得它这样做,我应该如何修复它?我是否应该使用一个
float
来代替?条件userDec%1==0
始终为真,任何整数除以1的余数始终为0
当scanf(“%d”,&userDec)
无法解析输入的值时,它返回0,当您的输入不是数字时会发生这种情况,您可以利用这种情况
要检查一个值是否有小数部分,我们可以使用math.h
库函数,该函数将double的小数部分与其整数部分分开并返回,因此是的,使用double
(而不是精度较低的float
)将是一个不错的策略
(在Linux中,使用gcc
可能需要使用-lm
编译器标志链接math.h
头。)
将这些更改应用到代码中,您将得到如下结果:
#include <stdlib.h>
#include <math.h>
int main(无效)
{
双用户DEC;
二重积分;
字符输入[100];
char*endptr=NULL;
INTC;
//将输入解析为字符串
while(printf(“请输入正整数(或EOF以退出):”&&scanf(“%99[^\n]”,input)==1)
{
errno=0;
userDec=strtod(输入,&endptr);//转换为双精度
//如果为负或溢出或输入无效或分数
如果(userDec<0 | | | |(userDec==大的|值&&errno==ERANGE)| |*endptr!='\0'| | modf(userDec,&integral))
{
printf(“对不起,这不是一个正整数。\n”);
}
其他的
{
printf(“%.0lf(基数-10)相当于”,userDec);
德克托宾(userDec);
printf(“(base-2)!\n”);
}
而((c=getchar())!='\n'&&c!=EOF){continue;}//清除缓冲区
如果(c==EOF){return EXIT_FAILURE;}//c=EOF,则视为不可恢复
}
返回退出成功;
}
当然,有了这样的东西,您需要支持转换器函数来接受更大的值,它现在只接受int
作为参数
无论哪种方式,代码中的所有这些输入限制都应该方便地记录在案。请记住,
scanf
返回成功转换和赋值的次数,或者在文件结束或读取错误时返回EOF
%d
转换说明符将跳过前导空格并读取十进制数字,直到第一个非十进制数字字符如果第一个非空白字符不是十进制数字,则匹配失败,scanf
将返回0
,而不是EOF
当您输入11.1
时,scanf
成功地将11
转换并分配给userDec
,并返回1
。但是,它会将剩余的.1
保留在输入流中,而这永远不会被清除
下次读取时,scanf
看到.1
并立即停止读取并返回0
。但是,您只测试了scanf
不会返回EOF
,因此它永远不会跳出循环
使用scanf
时,您最好根据您希望成功转换的项数进行测试-在这种情况下,您的测试应该是
if ( res != 1 )
break;
我将按如下方式重新构造您的读取循环:
while ( 1 )
{
// prompt
if ( (res = scanf( "%d", &userDec)) != 1 )
{
// print error message
break;
}
else
{
if ( userDec <= 0 )
{
// print error message
}
else
{
// process input
}
}
}
if ( res != EOF )
{
// had a matching failure from bad input
}
else
{
// user signaled EOF
}
最可靠的方法不使用
scanf()
读取用户输入行。而是使用fgets()
,然后使用strto*()
和friends解析字符串
由于OP寻找的是整数或带整数值的浮点数形式的有效输入,所以构造辅助程序例程来做好每项工作
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
void base(int n) {
if (n == 0)
return;
base(n / 2);
printf("%d", n % 2);
}
// Return error flag, 0 implies success
int String2int(int *dest, const char *s, int min, int max) {
if (dest == NULL)
return 1;
*dest = 0;
if (s == NULL)
return 1;
errno = 0;
char *endptr;
long L = strtol(s, &endptr, 0);
if (s == endptr)
return 1; // no conversion
if (errno == ERANGE || L < min || L > max)
return 1; // out of range
while (isspace((unsigned char) *endptr))
endptr++;
if (*endptr)
return 1; // Extra text after input
*dest = (int) L;
return 0;
}
int String2Whole(double *dest, const char *s, double min, double max_plus1) {
if (dest == NULL)
return 1;
*dest = 0.0;
if (s == NULL)
return 1;
errno = 0;
char *endptr;
double d = strtof(s, &endptr);
if (s == endptr)
return 1; // no conversion
// Save whole part into dest
if (modf(d, dest))
return 1; // Test return of non-zero fractional part.
if (d < min || d >= max_plus1)
return 1; // out of range
while (isspace((unsigned char) *endptr))
endptr++;
if (*endptr)
return 1; // Extra text after input
return 0;
}
userDec%1==0
应该测试什么条件?当然,除以1
总会留下0
的余数。scanf函数希望得到一个整数,而不是浮点或双精度类型。我假设整数输入没有同样的问题。您可能还需要一个单独的函数将小数部分转换为二进制代码>从输入中提取字符,直到找到与格式字符串不匹配的字符。因此,如果您输入12.34
scanf将取1
和2
,然后找到
,但%d
格式中不允许小数点,因此它将停止取字符。然后转换12
并返回到scanf,但scanf找到的第一个字符是
,它无法使用该字符,因此停止。但是你没有检查返回码。要修复它,请检查scanf的返回代码,如果失败,则F设置行的其余部分以收集.34\n
,然后再次扫描。res=(int)(res)代码>-这是一个完全无用的语句。它打算做什么?@Amy在int
中没有小数部分哦,是的,对不起,我想我在我最初的问题中没有解释太多。我希望输入11.1告诉用户它不工作。我的代码只是重复了“请输入…”语句。那么我应该作为一个浮标来扫描吗?@osito_solito,是的,是的
int main(void)
{
double userDec;
double integral;
char input[100];
char *endptr = NULL;
int c;
// parse input as string
while (printf("Please enter a positive whole number (or EOF to quit): ") && scanf("%99[^\n]", input) == 1)
{
errno = 0;
userDec = strtod(input, &endptr); // convert to double
// if negative or overflow or invalid input or fractional
if (userDec < 0 || (userDec == HUGE_VAL && errno == ERANGE) || *endptr != '\0' || modf(userDec, &integral))
{
printf("Sorry, that was not a positive whole number.\n");
}
else
{
printf("%.0lf (base-10) is equivalent to ", userDec);
DecToBin(userDec);
printf(" (base-2)!\n");
}
while ((c = getchar()) != '\n' && c != EOF) { continue; } // clear buffer
if (c == EOF) { return EXIT_FAILURE; } // c = EOF, treated as unrecoverable
}
return EXIT_SUCCESS;
}
if ( res != 1 )
break;
while ( 1 )
{
// prompt
if ( (res = scanf( "%d", &userDec)) != 1 )
{
// print error message
break;
}
else
{
if ( userDec <= 0 )
{
// print error message
}
else
{
// process input
}
}
}
if ( res != EOF )
{
// had a matching failure from bad input
}
else
{
// user signaled EOF
}
int itemsRead;
int userDec;
char dummy;
/**
* Read the next integer input and the character immediately
* following.
*/
itemsRead = scanf( "%d%c", &userDec, &dummy );
/**
* Here are the possible scenarios:
*
* 1. If itemsRead is 2, then we read at least one decimal digit
* followed by a non-digit character. If the non-digit character
* is whitespace, then the input was valid. If the non-digit
* character is *not* whitespace, then the input was not valid.
*
* 2. If itemsRead is 1, then we read at least one decimal digit
* followed immediately by EOF, and the input was valid.
*
* 3. If itemsRead is 0, then we had a matching failure; the first
* non-whitespace character we saw was not a decimal digit, so the
* input was not valid.
*
* 4. If itemsRead is EOF, then we either saw an end-of-file condition
* (ctrl-d) before any input, or there was a read error on the input
* stream.
*
* So, our test is if itemsRead is less than 1 OR if itemsRead is 2 and
* the dummy character is not whitespace
*/
if ( itemsRead < 1 || itemsRead == 2 && !isspace( dummy ) )
{
// input was not valid, handle as appropriate.
}
else
{
// input was valid, process normally
}
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
void base(int n) {
if (n == 0)
return;
base(n / 2);
printf("%d", n % 2);
}
// Return error flag, 0 implies success
int String2int(int *dest, const char *s, int min, int max) {
if (dest == NULL)
return 1;
*dest = 0;
if (s == NULL)
return 1;
errno = 0;
char *endptr;
long L = strtol(s, &endptr, 0);
if (s == endptr)
return 1; // no conversion
if (errno == ERANGE || L < min || L > max)
return 1; // out of range
while (isspace((unsigned char) *endptr))
endptr++;
if (*endptr)
return 1; // Extra text after input
*dest = (int) L;
return 0;
}
int String2Whole(double *dest, const char *s, double min, double max_plus1) {
if (dest == NULL)
return 1;
*dest = 0.0;
if (s == NULL)
return 1;
errno = 0;
char *endptr;
double d = strtof(s, &endptr);
if (s == endptr)
return 1; // no conversion
// Save whole part into dest
if (modf(d, dest))
return 1; // Test return of non-zero fractional part.
if (d < min || d >= max_plus1)
return 1; // out of range
while (isspace((unsigned char) *endptr))
endptr++;
if (*endptr)
return 1; // Extra text after input
return 0;
}
char *doit(void) {
int i = 0;
char buf[100];
if (fgets(buf, sizeof buf, stdin) == NULL) {
return "Input closed";
}
if (String2int(&i, buf, 0, INT_MAX)) {
double x;
if (String2Whole(&x, buf, 0.0, (INT_MAX / 2 + 1) * 2.0)) {
return "Invalid input";
}
i = (int) x;
}
printf("O happy day! %d\n", i);
return 0;
}
int main(void) {
doit();
}