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

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

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

二进制读写

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

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.初始运行界面

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


2.添加学生功能

C语言文件操作以及学生数据输入储存系统实例_十六进制_02


3.保存学生功能

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

5.退出

C语言文件操作以及学生数据输入储存系统实例_十六进制_04


6.再次进入读取数据

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


7.打印数据

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


转载请注明出处,本代码开源,地址:https://github.com/Heartfirey/Student-Management-System-By-C

新人求收藏点赞~谢谢