【问题标题】:C program skipping printf and scanf statementsC 程序跳过 printf 和 scanf 语句
【发布时间】:2018-05-27 18:28:56
【问题描述】:

我下面的程序在 C 中执行凯撒密码。出于某种原因,在用户输入消息后,printf(" \nEnter key:")scanf("%d", &key) 语句被“跳过”。我的想法与输入缓冲区有关,输入缓冲区有一个字符和换行符,导致跳转(因此fflush 尝试)。如何防止这种行为?

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

int main() {
    char message[50], ms;
    int i, key, choice;

    printf("Enter 1. to Encrypt, or 2. to Decrypt: ");
    scanf(" %d", &choice);

    printf("Enter a message to process: ");
    scanf(" %c", message);
    printf(" \nEnter key:");
    fflush(stdin);
    scanf("%d", &key);

    for (i = 0; message[i] != '\0'; ++i) {
        ms = message[i];
        if (ms >= 'a' && ms <= 'z' && choice == 1) {
            ms = ms + key;
            if (ms >= 'a' && ms <= 'z' && choice == 2) {
                ms = ms - key;
                if (ms > 'z') {
                    ms = ms - 'z' + 'a' - 1;
                }
            }
            message[i] = ms;
        } else
        if (ms >= 'A' && ms <= 'Z' && choice == 1) {
            ms = ms + key;
            if (ms >= 'A' && ms <= 'Z' && choice == 2) {
                ms = ms - key;
            }
            if (ms > 'Z') {
                ms = ms - 'Z' + 'A' - 1;
            }
            message[i] = ms;
        }
        if (choice == 1) {
            printf(" \nEncrypted message: %s", message);}
        else if (choice == 2) {
            printf(" \nDecrypted message: %s", message);}
    }
}

【问题讨论】:

  • fflush(stdin) 永远不会正确。 fflush 用于输出,而不是输入。
  • 运行时,我得到这个输出:Enter 1. to Encrypt, or 2. to Decrypt: 1 Enter a message to process: hello Enter key:1 Encrypted message: i。看来我没有跳过,但可能还有其他问题。
  • 在评论2后面scanf(" %c", message);是不正确的。 message 是一个数组,衰减为指针,而不是 char。编译器警告过你吗?我没有,但直到你纠正输出是荒谬的。
  • scanf 不是一个很好的函数,因为它在执行转换失败时消耗输入的不可预测性。考虑使用 fgets 逐行读取输入,然后使用 sscanf,同时检查标准库函数的返回值。
  • gets 既危险又过时。请使用fgets。不要混用这些方法。在其输入中使用fgets,然后使用sscanf

标签: c encryption printf scanf fflush


【解决方案1】:

@ddisec 我在你的代码中注意到3 mistakes

首先你的scanf(" %c", message);。这里你必须使用%s (String)

第二个结果打印语句应该在for-loop之外。

第三次将if(ms &gt;= 'a' &amp;&amp; ms &lt;= 'z'&amp;&amp; choice == 2) 放入if (ms &gt;= 'a' &amp;&amp; ms &lt;= 'z' &amp;&amp; choice == 1) 没有任何意义。

试试这个更正的代码:-

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

int main()
{
    char message[50], ms;
    int i, key, choice;

    printf("Enter 1. to Encrypt, or 2. to Decrypt: ");
    scanf("%d", &choice);
    getchar();                                              // to handle unwanted newline.
    printf("Enter a message to process: ");
    scanf("%49[^\n]", message);
    printf(" \nEnter key:");
    scanf("%d", &key);

    for (i = 0; message[i] != '\0'; ++i)
    {
        ms = message[i];
        if (ms >= 'a' && ms <= 'z' && choice == 1)
        {
            ms = ms + key;
        }
        else if (ms >= 'a' && ms <= 'z' && choice == 2)
        {
            ms = ms - key;
        }
        else if (ms > 'z')
            {
                ms = ms - 'z' + 'a' - 1;
            }
        else if (ms >= 'A' && ms <= 'Z' && choice == 1)
        {
            ms = ms + key;
        }
        else if (ms >= 'A' && ms <= 'Z' && choice == 2)
        {
            ms = ms - key;
        }
        else if (ms > 'Z')
        {
            ms = ms - 'Z' + 'A' - 1;
        }

        message[i] = ms; // Only single modification code needed.
    }
    if (choice == 1)
    {
        printf(" \nEncrypted message: %s", message);
    }
    else if (choice == 2)
    {
        printf(" \nDecrypted message: %s", message);
    }
}

【讨论】:

  • 谢谢!我确实注意到我的 printf 最后在循环内。在选择 == 1 中包含选择 == 2 语句对我来说是一个愚蠢的错误。我还在学习很多东西!
  • 解密时还应该考虑ms &lt; 'a',我们是小写模式,或者ms &lt; 'A' 是大写模式,如果需要加26。 If (ms &gt; 'Z') ms-=26 对我来说更有意义。
【解决方案2】:

您的代码存在多个问题:

  • 您输入消息的方式不正确:scanf(" %c", message); 将单个字节读入message 第一个元素,甚至没有将其设为 C 字符串。改用它来阅读带有嵌入空格的消息:

    scanf("%49[^\n]", message);
    
  • 其余代码中存在逻辑错误:例如,您在仅在 choice == 1 时执行的块内测试 choice == 2...

这是一个简化版:

#include <stdio.h>

int main() {
    char message[50];
    int i, key, choice;

    printf("Enter 1. to Encrypt, or 2. to Decrypt: ");
    if (scanf("%d", &choice) != 1)
        return 1;

    printf("\nEnter a message to process: ");
    if (scanf("%49[^\n]", message) != 1)
        return 1;
    printf("\nEnter key:");
    if (scanf("%d", &key) != 1)
        return 1;

    for (i = 0; message[i] != '\0'; ++i) {
        int ms = message[i];
        if (ms >= 'a' && ms <= 'z') {
            if (choice == 1)
                ms = 'a' + ((ms - 'a') + key) % 26;
            if (choice == 2)
                ms = 'a' + ((ms - 'a') + 26 - key) % 26;
            message[i] = ms;
        } else
        if (ms >= 'A' && ms <= 'Z') {
            if (choice == 1)
                ms = 'A' + ((ms - 'A') + key) % 26;
            if (choice == 2)
                ms = 'A' + ((ms - 'A') + 26 - key) % 26;
            message[i] = ms;
        }
    }
    if (choice == 1)
        printf("\nEncrypted message: %s\n", message);
    if (choice == 2)
        printf("\nDecrypted message: %s\n", message);
    }
    return 0;
}

【讨论】:

  • 很好,这似乎要简单得多。但是,当我在 VS17 中构建/运行时,此代码似乎不起作用。
  • @ddisec:试试这个修改后的版本,将ms 定义为int。错误信息是什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多