• fscanf_s与scanf_s的宽度参数与缓冲区参数分析


    fscanf_s函数 

    在文件操作中经常会用到fscanf这个函数,但是在VC和VS中会有警告

    意思是编译器觉得fscanf不安全,叫你考虑用一下fscanf_s这个函数来代替fscanf,fscanf_s比fscanf多使用了一个参数

    fscanf函数原型:

    int fscanf( FILE *stream, const char *format [, argument ]...

    fscanf_s函数原型:

    int fscanf_s( FILE *stream, const char *format [, argument ]...

    fscanf_s的第四个参数是最多读取的字符数(注意:这个最多读取的字符数的大小是包括的末尾的('')NULL的),下面我们来简单测试一下第四个参数,先上代码:

    FILE *fp;
    char ss[10];
    
    fp = fopen("E:\ww.txt", "r+");
    fscanf_s(fp , "%s", ss, 10);
    
    printf("%s", ss);

     ww.txt文件中的内容为

    运行结果为:

    第四个参数10指的是最多读取的字符数,是包含了字符串末尾的''的,所以实际上最多可以读取的字符只有10-1=9个字符,如果读取的字符串长度大于9,那么fscanf_s不会向ss数组中读入任何内容,只

    将数组第一个元素赋值为'',下面来测试一下

    将ww.txt中的内容改为

    运行结果:

    可以使用断点调试来观察数组ss的的值

    还有一点必须要注意,第四个参数是无符号类型的

    意思是:0 <= 第四个参数 <= 数组的长度,意思是下面这种写法是不允许的

    char ss[10];
    fscanf_s(fp , "%s", ss, 11);

    编译阶段不会报错,但是无法运行(无论读取内容的是否大于缓冲区大小

    在微软的官方手册中有这样一段话

    当输入的数据太大时,除非指定了宽度的大小否则不会向缓冲区写入任何数据

    意思是有一种方法可以让fscanf_s在读取超过最多读取的字符数的内容时,仍然只读取指定了宽度大小的数据,方法如下

    fscanf_s(fp , "%5s", ss, 10);

    与上面不同的是,我们在格式控制符%s这个加了一个宽度控制,意思是最多读取5个字符

    此时ww.txt的内容为明显文本文件的字符数大于了10,但是由于我们加了宽度控制,fscanf_s仍然会读取5个字符到ss数组中

    运行效果:

    scanf_s函数

     scanf_s的第四个参数也是最多读取的字符数,这和fscanf_s完全一样这里就不再赘述了,读者可以看一微软官方文档中对buffer size的描述

    重点:一、buffer size包括了末尾的NULL          

       二、buffer size参数描述的允许读取的最大的字符数,而不是字节数

    因为是最大的字符数,建议在使用这个参数的时候使用_countof这个宏,而不是sizeof,在对char类型的数组限制最大字符数时sizeof和_countof都可以,但是在对宽字符wchar_t类型的数组使用时就不能使用sizeof了,

    应该用_countof,最好在前面加上(unsigned)强制转换为无符号数

     

    _countof

    _countof是定义在stdlib.h中的一个宏

    _countof作用是计算静态数组中的元素个数,常见的使用方法如下

    1 char ss[10];
    2 scanf_s("%s", ss, (unsigned)_countof(ss));

    如果对指针使用_countof,则会产生错误的结果,因为数组在作为参数传递时会退化为指针,这意味着在函数内部不能直接使用_countof来得到数组中元素的个数

    补充:对于fscanf_s中第四个参数以及宽度控制参数的测试

    1、无宽度控制,有缓冲区控制

    1 char ss[10];
    2 fscanf_s(fp, "%s", ss, (unsigned)_countof(ss));

    2、有宽度控制,有缓冲区控制

    宽度控制大小 < 缓冲区大小

    char ss[10];
    fscanf_s(fp, "%5s", ss, (unsigned)_countof(ss));

    宽度控制大小 = 缓冲区大小

    char ss[10];
    fscanf_s(fp, "%10s", ss, (unsigned)_countof(ss));

    宽度控制大小 > 缓冲区大小

    char ss[10];
    fscanf_s(fp, "%12s", ss, (unsigned)_countof(ss));

    测试结果:

  • 相关阅读:
    NYOJ 625 笨蛋的难题(二)
    NYOJ 102 次方求模
    ZJU Least Common Multiple
    ZJUOJ 1073 Round and Round We Go
    NYOJ 709 异形卵
    HDU 1279 验证角谷猜想
    BNUOJ 1015 信息战(一)——加密程序
    HDU 1202 The calculation of GPA
    "蓝桥杯“基础练习:字母图形
    "蓝桥杯“基础练习:数列特征
  • 原文地址:https://www.cnblogs.com/lanhaicode/p/10742790.html
Copyright © 2020-2023  润新知