com.c
Upload User: bafish
Upload Date: 2021-11-22
Package Size: 158k
Code Size: 12k
Development Platform:

Visual C++

  1. #include "com.h"
  2. /*********************************************************
  3. *函数名:loadFromFile
  4. *形参:style,生成有序链表的排序方式,
  5. * style=1,按姓名升序排序
  6. * style=2,按姓名降序排序
  7. * style=3,按薪水升序排序
  8. * style=4,按薪水升序排序
  9. * style=其他,按编号升序排序
  10. *返回值:生成链表的头指针
  11. *函数功能:从文件中把数据全部读出,用插入法生成链表并返回头指针head
  12. *作者:qjh
  13. *编写日期:2008-9-18
  14. **********************************************************/
  15. MEMBER * loadFromFile( int style )
  16. {
  17. MEMBER *head;  //链表的头指针
  18. MEMBER *node;  //申请新结点的指针
  19. FILE *fp;  //文件指针
  20. char ch;  //保存用户是否要创建文件的变量
  21. fp = fopen( FILENAME , "rb" );
  22. if ( NULL == fp )  //文件打开不成功
  23. {
  24. printf("数据文件不存在.n");
  25. printf("是否需要重新创建新文件(y/n):");
  26. ch = getche( );//接收用户的选择输入//getch(), getchar()
  27. if ( 'y' == ch || 'Y' == ch )
  28. {
  29. fp = fopen( FILENAME , "wb" );
  30. fclose(fp);
  31. fp = fopen( FILENAME , "rb" );
  32. }
  33. else   //用户选择的是不创建文件,退出系统
  34. {
  35. exit(0);
  36. }
  37. }
  38. //申请头结点
  39. head = ( MEMBER * )malloc(sizeof(MEMBER));
  40. head->next = NULL;
  41. node = ( MEMBER *)malloc(sizeof(MEMBER));
  42. node->next = NULL;
  43. if ( fread(node, sizeof(MEMBER), 1, fp ) == 1 )//如果读取成功
  44. {
  45. //将结点插入到链表中
  46. //MEMBER * insert(MEMBER *head,MEMBER *newNode,int style)
  47. head = insert( head, node, style);
  48. while ( !feof( fp ) )//没有到文件尾
  49. {
  50. node = ( MEMBER *)malloc(sizeof(MEMBER));
  51. node->next = NULL;
  52. if ( fread(node, sizeof(MEMBER), 1, fp ) == 1 )
  53. {
  54. head = insert( head, node, style);
  55. }
  56. else
  57. {
  58. free(node);
  59. }
  60. }
  61. }
  62. //关闭文件
  63. fclose(fp);
  64. return head;
  65. }
  66. /*********************************************************
  67. *函数名:insert
  68. *形参:head,要被插入的链表的头指针; 
  69. * newNode,要插入的结点的指针;
  70. * style,排序方式
  71. *返回值:更新后链表的头指针
  72. *函数功能:将新结点newNode插入到链表head中,按指定的排序方式style插入,
  73. * 默认按编号升序插入
  74. * style=1,按姓名升序排序
  75. * style=2,按姓名降序排序
  76. * style=3,按薪水升序排序
  77. * style=4,按薪水升序排序
  78. * style=其他,按编号升序排序
  79. *作者:qjh
  80. *编写日期:2008-9-18
  81. **********************************************************/
  82. MEMBER * insert(MEMBER *head,MEMBER *newNode,int style)
  83. {
  84. MEMBER *p1, *p2;
  85. p1 = head;
  86. p2 = head->next;
  87. switch( style )
  88. {
  89. case 1:   //按姓名升序插入
  90. while ( p2 != NULL )
  91. {
  92. if ( strcmp (p2->name , newNode->name ) < 0 )
  93. {
  94. p1 = p1->next;
  95. p2 = p2->next;
  96. }
  97. else
  98. break;
  99. }
  100. break;
  101. case 2:  //按姓名降序插入
  102. while ( p2 != NULL )
  103. {
  104. if ( strcmp (p2->name , newNode->name ) > 0 )
  105. {
  106. p1 = p1->next;
  107. p2 = p2->next;
  108. }
  109. else
  110. break;
  111. }
  112. break;
  113. case 3:  //按薪水升序插入
  114. while ( p2 != NULL )
  115. {
  116. if ( p2->salary < newNode->salary )
  117. {
  118. p1 = p1->next;
  119. p2 = p2->next;
  120. }
  121. else
  122. break;
  123. }
  124. break;
  125. case 4:  //按薪水降序插入
  126. while ( p2 != NULL )
  127. {
  128. if ( p2->salary > newNode->salary )
  129. {
  130. p1 = p1->next;
  131. p2 = p2->next;
  132. }
  133. else
  134. break;
  135. }
  136. break;
  137. default: //按编号升序插入
  138. while ( p2 != NULL )
  139. {
  140. if ( strcmp (p2->number , newNode->number ) < 0 )
  141. {
  142. p1 = p1->next;
  143. p2 = p2->next;
  144. }
  145. else
  146. break;
  147. }
  148. break;
  149. }
  150. newNode->next = p2;
  151. p1->next = newNode;
  152. return head;
  153. }
  154. /*********************************************************
  155. *函数名:writeToFile
  156. *形参:要写入的链表的头指针
  157. *返回值:无
  158. *函数功能:将头指针为head的链表全部写入到文件中
  159. *作者:qjh
  160. *编写日期:2008-9-18
  161. **********************************************************/
  162. void writeToFile(MEMBER *head)
  163. {
  164. MEMBER *p;  
  165. FILE *fp;
  166. if ( NULL == head )
  167. {
  168. printf("链表头指针为空,无法继续操作n");
  169. return; //退出函数,并非退出整个程序
  170. }
  171. fp = fopen( FILENAME , "wb" );
  172. if ( NULL == fp )
  173. {
  174. printf("文件打开不成功,无法继续操作n");
  175. return ;
  176. }
  177. p = head->next;
  178. while ( p != NULL )  //链表未结束
  179. {
  180. fwrite( p , sizeof( MEMBER ), 1, fp );//将结点p写入到文件中
  181. p = p->next;  //p后移一个结点
  182. }
  183. fclose( fp );
  184. }
  185. /*********************************************************
  186. *函数名:newNode
  187. *形参:head,链表的头指针
  188. *返回值:新建结点的指针
  189. *函数功能:新建一个结点,并从键盘为新结点赋值
  190. *作者:qjh
  191. *编写日期:2008-9-18
  192. **********************************************************/
  193. MEMBER * newNode(MEMBER *head)
  194. {
  195. //定义变量结点指针node,float tmp, char tmpDate[12];
  196. MEMBER *node; //
  197. float tmp;  //用来临时存储浮点数,并最终赋值到结构体中
  198. char tmpDate[12];//用来输入一个日期字符串(yyyy-mm-dd)
  199. //申请结点空间 存储到 node
  200. node = ( MEMBER * )malloc( sizeof( MEMBER ) );
  201. if ( NULL == node )  //申请不成功
  202. {
  203. printf("结点申请不成功n");
  204. return NULL;
  205. }
  206. node->next = NULL;
  207. //输入编号,并验证
  208. do 
  209. {
  210. printf("输入编号");
  211. gets( node->number );
  212. if ( strlen( node->number ) == 0 )//字符串为空
  213. {
  214. continue; //转去重新输入
  215. }
  216. //验证编号是否唯一
  217. //int unique(MEMBER* head,char * number);
  218. if ( unique( head, node->number ) == 0 ) //编号重复了
  219. {
  220. printf("编号有重复 ");
  221. continue;
  222. }
  223. break;//编号验证通过了,跳出循环
  224. }while(1);
  225. //输入姓名,并验证
  226. do 
  227. {
  228. printf("输入姓名");
  229. gets( node->name );
  230. if ( strlen( node->name ) == 0 )//字符串为空
  231. {
  232. continue; //转去重新输入
  233. }
  234. break;//姓名验证通过了,跳出循环
  235. }while(1);
  236. //输入角色代号,并验证
  237. do 
  238. {
  239. printf("输入角色代号(0-3)");
  240. if ( scanf( "%d", &node->role )  == 0)//输入的不是整型数据
  241. {
  242. while ( getchar() != 'n' );  //清除键盘缓冲区
  243. continue;
  244. }
  245. if ( node->role <0 || node->role > 3 )//不在0-3之间
  246. {
  247. while ( getchar() != 'n' );  //清除键盘缓冲区
  248. continue; //转去重新输入
  249. }
  250. break;//角色验证通过了,跳出循环
  251. }while(1);
  252. //输入年龄,并验证
  253. do 
  254. {
  255. printf("输入年龄");
  256. if ( scanf( "%d", &node->age )  == 0)//输入的不是整型数据
  257. {
  258. while ( getchar() != 'n' );  //清除键盘缓冲区
  259. continue;
  260. }
  261. if ( node->role <0  )//
  262. {
  263. while ( getchar() != 'n' );  //清除键盘缓冲区
  264. continue; //转去重新输入
  265. }
  266. break;//年龄验证通过了,跳出循环
  267. }while(1);
  268. //输入身高,并验证
  269. do 
  270. {
  271. printf("输入身高");
  272. if ( scanf( "%f", &tmp )  == 0)//输入的不是浮点型数据
  273. {
  274. while ( getchar() != 'n' );  //清除键盘缓冲区
  275. continue;
  276. }
  277. if ( tmp <0  )//不是正数
  278. {
  279. while ( getchar() != 'n' );  //清除键盘缓冲区
  280. continue; //转去重新输入
  281. }
  282. node->high = tmp;
  283. break;//身高验证通过了,跳出循环
  284. }while(1);
  285. //输入体重,并验证
  286. do 
  287. {
  288. printf("输入体重");
  289. if ( scanf( "%f", &tmp )  == 0)//输入的不是浮点型数据
  290. {
  291. while ( getchar() != 'n' );  //清除键盘缓冲区
  292. continue;
  293. }
  294. if ( tmp <0  )//不是正数
  295. {
  296. while ( getchar() != 'n' );  //清除键盘缓冲区
  297. continue; //转去重新输入
  298. }
  299. node->weight = tmp;
  300. break;//体重验证通过了,跳出循环
  301. }while(1);
  302. //输入薪水,并验证
  303. do 
  304. {
  305. printf("输入薪水");
  306. if ( scanf( "%f", &tmp )  == 0)//输入的不是浮点型数据
  307. {
  308. while ( getchar() != 'n' );  //清除键盘缓冲区
  309. continue;
  310. }
  311. if ( tmp <0  )//不是正数
  312. {
  313. while ( getchar() != 'n' );  //清除键盘缓冲区
  314. continue; //转去重新输入
  315. }
  316. node->salary = tmp;
  317. break;//薪水验证通过了,跳出循环
  318. }while(1);
  319. while (getchar( ) != 'n' ) ;//清除键盘缓冲区
  320. //输入加入日期,并验证
  321. do 
  322. {
  323. printf("输入加入日期");
  324. gets( tmpDate );
  325. //验证加入时间是否有效
  326. //int checkDate(MEMBER *newNode, char *tmpDate);
  327. if ( checkDate( node, tmpDate ) == 0 ) //日期不合法
  328. {
  329. printf("日期格式有误 ");
  330. continue;
  331. }
  332. break;//日期验证通过了,跳出循环
  333. }while(1);
  334. //返回结点指针
  335. return node;
  336. }
  337. /*********************************************************
  338. *函数名:list
  339. *形参:无
  340. *返回值:无
  341. *函数功能:从文件读入数据,形成链表,并遍历链表输出所有数据
  342. *作者:qjh
  343. *编写日期:2008-9-18
  344. **********************************************************/
  345. void list(MEMBER *head)
  346. {
  347. MEMBER *p; //定义指针p
  348. p= head->next;
  349. printf("%6s", "编号");
  350. printf("%10s", "姓名");
  351. printf("%8s" , "角色");
  352. printf("%5s", "年龄");
  353. printf("%10s", "身高");
  354. printf("%10s", "体重");
  355. printf("%12s", "薪水");
  356. printf("%12sn", "加入日期");
  357. while ( p != NULL )
  358. {
  359. printf("%6s", p->number);//输出编号
  360. //输出姓名
  361. printf("%10s", p->name);
  362. //。。。
  363. printf("%8s" , roleSet[p->role]);
  364. printf("%5d", p->age);
  365. printf("%10.1f", p->high);
  366. printf("%10.1f", p->weight);
  367. printf("%12.2f", p->salary);
  368. printf("%6d-%2d-%2dn", p->joinDate.year,
  369.  p->joinDate.month,
  370.  p->joinDate.day);
  371. p = p->next;
  372. }
  373. }
  374. /*********************************************************
  375. *函数名:unique
  376. *形参:链表的头指针head,
  377. * 要判断的编号字符指针number
  378. *返回值:编号已经存在返回0,
  379. *  编号不存在返回1
  380. *函数功能:判断新输入的编号在链表中是否已经存在
  381. *作者:qjh
  382. *编写日期:2008-9-18
  383. **********************************************************/
  384. int unique(MEMBER* head,char * number)
  385. {
  386. MEMBER *p;  //结点指针
  387. int flag; //标识是否唯一的变量(0表示不唯一,1表示唯一)
  388. flag = 1; //先假定本次编号验证会通过
  389. p = head->next;
  390. while ( p != NULL )
  391. {
  392. if ( strcmp( p->number , number ) == 0 ) //两 个字符串相同
  393. {
  394. flag = 0;
  395. return flag;
  396. }
  397. p = p->next;  //p后移
  398. }
  399. return flag;
  400. }
  401. /*********************************************************
  402. *函数名:checkDate
  403. *形参:链表的头指针head,
  404. * 要判断的日期字符指针number
  405. *返回值:输入正确1,
  406. *  输入不正确返回0
  407. *函数功能:判断新输入的日期格式是否正确,正确则赋值给newNode返回1,
  408. * 否则返回0
  409. *作者:qjh
  410. *编写日期:2008-9-18
  411. **********************************************************/
  412. int checkDate(MEMBER *newNode, char *tmpDate)
  413. {
  414. unsigned int i, j;//数组的循环变量
  415. int d[8];//用来将输入的字符转换为年、月、日对应的数值
  416. int flag; //标识验证是否成功的变量(0不成功、1成功)
  417. flag = 1;  //假定本次验证会成功
  418. if ( strlen( tmpDate ) != 10 ) //字符串长度不符
  419. {
  420. flag = 0;
  421. return flag;
  422. }
  423. if ( !(tmpDate[0] >= '0' && tmpDate[0] <= '9') )
  424. {
  425. flag = 0; 
  426. return flag;
  427. }
  428. if ( !(tmpDate[1] >= '0' && tmpDate[1] <= '9') )
  429. {
  430. flag = 0; 
  431. return flag;
  432. }
  433. if ( !(tmpDate[2] >= '0' && tmpDate[2] <= '9') )
  434. {
  435. flag = 0; 
  436. return flag;
  437. }
  438. if ( !(tmpDate[3] >= '0' && tmpDate[3] <= '9') )
  439. {
  440. flag = 0; 
  441. return flag;
  442. }
  443. if ( tmpDate[4] != '-' )
  444. {
  445. flag = 0; 
  446. return flag;
  447. }
  448. if ( !(tmpDate[5] >= '0' && tmpDate[5] <= '9') )
  449. {
  450. flag = 0; 
  451. return flag;
  452. }
  453. if ( !(tmpDate[6] >= '0' && tmpDate[6] <= '9') )
  454. {
  455. flag = 0; 
  456. return flag;
  457. }
  458. if ( tmpDate[7] != '-' )
  459. {
  460. flag = 0; 
  461. return flag;
  462. }
  463. if ( !(tmpDate[8] >= '0' && tmpDate[8] <= '9') )
  464. {
  465. flag = 0; 
  466. return flag;
  467. }
  468. if ( !(tmpDate[9] >= '0' && tmpDate[9] <= '9') )
  469. {
  470. flag = 0; 
  471. return flag;
  472. }
  473. //将每位数字字符转换成对应的数值,并且存储到数组d的各个元素中
  474. i = 0;
  475. for (j=0; j<strlen(tmpDate); j++)
  476. {
  477. if (tmpDate[j] != '-' )//不是‘-’,就是数字字符
  478. {
  479. d[i] = tmpDate[j] - '0';
  480. i++;
  481. }
  482. }
  483. //将年、月、日存储到结构体对应的成员中
  484. newNode->joinDate.year = d[0]*1000+d[1]*100+d[2]*10+d[3];
  485. newNode->joinDate.month = d[4]*10+d[5];
  486. newNode->joinDate.day = d[6]*10+d[7];
  487. if ( newNode->joinDate.year > 3000 || 
  488.  newNode->joinDate.year < 0 )
  489. {
  490. flag = 0;
  491. return flag;
  492. }
  493. if ( newNode->joinDate.month <1 ||
  494.  newNode->joinDate.month >12 )
  495. {
  496. flag = 0;
  497. return flag;
  498. }
  499. if ( newNode->joinDate.day < 1 ||
  500.  newNode->joinDate.day > 31 )
  501. {
  502. flag = 0;
  503. return flag;
  504. }
  505. flag = 1; 
  506. return flag;
  507. }
  508. /*********************************************************
  509. *函数名:freeList
  510. *形参:要释放的链表的头指针
  511. *返回值:无
  512. *函数功能:释放链表所有结点所占内存
  513. *作者:qjh
  514. *编写日期:2008-9-18
  515. **********************************************************/
  516. void freeList( MEMBER *head )
  517. {
  518. MEMBER *p , *q ;
  519. p = head;
  520. q = head->next;
  521. while ( q != NULL )
  522. {
  523. free( p );
  524. p = q;
  525. q = q->next;
  526. }
  527. free( p );
  528. head = NULL;
  529. }