【问题标题】:Scanf preventing a C pragram from loopingScanf 防止 C 程序循环
【发布时间】:2021-11-30 16:21:22
【问题描述】:

我正在尝试编写一个程序,该程序将罗马数字作为输入,然后将它们转换为十进制值。用户必须首先声明他们要输入多少个罗马数字(一个或两个)。

我正在使用一个 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;
}

【问题讨论】:

  • 看起来您正在尝试将字符串读入单个字符...
  • 程序仍然无法运行。我之前尝试了很多东西,只有 %s 对我有用,所以我把它放进去。我尝试用 %c 替换它,但问题仍然存在。除非我将 scanf 的返回值分配给其他变量,否则它不会循环两次。

标签: c scanf


【解决方案1】:

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 中读取一行到字符缓冲区input 中,该缓冲区可以容纳20 个字符(其中一个必须是空终止字符)。

input[strcspn(input, "\n")] = '\0';

这将在输入字符串中找到第一个换行符并将其设置为'\0'。这有效地删除了换行符,而不是fgets 将包含在输入字符串中。

如果输入字符串超过 0 个字符,我们将评估第一个字符。如果它是一个罗马数字,我们返回它。功能完成!

如果它不是罗马数字,或者字符串长度为零字符,我们将打印错误消息,然后循环重新开始。

希望以这种方式获取您的意见,而没有问题的scanf 将帮助您解决更大的问题。

【讨论】:

  • 我会检查fgets的返回。此外,仅使用strlen 来检查第一个字符是很痛苦的,if (*input != '\n') 更短更快。最后,在fgets 中使用sizeof input 而不是19。
  • 或者,既然你已经计算了字符串的长度,那就做size_t len; ... input[(len=strcspn(input, "\n"))] = 0; .. if (len) { ... }
  • 公平积分。我追求的是直率而不是聪明。
  • 关闭 1. 20 即可。使用fgets(input, sizeof input, stdin);
  • 对于这个任务,input[strcspn(input, "\n")] = '\0';if (strlen(input) &gt; 0) 都可以删除。
【解决方案2】:

只是决定无缘无故停止工作。

下面的 "%s" attmeps 无法形成 字符串,而 numeral 对于搅拌 "" 来说只是大 enoguh。

    //char numeral = 'O';
    //scanf("%s", &numeral); // The problematic line.

    char numeral[100];
    if (scanf("%99s", &numeral) == 1) {
      // Success, continue and use `numeral`

converted_val = convert_numerals(numeral); 也需要更改,因为它只处理 1 个char

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-12
    • 1970-01-01
    • 2016-05-18
    • 1970-01-01
    • 2015-03-15
    • 2014-08-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多