【实验题目】数据表示实验
【实验目的】掌握结构数据的保存和读取的方法。
【实验环境】
Windows + VS 2017+DEV C++
【实验内容】
(1)结构数据保存和读出
实验要求:
循环输入员工(Person)的信息,每输入一个员工的信息,立即写入文件(Persons.txt),直到输入的姓名为空时跳出循环。然后,读出该文件,显示每个Person的信息。
Person的信息表示:
struct Person {
char username[USER_NAME_LEN]; // 员工名
int level; // 工资级别
char email[EMAIL_LEN]; // email地址
DWORD sendtime; // 发送时间
time_t regtime; // 注册时间
};
源码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define BUF_LEN 100
#define USER_NAME_LEN 20
#define EMAIL_LEN 80
#define TIME_BUF_LEN 30
typedef unsigned long DWORD;
struct Person {
char username[USER_NAME_LEN]; // 员工名
int level; // 工资级别
char email[EMAIL_LEN]; // email地址
DWORD sendtime; // 发送时间
time_t regtime; // 注册时间
};
int main()
{
char pts[TIME_BUF_LEN]; // 时间字符串
time_t now; // 当前时间
(void)time(&now); // 取得系统时间
ctime_s(pts, TIME_BUF_LEN, &now); // 把时间转换为字符串
printf(pts);
struct Person personSent; // 要发送的员工记录
struct Person personRead;
char textBuf[100]; // 文本缓冲
int numberBuf; // 数字缓冲
FILE *fp;
errno_t err;
int i = 0;
char buf[sizeof(Person)];
printf("员工姓名: ");
gets_s(textBuf, BUF_LEN);
strcpy_s(personSent.username, textBuf);
while (textBuf[0] != ' ')
{
i++;
printf("工资级别: ");
scanf_s("%d", &numberBuf, sizeof(int));
getchar();
personSent.level = numberBuf;
printf("邮箱地址: ");
gets_s(textBuf, BUF_LEN);
strcpy_s(personSent.email, textBuf);
personSent.sendtime = (DWORD)now;
personSent.regtime = now;
//读入文件
printf("\n");
if ((err = fopen_s(&fp, "Persons.txt", "a+")) != 0)
{
printf("cannot open file\n");
exit(0);
}
if (fwrite(&personSent, sizeof(struct Person), 1, fp) != 1)
printf("file write error\n");
fclose(fp);
printf("员工姓名: ");
gets_s(textBuf, BUF_LEN);
strcpy_s(personSent.username, textBuf);
}
printf("\n输出员工信息\n");
//输出文件
if ((err = fopen_s(&fp, "Persons.txt", "r")) != 0)
{
printf("cannot open file\n");
exit(0);
}
while (i != 0)
{
i--;
fread(&personRead, sizeof(struct Person), 1, fp);
char regtime[TIME_BUF_LEN];
char sendtime[TIME_BUF_LEN];
printf("员工姓名: %s\r\n", personRead.username);
printf("工资级别:%d\r\n", personRead.level);
printf("邮箱地址:%s\r\n", personRead.email);
time_t t1 = (time_t)personRead.sendtime;
ctime_s(sendtime, TIME_BUF_LEN, &t1);
printf("发送时间:%s", sendtime);
ctime_s(regtime, TIME_BUF_LEN, &personRead.regtime);
printf("注册时间:%s", regtime);
printf("\n");
}
fclose(fp);
}
(2) 多文件合并保存和读出
实验要求:
循环输入多个文件名(不超过200MB,可以自己确定),每输入一个,就把该文件的文件名(最多300字节)、文件大小(long)和文件内容写入文件FileSet.pak中,输入文件名为空时跳出循环。然后,读FileSet.pak,每读出一个文件就把它原来的文件名加上一个序号保存起来。
-
合并时可以先取得文件大小,然后边读边写。
-
源码:
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
struct FILEStruct //文件结构
{
char filename[300];
int filesize;
}Node[40];
errno_t err;
int file_size(char* filename) //文件大小
{
FILE *fp=fopen(filename,"r");
if(!fp) return -1;
fseek(fp, 0L, SEEK_END);
int size = ftell(fp);
fclose(fp);
return size;
}
char *insert(char *s1, char *s2, int n)
{
int len1 = 0, len2 = 0, j = 0, k = 0;
char s4[30];
char *s3 = s4;
if (s1 == NULL)
return NULL;
if (s2 == NULL)
return s1;
len1 = strlen(s1);
len2 = strlen(s2);
if (n > len1)
return NULL;
for (int i = 0; i < n; i++)
{
j++;
}
for (int i = 0; i < len1; i++)
{
s4[k++] = s1[i];
}
for (int i = 0; i < len2; i++)
s1[j++] = s2[i];
for (int i = n; i < len1; i++)
s1[j++] = s4[i];
s1[j] = '\0';
return s1;
}
struct FILEStruct temp;
int main()
{
FILE *srcfile;
FILE *destfile;
char buf[40];
int i = 0;
char destfname[300] = "C:\\ceshi\\FileSet.pak"; //用于目标文件地址
printf("打包结束条件为输入空格和回车符\n");
printf("\n");
printf("请输入文件名(含地址):");
gets(Node[i].filename);
//Node[i].filesize = file_size(Node[i].filename);
destfile = fopen(destfname, "wb"); //打开要写入的二进制文件
if (destfile==NULL)
{
printf("写入文件未找到!\n");
fclose(destfile);
exit(1); //中止程序
}
while (Node[i].filename[0] != ' ')
{
Node[i].filesize = file_size(Node[i].filename);
srcfile = fopen(Node[i].filename, "rb"); //打开要读取的二进制文件
if (srcfile==NULL)
{
printf("读入文件未找到!\n");
exit(1); //中止程序
}
fwrite(&Node[i], sizeof(struct FILEStruct), 1, destfile);
int len = 0;
while ((len = fread(buf, 1, 40, srcfile)) >= 40)
{ //可以一次读取
fwrite(buf, 1, 40, destfile);
}
fwrite(buf, 1, len, destfile);
fclose(srcfile);
i++;
printf("请输入文件名(含地址):");
gets(Node[i].filename);
}
fclose(destfile);
printf("打包结束\n");
printf("\n");
//读出文件
destfile = fopen(destfname, "rb"); //打开要读出的二进制文件
if (destfile==NULL)
{
printf("读出文件未找到!\n");
fclose(destfile);
exit(1); //中止程序
}
char *newfilename;
char *newstr;
int count;
int j = 0;
char shuzi[30];
int x = i;
char jieyafile[300];
printf("请输入解包文件夹:");
gets(jieyafile);
printf("\n");
char *find1;
while (i > 0)
{
fread(&temp, sizeof(struct FILEStruct), 1, destfile);
find1 = strrchr(temp.filename, '\\');
char jieyanewfile[300];
int len4= strlen(jieyafile);
strcpy(jieyanewfile, jieyafile);
newstr = insert(jieyanewfile, find1, len4);
char newstr1[100];
strcpy(newstr1, newstr);
int cnt=1;
while((srcfile = fopen(newstr1, "rb"))!=NULL )
{
cnt++;
if(cnt==2)
{
char fu[30] = "()";
char shuzi[30]={};
int w=0;
itoa(cnt, shuzi,10);
char *fu1 = insert(fu, shuzi, 1);
char *find = strrchr(newstr, '.');
int len1 = strlen(find);
int len2 = strlen(newstr);
int n = len2 - len1;
newfilename = insert(newstr1, fu1, n);
strcpy(newstr1,newfilename);
}
else
{
char c=cnt+'0';
char c1=cnt-1+'0';
int k=0;
while(newstr1[k]!=c1)
{
k++;
}
newstr1[k]=c;
}
fclose(srcfile);
}
fclose(srcfile);
printf("%s\n",newstr1);
srcfile = fopen(newstr1, "wb"); //打开要写入的二进制文件
if (srcfile==NULL)
{
printf("写入文件未找到!\n");
exit(1); //中止程序
}
int lenth = temp.filesize;
char s;
while (lenth > 0)
{
fread(&s, 1, 1, destfile);
fwrite(&s, 1, 1, srcfile);
lenth--;
}
fclose(srcfile);
i--;
}
fclose(destfile);
printf("解包结束\n");
}