gpt4 book ai didi

c - 用scanf替换简单方程式中的get会使程序崩溃

转载 作者:太空宇宙 更新时间:2023-11-04 01:58:18 26 4
gpt4 key购买 nike

我正在通过C寻找假人。它有一个示例代码,用于使用getsatoi将英寸转换为厘米(p.135,如果有文本的话)。
现在,我想尝试使用scanf而不是可怕的gets,这是我能想到的最好的方法(基于作者提供的代码)。

#include <stdio.h>
#include <stdlib.h>

int main()
{
float height_in_cm;
char height_in_inches;

printf("Enter your height in inches: ");
scanf("%c"),&height_in_inches;
height_in_cm = atoi(height_in_inches)*2.54;
printf("You are %.2f centimetres tall.\n",height_in_cm);
return(0);
}

程序启动了,但输入之后就崩溃了。我哪里做错了?

最佳答案

scanf()可以为您提供答案时,为什么还要花时间转换答案?

#include <stdio.h>

int main(void)
{
float height_in_inches;

printf("Enter your height in inches: ");
if (scanf("%f", &height_in_inches) == 1)
{
float height_in_cm = height_in_inches * 2.54;
printf("You are %.2f inches or %.2f centimetres tall.\n",
height_in_inches, height_in_cm);
}
else
printf("I didn't understand what you said\n");
return(0);
}

如果必须读取字符串,请使用 fgets()
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
char line[4096];

printf("Enter your height in inches: ");
if (fgets(line, sizeof(line), stdin) != 0)
{
double height_in = strtod(line, 0);
double height_cm = height_in * 2.54;
printf("You are %.2f inches or %.2f centimetres tall.\n",
height_in, height_cm);
}
return(0);
}

注意,两个程序都会在使用输入结果之前检查输入是否发生。你可以争辩说,对 strtod()调用的错误检查是非常乏味的;我同意。注意,我在第一个片段中的 float和第二个片段中的 double之间切换;两者都可以工作。当结果是一个小数时,我看不出将输入限制为整数值的特殊原因。回显输入和输出通常也是有益的;如果回显的内容不是您认为输入的内容,则这是一个很好的提示,表明某些内容出现了严重错误,并使您在代码的正确区域进行搜索。
注意:地毯下面有一些小细节,特别是在第一个例子中,关于 floatdouble以及 scanf()printf()。鉴于下面的评论,它们目前与OP无关。
对原始代码的最小修复
由于上面的代码比OP所识别的还要复杂,下面是对原始代码的一组更简单的修复。输入到数组(string)中的字符串是关键点;这也需要更改 scanf()调用。
通过使用一个大的缓冲区,我们可以假设用户不能通过在终端键入来溢出输入。不过,这对于机器驱动的输入是不合适的。
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
float height_in_cm;
char height_in_inches[4096]; // Array, big enough to avoid most overflows

printf("Enter your height in inches: ");
// Missing error check on scanf() — too advanced as yet
scanf("%s", height_in_inches); // Format specifier, parentheses, ampersand
height_in_cm = atoi(height_in_inches) * 2.54;
printf("You are %s inches or %.2f centimetres tall.\n",
height_in_inches, height_in_cm);
return(0);
}

一行输入有多长?
user3629249 commented
可以通过以下方法节省大量堆栈空间:
注意“int”最多只有12个字符,因此输入缓冲区的最大长度为13个字符(允许使用NUL字符串终止字节)
scanf()限制为12个字符。即,' scanf( "%12s", myCharArray );
在C语言中,数组的名称会退化为数组的地址,因此不需要在“myCharArray”中前导“&”。
第3点是正确的;如果使用 char myCharArray[13];,则在调用 &myCharArray等时不使用 scanf();只使用 myCharArray。如果您误用了 &,一个好的编译器会指出您的方法的错误。
不过,我对第1点和第2点有意见。注意,如果用户在线上键入9876432109876543210,那么将 scanf()%12s一起使用对消除无效输入没有多大帮助,可以避免很多麻烦。它将在行上留下8个未读的数字,所读的内容仍将溢出32位整数。如果在较长字符串上使用 strtoX()函数系列而不是 atoi(),则它们会检测到溢出等问题,而 scanf()%d都不会检测到溢出。(这是主答案中隐藏的许多要点之一。)
此外,在具有兆字节(通常是千兆字节主内存)的系统上,堆栈上的4kib不是主要问题。也就是说,我使用4kib作为其冲击值的一部分;但是POSIX要求最小值为2048。
如果您正在读取基于行的输入,这通常是在命令行应用程序中进行输入的一种好方法,那么您需要确保读取整行,因为使用部分行进行模糊处理会造成混乱并使错误报告变得困难。 atoi()plus fgets()处理的一个主要优点是,您可以在错误报告中使用完整的行,而不是在处理部分行后剩下的行。如果第一次尝试失败,您还可以尝试以不同的方式扫描字符串;对于 sscanf()系列中的直接文件I/O函数,您不能这样做。
如果你天真地没有意识到人们在你想打短线的时候会打长线,那么你就可以把剩菜作为一条新的线——而不需要进一步的用户交互——当它真的是前一行输入的糟粕时。例如,如果您扫描20个数字中的12个,那么下一个输入将得到剩余的8个数字,而不需要等待用户键入任何新的内容,即使您提示他们输入更多的内容。(另外,请注意 using scanf();它最多是特定于系统的,它是否做了任何有用的事情。)
我用了4千磅的缓冲液。如果您想安全地防止程序在一行上发送兆字节的JSON编码数据,那么需要使用POSIX的 scanf()函数来读取该行。它为整行分配足够的空间,除非内存不足。对于大多数学生实践工作,4kib缓冲区和 fflush(stdin)是一个合理的替代品。我愿意协商2的幂,只要指数至少是8,这个值至少是256。例如,将行缓冲区限制为80个字符并不能阻止用户在一行中输入超过80个字符。这只是意味着额外的字符不太可能被适当地处理。将缓冲区限制为13个字符并不能为您带来任何价值,IMO,“节省堆栈空间”是一种过早的优化。

关于c - 用scanf替换简单方程式中的get会使程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30698570/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com