C言語ファイルの操作と学生データ入力ストレージシステムの例

1.入力と出力をフォーマットします

  • printf:%[フラグ] [幅] [。prec] [hlL]タイプ
  • scanf:%[フラグ]タイプ

Printfパラメーターの説明:

国旗 意味
- 左揃え
+ +または-を前に置く
(スペース) 正の数は空白のまま
0 0パディング
幅または精度 意味
最小字符数
* 次のパラメータは文字数です
。数 小数点以下の桁数
。* 次のパラメータは、小数点以下の桁数です
タイプの変更 意味
hh シングルバイト
h ショート
l 長いです
ll 長い長い
L ロングダブル
タイプ 効果 タイプ 効果
iまたはd 整数整数 g フローティングポイントタイプフロート
u Unsigned int G フローティングポイントタイプフロート
O オクタル aまたはA 六角形の浮動小数点
バツ ヘキサデシマル c キャラクター文字
バツ 大文字の16進数 s ストリング
fまたはF フローティングポイントタイプフロート、6 p ポインタ
eまたはE インデックス n 読み取り/書き込みの数

Scanfパラメーターの説明:

国旗 意味 国旗 意味
* 飛び越える l ロング、ダブル
純粋な数字 最大文字数 ll 長い長い
hh キャラクター文字 L ロングダブル
h ショート
タイプ 効果 タイプ 効果
d 整数整数 s 文字列(単語)
整数、16進数または8進数の場合があります […] 許可される文字
u Unsigned int p ポインタ
O オクタル a、e、f、g フローティングポイントタイプフロート
バツ ヘキサデシマル c キャラクター文字

printfとscanfの戻り値:

printf:出力される文字数

scanf:読み取ったアイテムの数を返します

2.ファイルの入力と出力

1.出力リダイレクトに<および>を使用します

実行時に、<xx.inを追加し、プログラムの入力としてxx.inを指定し、> xxx.outを追加し、実行中のプログラムの結果をxxx.outに出力できます。

2.ファイル

FILE * fopen(const char *パスの制限、const char *モードの制限);

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.二进制文件

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

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

二进制读写

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
おすすめ