• 文件操作方法fscanf


    直入主题,首先把经典方法放在前面:

    如下情况大量有规律的数据存储在文件中格式化的读取方法:

    Almond #EED9C4

    Antique Brass #C88A65

    Apricot #FDD5B1

    Aquamarine #71D9E2

    Asparagus #7BA05B

    .............................

    先上代码:

     1         FILE *fp;          //定义文件指针
    2 char a[20]={0}; //定义两个数组来接受数据 3 char b[20]={0}; 4 5 fp=fopen("/Users/My/file","r"); //打开文件 6 if(fp==NULL) 7 { 8 printf("open the file is error! "); 9 exit(0); 10 } 11 fseek(fp,0,SEEK_SET); //获取文件内部指针 12 13 15 while(2==fscanf(fp,"%[^#]%s ",a,b)) //使用fscanf函数格式化读取文件里的数据,使用#号作为分隔符 16 { 17 printf("a=%s-------- b=%s ",a,b); 18 // printf("sizea=%ld ",sizeof(a)); 19 // NSLog(@"astring=%@",[NSString stringWithFormat:@"%s",a]); 20 } 21 22 fclose(fp); //关闭文件


    读取结果:

    a=Shadow,   b=#837050

    a=Shamrock,   b=#33CC99

    a=Shocking,Pink,   b=#FF6FFF

    a=Silver    b=#C9C0BB

    a=Sky Blue    b=#76D7EA

    a=Spring Green    b=#ECEBBD

    a=Sunglow    b=#FFCC33

    a=Sunset Orange    b=#FE4C4

    解释:

    这里使用的C语言提供的一种格式化读取方法,非常像 正则表达式 的读取方式,"%[^#]%s "这里的含义就是以#为分隔符读取数据,把数据分为两部分, 表示读到换行符为止.使用while循环可以读取一个完整的文件直到结束.

    所以在最后用a,b可以分别接收到#号前后的数据并存入其中,每次只读取一行.

    特别注意:

    如果把上边的   %[^#]%s  替换为"%[^#]#%s "得到的结果如下:

    a=Shadow,   b=837050

    a=Shamrock,   b=33CC99

    a=Shocking,Pink,   b=FF6FFF

    a=Silver    b=C9C0BB

    a=Sky Blue    b=76D7EA

    a=Spring Green    b=ECEBBD

    a=Sunglow    b=FFCC33

    a=Sunset Orange    b=FE4C40

     再如果替换为 %[^#] %[#^] 结果会发生如下错误:

    a=Shadow,   b=#

    a=837050

    Shamrock,   b=#

    a=33CC99

    Shocking,Pink,   b=#

    替换为"%[^#]%[#83^] "结果如下:

    a=Shadow,   b=#83

    a=050

    Shamrock,   b=#33

    a=C99

    Shocking,Pink,   b=#

    a=F6FFF

    Silver    b=#

    a=9C0BB

    Sky Blue    b=#

    a=6D7EA

    Spring Green    b=#

    (上边这个有点不懂,不仅只按尽可能匹配的截取方式截取,而且文件指针的位置还跳过一个

      b=#83

    a=050

    ) 原来是#837050,但是他的结果把7给跳过了,Why???????????????????????????????????????????????

    再次替换为 "%[^#]%[^] " 或者%[^#]%[^ ]结果如下:

    a=Shadow,   b=#837050

    a=

    Shamrock,   b=#33CC99

    a=

    Shocking,Pink,   b=#FF6FFF

    a=

    Silver    b=#C9C0BB

    a=

    Sky Blue    b=#76D7EA

    a=

    Spring Green    b=#ECEBBD

    a=

    Sunglow    b=#FFCC33

    我们发现此时从第二次开始,每次先读取了一个换行符 ,此时可以认为从第一次读取介绍后,文件内部指针每次都以 为介绍标识,停留在了 上,所以每次第一个读取的先是换行符 ,所以造成了上述结果.(只是猜测没有具体测试,这几种变化我也不太懂).

    后来补充:上面的猜测现在已经证实是正确的了,当把while改为如下:

     while(2==fscanf(fp,"%[^#]%[^] ",a,b))

            {

                fseek(fp, ftell(fp)+1, SEEK_SET);

                printf("a=%s   b=%s ",a,b);

             }

    发现结果如下:

    a=Shadow,   b=#837050

    a=Shamrock,   b=#33CC99

    a=Shocking,Pink,   b=#FF6FFF

    a=Silver    b=#C9C0BB

    a=Sky Blue    b=#76D7EA

     总结:  "%[^#]%s 和"%[^#]%[^] 或者%[^#]%[^ ]的区别:

    前者%s 是读取到 的下一个位置,后者%[^] 或者%[^#]%[^ ]是读取到 止.

     %[^#]%s ,  %[^#]#%s ,   %[^#] %[#XXX^] 的区别:

    %[^#]%s :以#号为分割符,前一个读取到#号为止(不包含#号),后一个字符读完到 的下一个指针位置.

    %[^#]#%s :  %[^#]是读取到#的前一个位置为止(不包含#), #%s 从#的后一个位置开始读取(不包括#),读取到 的下一个位置

    %[^#] %[#XXX^] :  %[#XXX^]尽最大可能的匹配#XXX读取(包含#),最大匹配后读取结束.如" %[#1232^] 遇到 #1525 读出结果为:#1

    对上面不太理解??没关系再来个类似的例子,我也加深下学习!

    文件中有如下数据:

    4,5,41,w,20.585828
    4,6,51,r,52.012547

    ........................

            FILE *fp;
            int fd;
            long dev;
            long offset;
            long length;
            char ch;
            double ts=0.000000;
            fp=fopen("/Users/My/file.save","r");
           if(fp==NULL)
            {
                printf("open the file is error!
    ");
                exit(0);
            }
            lseek(fd,0,SEEK_SET);
            
            //具体解释:fscanf(fp,"%ld,%ld,%ld,%c,%lf
    ",&dev,&offset,&length,&ch,&ts)
    // 亲,这里的 %ld,%ld,%ld,%c,%lf 可不是像下面printf里字符串含义. 这里的逗号(',')代表的是以逗号(',')为分 // 隔符(或称为分割单位),以此作为分割数据的依据,因此逗号必不可少,换行符 则是解析完一行数据的依据.
    // 所以说上面的逗号','和' '都是必不可少的,否则会造成程序错误,读取失败(多多理解)
             while(5==fscanf(fp,"%ld,%ld,%ld,%c,%lf
    ",&dev,&offset,&length,&ch,&ts)) 
    {
    // 这里的逗号','和' '是来规范输出后的格式,可以省略,但是fscanf中得绝对不可以省略.
    printf("%ld,%ld,%ld,%c,%lf ",dev,offset,length,ch,ts);
    }
    fclose(fp);

     再举一例: 这个例子很好的说明了fscanf是如何格式化读取文件的

        long l;

        float fp;

        char s[81];

        char c;

        stream=fopen("/Users/lanou3g/fscanf.out","w+");

        if(stream==NULL)

            printf("Thefilefscanf.outwasnotopened ");

        else

        {

            fprintf(stream,"%s,%d,%f,%c","a-string",

                    65000,3.14159,'x');       // 这个是格式化写入文件,和fscanf是相反的操作,字符串的具体意义和fscanf相似,他们俩配合的相当完美

            /*Setpointertobeginningoffile:*/

            fseek(stream,0L,SEEK_SET);

            /*Readdatabackfromfile:*/

            fscanf(stream,"%[^,]",s);   // 注意这里字符串的格式化读取时的格式是%[^,] 说明读取的是字符串且用逗号分割,这个和第一个例子中 %[^#]%s 的用法很相似, %[^#]%s 的意思是读取#号分割的前后字符串,第一个字符串必须是格式化的%[^#]以便和后边的字符串做区分,第二个由于后面读到行尾所以可以直接写%s [特别注意的时%s#%s 的写法和    %[^#]%[^]的写法是错误的,具体原因我也还不太清楚].

            fscanf(stream,",%ld",&l);  //下面几个数据都是用",格式符"作为格式化输出标准, "%ld,"这种逗号放后面的写法是错误的. 

            fscanf(stream,",%f",&fp);

            fscanf(stream,",%c",&c);

            /*Outputdataread:*/

            printf("%s ",s);

            printf("%ld ",l);

            printf("%f ",fp);

            printf("%c ",c);

            fclose(stream);

        }

    如果把上面的例子中   fscanf(stream,"%[^,]",s);改为fscanf(stream,"%s,",s);读取结果发生错误如下:

    a-string,65000,3.141590,x

    0

    0.000000

     

  • 相关阅读:
    user-agent
    java8中的stream().filter()的使用和Optional()
    hibernate中复合主键的使用
    HikariCP和spring-boot-devtools了解
    springboot与springcloud的版本问题
    libSVM简介及核函数模型选择
    支持向量机:Numerical Optimization,SMO算法
    SVM计算过程,对偶形式,核函数
    SVM入门——线性分类器的求解,核函数
    【转】SVM入门(一)SVM的八股简介
  • 原文地址:https://www.cnblogs.com/lovelifeloveme/p/3903089.html
Copyright © 2020-2023  润新知