学生成绩管理系统-MySQL版-Part8-输出数据
本文已被浏览5695次
今天期末考试结束,为了纪念发篇博文。(shen me gui)
上次写到了第七部分的导入数据,作为一个软件,IO是成对出现的,有I(Input)就要有O(Output),本篇文章将会介绍一下对于输出的问题,不管是输出到屏幕上,亦或是输出至文件中,都在本次的讨论范围内。
一、输出到屏幕
输出到屏幕上的是比较简单的一个部分,直接用MySQL的SELECT查询语句即可,把数据表所有数据全部读出来,随后再逐行打印出数据即可。
二、输出到文件
这里的文件指的是csv和sql文件。
对于CSV文件来说,本身的文件结构并不是很复杂,直接把在屏幕输出时候输出的制表符t替换成英文半角逗号即可,换行不变。
对于SQL文件就稍微的复杂些,因为要涉及到将表的结构和数据转化为SQL语句,同时也要符合上一节叙述到的SQL文件的注释类型,具体如何获取表结构和数据并构成SQL文件,就直接看代码吧。
下面是对于输出数据
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <windows.h>
#include <mysql.h>
#include <conio.h>
//引入有用没用的头文件(傻傻的分不清)
extern MYSQL mysql;
extern MYSQL_RES *result;
extern MYSQL_ROW row;
extern MYSQL_FIELD *field;
//继承变量
char Host[15];
char Port[8];
char Username[10];
char Password[20];
char DB[10];
//并没有卵用的几个函数,直接粘来的
//函数原型列表
int LoadSettings();
int Install(int mode);
int Connect_DB();
int Get_Score_Table(int Index,char* str);
int Get_Table_Field(const char *table,int Index,char *Fieldname);
int Show_Table(const char *tablename,const char *title,const char *sqlplus);
void ChangeColorScreen(const char* color);
void ChangeWindowSize(int Width,int Height);
void Pause(int mode);
void CS();
void Ring();
void Login();
void Exit();
void ChangeWindowSize(int Width,int Height);
void ChangeWindowTitle(const char* title);
void strrpl(char* pDstOut, char* pSrcIn, const char* pSrcRpl, const char* pDstRpl);
int Sum_ints(int number);
int Export_Score();
int Export_Score_ToScreen(int TableIndex);
int Export_Score_ChoseTarget(int tableselect);
int Export_Score_ToCSV(int Index);
int Export_Score_ToSQL(int Index);
int Get_Score_Table(int Index,char* str);
int Core();
//功能入口函数
int Export_Score() {
char sql[100],temp[100],select[10];
int lines,item=1,i;
ChangeWindowTitle("导出数据");
//获取所有数据表
sprintf(sql,"Show Tables like 'scm_class_%%'");
mysql_query(&mysql,sql);
result=mysql_store_result(&mysql);
lines=mysql_num_rows(result);
ChangeWindowSize(40,lines+14);
printf("╔═════════════════╗n");
printf("║ 学生成绩管理系统 ║n");
printf("║ 导出成绩单 ║n");
printf("╟─────────────────╢n");
//注意:如果想要导出数据,必须要有数据才行,故在之前判断一下
if(lines==0) {
printf("║ 当前数据库中没有可用成绩单! ║n");
printf("║ 按任意键返回主菜单! ║n");
printf("╟─────────────────╢n");
printf("║ JerrySoft Copyright. ║n");
printf("╚═════════════════╝n>");
Pause(0);
return 0;
}
//在有数据情况下,打印成绩单列表
printf("║ 请选择希望导出的成绩单: ║n");
while((row=mysql_fetch_row(result))) {
strrpl(temp,row[0],"scm_class_","");
printf("║ [%d] %s",item,temp);
for(i=strlen(temp)+Sum_ints(item)-1; i<28; i++) {
printf(" ");
}
printf("║n");
item++;
}
printf("╟─────────────────╢n");
printf("║ [B] 返回上级菜单 ║n");
printf("╟─────────────────╢n");
printf("║ JerrySoft Copyright. ║n");
printf("╚═════════════════╝n>");
fflush(stdin);
//获取输入
gets(select);
//根据选择进行跳转函数
if(atoi(select)>0&&atoi(select)<item) {
Export_Score_ChoseTarget(atoi(select));
} else if(strcasecmp(select,"B")==0) {
return 0;
} else {
printf("请输入有效数据!");
Sleep(1000);
}
Export_Score();
return 0;
}
//选择导出目标
int Export_Score_ChoseTarget(int tableselect) {
char select,tablename[20],temp[30];
CS();
Get_Score_Table(tableselect,tablename);
strrpl(tablename,tablename,"scm_class_","");
sprintf(temp,"输出:%s",tablename);
ChangeWindowTitle(temp);
printf("╔═════════════════╗n");
printf("║ 学生成绩管理系统 ║n");
printf("║ 输出成绩单 ║n");
printf("╟─────────────────╢n");
printf("║ 请选择导出目标: ║n");
printf("║ [1] 打印至屏幕 ║n");
printf("║ [2] 导出到*.sql文件 ║n");
printf("║ [3] 导出到*.csv文件 ║n");
printf("╟─────────────────╢n");
printf("║ [B] 返回主菜单 ║n");
printf("╟─────────────────╢n");
printf("║ JerrySoft Copyright. ║n");
printf("╚═════════════════╝n");
fflush(stdin);
select=getch();
switch(select) {
case '1':
Export_Score_ToScreen(tableselect);
break;
case '2':
Export_Score_ToSQL(tableselect);
break;
case '3':
Export_Score_ToCSV(tableselect);
break;
case 'b':
case 'B':
Core();
break;
default:
Export_Score_ChoseTarget(tableselect);
break;
}
return 0;
}
//打印至屏幕
int Export_Score_ToScreen(int TableIndex) {
char Table[20],sql[100],FieldName[20];
char addsql[50];
int i,j,select;
Get_Score_Table(TableIndex,Table);
ChangeWindowTitle("输出顺序");
CS();
sprintf(sql,"SELECT * From %s",Table);
mysql_query(&mysql,sql);
result=mysql_store_result(&mysql);
ChangeWindowSize(40,11+mysql_num_fields(result));
//考虑到一个升降序的问题,在输出前询问用户
printf("╔═════════════════╗n");
printf("║ 学生成绩管理系统 ║n");
printf("║ 导出成绩单 ║n");
printf("╟─────────────────╢n");
printf("║ 请选择输出排序索引: ║n");
printf("║ [1] 按照导入数据时的顺序 ║n");
field=mysql_fetch_field(result);
//然而只是在列举所有的字段
for(i=1; i<mysql_num_fields(result); i++) {
field=mysql_fetch_field(result);
printf("║ [%d] %s",i+1,field->name);
for(j=(field->name_length)*2+Sum_ints(i+1)+4; j<38; j++) {
printf(" ");
}
printf("║n");
}
printf("╟─────────────────╢n");
printf("║ JerrySoft Copyright. ║n");
printf("╚═════════════════╝n>");
Index_Error:
fflush(stdin);
scanf("%d",&select);
//获取输入
if(select<0||select>mysql_num_fields(result)) {
printf("选项无效,请重试!n>");
goto Index_Error;
}
//根据字段序号获取字段
Get_Table_Field(Table,select,FieldName);
CS();
ChangeWindowSize(63,13);
ChangeWindowTitle("排序法则");
printf("╔═════════════════════════════╗n");
printf("║ 学生成绩管理系统 ║n");
printf("║ Mysql版 ║n");
printf("╟─────────────────────────────╢n");
printf("║ 请选择您希望的输出方式: ║n"
"║ [1]升序(从小到大,字典顺序) ║"
"║ [2]降序(从大到小,逆字典顺序) ║");
printf("╟─────────────────────────────╢n");
printf("║ JerrySoft Copyright. ║n");
printf("╚═════════════════════════════╝n>");
Desc_Asc_ERR:
fflush(stdin);
scanf("%d",&select);
if(strcmp(FieldName,"姓名")==0) {
if(select==1) {
//此处是针对于姓名升降序的排列,还没搞懂,先空着
} else if(select==2) {
//此处是针对于姓名升降序的排列,还没搞懂,先空着
} else {
goto Desc_Asc_ERR;
}
} else {
//其他全是分数的好说了,在后面加个排序条件即可
if(select==1) {
sprintf(addsql,"order by %s asc",FieldName);
} else if(select==2) {
sprintf(addsql,"order by %s desc",FieldName);
} else {
goto Desc_Asc_ERR;
}
}
Show_Table(Table,"输出到屏幕",addsql);
Pause(1);
return 0;
}
//输出至CSV
int Export_Score_ToCSV(int Index) {
char Tablename[100];
char temp[100],FileTarget[200];
char Location[100];
char sql[1000];
char choice;
FILE *FilePointer;
int i,j;
CS();
Get_Score_Table(Index,Tablename);
ChangeWindowSize(55,10);
//首先需要一个存放目录
printf("请输入输出文件存放目录(可直接把文件夹拖进来,最后不加\)n>");
FileLocation:
fflush(stdin);
gets(Location);
if(strcmp(Location,"back")==0) return 0;
strrpl(temp,Tablename,"scm_class_","");
sprintf(FileTarget,"%s\%s.csv",Location,temp);
//以写入方式打开文件
if((FilePointer=fopen(FileTarget,"w"))==NULL) {
//失败提示后调回
printf("创建%s失败,请确定此目录存在并可写!n请重新输入n返回请输入back>",temp);
goto FileLocation;
} else {
//准备导出数据
sprintf(sql,"SELECT * From %s",Tablename);
mysql_query(&mysql,sql);
result=mysql_store_result(&mysql);
printf("正在导出科目数据...n");
field=mysql_fetch_field(result);
//将科目写入csv文件
for(i=1,field=mysql_fetch_field(result); i<mysql_num_fields(result); i++,field=mysql_fetch_field(result)) {
fprintf(FilePointer,"%s",field->name);
if(i+1==mysql_num_fields(result)) {
fprintf(FilePointer,"n");
} else {
fprintf(FilePointer,",");
}
}
printf("正在导出数据...n");
//将具体成绩数据写入csv文件
for(i=0,row=mysql_fetch_row(result); i<mysql_num_rows(result); i++,row=mysql_fetch_row(result)) {
for(j=1; j<mysql_num_fields(result); j++) {
fprintf(FilePointer,"%s",row[j]);
if(j+1==mysql_num_fields(result)) {
fprintf(FilePointer,"n");
} else {
fprintf(FilePointer,",");
}
}
}
fclose(FilePointer);
CS();
printf("导出成功!n是否打开导出文件?n[Y/N]");
ReChoice:
//最后问一下要不要打开文件
choice=getch();
switch(choice) {
case 'Y':
case 'y':
sprintf(temp,"start %s",FileTarget);
system(temp);
break;
case 'N':
case 'n':
break;
default:
printf("n请输入正确的内容[Y/N]:");
goto ReChoice;
}
}
return 0;
}
int Export_Score_ToSQL(int Index) {
char TableName[100],sql[1000];
char Location[1000],temp[100],selected;
char Folder[1000];
int FieldsSum=0,i,j,Prikey=-1;
MYSQL_ROW Columns[1000];
FILE *SQLER;
Get_Score_Table(Index,TableName);
CS();
ChangeWindowTitle("导出到SQL文件");
ChangeWindowSize(63,12);
printf("╔═════════════════════════════╗n");
printf("║ 学生成绩管理系统 ║n");
printf("║ 基于MySQL ║n");
printf("╟─────────────────────────────╢n");
printf("║ 请输入导出的SQL文件的存放目录(或者直接拖入一个文件夹,最后║n"
"║ 不加\) ║n");
printf("╟─────────────────────────────╢n");
printf("║ JerrySoft Copyright. ║n");
printf("╚═════════════════════════════╝n>");
Get_SQL_Location:
//和上面一样要获取存放目录并以写入方式打开文件
gets(Folder);
sprintf(Location,"%s\%s.sql",Folder,TableName);
if((SQLER=fopen(Location,"w"))==NULL) {
printf("%s不可写,请重新输入>",Location);
goto Get_SQL_Location;
}
//准备数据表的各个字段属性
sprintf(sql,"SHOW columns from %s",TableName);
mysql_query(&mysql,sql);
result=mysql_store_result(&mysql);
for(FieldsSum=0; FieldsSum<mysql_num_rows(result); FieldsSum++) {
Columns[FieldsSum]=mysql_fetch_row(result);
}
//刚刚开始写几行注释
fprintf(SQLER,"-- 学生成绩管理系统专用导出文件n");
fprintf(SQLER,"-- 基于酷炫狂拽的MySQL数据库n");
fprintf(SQLER,"-- Host:%sn",Host);
strrpl(temp,TableName,"scm_class_","");
fprintf(SQLER,"-- 班级:%snn",temp);
fprintf(SQLER,"-- n-- 数据库:%sn-- ",DB);
fprintf(SQLER,"-- -------------------n");
fprintf(SQLER,"-- 表名:%sn",TableName);
fprintf(SQLER,"-- nn-- 表的结构n");
//判断表的存在并创建表格
fprintf(SQLER,"CREATE TABLE IF NOT EXISTS `%s` (n",TableName);
//转储表格各个项目的类型
for(i=0; i<FieldsSum; i++) {
fprintf(SQLER," `%s` %s NOT NULL %s",Columns[i][0],Columns[i][1],Columns[i][5]);
if(i+1!=FieldsSum) {
fprintf(SQLER,",n");
}
if(Prikey==-1&&strcasecmp(Columns[i][3],"PRI")) Prikey=i;
}
//搞到那个主键的属性一般是ID
if(Prikey!=-1) fprintf(SQLER,",nPRIMARY KEY(`%s`)n",Columns[Prikey][0]);
sprintf(sql,"SELECT * From %s",TableName);
mysql_query(&mysql,sql);
result=mysql_store_result(&mysql);
fprintf(SQLER,") ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=%d;nn",(int)(mysql_num_rows(result)+1));
//执行数据插入前先清空数据表
fprintf(SQLER,"--清空数据n");
fprintf(SQLER,"TRUNCATE TABLE `%s`;",TableName);
fprintf(SQLER,"INSERT INTO `%s` (",TableName);
//开始写入数据
for(i=0; i<FieldsSum; i++) {
fprintf(SQLER,"`%s`",Columns[i][0]);
if(i+1!=FieldsSum) {
fprintf(SQLER,", ");
} else {
fprintf(SQLER,") VALUESn");
}
}
//写入数据
for(i=0; i<mysql_num_rows(result); i++) {
row=mysql_fetch_row(result);
fprintf(SQLER,"(");
for(j=0; j<FieldsSum; j++) {
fprintf(SQLER,"`%s`",row[j]);
if(j+1!=FieldsSum) {
fprintf(SQLER,",");
} else {
if(i+1!=mysql_num_rows(result)) {
fprintf(SQLER,"),n");
} else {
fprintf(SQLER,");");
}
}
}
}
//成功结束并关闭文件
fclose(SQLER);
ToSQL_Folder_Err:
CS();
printf("导出成功!是否打开对于文件目录[Y/N]>");
selected=getch();
switch(selected) {
case 'Y':
case 'y':
sprintf(temp,"explorer %s",Folder);
system(temp);
break;
case 'N':
case 'n':
break;
default:
Ring();
goto ToSQL_Folder_Err;
}
return 0;
}
三、查询数据
这里有一个问题是查询。查询用到的也是SELECT语句,由于之前在百度上并没有找到可以全表搜索的语句,所以就用了一堆的OR连接各个判断语句,导致此处执行的mysql语句非常的长,虽然目前还没有发生溢出的情况,但是这个Bug是有可能出现的。写完程序后反过来写博客的时候发现可以直接用若干个查询来查找,然后将所有查询到的数据存到一个总的数组中,去除重复项目后输出即可(然而并没有这么做)。
//引入头文件
#include <stdio.h>
#include <windows.h>
#include <mysql.h>
#include <string.h>
//继承变量
extern MYSQL mysql;
extern MYSQL_RES *result;
extern MYSQL_ROW row;
extern MYSQL_FIELD *field;
//声明一些函数原型
void ChangeColorScreen(const char *color);
void ChangeWindowSize(int Width,int Height);
void ChangeWindowTitle(const char *title);
void CS();
void Pause(int mode);
void JR_SetColor(int textcolor,int bgcolor);
void strrpl(char* pDstOut, char* pSrcIn, const char* pSrcRpl, const char* pDstRpl);
int Query_Score_Show(char *KeyWord);
//查询主入口
int Query_Score() {
char select[20];
ChangeWindowSize(63,12);
ChangeWindowTitle("成绩查询");
CS();
printf("╔═════════════════════════════╗n");
printf("║ 学生成绩管理系统 ║n");
printf("║ 基于MySQL ║n");
printf("╟─────────────────────────────╢n");
printf("║ 请输入关键字: ║n");
printf("║ 关键字可以是一个同学的名字,一个分数.输入exit返回主菜单 ║n");
printf("╟─────────────────────────────╢n");
printf("║ JerrySoft Copyright. ║n");
printf("╚═════════════════════════════╝n>");
fflush(stdin);
scanf("%s",select);
if(strcasecmp(select,"exit")==0) {
return 0;
}
Query_Score_Show(select);
Query_Score();
return 0;
}
//查询主程序
int Query_Score_Show(char *KeyWord) {
char sql[1000],sql2[1000];
char tables[100][20],classname[100],title[20];
int tabs=0;
int i,j;
sprintf(sql,"Show Tables Like 'scm_class_%%'");
mysql_query(&mysql,sql);
result=mysql_store_result(&mysql);
//这里把所有的表格都先轮询一遍,计划在所有表格中查找数据
while((row=mysql_fetch_row(result))) {
sprintf(tables[tabs],row[0]);
tabs++;
}
for(i=0; i<tabs; i++) {
//查询列表
sprintf(sql,"show columns from %s",tables[i]);
mysql_query(&mysql,sql);
//构建查询指定列
result=mysql_store_result(&mysql);
sprintf(sql,"SELECT ");
row=mysql_fetch_row(result);
memset(sql2,0,1000);
for(j=1; j<mysql_num_rows(result); j++) {
row=mysql_fetch_row(result);
//这就是要去写那个长的不得了的判断语句
if(j+1!=mysql_num_rows(result)) {
sprintf(sql,"%s%s,",sql,row[0]);
sprintf(sql2,"%s %s like '%s' OR",sql2,row[0],KeyWord);
} else {
sprintf(sql,"%s%s",sql,row[0]);
sprintf(sql2,"%s %s like '%s'",sql2,row[0],KeyWord);
}
}
//构建查询表格
sprintf(sql,"%s From %s Where %s",sql,tables[i],sql2);
mysql_query(&mysql,sql);
result=mysql_store_result(&mysql);
if(mysql_num_rows(result)>0) {
//搞到数据就输出
strrpl(classname,tables[i],"scm_class_","");
sprintf(title,"在%s中找到%d条",classname,(int)mysql_num_rows(result));
ChangeWindowSize(mysql_num_fields(result)*8+1,mysql_num_rows(result)+5);
ChangeWindowTitle(title);
field=mysql_fetch_field(result);
JR_SetColor(10,1);//涂成绿的
//输出字段名
for(j=1; j<mysql_num_fields(result); j++) {
field=mysql_fetch_field(result);
printf("%st",field->name);
}
JR_SetColor(15,1);//恢复
printf("n");
while((row=mysql_fetch_row(result))) {
for(j=1; j<mysql_num_fields(result); j++) {
if(strcmp(row[j],KeyWord)==0){
//如果匹配查询字符串,用红色高亮
JR_SetColor(12,1);
printf("%st",row[j]);
JR_SetColor(15,1);
}else{
//不匹配就原色
printf("%st",row[j]);
}
}
printf("n");
}
if(i+1!=tabs){
//对于中间表和末尾表显示不同的提示信息
printf("按任意键显示下一表格>");
}else{
printf("输出结束按任意键返回上级菜单>");
}
Pause(0);
}
//没有就下一个表继续找
}
return 0;
}






评论
您需要 先登录 才可以回复.