我有这段代码来验证用户输入。条件:输入的值应仅为零或正数。不接受负值和字母字符。
这是我的代码,只是继续循环:
#include <stdio.h>
int main ()
{
int a, b, c, d;
printf ("enter value for a:");
do {
b = 0;
scanf ("%d", &a);
if (!isdigit(a)) {
printf("Number must be numeric!:\n");
b++;
}
else if (a < 0) {
printf ("number must be postive\n");
b++;
} else {
printf("\neverything is goood\n");
}
} while (b != 0);
}
答案 0 :(得分:4)
isdigit()
期待ASCII编码字符,但scanf
%d
参数将ASCII编码数字(字符串)转换为实际数字。
即。如果输入'1'
,ASCII代码为0x31
,则scanf("%d",...
会将其转换为值1
。 ASCII码1为不数字。
要解决此问题,请:
a
类型char
并使用scanf
格式说明符%c
,然后isdigit()
将按您的要求执行。strtol
读取多个字符,并使用char **endptr
参数执行自己的错误检查。此外,您应该打开编译器警告并包含包含isdigit()
函数ctype.h
的头文件。
答案 1 :(得分:1)
一旦用户犯了错误,b总是&gt; 0.在输入正确的信息后(即在你的printf(“\ neverything good / n”)之后,你需要添加一个设置b = 0的行;声明。只需确保将{&amp;}添加到之前的else语句中它,因此printf&amp; new b = 0;语句将包含在该分支中)
答案 2 :(得分:1)
以下是我可以发现的代码问题:
scanf
与%d
格式说明符一起使用,该格式说明符已将输入解析为整数值。因此,无需检查isdigit
是否为数字。实际上,isdigit
正在检查十进制数字符,因此您的使用不正确。scanf
返回。你应该。如果出现错误(即值为非数字),则不会从流中删除输入。换句话说,你会一遍又一遍地试图解析相同的坏值。话虽如此,这里有一些可能适合你的代码:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
static void skip_input(FILE *stream)
{
int c;
do {
c = fgetc (stream);
} while (c != EOF && c != '\n');
}
int main()
{
int a;
int r;
printf("Please enter a value: ");
for (;;) {
r = scanf("%d", &a);
if (r == EOF)
return EXIT_FAILURE;
if (r != 1) {
printf("Number must be numeric!\n");
skip_input(stdin);
} else if (a < 0) {
printf("Number must be postive\n");
skip_input(stdin);
} else {
printf("Everything is goood\n");
break;
}
}
return EXIT_SUCCESS;
}
希望它有所帮助。
答案 3 :(得分:0)
您正在使用b作为错误标记。
在“一切都很好”中,尝试设置b=0;
此外,如果您这样做,您可以摆脱b++;
行,只需初始化b=1;
如果你需要报告用户搞砸了多少次,你应该只做b++
,我认为你不需要它?
答案 4 :(得分:0)
这里有几个问题。
第一个是没有检查scanf()的返回值。如果输入可用,则scanf返回已分配的变量数,在这种情况下可以是0或1(因为您只是尝试分配一个变量)。如果用户输入一个非数字字符,那么循环将重复执行,而不会等待更多的用户输入,因为有可用的输入,但它永远不会匹配您的“%d”转换。如果你想使用scanf(),那么你必须检查返回值。如果返回值为零,则输入非数字值,这意味着您必须通过读取直到行的末尾从输入缓冲区中清除该值。如果返回值等于EOF,则表明发生了I / O错误或者您到达了流的末尾。如果返回值为1,那么您知道该值是数字,这使我遇到下一个问题。
例程isdigit()采用整数参数,但它期望整数值表示一个字符。由于您使用scanf()将输入转换为整数,因此存储在a中的值不再表示字符;它代表一个实际数字。因此,如果用户输入对应于数字字符的数字,则对isdigit()的调用将仅返回true值。在我的语言环境中,这意味着只有当用户输入48到57之间的数字时,验证才会成功。如果你正在使用scanf(),则不需要进行isdigit()检查,因为只有当用户输入数值时,scanf()才会返回值1。
老实说,但是,我不会使用scanf()来读取用户输入,如果我可以准确地避免它,因为如果用户输入错误就需要刷新输入缓冲区。我不完全确定你的要求是什么,但我会假设你应该从命令行读取一个正整数,并且数字位数无关紧要。
在这种情况下,您可能希望使用fgets()来读取用户输入,然后使用strtol()将值转换为带符号的长整数并同时执行验证:
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <errno.h>
#include <ctype.h>
#include <string.h>
int main () {
long result;
long len;
int is_valid = 0;
char buf[128];
char *arg;
char *end;
while (!is_valid) {
/* Prompt the user for the integer. */
printf("Enter a non-negative integer: ");
if (fgets(buf, sizeof(buf), stdin) == NULL) {
printf("Giving up so soon?\n");
break;
}
/* Verify that the input doesn't exceed our buffer length. */
len = strlen(buf);
if (buf[len] != '\n') {
printf("Input buffer length exceeded - aborting.\n");
exit(1);
}
/* Skip any leading whitespace. */
for (arg = buf; isspace(*arg); arg++);
/* Attempt to convert the argument. */
errno = 0;
result = strtol(arg, &end, 10);
if (errno == EINVAL) {
printf("Please enter a numeric value.\n");
continue;
}
if (errno == ERANGE) {
printf("Numeric value out of range.\n");
continue;
}
/* Check for non-whitespace characters after the end of the integer. */
for (; isspace(*end); end++);
if (*end != '\0') {
printf("Please enter a numeric value.\n");
continue;
}
/* Verify that the number is non-negative. */
if (result < 0) {
printf("Please enter a positive value.\n");
continue;
}
/* The number is valid. */
printf("Excellent!\n");
is_valid = 1;
}
return 0;
}
这并不完美;如果超过输入缓冲区长度则中止不完全是用户友好的。但是,它应该处理验证问题。