【问题标题】:School programming class problems (Visual Studio)学校编程课题(Visual Studio)
【发布时间】:2019-02-11 23:15:32
【问题描述】:

我刚开始学习编程,在学校老师使用的是 Macbook 和一个名为“X-Code”的程序,而在家里我有 Visual Studio (2017) 的 windows。 教员对“setbuf”是什么给出了0解释,还说我们必须在Visual Studio中使用scanf有点不同。现在我在家,完全无助。其实VS说不如试试scanf_s,所以我就做了,程序一直运行,直到我可以输入“操作”。在我输入前两个参数后,它会停止,并且窗口会自行关闭。有没有人能帮帮我,对我不明白的事情给我一点解释?

提前致谢。 这是我写的代码

void main() {

    int a, b, c;
    char m;

    printf("Erstes Argument: ");
    scanf_s("%d", &a);

    printf("Zweites Argument: ");
    scanf_s("%d", &b);

    printf("Operation: "),
    //setvbuf(stdin,NULL); 
    scanf_s("%c", &m);

    if (m == '*') {
        c = a * b;
        printf("%d * %d = %d \n", a, b, c);
    }
    else {
        printf("Falsche Operation! \n");
    }

    return 0;
}

【问题讨论】:

  • 其实 VS 说不如试试 scanf_s 是的,Visual Studio 提倡不可移植的、Microsoft 特定的语言扩展,带有关于所需功能的误导性消息由于 C 标准 被“弃用”。请参阅open-std.org/jtc1/sc22/wg14/www/docs/n1967.htm:“由于与规范存在大量偏差,因此不能将 Microsoft 实现视为符合或可移植的。”另见stackoverflow.com/questions/119578/…
  • 您可以阅读有关 MSVC 2017 库函数 setbuf here 的信息。将此页面添加为书签,以供将来参考。
  • 您的老师可能与我的观点不同:MS 想要统治世界,并警告它认为您不应该使用的标准功能。请坚持使用 C 标准函数。在任何 #include 指令之前,我将以下 3 行放在 MSVC 代码中:#define _CRT_SECURE_NO_WARNINGS#define _CRT_SECURE_NO_DEPRECATE#define _CRT_NONSTDC_NO_DEPRECATE。可悲的是,他们的一些所谓的“更安全”版本根本不安全,或者有使用标准功能的安全方法。特别是他们的scanf_s 系列比标准函数更难使用。
  • 例如,你错误地使用了scanf_s("%c", &m);,因为它需要一个长度参数:"不像scanfwscanfscanf_swscanf_s需要缓冲区大小为cCsS 或包含在[] 中的字符串控制集类型的所有输入参数指定。以字符为单位的缓冲区大小作为紧随其后的附加参数传递指向缓冲区或变量的指针。”
  • 最好在您的家用计算机上安装 x-code,而忘记使用 MS 进行 C 编程。这是一般建议。

标签: c windows macos visual-studio-2017 scanf


【解决方案1】:

如果您想使用所有 MS 细微差别和不可移植的库调用,您可以这样做,但要明白,它最终会教您使用语言标准中未记录的函数进行编码。

为此,还要了解 C“语言”有两个主要组成部分:实际语言本身(是什么使它成为 C 代码),以及一个强制性随附的标准函数库(其中一些你很熟悉,@ 987654322@、scanf 等)。可以学习第一部分语言,并了解它是如何独立于随附的标准库工作的。最后,后者(库)为您提供了大量可以利用的操作,如果您严格保持在标准定义的范围内,您的代码将更加健壮、可移植和任何熟悉 say-same 的 C 工程师都可以理解。

无论如何,使用 Microsoft 选择强加给用户实施的库扩展使您的程序“工作”的最小更改是:

#include <stdio.h>

// FIXED return type
int main() {

    int a, b, c;
    char m;

    printf("Erstes Argument: ");
    scanf_s("%d", &a);

    printf("Zweites Argument: ");
    scanf_s("%d", &b);

    printf("Operation: ");

    // FIXED arguments passed to setvbuf
    setvbuf(stdin, NULL, _IONBF, 0);

    // FIXED arguments passed to scanf_s
    // FIXED added white space consumption prior to character read
    scanf_s(" %c", &m, 1);

    if (m == '*') 
    {
        c = a * b;
        printf("%d * %d = %d \n", a, b, c);
    }
    else 
    {
        printf("Falsche Operation! \n");
    }

    return 0;
}

不依赖于 MS-isms 的适当的、符合标准的版本可能是:

#include <stdio.h>

int main() {

    int a, b, c;
    char m;

    printf("Erstes Argument: ");
    scanf("%d", &a);

    printf("Zweites Argument: ");
    scanf("%d", &b);

    printf("Operation: ");
    scanf(" %c", &m);

    if (m == '*') 
    {
        c = a * b;
        printf("%d * %d = %d \n", a, b, c);
    }
    else 
    {
        printf("Falsche Operation! \n");
    }

    return 0;
}

如果没有功能禁用宏 _CRT_SECURE_NO_WARNINGS,您将收到来自 MS 的大量三个警告,说明您应该使用它们的“更安全”功能。尽管他们勇敢地尝试让我们的程序更安全,但人们很容易争论如果工程师们只是学会了如何正确地编写更安全的代码会更好。

最后,您的代码还没有完成。您应该检查您的 IO 调用是否成功。现在,您假设用户为ab 提供的任何输入都是正确解析的有效整数。如果不是这种情况,您的代码会继续前进,最终使用不确定的数据进行计算,并在该过程中调用未定义的行为。 scanf 有一个记录在案的返回码是有原因的。使用它。

【讨论】:

  • 与包含空格的" %c" 很好地接触,这将消耗任何前导空格,OP 可能不知道大多数格式说明符会自动完成此操作,但"%c" 不会自动完成。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-03
  • 1970-01-01
  • 2022-08-20
  • 1970-01-01
  • 1970-01-01
  • 2020-12-20
  • 2011-02-19
相关资源
最近更新 更多