P304
练习12-1
文件缓冲区:内存中用于数据存储的数据块,在文件处理过程中,程序需要访问该缓冲区实现数据的存取。
在C程序中,文件类型指针主要的功能是:指向文件的缓冲区,通过移动指针实现对文件的操作。
P306
练习12-2
#include<stdio.h> //练习12-2
#include<stdlib.h>
main()
{
int i,offset;
char pw[80];
FILE *fp;
if((fp=fopen("凯撒密码.txt","w"))==NULL){
printf("文件打开失败!");
exit(0);
}
printf("输入一个正整数offset:");
scanf("%d",&offset);
getchar();//接受空格
printf("请输入一个字符串:");
gets(pw);
for(i=0;pw[i]!='\0';i++)//循环取出
{
if(pw[i]>='A'&&pw[i]<='Z'){//经检验,程序没有问题,可能是编译器的问题,字母B和b无法输出。(即输入Z 应输出B,无法正常显示)。
if((pw[i]+offset)<'Z'){//未超过最大的字母
pw[i]+=offset;
}else pw[i]=pw[i]-('Z'-offset);//越界,倒着减
}else if(pw[i]>='a'&&pw[i]<='z'){
if((pw[i]+offset)<'z'){
pw[i]=pw[i]+offset;
}else pw[i]=pw[i]-('z'-offset);
}else pw[i]=pw[i];
}
fprintf(fp,"%s",pw);
fclose(fp);
}
P311
第一问:判断文件是否结束,EOF是文件结束符。
#include<stdio.h>//练习12-3
#include<stdlib.h>
int main(void)
{
FILE *fp1,*fp2;
int count=0;
char ch,ch1;
if((fp1=fopen("f12-2.txt","r"))==NULL){
printf("文件f12-2打开失败!");
exit(0);
}
if((fp2=fopen("f12-3.txt","w"))==NULL){
printf("文件f12-3打开失败!");
exit(0);
}
while(!feof(fp1)){
ch=fgetc(fp1);
if(ch!=EOF){
fputc(ch,fp2);
}
}
fclose(fp1);
fclose(fp2);
if((fp2=fopen("f12-3.txt","r"))==NULL){
printf("文件f12-3打开失败!");
exit(0);
}
while(!feof(fp2)){
ch1=fgetc(fp2);
if(ch1!=EOF){
if(ch1!=' ')//包括了回车,有5个
count++;
}
}
printf("f12-3中的字符数量为:%d",count);
fclose(fp2);
return 0;
}
P317
练习12-4到12-6
#include<stdio.h>//练习12-4
#include<stdlib.h>
int main(void)
{
FILE *fp;
char ch;
int count=1;
if((fp=fopen("letter.txt","r"))==NULL){
printf("文件打开失败!");
exit(0);
}
while(!feof(fp)){
ch=fgetc(fp);
if(ch!=EOF){
if(ch>='A'&&ch<='Z'){
ch=ch+32;
}
if(ch=='\n') count++;
}
printf("%c",ch);
}
printf("\n共%d行",count);
return 0;
}
#include<stdio.h>//练习12-5
#include<stdlib.h>
int main(void)
{
FILE *fp;
char ch,ch1;
if((fp=fopen("f3.txt","w+"))==NULL){
printf("文件打开失败!");
exit(0);
}
printf("请输入一行字符:");
while((ch=getchar())!='\n'){
fprintf(fp,"%c",ch);
}
rewind(fp);
while(!feof(fp)){
ch=fgetc(fp); //用fscanf会将最后一个字符重复输出两遍
if(ch!=EOF) printf("%c",ch);
}
fclose(fp);
return 0;
}
#include<stdio.h>//练习12-6 实数取整写入文件
#include<stdlib.h>
void splitfloat(double x,int *intpart,double *fracpart)
{
*intpart=(int)x;//强制转换为整型
*fracpart=x-*intpart;//直接减去整数部分可得小数部分
}
int main(void)
{
FILE *fp1,*fp2;
int intpart;//x=345.89,小数部分为0.890015
double z,fracpart,a;//x=123.456,小数部分会输出为0.456001
if((fp1=fopen("f1.txt","r"))==NULL){
printf("文件f1打开失败!");
exit(0);
}
if((fp2=fopen("f2.txt","w"))==NULL){
printf("文件f2打开失败!");
exit(0);
}
while(!feof(fp1)){
fscanf(fp1,"%lf",&z);//读取
if(z!=EOF){
splitfloat(z,&intpart,&fracpart);//拆分整数和小数部分
// printf("整数部分:%d\n小数部分:%lf\n",intpart,fracpart);//帮助检验
if(fracpart>=0.5){//小数部分 四舍五入
intpart=intpart+1;
// printf("整数部分:%d\n小数部分:%lf\n",intpart,fracpart);//帮助检验
}
fprintf(fp2,"%d\n",intpart);
}
}
return 0;
}
P321
练习12-7
#include"stdio.h"//练习12-7
#include"stdlib.h"
#include"process.h"
#include"string.h"
long size;
struct LogData{
long logid;
char logdate[11];
char lognote[15];
double charge;
double balance;
};
int inputchoice()
{
int mychoice;
printf("\nEnter your choice:\n");
printf("1-Add a new cash LOG.\n2-List All Cash LOG.\n");
printf("3-Query Last Cash LOG.\n4-Update a LOG\n0-End program.\n");
scanf("%d",&mychoice);
return mychoice;
}
long getLogcount(FILE *cfptr)
{
long begin,end,logcount;
fseek(cfptr,0L,SEEK_SET);
begin=ftell(cfptr);
fseek(cfptr,size,SEEK_END);
end=ftell(cfptr);
logcount=(end-begin)/size-1;
return logcount;
}
void ListAllLog(FILE *cfptr)
{
struct LogData log;
fseek(cfptr,0L,SEEK_SET);
fread(&log,size,1,cfptr);
printf("logid\tlogdata \tlognote \tcharge\t\tbalance\n");
while(!feof(cfptr)){
printf("%ld\t%s\t%s\t%.2lf\t\t%.2lf\n",log.logid,log.logdate,log.lognote,log.charge,log.balance);
fread(&log,size,1,cfptr);
}
}
int QueryLastLog(FILE *cfptr)
{
struct LogData log;
long logcount;
int flag=0;
logcount=getLogcount(cfptr);
if(logcount>0)
{
fseek(cfptr,size*(logcount-1),SEEK_SET);
fread(&log,size,1,cfptr);
flag=1;
printf("The last log is:\n");
printf("logid:%-6ld\nlogdate:%-11s\nlognote:%-15s\n",log.logid,log.logdate,log.lognote);
printf("charge:%-10.2lf\nbalance:%-10.2lf\n",log.charge,log.balance);
}
else printf("no logs is file!\n");
return flag;
}
void AddNewLog(FILE *cfptr)
{
struct LogData log,lastlog;
long logcount;
printf("Input logdate(format:2006-01-01):");
scanf("%s",log.logdate);
printf("Input lognote:");
scanf("%s",log.lognote);
printf("Input Charge:Income+and expend-:");
scanf("%lf",&log.charge);
logcount=getLogcount(cfptr);
if(logcount>0){
fseek(cfptr,size*(logcount-1),SEEK_SET);
fread(&lastlog,size,1,cfptr);
log.logid=lastlog.logid+1;//记录号按顺序是上次的号+1
log.balance=log.charge+lastlog.balance ;
}
else {
log.logid=1;
log.balance=log.charge;
}
rewind(cfptr);
printf("logid=%ld\n",log.logid);
fwrite(&log,sizeof(struct LogData),1,cfptr);
}
void UpdateLog(FILE *cfptr)//修改 ,先查询再修改
{
FILE *fp;
struct LogData log[1000],newlog,*plog=log;
long id,logcount,i,index=-1;
char ch;
printf("请输入一个记录ID:");
scanf("%ld",&id);
logcount=getLogcount(cfptr); //获取记录数
rewind(cfptr);
fread(plog,size,logcount,cfptr);
for(i=0;i<logcount;i++){
if(id==log[i].logid){ //找到
printf("logid\tlogdata \tlognote \tcharge\t\tbalance\n");//显示当前记录
printf("%ld\t%s\t%s\t%.2lf\t\t%.2lf\n",
log[i].logid,log[i].logdate,log[i].lognote,log[i].charge,log[i].balance);
index=i;
break;
}
}
rewind(cfptr); //有或者没有都无影响
if(index>=0){//没有找到
printf("Input logdate(format:2020-01-01):");
scanf("%s",newlog.logdate);
printf("Input lognote:");
scanf("%s",newlog.lognote);
printf("Input Charge:Income+ and expend-:");
scanf("%lf",&newlog.charge);
if(strcmp(log[index].lognote,newlog.lognote)!=0)//比较,如果不相同,则修改
strcpy(log[index].lognote,newlog.lognote);
if(strcmp(log[index].logdate,newlog.logdate)!=0)
strcpy(log[index].logdate,newlog.logdate);
if(newlog.charge!=log[index].charge){//如果输入的收支额度改变,重新计算余额
newlog.balance=log[index].balance-log[index].charge+newlog.charge;
log[index].charge=newlog.charge;
log[index].balance=newlog.balance;
for(i=index+1;i<logcount;i++)//当前记录之后的每条记录余额信息更新
log[i].balance=log[i-1].balance+log[i].charge;
}
rewind(cfptr);
fwrite(plog,size,logcount,cfptr); //更新回文件,此处用只读的方式打开
}
else{
printf("Error logid and try another!\n");
}
}
int main(void)
{
FILE *fp;
int choice;
if((fp=fopen("cashbox.dat","ab+"))==NULL){//以此方式打开,写入的数据会被添加到原有数据的后面。所以更新要重新用rb+的方式打开
printf("can not open file cashbox.dat!\n");
exit(0);
}
size=sizeof(struct LogData);
while((choice=inputchoice())!=0){
switch(choice){
case 1:AddNewLog(fp);break;
case 2:ListAllLog(fp);break;
case 3:QueryLastLog(fp);break;
case 4:fp=fopen("cashbox.dat", "rb+");UpdateLog(fp);break;//增加文件打卡方式为只读,则只更新不添加
default:printf("Input Error.");break;
}
}
fclose(fp);
return 0;
}