C语言文件操作以及学生数据输入储存系统实例

1.格式化输入输出

  • printf: %[flags] [width] [.prec] [hlL]type
  • scanf: %[flag]type

printf参数说明:

flag 含义
- 左对齐
+ 在前面放置 + 或 -
(space) 正数留空
0 0填充
width或prec 含义
number 最小字符数
* 下一个参数是字符数
.number 小数点后的位数
.* 下一个参数是小数点后的位数
类型修饰 含义
hh 单个字节
h short
l long
ll long long
L long double
type 作用 type 作用
i 或 d 整数型int g 浮点型float
u 无符号整型unsigned int G 浮点型float
o 八进制 a 或 A 十六进制浮点
x 十六进制 c 字符型char
X 字母大写的十六进制 s 字符串
f 或 F 浮点型float, 6 p 指针
e 或 E 指数 n 读入/写出的个数

scanf参数说明:

flag 含义 flag 含义
* 跳过 l long, double
纯数字 最大字符数 ll long long
hh 字符型char L long double
h 短整型short
type 作用 type 作用
d 整数型int s 字符串(单词)
i 整数,可能为十六进制或八进制 […] 所允许的字符
u 无符号整型unsigned int p 指针
o 八进制 a,e,f,g 浮点型float
x 十六进制 c 字符型char

printf和scanf的返回值:

printf: 输出的字符数

scanf: 返回读入的项目数

2.文件输入输出

1.使用<和>做输出重定向

在运行时, 附加< xx.in,可以指定xx.in作为程序的输入, 附加> xxx.out, 可以将程序运行的结果输出至xxx.out中

2.FILE

FILE* fopen(const char * restrict path, const char * restrict mode);

int fclose(FILE *stream);

fscanf(FILE *, …);

fprintf(FILE *, …);

打开文件的标准代码

FILE *fp = fopen("file", "r");
if(fp){
    
    
    fscanf(fp,~);
    fclose(fp);
}else{
    
    
    ...
}
fopen"~" 对应操作
r 打开只读
r+ 打开读写,从文件头开始
w 打开只写,如果不存在则新建,如果存在则清空
w+ 打开读写,如果不存在则新建,如果存在则清空
a 打开,追加如果不存在则新建,如果存在则从文件尾开始
(再附加)x 只新建,如果文件已存在则不能打开

3.二进制文件

  • 所有的文件最终都是二进制的
  • 二进制文件是需要专门的程序来读写的文件
  • 文本的输入输出是格式化,可能经过转码

程序需要通过第三方库读写文件,很少直接读取二进制文件了

扫描二维码关注公众号,回复: 12162901 查看本文章

二进制读写

size_t fread(void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream);

size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream);

注意:FILE指针是最后一个参数,返回的是成功读写后的字节数

nitems ?

  • 二进制文件的读写一般都是通过对一个结构变量的操作进行的
  • nitems的作用是用来声明这种词读写几个结构变量

在文件中定位

long ftell(FILE *stream); //得到文件指针的偏移量并返回,需要用变量接收!

int fseek(FILE *stream, long offset, int whence);//将文件指针移动到指定位置,offset为偏移字节数,开头则为 0L

SEEK_SET: 从头开始

SEEK_CUR: 从当前位置开始

SEEK_END: 从尾开始

可移植性

在int为32位的机器上写出的数据文件无法直接在int为64位的机器上正确读出

  • 一个较好地解决方案是放弃使用int类型,而是使用typedef声明一个具有具体大小的类型
  • 更好的方案是使用文本,可以解决跨平台数据读写问题

4.一个实例:学生数据储存系统(开源)

#include <stdio.h>
#include <stdlib.h>
#define STR_LEN 40

typedef struct student{
    
    
    char name[STR_LEN];     //名字,字符串表示
    int gender;             //性别,0表示无,1表示男性,2表示女性
    int age;                //年龄,整数表示
}student;

void menu(int flag, int *num);              //用于展示系统功能并引导进入各功能
void read(student *p, int *num);            //用于读入学生数据到缓存
void init(int *num);                        //用于初始化数据库(内存),num指示运行状态
void show(student *p, int *num);            //用于打印学生数据
void showline();                            //打印一行分割线,更加美观
void open(student *p, int *num, int flag);  //用于打开本地文件读取数据
void save(student *p, int *num);            //用于保存学生数据到本地文件

student *data = NULL;   //用作数组头指针,初始化为NULL

int main(){
    
    
    system("cls");
    int num = 0;
    int flag = 0;         //flag 用于指示系统的运行状态,0表示首次打开,1表示已经打开,-1表示运行出错
    menu(flag++, &num);   //进入菜单,状态为0,同时注册状态为1
    return 0;
}

