scanf 第三次无法正常工作
scanf doesn't work properly for third time
我正在尝试编写一个简单的 C 程序。输入格式是这样的:
Enter a: <a>
我想输入 a、b、c 和 d,但是 scanf 对 c 和 d 不起作用,程序在那个点上崩溃了。
#include <stdio.h>
#include <math.h>
int main(){
int a, b, c, d;
char ch;
printf("Enter a:");
scanf("%c%d%c", &ch, &a, &ch);
printf("Enter b:");
scanf("%c%d%c", &ch, &b, &ch);
printf("Enter c:");
scanf("%c%d%c", &ch, &c, &ch);
printf("Enter d:");
scanf("%c%d%c", &ch, &d, &ch);
double ans;
ans=(a*b/c + c*d/a)/(b*a/c + d*b/a);
ans=fabs(ans);
printf("Formula 1 result = <%lf>", ans);
return 0;
}
double ans;
ans=(a*b/c + c*d/a)/(b*a/c + d*b/a);
C 语言在确定其类型时不考虑您对结果的处理。因此,您将此操作的结果分配给 double
对结果的计算方式没有任何影响,它只是将整数结果转换为双精度数。当你用整数除以整数时,你得到整数除法。
你可以这样做:
ans=(a*1.0*b/c + c*1.0*d/a)/(b*1.0*a/c + d*1.0*b/a);
与非整数的乘法强制使用非整数乘法、加法和除法。
有 3 个格式转换说明符不会跳过前导白色 space。它们是 %c
(您正在使用)、%[…]
扫描集和 %n
.
当您输入时:
Enter a:<1>
Enter b:<2>
第一个<
满足第一个%c
; 1
匹配 %d
,>
匹配第二个 %c
,所以到目前为止一切正常。
但是,第二批输入将换行符从第一行读取到第一行 %c
,然后无法将 <
转换为整数并停止,留下 <
用于处理下一个输入。
给出了Enter c:
提示,但是<2>
因为格式正确所以处理了,所以给出了Enter d:
提示
有多种方法可以解决此问题,包括:
- 在格式字符串的第一个
%c
之前插入一个空格。这将跳过白色 space,包括换行符,并为您提供预期的行为。这可能是最简单的修复方法。
- 读取行并使用
sscanf()
处理它们。这通常是最好的解决方案。 (使用 fgets()
阅读该行。)
无论哪种情况,请检查 scanf()
系列函数 return 的值是否正确 (3)。并使用两个变量 int c1, c2;
来读取字符并验证用户是否输入了您需要的内容。
最低限度的修正是:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int a, b, c, d;
char c1, c2;
printf("Enter a: ");
if (scanf(" %c%d%c", &c1, &a, &c2) != 3 || c1 != '<' || c2 != '>')
fprintf(stderr, "Bogus input!\n"), exit(1);
printf("Enter b: ");
if (scanf(" %c%d%c", &c1, &b, &c2) != 3 || c1 != '<' || c2 != '>')
fprintf(stderr, "Bogus input!\n"), exit(1);
printf("Enter c: ");
if (scanf(" %c%d%c", &c1, &c, &c2) != 3 || c1 != '<' || c2 != '>')
fprintf(stderr, "Bogus input!\n"), exit(1);
printf("Enter d: ");
if (scanf(" %c%d%c", &c1, &d, &c2) != 3 || c1 != '<' || c2 != '>')
fprintf(stderr, "Bogus input!\n"), exit(1);
double ans;
ans=(a*b/c + c*d/a)/(b*a/c + d*b/a);
ans=fabs(ans);
printf("Formula 1 result = <%lf>\n", ans);
return 0;
}
我懒得在 if
语句后使用逗号运算符。不过,最好使用一个函数来管理输入:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
static void get_number(int *var, const char *name)
{
char c1, c2;
printf("Enter %s: ", name);
if (scanf(" %c%d%c", &c1, var, &c2) != 3 || c1 != '<' || c2 != '>')
{
fprintf(stderr, "Bogus input!\n");
exit(1);
}
}
int main(void)
{
int a, b, c, d;
get_number(&a, "a");
get_number(&b, "b");
get_number(&c, "c");
get_number(&d, "d");
double ans;
ans=(a*b/c + c*d/a)/(b*a/c + d*b/a);
ans=fabs(ans);
printf("Formula 1 result = <%lf>\n", ans);
return 0;
}
最好还是使用:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
static int get_number(const char *name)
{
char buffer[4096];
printf("Enter %s: ", name);
if (fgets(buffer, sizeof(buffer), stdin) == 0)
{
fprintf(stderr, "EOF or error on input\n");
exit(1);
}
char c1, c2;
int val;
if (sscanf(buffer, " %c%d%c", &c1, &val, &c2) != 3 || c1 != '<' || c2 != '>')
{
/* buffer contains a newline unless you typed more than 4095 characters before the newline */
fprintf(stderr, "Bogus input (does not match <number>): %s", buffer);
exit(1);
}
return val;
}
int main(void)
{
int a = get_number("a");
int b = get_number("b");
int c = get_number("c");
int d = get_number("d");
double ans = fabs((a*b/c + c*d/a) / (b*a/c + d*b/a));
printf("Inputs: a = %d, b = %d, c = %d, d = %d\n", a, b, c, d);
printf("Formula 1 result = <%lf>\n", ans);
return 0;
}
请注意代码如何使用 fgets()
加上 sscanf()
,这意味着错误消息可以告诉用户他们输入的内容不是预期的。它还使用函数 return 值,导致显示的代码更简单。并且输出包括用于检查的输入值。您的提交系统可能不需要它,但它肯定会在您开发代码时对您有所帮助。
您可以进行升级以处理 double
值作为输入;不难。
我正在尝试编写一个简单的 C 程序。输入格式是这样的:
Enter a: <a>
我想输入 a、b、c 和 d,但是 scanf 对 c 和 d 不起作用,程序在那个点上崩溃了。
#include <stdio.h>
#include <math.h>
int main(){
int a, b, c, d;
char ch;
printf("Enter a:");
scanf("%c%d%c", &ch, &a, &ch);
printf("Enter b:");
scanf("%c%d%c", &ch, &b, &ch);
printf("Enter c:");
scanf("%c%d%c", &ch, &c, &ch);
printf("Enter d:");
scanf("%c%d%c", &ch, &d, &ch);
double ans;
ans=(a*b/c + c*d/a)/(b*a/c + d*b/a);
ans=fabs(ans);
printf("Formula 1 result = <%lf>", ans);
return 0;
}
double ans;
ans=(a*b/c + c*d/a)/(b*a/c + d*b/a);
C 语言在确定其类型时不考虑您对结果的处理。因此,您将此操作的结果分配给 double
对结果的计算方式没有任何影响,它只是将整数结果转换为双精度数。当你用整数除以整数时,你得到整数除法。
你可以这样做:
ans=(a*1.0*b/c + c*1.0*d/a)/(b*1.0*a/c + d*1.0*b/a);
与非整数的乘法强制使用非整数乘法、加法和除法。
有 3 个格式转换说明符不会跳过前导白色 space。它们是 %c
(您正在使用)、%[…]
扫描集和 %n
.
当您输入时:
Enter a:<1>
Enter b:<2>
第一个<
满足第一个%c
; 1
匹配 %d
,>
匹配第二个 %c
,所以到目前为止一切正常。
但是,第二批输入将换行符从第一行读取到第一行 %c
,然后无法将 <
转换为整数并停止,留下 <
用于处理下一个输入。
给出了Enter c:
提示,但是<2>
因为格式正确所以处理了,所以给出了Enter d:
提示
有多种方法可以解决此问题,包括:
- 在格式字符串的第一个
%c
之前插入一个空格。这将跳过白色 space,包括换行符,并为您提供预期的行为。这可能是最简单的修复方法。 - 读取行并使用
sscanf()
处理它们。这通常是最好的解决方案。 (使用fgets()
阅读该行。)
无论哪种情况,请检查 scanf()
系列函数 return 的值是否正确 (3)。并使用两个变量 int c1, c2;
来读取字符并验证用户是否输入了您需要的内容。
最低限度的修正是:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int a, b, c, d;
char c1, c2;
printf("Enter a: ");
if (scanf(" %c%d%c", &c1, &a, &c2) != 3 || c1 != '<' || c2 != '>')
fprintf(stderr, "Bogus input!\n"), exit(1);
printf("Enter b: ");
if (scanf(" %c%d%c", &c1, &b, &c2) != 3 || c1 != '<' || c2 != '>')
fprintf(stderr, "Bogus input!\n"), exit(1);
printf("Enter c: ");
if (scanf(" %c%d%c", &c1, &c, &c2) != 3 || c1 != '<' || c2 != '>')
fprintf(stderr, "Bogus input!\n"), exit(1);
printf("Enter d: ");
if (scanf(" %c%d%c", &c1, &d, &c2) != 3 || c1 != '<' || c2 != '>')
fprintf(stderr, "Bogus input!\n"), exit(1);
double ans;
ans=(a*b/c + c*d/a)/(b*a/c + d*b/a);
ans=fabs(ans);
printf("Formula 1 result = <%lf>\n", ans);
return 0;
}
我懒得在 if
语句后使用逗号运算符。不过,最好使用一个函数来管理输入:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
static void get_number(int *var, const char *name)
{
char c1, c2;
printf("Enter %s: ", name);
if (scanf(" %c%d%c", &c1, var, &c2) != 3 || c1 != '<' || c2 != '>')
{
fprintf(stderr, "Bogus input!\n");
exit(1);
}
}
int main(void)
{
int a, b, c, d;
get_number(&a, "a");
get_number(&b, "b");
get_number(&c, "c");
get_number(&d, "d");
double ans;
ans=(a*b/c + c*d/a)/(b*a/c + d*b/a);
ans=fabs(ans);
printf("Formula 1 result = <%lf>\n", ans);
return 0;
}
最好还是使用:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
static int get_number(const char *name)
{
char buffer[4096];
printf("Enter %s: ", name);
if (fgets(buffer, sizeof(buffer), stdin) == 0)
{
fprintf(stderr, "EOF or error on input\n");
exit(1);
}
char c1, c2;
int val;
if (sscanf(buffer, " %c%d%c", &c1, &val, &c2) != 3 || c1 != '<' || c2 != '>')
{
/* buffer contains a newline unless you typed more than 4095 characters before the newline */
fprintf(stderr, "Bogus input (does not match <number>): %s", buffer);
exit(1);
}
return val;
}
int main(void)
{
int a = get_number("a");
int b = get_number("b");
int c = get_number("c");
int d = get_number("d");
double ans = fabs((a*b/c + c*d/a) / (b*a/c + d*b/a));
printf("Inputs: a = %d, b = %d, c = %d, d = %d\n", a, b, c, d);
printf("Formula 1 result = <%lf>\n", ans);
return 0;
}
请注意代码如何使用 fgets()
加上 sscanf()
,这意味着错误消息可以告诉用户他们输入的内容不是预期的。它还使用函数 return 值,导致显示的代码更简单。并且输出包括用于检查的输入值。您的提交系统可能不需要它,但它肯定会在您开发代码时对您有所帮助。
您可以进行升级以处理 double
值作为输入;不难。