首页 > 代码库 > 8.12 项目实现第二阶段

8.12 项目实现第二阶段

实现代码如下:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. typedef struct
  5. {
  6. char * key; //单词的指针
  7. int ntrans; //解释的个数
  8. char ** trans; //解释的指针数组
  9. }WORD, * pW;
  10. //词典使用帮助信息
  11. void show_help()
  12. {
  13. printf("./main -opt <-r/-w>\n");
  14. printf("-text load dict.txt and use\n");
  15. printf("-bin <-r/-w>load dict.dat and use\n");
  16. printf(" -r read dict.dat and use\n");
  17. printf(" -w read dict.txt and creat dict.dat\n");
  18. }
  19. //打印出错信息
  20. void sys_err(char * str)
  21. {
  22. printf("%s \n",str);
  23. exit(-1);
  24. }
  25. //获取单词的个数
  26. int get_word_count(char * pathname)
  27. {
  28. int len = 0;
  29. char buf[1024];
  30. FILE * fp = fopen(pathname , "r");
  31. if(!fp)
  32. sys_err("open file error!");
  33. while( fgets( buf , sizeof(buf) , fp) != NULL)
  34. {
  35. len++;
  36. }
  37. return len / 2;
  38. }
  39. //为每个单词的解释开辟存储空间
  40. int trans_assign(pW w , char * str)
  41. {
  42. int n = 0 , i = 0;
  43. char *tmp[50]; //临时指针数组,用来存储每个解释的指针【思想好】
  44. w->ntrans = 0;
  45. char *p = strtok( str , "@");
  46. if(!p) return 0;
  47. tmp[n++] = p;
  48. while( (p = strtok(NULL , "@")) != NULL)
  49. tmp[n++] = p;
  50. w->ntrans = n;
  51. w->trans = malloc( n * sizeof(char *));
  52. for( i = 0 ; i < n ; ++i)
  53. {
  54. w->trans[i] = malloc( strlen(tmp[i]) +1 );
  55. strcpy(w->trans[i] , tmp[i]);
  56. }
  57. return n;
  58. }
  59. //把文本txt的内容初始化到结构体数组里
  60. void init_word_text(char * pathname , pW w , int n)
  61. {
  62. int i , len;
  63. char buf[1024];
  64. FILE * fp = fopen( pathname , "r");
  65. if(!fp)
  66. sys_err("open file error!");
  67. for( i = 0 ; i < n ; ++i)
  68. {
  69. // word
  70. fgets( buf , sizeof(buf) , fp);
  71. len = strlen(buf);
  72. buf[ len - 1] = ‘\0‘; //把 \n 换成 \0
  73. w[i].key = malloc( len - 1);
  74. strcpy( w[i].key , buf + 1);
  75. // trans
  76. fgets( buf , sizeof(buf) , fp);
  77. len = strlen(buf);
  78. buf[ len - 1] = ‘\0‘;
  79. trans_assign( &w[i] , buf + 6 );//+6表示把解释的Trans:去掉
  80. }
  81. fclose(fp);
  82. }
  83. //展示每一个单词和解释
  84. void show_word(WORD w)
  85. {
  86. int i;
  87. // printf("%s\n" , w.key);
  88. // printf("%d\n" , w.ntrans);
  89. printf("\n");
  90. for( i = 0 ; i < w.ntrans ; ++i)
  91. printf("%-3d:%s\n",i+1,w.trans[i]);
  92. }
  93. //展示所有的单词及解释
  94. void show_word_arr(pW w , int n)
  95. {
  96. int i;
  97. for( i = 0 ; i < n ; ++i)
  98. show_word(w[i]);
  99. }
  100. //交换两个结构体
  101. void swap(pW m , pW n)
  102. {
  103. WORD temp = *m;
  104. *m = *n;
  105. *n = temp;
  106. }
  107. //用来查找快速排序的分割元素
  108. int partition(pW w , int l , int r)
  109. {
  110. int i,j;
  111. for(i = l+1 , j = l ; i <= r ; ++i)
  112. {
  113. if(strcmp(w[i].key , w[l].key) < 0)
  114. {
  115. swap( &w[i] , &w[++j]);
  116. }
  117. }
  118. swap( &w[l] , &w[j]);
  119. return j;
  120. }
  121. //快速排序
  122. void quick_sort(pW w , int l , int r)
  123. {
  124. if( l >= r) return;
  125. int k = partition(w , l , r);
  126. quick_sort(w , l , k-1);
  127. quick_sort(w , k+1 , r);
  128. }
  129. //排序接口函数
  130. void sort_word(pW w , int n)
  131. {
  132. quick_sort( w , 0 , n-1);
  133. printf("初始化完成\n");
  134. }
  135. //判断用户是否退出
  136. int is_exit(char * str)
  137. {
  138. if(strcmp(str,"exit") == 0)
  139. return 1;
  140. else
  141. return 0;
  142. }
  143. //查找用户输入的单词,二分查找法
  144. int search_word(pW w , int n , char * str)
  145. {
  146. int l = 0, r = n -1, mid;
  147. while( l <= r)
  148. {
  149. mid = (l+r)/2;
  150. if(strcmp(w[mid].key , str) < 0)
  151. l = mid +1;
  152. else if(strcmp(w[mid].key , str) > 0)
  153. r = mid -1;
  154. else
  155. return mid;
  156. }
  157. return -1;
  158. }
  159. //释放每个单词申请的动态内存
  160. void free_word(pW w , int n)
  161. {
  162. int i,j;
  163. for(i = 0 ; i < n ; ++i)
  164. {
  165. free(w[i].key);
  166. for(j = 0 ; j < n ; ++j)
  167. {
  168. free(w[i].trans[j]);
  169. }
  170. free(w[i].trans);
  171. }
  172. }
  173. //把结构体数组写到二进制文件里
  174. void write_word_bin(char * pathname , pW word , int n)
  175. {
  176. int i , j , len;
  177. FILE * fp = fopen( pathname , "w");//打开dict.bin准备写入
  178. fwrite( &n , sizeof(n) , 1 , fp);//先把总行数写进去
  179. for( i = 0 ; i < n ; ++i)
  180. {
  181. len = strlen(word[i].key) + 1;// +1 这个坑啊
  182. fwrite( &len ,sizeof( int ), 1,fp ); // 写进去单词的长度
  183. fwrite( word[i].key , len , 1 , fp); //写进去单词的内容
  184. fwrite( &word[i].ntrans , sizeof( int ) , 1 , fp);//写进去解释的个数
  185. for( j = 0 ; j < word[i].ntrans ; ++j)
  186. {
  187. len = strlen( word[i].trans[j] ) + 1;//计算出每个解释的长度
  188. fwrite( &len ,sizeof( int ), 1, fp );//写进去每个解释的长度
  189. fwrite( word[i].trans[j] , len , 1 ,fp );//写进去每个解释的内容
  190. }
  191. }
  192. fclose(fp);
  193. }
  194. //从二进制文件读到结构体数组内
  195. void read_from_bin(char * pathname , pW word , int n)
  196. {
  197. int i , j , len;
  198. FILE * fp = fopen( pathname , "r");//打开dict.bin
  199. fseek( fp , 4 , SEEK_SET);//偏移4个字节,因为之前取出4个总行数了
  200. for( i = 0 ; i < n ; ++i)
  201. {
  202. fread(&len ,sizeof( int ), 1, fp );//把单词的长度读取出来
  203. word[i].key = malloc( len ); //为单词开辟存储空间
  204. fread( word[i].key , len , 1 , fp); //把单词读取出来
  205. fread( &word[i].ntrans , sizeof( int ) , 1 , fp);//把解释个数读取过来
  206. word[i].trans = malloc( word[i].ntrans * sizeof(char * ));//开辟解释空间
  207. for( j = 0 ; j < word[i].ntrans ; ++j)
  208. {
  209. fread( &len ,sizeof( int ), 1, fp );//读取每个解释的长度
  210. word[i].trans[j] = malloc( len );//开辟每个解释的空间
  211. fread( word[i].trans[j] , len , 1 ,fp );//把每个解释读取出来
  212. }
  213. }
  214. fclose(fp);
  215. }
  216. int main(int argc , char * argv[])
  217. {
  218. if(argc < 2) //如果命令行参数小于2,退出
  219. {
  220. show_help();
  221. return -1;
  222. }
  223. int n , res , m;
  224. char buf[1024];
  225. pW word = NULL;
  226. if( strcmp(argv[1] , "-text") == 0) //但参数为-text时候,从文本读
  227. {
  228. n = get_word_count("dict.txt");
  229. word = malloc( n * sizeof(*word) );
  230. init_word_text("dict.txt", word , n);
  231. sort_word( word , n);
  232. // show_word_arr( word , n);
  233. }
  234. else if( strcmp(argv[1] , "-bin") == 0)
  235. {
  236. if(argv[2])
  237. {
  238. if( strcmp(argv[2] , "-r") == 0)
  239. {
  240. FILE * fp = fopen( "dict.bin" , "r");//打开dict.bin
  241. if(!fp) sys_err("not bin file! now please\t-bin -w");
  242. fread( &n , sizeof( int ) , 1 , fp); //读取有多少行
  243. fclose( fp );
  244. word = malloc( n * sizeof(*word));//开辟结构体数组内存空间
  245. read_from_bin("dict.bin" , word , n);
  246. }
  247. else if( strcmp(argv[2] , "-w") == 0)
  248. {
  249. n = get_word_count("dict.txt");
  250. word = malloc( n * sizeof(*word));
  251. init_word_text("dict.txt",word,n);
  252. sort_word( word , n);
  253. write_word_bin("dict.bin" , word , n);
  254. }
  255. else
  256. {
  257. show_help();
  258. return -1;
  259. }
  260. }
  261. else
  262. {
  263. show_help();
  264. return -1;
  265. }
  266. }
  267. else
  268. {
  269. show_help();
  270. return -1;
  271. }
  272. while(1)
  273. {
  274. printf("please input your word : \n");
  275. fgets(buf,sizeof(buf),stdin);
  276. m = strlen(buf);
  277. buf[m-1] = ‘\0‘;
  278. if(is_exit(buf))
  279. break;
  280. res = search_word( word , n , buf);
  281. if(res != -1)
  282. show_word(word[res]);
  283. else
  284. printf("\nnot find\n");
  285. }
  286. free_word(word , n);
  287. free(word);
  288. return 0;
  289. }



来自为知笔记(Wiz)


附件列表

     

    8.12 项目实现第二阶段