【问题标题】:String input using C scanf_s使用 C scanf_s 的字符串输入
【发布时间】:2014-06-16 05:10:51
【问题描述】:

我一直在尝试自己寻找答案,但我找不到。 我想插入编程的一部分,它读取像“Hello”这样的字符串并存储并可以在需要时显示它,以便printf("%s", blah); 产生Hello

这是给我带来麻烦的代码部分

char name[64];
scanf_s("%s", name);
printf("Your name is %s", name);

我知道printf 不是问题;在提示后输入某些内容后程序崩溃。请帮忙?

【问题讨论】:

  • scanf 的“安全”版本要求您提供缓冲区的长度。
  • 只需使用scanf(),而不是这个scanf_s()。或者,更好的是fgets()
  • 你有相同的堆栈跟踪吗?如果是,请发布。
  • 如果使用scanf,您必须指定长度以避免缓冲区溢出:scanf("%63s", name);
  • 这对我有用:stackoverflow.com/a/17067317/830514,我使用的是 VS 2013,C 程序。

标签: c string scanf c11 tr24731


【解决方案1】:

来自 ISO/IEC 9899:2011 标准附件 K.3.5.3.2 中 fscanf_s() 的规范:

fscanf_s 函数等效于 fscanf,除了 cs[ 转换 说明符适用于一对参数(除非赋值抑制由 *)。这些参数中的第一个与fscanf 相同。这个论点是 在参数列表中紧随其后的是第二个参数,其类型为 rsize_t 并给出第一个参数指向的数组中的元素数 的一对。如果第一个参数指向一个标量对象,它被认为是一个数组 一个元素。

和:

scanf_s 函数等价于 fscanf_s,参数为 stdin 插入到scanf_s 的参数之前。

MSDN 说了类似的话(scanf_s()fscanf_s())。

您的代码没有提供长度参数,因此使用了其他数字。它不确定它找到什么值,所以你会从代码中得到古怪的行为。您需要更多类似的东西,换行有助于确保实际看到输出。

char name[64];
if (scanf_s("%s", name, sizeof(name)) == 1)
    printf("Your name is %s\n", name);

【讨论】:

  • 不应该将scanf_s 的第三个参数转换为(unsigned int),因为sizeof 返回一个size_t 类型的值?
  • @CoolGuy:如果你要转换它,它应该转换为rsize_t(参见答案中的引用),但是K.3.3 通用定义<stddef.h> 说(完整地):标题 定义了一个类型。类型是 rsize_t,即类型 size_t 并引用脚注 385,它说: 参见<stdint.h> 中对RSIZE_MAX 宏的描述。RSIZE_MAX 的讨论要广泛得多,但其目的是它通常应该小于SIZE_MAX,与@987654351 @ 是建议的大小。
【解决方案2】:

我在大学课程中经常使用它,所以它在 Visual Studio 中应该可以正常工作(在 VS2013 中测试):

char name[64]; // the null-terminated string to be read
scanf_s("%63s", name, 64);
// 63 = the max number of symbols EXCLUDING '\0'
// 64 = the size of the string; you can also use _countof(name) instead of that number
// calling scanf_s() that way will read up to 63 symbols (even if you write more) from the console and it will automatically set name[63] = '\0'
// if the number of the actually read symbols is < 63 then '\0' will be stored in the next free position in the string
// Please note that unlike gets(), scanf() stops reading when it reaches ' ' (interval, spacebar key) not just newline terminator (the enter key)
// Also consider calling "fflush(stdin);" before the (eventual) next scanf()

参考:https://msdn.microsoft.com/en-us/library/w40768et.aspx

【讨论】:

    【解决方案3】:
        #include<stdio.h>
    
        int main()
        {
          char name[64];
    
          printf("Enter your name: ");
          scanf("%s", name);
          printf("Your name is %s\n", name);
    
         return 0;
        }
    

    【讨论】:

    • 不是吗:scanf("%s", name); (没有'&')?
    • '&' 在这里不是必需的。数组名本身会给出数组的地址。
    • &amp;name 上的 &amp; 没有害处,但不是必需的。把它关掉,因为你了解数组和指针之间的关系。如果您了解这种关系,请阅读它,然后将多余的&amp; 关闭。
    • Hmmm ... 指针转换可能有误。在这种情况下,假设编译器以不同于其他指针的方式存储指向数组的指针,可能会表现出不同的行为。
    • @dmckee:符号&amp;name 在问题的上下文中生成char (*)[64] (char name[64];)。 %s 格式需要 char *,而简单地引用 name 会产生 char *。如您所见,这两种类型完全不同。不幸的是,&amp;name 的值被视为void *name 的值被视为void * 相同。这允许scanf("%63s", &amp;name) '工作',但不会阻止它不正确。
    【解决方案4】:
    #include<stdio.h>
    
    int main()
    {
      char name[64];
      printf("Enter your name: ");
      gets(name);
      printf("Your name is %s\n", name);
     return 0;
    }
    

    【讨论】:

    • 欢迎来到 Stack Overflow!虽然此代码可能会回答问题,但提供有关 如何 和/或 为什么 解决问题的附加 context 将提高答案的长期价值。提及为什么这个答案比其他答案更合适也没有什么坏处。
    • 啊,是的。没有上下文且不回答问题的代码 sn-p。太棒了。
    【解决方案5】:

    你应该这样做:scanf ("%63s", name);

    更新

    以下代码对我有用:

    #include <stdio.h> 
    int main(void) { 
        char name[64]; 
        scanf ("%63s", name); 
        printf("Your name is %s", name); 
        return 0; 
    }
    

    如果您使用的是视觉工作室, 转到Project properties -&gt; Configuration Properties -&gt; C/C++-&gt; Preprocessor -&gt; Preprocessor Definitions 点击edit 并添加_CRT_SECURE_NO_WARNINGS 点击确定,应用设置并再次运行。

    注意:这仅在您正在做作业或类似的事情时才有用,并且不建议用于生产。

    【讨论】:

    • 还是不行,它不再崩溃了,但是printf不会显示结果。
    • 我试过了,它成功了,#include int main(void) { char name[64]; scanf ("%63s", 名称); printf("你的名字是 %s", name);返回0; }
    • 我正在使用 Visual Studio,它不会让我使用 scanf,只能使用 scanf_s,但即使使用缓冲区,它也不起作用,只是在之后跳过 printf 中的 %s。
    • 你开始了一个visual c++项目?
    • 转到项目属性->配置属性->C/C++->预处理器->预处理器定义点击编辑并添加_CRT_SECURE_NO_WARNINGS点击确定,应用设置并运行项目
    猜你喜欢
    • 2017-05-03
    • 2012-10-05
    • 1970-01-01
    • 2021-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多