void menu(int flag, int *num){
    
    
    if(flag == 0) printf("Welcome to student management system! Please choose the function and intput the number:\n");
    else if(flag == 1) printf("Welcome back! Please choose the function and intput the number:\n");
    else if(flag == -1) printf("Error! Please Reboot the program and try again!");
    printf("\t1.Adding data\n\t2.Viewing data\n\t3.Save data\n\t4.Open data\n\t5.Quit\n\t");
    int choice = 0;
    scanf("%d", &choice);
    switch(choice){
    
    
        //选择1,则进入读入数据程序
        case 1:{
    
    
            printf("\033[0;35mPlease input the number of data which you want to input:\033[0m");
            scanf("%d", num);
            init(num);
            read(data, num);
            return;
        }
        //选择2,则进入输出数据程序
        case 2:{
    
    
            show(data, num);
        }
        //选择3,则进入保存数据程序
        case 3:{
    
    
            save(data, num);
            return;
        }
        //选择4,则进入读取数据程序
        case 4:{
    
    
            open(data, num, flag);
        }
        //选择5,则进入退出菜单程序
        case 5: exit(0);
        default: {
    
    
            printf("\033[0;31mError: Cannot identify your input!\033[0m");
            return;
        }
    }
}

void init(int *num){
    
    
    data = (student*)malloc((*num)*sizeof(student));   //为读入的数据动态开内存
    for(int i = 0; i < *num; i++){
    
    
        for(int j = 0; j < STR_LEN; j++){
    
    
            data->name[j] = 0;
        }
        data->gender = 0;
        data->age = 0;
        data++;
    }
    data -= *num;    //指针置初始位置
    read(data, num);
}

void read(student *p, int *num){
    
    
    for(int i = 0; i < *num; i++){
    
    
        printf("\tStudent Name:");
        scanf("%s", p->name);
        printf("\tStudent Gender(1-Male;2-Female):");
        scanf("%d",&(p->gender));
        printf("\tStudent Age:");
        scanf("%d",&(p->age));
        showline();
        printf("\033[0;33m%d students has been added, remaining %d students.\033[0m\n", i+1, *num-i);
        showline();
        p++;
    }
    showline();
    printf("\033[0;32mAll students's data has benn added to the system.now back to main system\033[0m\n");
    showline();
    menu(1, num);    //返回菜单,状态为1
}

void show(student *p, int *num){
    
    
    for(int i = 0; i < *num; i++){
    
    
        showline();
        printf("\tName: %s\n",p->name);
        if(p->gender == 1) printf("\tGender: Male\n");
        else if(p->gender == 2) printf("\tGender: Female\n");
        else printf("\tGender: Unidentified\n");
        printf("\tAge: %d\n", p->age);
        p++;
    }
    showline();
    printf("\033[0;32mAll data has benn printed on the screen! Now back to menu...\033[0m\n");
    showline();
    menu(1, num);
}

void save(student *p, int *num){
    
    
    FILE *fp = fopen("studentdata", "w+");
    if(fp){
    
    
        fwrite(p, sizeof(student), *num, fp);
        fclose(fp);
        printf("\033[42;37m Save Success!\033[0m\n");
    }
    else printf("\033[41;37m Save Failed!\033[0m\n");
    menu(1, num);
}

void open(student *p, int *num, int flag){
    
    
    *num = 0;
    FILE *fp = fopen("studentdata", "r");
    if(fp){
    
    
        fseek(fp, 0L, SEEK_END);     //移动指针到文件尾
        long size = ftell(fp);              //此时fp的偏移字节数即为文件总数据大小
        *num = size/(sizeof(student));      //通过除法计算数据块数量
        fseek(fp, 0L, SEEK_SET);     //移动指针到文件头

        if(flag == 1) free(data);           //如果运行状态为1,应当释放内存重新申请
        data = (student *)malloc((*num)*sizeof(student));
        p = data;

        fread(data, sizeof(student), *num, fp);

        showline();
        printf("\033[0;34mA total of %d data were successfully read.\033[0m\n", *num);
        showline();
    }
    else printf("\033[41;37mRead Failed!\033[0m\n");
    menu(1, num);
}

void showline(){
    
    
    for(int i = 0; i < 50; i++){
    
    
        printf("*-");
    }
    printf("*\n");
}

项目截图

1.初始运行界面
初始运行界面
2.添加学生功能
添加学生功能
3.保存学生功能
保存学生功能

5.退出
退出
6.再次进入读取数据
再次进入读取数据
7.打印数据
打印学生数据
转载请注明出处,本代码开源,地址:https://github.com/Heartfirey/Student-Management-System-By-C
新人求收藏点赞~谢谢

猜你喜欢

转载自blog.csdn.net/yanweiqi1754989931/article/details/107693461