//
// main.c
// StudentManagement
//
// Created by tusm on 15-7-20.
// Copyright (c) 2015年 tusm. All rights reserved.
//
#include "Constants.h"
#include "Student.h"
#include <stdio.h>
#include <stdlib.h>
//使用枚举,对操作不同选项填充文字说明
typedef enum operation {
kLoginOperationStyleAddNew = 1,
kLoginOperationStyleSelect,
kLoginOperationStyleUpdate,
kLoginOperationStyleStatistic,
kLoginOperationStyleOutput,
kLoginOperationStyleExit,
}kLoginOperationStyle;
int main(int argc, const char * argv[]){
//定义一个结构体指针,指向保存员工信息的内存的首地址
Student *studentPointer = NULL;
int total=0;
//获取数据源
total = initDataSource(&studentPointer);
//while循环
while (1) {
char *format="\t请选择以下操作:\n \t1.输入\n \t2.查询\n \t3.更新\n \t4.统计\n \t5.输出\n \t6.退出\n";
int choice = alert(format, 1, 6);
int currentInputedNum=0;//记录这次输入的人数
Student *inputedPointer=NULL;
Student *tempfindPointer=NULL;
switch (choice) {
case kLoginOperationStyleAddNew: //输入
/* printf("\t请选择以下操作:\n\t1.打开文件\n\t2.使用键盘\n请输入您的操作:");
scanf("%d",&selectChoice);
if (selectChoice==1) {
//1.打开文件
total=fileInput(&studentPointer);
break;
}else{
//2.使用键盘
//将输入的新信息放在studentPointer中
studentPointer=inputInfo(¤tInputedNum,total);
total += currentInputedNum;
break;
} */
//怎么说捏。。
//打开文件进行文件操作,和使用键盘,本质上是一回事
//如果单纯用键盘输入的话,是转瞬即逝的,关闭程序就没有了。(完全可以写一个跟文件无关学生管理系统)
//但如果想键盘输入的东西加到文件里面操作或者文件本身的内容操作的话,可以是一回事。
inputedPointer=inputInfo(¤tInputedNum,total);
studentPointer=combineInfo(studentPointer, inputedPointer,total, currentInputedNum);
total+=currentInputedNum;
break;
case kLoginOperationStyleSelect:
//查询
tempfindPointer=selectInfo(studentPointer, total);
if (tempfindPointer==NULL) {
printf("所查询为空\n");
}else{
show(tempfindPointer,1);
}
/*错误写法
selectInfo(studentPointer, total);
show(studentPointer, total);
//如果不引入tempfindPointer,后面show(studentPointer,total的话
//还是会打印出所有的
//因为虽然有返回值,但没接收。用的还是所有的。并且打印了total回。
所以应接收到地址后打印一次
*/
break;
case kLoginOperationStyleUpdate:
//更新
updateInfo(&studentPointer,&total);
break;
case kLoginOperationStyleStatistic:
printf("统计功能待开发\n");
break;
case kLoginOperationStyleOutput:
outputInfo(studentPointer,total);
break;
case kLoginOperationStyleExit:
//释放分配的内存
printf("是否保存到文件:\n (1.是 2.否)");
int i=0;
scanf("%d",&i);
if (i==1) {
save(studentPointer, total);
}
free(studentPointer); //<stdlib.h>
exitSystem(true);
break;
default:
break;
}
}
return 0;
}
/*软件开发
1需求分析:根据对其工作情况的了解,列出大致需求(分析师)
2总体设计:大致需要那几个模块 如输入 管理 统计 输出
3详细设计 每个模块里详细的功能实现,具体到每个函数的实现
4编程 根据详细设计的步骤实现(码工)
5测试
6维护
*/
//
// Student.h
// StudentManagement
//
// Created by tusm on 15-7-20.
// Copyright (c) 2015年 tusm. All rights reserved.
//
#ifndef StudentManagement_Student_h
#define StudentManagement_Student_h
#include "Constants.h"
#include <stdio.h>
#include <stdbool.h>
//提示选择操作
int alert(char *format,int min,int max);
//初始化数据源
int initDataSource(Student **pointer);
//文件输入
//int fileInput(Student **Pointer);
//添加功能:从终端输入信息,并返回结构体指针
Student *inputInfo(int *num,int totalNumber);
//合并功能:将新添加的信息合并到结构体指针中
Student *combineInfo(Student *destPointer,Student *sourcePointer, int desCount,int sourceCount);
//查询功能:
Student *selectInfo(Student *studentPointer,int total);
//更新功能:修改、删除、插入、排序
void updateInfo(Student **studentPointer,int *total);
//输出功能
void show(const Student *pointer,int num);
//保存功能:将数据保存到文件里面去
void save(const Student *pointer,int num);
void outputInfo(Student *studentPointer,int total);
//退出功能
void exitSystem(bool status);
#endif
//
// Student.c
// StudentManagement
//
// Created by tusm on 15-7-20.
// Copyright (c) 2015年 tusm. All rights reserved.
//
#include <stdio.h>
#include "Constants.h"
#include "Student.h"
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
int chooseOperation(int min,int max){
int operation=0;
do {
printf("请输入您的操作:");
scanf("%d",&operation);
} while (operation<min || operation>max);
return operation;
}
//提示选择操作
int alert(char *format,int min,int max){
printf("********************\n");
printf("%s",format);
printf("********************\n");
return chooseOperation(min, max);
}
//
从文件输入
//int fileInput(Student **Pointer){
// Student *pointer = NULL;
// int count=0;
// FILE *fp=fopen(kFilePath, "r");
// if (fp == NULL) {
// printf("File open error!\n");
// exit(EXIT_FAILURE);} //导入头文件stdlib.h
//
// while (1) {
// if (count == 0) {
// pointer = (Student *)malloc(1 * sizeof(Student));
// if (pointer == NULL) {
// printf("Error: malloc!\n");
// exit(EXIT_FAILURE);
// }
// } else{
// pointer = (Student *)realloc(pointer,(count+1)*sizeof(Student));
// if (pointer == NULL) {
// printf("Error: malloc!\n");
// exit(EXIT_FAILURE);
// }
// }
// // rewind(fp);
// // fread(pointer+count, sizeof(pointer), 1, fp);
// fscanf(fp, "%s %lld %ld %ld",pointer[count].name,&pointer[count].teleNum,&pointer[count].QQNum,&pointer[count].QQNum);
// printf( "%s %lld %ld %ld\n",pointer[count].name,pointer[count].teleNum,pointer[count].QQNum,pointer[count].QQNum);
//
// if (feof(fp) != 0) {
// //正常读完
// printf(" %s %lld %ld %ld\n",pointer[count].name,pointer[count].teleNum,pointer[count].QQNum,pointer[count].dormNum);
// break;
// }
//
// if (ferror(fp) != 0) {
// //出错了
// printf("Error: read !\n");
// exit(EXIT_FAILURE);
// }
// count++;
// }
//
// *Pointer=pointer;
//
// //关闭文件
// fclose(fp);
// return count;
//}
//
// // Student *tempPointer=NULL;
// //fread是从文件到终端读过来 fwrite是从终端向文件写入一个数据块。区分好
// fread(pointer+count,sizeof(Student),1,fp);
// if (feof(fp)!=0) {
// break; //正常读完
// }
// if (ferror(fp)!=0) {//出错了
// printf("error:read!");
// exit(EXIT_FAILURE);
// }
//
// count++;
// *Pointer=pointer;
// }
// *pointer=tempPointer; //关于二级指针和函数有点晕
/*
一级指针可以在函数内部修改形参指针指向的内容,
如 void modify(int *a){(*a++)};
void main(){
int a=5;
modify(&a);
printf("%d",a); //结果是6
}
普通写法int *p; p=(int *)malloc(1*sizeof(int));
如果我们想改变实参本身,(如上面的p,不是改变p指向的内容,而是改变指针值)的话,就需要二级指针作为参数来改变指针值。
即 void(char **a){(*a=malloc分好的)};
*/
//fclose(fp);
// return count;/
//}
//导入员工信息 - 初始化数据源
int initDataSource(Student **pointer){
//从文件导入员工信息
//打开文件,如果不存在创建一个文件
FILE *fp = fopen(kFilePath, "r");
if (fp == NULL) {
//打开文件出错
printf("file open error !");
exit(EXIT_FAILURE);
}
Student *tempPointer = NULL;
int count = 0;
while (1) {
if (count == 0) {
tempPointer = (Student *)malloc(1 *sizeof(Student));
if (tempPointer == NULL) {
printf("Error: malloc!\n");
exit(EXIT_FAILURE);
}
} else{
tempPointer = (Student *)realloc(tempPointer ,(count + 1) * sizeof(Student));
if (tempPointer == NULL) {
printf("Error: malloc!\n");
exit(EXIT_FAILURE);
}
}
fread(tempPointer + count, sizeof(Student),1, fp);
if (feof(fp) != 0) {
//正常读完
break;
}
if (ferror(fp) != 0) {
//出错了
printf("Error: read !\n");
exit(EXIT_FAILURE);
}
count++;
}
*pointer = tempPointer;
//关闭文件
fclose(fp);
return count;
}
//添加功能:从终端输入信息,并返回结构体指针
Student *inputInfo(int *num,int totalNumber){
//第一次输入时num是输入的学生数目(0开始),totalNumber是目前的人数
Student *tempPointer=NULL;
bool isFirst=true;//bool要引入stdbool.h 用来判定是否是第一个学生
//循环输入信息
while (1) {
Student oneStudent;
printf("********************\n");
printf("请输入姓名:\n");
scanf("%s",oneStudent.name);
printf("请输入电话号码:\n");
scanf("%lld",&oneStudent.teleNum);
printf("请输入QQ号码:\n");
scanf("%ld",&oneStudent.QQNum);
printf("请输入寝室号码:\n");
scanf("%ld",&oneStudent.dormNum);
if (isFirst==true){
//分配一片内存给tempPointer(类似于容器?)来保存学生信息
tempPointer=(Student *)malloc(1*sizeof(Student));
if (tempPointer==NULL) {
printf("malloc error");
exitSystem(false);
}
*num += 1;
isFirst = false;
}else{
//不是第一位学生,增加一片内存来保存其信息
tempPointer=(Student *)realloc(tempPointer, sizeof(Student)*(*num+1));
if (tempPointer==NULL) {
printf("realloc error!");
exitSystem(false);
}
//成功分配内存后,记录输入的学生数量
*num += 1;
}
//可以保存学生信息了(malloc和realloc内存分配成功)
tempPointer[*num-1] = oneStudent;
//下一步做法
char *nextStep="\t1.继续\n \t2.结束\n";
int result=alert(nextStep, 1, 2);
if (result == 2) {
break;
}//言下之意是,选择2.结束就跳出while,返回tempPointer。选择1.继续则继续while循环。
}
return tempPointer; //这是while循环外的
}
//合并功能:将新添加的信息合并到结构体指针中
Student *combineInfo(Student *destPointer, Student *sourcePointer, int desCount, int sourceCount){
//判断指针是否为空
if (destPointer == NULL && sourcePointer==NULL) {
return NULL;
}else if (destPointer==NULL){
return sourcePointer;
}else if(sourcePointer==NULL){
return destPointer;
}
//重新分配一个能够容纳desCount+sourceCount的内存
destPointer=(Student *)realloc(destPointer,(desCount+sourceCount)*sizeof(Student));
//指针名=(数据类型*)realloc(要改变内存大小的指针名,新的大小)
//出错:是sizeof(Student)而不是sizeof(destPointer)啊啊。。。
if (destPointer==NULL) {
printf("realloc error!");
exitSystem(false);
}
//将source的数据添加到dest
for (int i=0; i<sourceCount; i++) {
destPointer[desCount+i]=sourcePointer[i];
}
//释放source的内存
free(sourcePointer);
return destPointer;
}
//查询功能:
Student *selectInfo(Student *studentPointer,int total){
char *foramt ="\t请选择查询方式:\n\t1.按电话号码查询\n\t2.按姓名查询\n\t3.返回\n";
int operation=alert(foramt, 1, 3);
long long num=0;
char name[30];
Student *pointer=NULL;
switch (operation) {
case 1:
printf("请输入电话号码:\n");
scanf("%lld",&num);
for (int i=0; i<total; i++) {
if (num == studentPointer[i].teleNum) {
pointer=studentPointer+i;
}
}
break;
case 2:
printf("请输入姓名:\n");
scanf("%s",name);
for (int i=0; i<total; i++) {
if (strcmp(name, studentPointer[i].name) ==0) {
pointer=studentPointer+i;
}
}
break;
case 3:
// printf("test fanhui\n");
pointer=NULL;
break;
default:
break;
}
return pointer;
//报错control reaches the end of non-void function是因为没写返回值
}
//处理查询结果:
//void dealWithSelectResult(){
//}
//更新功能:
void updateInfo(Student **studentPointer,int *total){
char *format ="\t1.修改记录\n\t2.删除信息\n\t3.插入数据\n\t4.返回\n";
int operation=alert(format, 1, 5);
Student *tempPointer=NULL;
int num=0;
switch (operation) {
case 1:
//1.修改记录其实这个并不需要传出指针的值,但为了将就其他case,我也可以用二级指针!
//(1)查询
tempPointer=selectInfo(*studentPointer,*total);
//(2)打印
show(tempPointer, 1);
//(3)选择修改内容
char *chageFormat="\t请选择要修改的内容:\n\t1.姓名\n\t2.手机号码\n\t3.QQ\n\t4.寝室号\n\t5.返回\n";
int changeOperation=alert(chageFormat,1, 5);
switch (changeOperation) {
case 1:
printf("请输入姓名:\n");
//tempPointer是结构体指针(指向结构体的指针),指向查询到的结构体
//*tempPointer 或者tempPoniter[i] 是结构体 用·
//tempPointer 是指针 用->
//结构体变量用.运算符来访问结构体的成员
//指向结构体的指针用->来访问其指向的结构体的成员
// scanf("%s",&(*tempPointer).name[30]);
//scanf("%s",&tempPointer->name[30]);
//两个表达含义相同
scanf("%s",(*tempPointer).name);
//同理scanf("%s",tempPointer->name);
//数组名是首地址,但是了[30]的话就不是了,而是一个个的%c
// 错误:scanf("%s",&(*tempPointer).name[30]);
break;
case 2:
printf("请输入手机号码:\n");
scanf("%lld",&(*tempPointer).teleNum);
break;
case 3:
printf("请输入QQ:\n");
scanf("%ld",&(*tempPointer).QQNum);
break;
case 4:
printf("请输入寝室号:\n");
scanf("%ld",&(*tempPointer).dormNum);
break;
case 5:
break;
default:
break;
}
printf("修改成功\n");
break;
case 2:
//2.删除记录
//(1)查询
tempPointer=selectInfo(*studentPointer,*total);
//(2)打印
show(tempPointer, 1);
// (*tempPointer).name[30]="";
(*tempPointer).QQNum=0;
(*tempPointer).teleNum=0;
(*tempPointer).dormNum=0;
break;
case 3:
//3.插入记录
// 合并并保存新的指针,改变总数
/*错误写法
void updateInfo(Student *studentPointer,int total){
insertPointer=inputInfo(&num,total);
studentPointer=combineInfo(studentPointer,insertPointer,total,num);
total+=num;
printf("test");
break;
只有出错是检验真理的唯一标准...!!!醉了
原因是:该函数需要是二级指针作参数,因为studentPointer自身的值要改变,而不仅仅是其指向的对象。就如句中: studentPointer=combineInfo(studentPointer,insertPointer,total,num);是自己理解的错误的单方面的赋值
并不能以函数传参传回去
就类似于函数里 void function(int a);a=10 并不能改变main函数里的a的值一样。需要void function(*p); *p=10;
//回去好好看书!*/
tempPointer=inputInfo(&num,*total);
*studentPointer=combineInfo(*studentPointer,tempPointer,*total,num);
//报错:in=Incompatible pointer types assigning to Student** from Student*
//原因:combine返回的时一个一级指针,但studentPointer在本函数里是个二级指针
//所以要写 *studentPointer
*total += num;
break;
case 4:
//4.返回
break;
default:
break;
}
}
//(1)输出到屏幕
void show(const Student *pointer,int num){
printf("*****************\n");
for (int i=0; i<num; i++) {
printf("姓名:%s\n",pointer[i].name);
printf("电话号码:%lld\n",pointer[i].teleNum);
printf("QQ:%ld\n",pointer[i].QQNum);
printf("寝室号:%ld\n",pointer[i].dormNum);
// getchar();
// getchar(); //暂停一下,等待输入
}
}
//报错:Thread 1:EXC_BAD_ACCESS 试图访问一个不存在的对象时候会报错,可能是过度release了,内存错误
//(2)输出到文件
void save(const Student*pointer,int num){
//打开文件
FILE *fp=fopen(kFilePath, "w+");
// for (int i=0; i<num; i++) {
// printf("********************\n");
// printf("姓名:%s\n",pointer[i].name);
// printf("电话号码:%lld\n",pointer[i].teleNum);
// printf("QQ:%ld\n",pointer[i].QQNum);
// printf("寝室号:%ld\n",pointer[i].dormNum);
// printf("********************\n");
// // getchar();
// // getchar(); //暂停一下,等待输入
// }
fwrite(pointer,sizeof(Student),num,fp);
fclose(fp);
}
//输出模块
void outputInfo(Student *studentPointer, int total){
char *format ="\t1.输出到文件\n\t2.输出到屏幕\n\t3.返回\n";
int operation = alert(format, 1, 3);
switch (operation) {
case 1:
save(studentPointer, total);
break;
case 2:
show(studentPointer, total);
break;
default:
break;
}
}
//退出功能
void exitSystem(bool status){
printf("********************\n");
if (status == true) {
printf("感谢您的使用,再见!\n");
}else{
printf("程序出错,停止运行。\n");
}
printf("********************\n");
if (status == true) {
exit(EXIT_SUCCESS);
}else{
exit(EXIT_FAILURE);
}
}
//添加功能往后是7月21日
//异常处理!
//
// Constants.h
// StudentManagement
//
// Created by tusm on 15-7-20.
// Copyright (c) 2015年 tusm. All rights reserved.
//
#ifndef StudentManagement_Constants_h
#define StudentManagement_Constants_h
#define kFilePath "/Users/tusm/Desktop/通讯录.txt"
typedef struct{
char name[30];
long long teleNum;
long QQNum;
long dormNum;
}Student;
#endif
//<span style="font-family: Arial, Helvetica, sans-serif;"></span><p>改了两个错</p><p>1. sizeof(student)写成了sizeof(destpointer)导致的各种内存错误</p><p>2. 用r的方式读文件 w+写</p><p> </p><p>文件的相关操作要复习啊哎 </p><p>还有3. scanf *(tempPointer).name == tempPointer ->name</p><p>不能带[30]</p><p>完了一块整理吧</p>
2015.7.24 改正后的稍简陋通讯录
最新推荐文章于 2023-01-11 21:23:54 发布