博客首页 注册 建议与交流 排行榜 加入友情链接
推荐 投诉 搜索: 帮助

F.U.Moon

For Unix,For Freedom... APUE-UNIX group: 51856822
  FUMoon.cublog.cn

关于作者
姓名:祖元
职业:学生
年龄:21
位置:江西
个性介绍:爱好UNIX,嵌入式
|| << >> ||
我的分类


一个非常有趣的问题--格式化输入
先来看一个简单的问题,声明如下两个字符数组:
         char a[20],b[20];
现在,用户输入两个字符串,分别赋值给 a 和 b ,格式为 "string1,string2"(不包括引号,两个字符串用不逗号分隔,string1 赋给 a, string2 赋给 b,string1 和 string2 当中可能有空格) ;用一个scanf函数来实现.
  
 
   是不是scanf("%s,%s",a,b);就OK了呢?```
 
 
   其实,一开始,我们的想法可能是简单的scanf("%s,%s",a,b);不然,scanf在扫描用户输入串的时候,只有碰到特定的分隔符(比如:TAB键,空格键,回车键...)才会认为一个串输入完毕,当然,这里也没有进行边界检查,如果我们输入了多于19个字符,就会产生溢出,也就是所谓的缓冲区溢出,要注意的是,这里不能输入20个字符,因为最后一个字符a[19]编译器会置为'\0'.
   因此我们用到格式:[]及*
(1).[]表示字符匹配,比如:
char str[20];
scanf(“%[1-9]”,str);/* [1-9] equal [123456789] */
当用户输入123456aaa456时,str=123456;当用户输入数据时,scanf会逐个检查缓冲区中的字符,一旦遇到不是1-9这几个字符时,就会立即跳出.
   
scanf(“%[^a]”,str);
当用户输入123 bc ,;dda时,str=123 bc ,;dd;脱字符[^a]表示一直扫描直到遇到字符a为止.
 
(2)*表示忽略字符,比如:
         char str[20];
         scanf(“%*3c%s”,str);/* ignore the first three char */
当用户输入abcdefg123时,str=defg123;
 
scanf(“%*[1-9]%s”,str);/* ignore the numbers1-9 in the head of the user’s input */
当用户输入12341231232142142132134abcdefg123时,str= abcdefg123;注意后面的123未被ignore.
 
好了,有了前面两点知道,要解决上面那个问题就很简单了,
char a[20],b[20];
scanf("%19[^,]%*[^,],%19s",a,b);/* install the first <=19 chars into array a,and ignore the rest chars before ‘,’ if the numbers of chars >19,then take the control char ‘,’  */
现在无论你怎么输入字符串,都不会有问题了,不会产生溢出,字符串的空格也能被接受.
比如用户输入:aa fd dd feij 343 3242 2342342 3232,1233333io324klja  dsfas dfsasdf
则a=aa fd dd feij 343 3;
   b=1233333io324klja  d;
 
那下面再来看一个问题:
在C盘底下有一个bankc.TXT文件,其内容为:
1000000041,"Rluii",10,3,13100000412,¥15570.00
 
1000000881,"Ooujw",6,8,13100008813,¥19265.00
1000018521,"Skrpb",2,8,13100185214,¥32907.00
1000388961,"Rbamc",9,4,13103889611,¥29199.00
1008168201,"Jxwfq",8,4,13181682013,¥18581.00
 
要求编写一个程序,将文件中的记录(每行一个记录)读出到一个结构体中,记录中第一,二,五个元素为字符串型且长度固定,第一个为10个符,第二个为5个字符第五个为11个字符,第三,四个元素为整形,第六个元素为double型,要注意的问题是,第二个元素要去除双引号,第五个元素要去除¥符号(UNICODE字符).
 
 

#include "stdio.h"
#define N 5
main()
{
     struct INFO
     {
        char id[11];/* id is fixed,the length is 10 add the NULL */
        char name[6];/* name is fixed,the length is 5 add the NULL */
        int con;
        int cx;
        char tel[12];/* tel is fixed,the length is 11 add the NULL */
        double money;
     }stu[N]={'\0','\0',0,0,'\0',0.0};/* this initialization is very importment */

     FILE *fp;
     int i;

     if((fp=fopen("c:\\bankc.txt","r")) == NULL)/* if in linux,take care of the path */
    {
        printf("Can't open destination file!\n");
        return 0;
    }
    for(i=0;i<N && !feof(fp);i++)
    {
        fscanf(fp,"%[^,]%*2c%[^\"]%*2c%d,%d,%[^,]%*3c%lf%*[\n]",stu[i].id,stu[i].name,&stu[i].con,&stu[i].cx,stu[i].tel,&stu[i].money);
        printf("%s,%s,%d,%d,%s,%.2lf\n",stu[i].id,stu[i].name,stu[i].con,stu[i].cx,stu[i].tel,stu[i].money);
    }
    fclose(fp);
                return 0;
}

fscanf函数也可以写成:

 

fscanf(fp,"%[^,],\"%[^\"]\",%d,%d,%[^,],¥%lf%*[\n]",stu[i].id,stu[i].name,&stu[i].con,&stu[i].cx,stu[i].tel,&stu[i].money);

 

这里要注意的是对于double型数据的输入,必须用%lf,而输出的时候我们可以用%f!

 TAG C scanf fscanf
发表于: 2008-05-27,修改于: 2008-05-27 21:00,已浏览129次,有评论1条 推荐 投诉


网友评论
网友: busycai 时间:2008-06-17 15:06:27 IP地址:202.114.10.★
非常不错。

 发表评论