c - Scanf 防止 C 程序循环
问题描述
我正在尝试编写一个程序,将罗马数字作为输入,然后将它们转换为十进制值。用户必须首先声明他们要输入多少个罗马数字(一个或两个)。
我正在使用一个 for 循环,它重复罗马数字的次数。如果只有一个数字,它不应该循环,或者如果有两个,它应该循环两次,因为我们需要一次将一个字母作为输入。
我遇到的问题是 for 循环内的 scanf 语句不断阻止程序循环。一旦我删除了 scanf 并静态分配了值,它就可以正常工作了。然后,在尝试解决该问题时,我尝试通过将其分配给一个新变量来打印出 scanf 正在返回的值,例如char snf = scanf("%s", &numeral);
,由于某种原因,它开始工作,正是我希望它工作的原因。我完全不知道它为什么现在工作以及为什么它阻止循环之前循环。谁能向我解释发生了什么事?
// A program to convert Roman Numerals to Decimals system.
#include <stdio.h>
int convert_numerals(char numeral){
switch(numeral){
case 'I':
return 1;
case 'V':
return 5;
case 'X':
return 10;
case 'L':
return 50;
case 'C':
return 100;
case 'D':
return 500;
case 'M':
return 1000;
default :
printf("\nError! You did not enter a valid numeral\n");
return 0;}}
int main(){
int Decimal_Val = 0; //Initializing the variable with 0 to avoid issues at check.
int Numeral_Count;
printf("How many characters does your Roman numerals have? 1 or 2\n");
scanf("%d",&Numeral_Count);
for (int i = 1; i < 1+Numeral_Count; ++i)
{
char numeral = 'O';
int converted_val;
printf("\n\nEnter numeral %d : ",i);
scanf("%s", &numeral); // The problematic line.
converted_val = convert_numerals(numeral);
if (Decimal_Val != 0)
{
if (Decimal_Val < converted_val)
{
Decimal_Val = converted_val - Decimal_Val;
}else{
Decimal_Val += converted_val;
}
}else{
Decimal_Val = converted_val;
}
}
printf("\nThe Roman numerals you entered are equal to %d in Decimals\n", Decimal_Val);
return 0;
}
解决方案
Scanf 可能是一个有问题的函数,尤其是对于字符。相反,尝试使用fgets
来读取一行,然后使用第一个字符。如果我们把它分解成一个单独的函数。(分解问题对于解决任何编程语言中的复杂问题都至关重要。)
char get_roman_numeral(const char *prompt, const char * error_msg) {
while (1) {
printf("%s: ", prompt);
char input[20] = {};
fgets(input, 19, stdin);
input[strcspn(input, "\n")] = '\0';
if (strlen(input) > 0) {
switch (input[0]) {
case 'i': case 'I':
case 'v': case 'V':
case 'x': case 'X':
case 'l': case 'L':
case 'c': case 'C':
case 'd': case 'D':
case 'm': case 'M':
return input[0];
default:
printf("%s\n", error_msg);
}
}
else {
printf("%s\n", error_msg);
}
}
}
把它分开,我们无限循环。每次我们打印我们提供的提示时,然后从stdin
char 缓冲区input
中读取一行,该缓冲区可以容纳 20 个字符(其中一个必须是空终止字符)。
input[strcspn(input, "\n")] = '\0';
这将在输入字符串中找到第一个换行符并将其设置为'\0'
. fgets
这有效地删除了输入字符串中包含的换行符。
如果输入字符串长于 0 个字符,我们将评估第一个字符。如果它是一个罗马数字,我们返回它。功能完成!
如果它不是罗马数字,或者字符串长度为零字符,我们将打印错误消息,然后循环重新开始。
希望以这种方式获取您的输入,没有问题scanf
将帮助您解决更大的问题。
推荐阅读
- office-interop - 有没有办法在 c# 中使用带有版本独立的 interop excel 生成 excel 报告?
- python - 如何继续处理车牌裁剪?
- html - Xpath 组合标签或节点
- javascript - 如何在 axios Reactjs 中发送查询参数
- python - 将数据写入 CSV 文件,而不在数据集之间添加空行
- android - 从文件管理器或其他应用程序将用户带到我的活动
- spring - 无法使用带有注释的 Spring 在 OpenApi 中将标头设置为可选
- angular - 将 @angular/material 与 Angular 9 一起使用会引发错误
- python - 对象可下标
- python-3.x - 使用 Python 图像库 (PIL) 保存 gif 图像时动画 GIF 图像像素化