zoukankan      html  css  js  c++  java
  • 【C语言入门教程】4.10 综合实例

    4.10.1 建立播放列表

    数据字典

    名称 数据类型 说明
    MAX_LENGTH 符号常量 用于定义数组长度,表示列表最大长度
    MAX_FILE_LENGTH 符号常量 用于定义数组长度,表示文件名最大长度
    GET_NAME 符号常量 用于scanf()函数输入文件名,说明输入字符串的长度,值为 %<MAX_FILE_LENGTH>s
    *p_list 整型指针数组 用于指定播放列表的顺序
    f_list 二维字符数组 用于保存播放列表中文件路径与名称,MAX_LENGTH作为第一维长度,MAX_FILE_LENGTH作为第二维长度
    i 整型变量 用于遍历播放列表,值域为 0 至 MAX_LENGTH - 1
    len 整型变量 用于保存播放列表当前长度,该长度小于 MAX_LENGTH
    select_value 整型变量 用于接收键盘输入的菜单选择
    exit_switch 字符变量 用于控制程序主操作循环的退出
    #include <stdio.h>
    #include <stdlib.h>
    
    #define MAX_LENGTH 5			// 定义数组长度,表示列表最大长度
    #define MAX_FILE_LENGTH 255	// 定义数组长度,表示文件名最大长度
    #define GET_NAME "%255s"		// 用于 scanf() 函数输入文件名,说明输入字符串的长度
    
    int main()
    {
    	unsigned int i, len;
    	char *p_list[MAX_LENGTH];		// 定义指针列表
    	char f_list[MAX_LENGTH][MAX_FILE_LENGTH + 1]; // 定义文件名列表,件名最大长度加 1 是用于存放字符串结束符
    	unsigned int j;	// 用于排序的循环控制变量
    	char *p_temp;		// 用于排序时交换指针列表中的数据
    
    	for (i = 0; i < MAX_LENGTH; i++) // 用循环对指针列表和文件名列表初始化
    	{
    		p_list[i] = NULL;	// 将指针列表指向NULL
    		f_list[i][0] = 0;	// 将字符串列表首位置 0
    	}
    
    	int select_value;			// 用于 接收键盘输入的菜单选择
    	char exit_switch = 1;		// 用于 控制程序主操作循环的退出
    	len = 0;					// 初始化列表长度
    
    	do
    	{
    		puts("请选择操作命令:");
    		puts("(1)添加新文件");
    		puts("(2)删除列表中的文件");
    		puts("(3)打印播放列表");
    		puts("(4)退出程序");
    		puts("(5)按文件名排序");
    
    		scanf("%1d", &select_value);	// 输入菜单选择
    		getchar();						// 吸收多余的输入字符
    
    		switch (select_value)
    		{
    			case 1: // 添加 文件
    
    				if (len < MAX_LENGTH)
    				{
    					puts("请输入文件名");
    					for (i = 0; i < MAX_LENGTH; i++)
    					{
    						if (!f_list[i][0]) // 二维字符数组行首为 0,则表示是空位
    						{
    							while (!scanf(GET_NAME, f_list[i])) // 输入文件名,并判断文件名是否有效
    							{
    								puts("请输入正确的文件名");
    							}
    							p_list[len++] = f_list[len]; // 将指针列表所对应的单元,指向文件名存放的内存地址
    							break;
    						}
    					}
    				}
    				else
    				{
    					puts("文件列表已满!");
    				}
    
    				break;
    			case 2: // 删除列表中的文件
    
    				puts("请输入文件编号:");
    				scanf("%u", &i);
    				if (i > 0 && i <= len) // 判断编号是否有效,有效的编码在 1 和 总长度之间
    				{
    					*p_list[--i] = NULL; // 通过指针间接引用文件列表,将目标文件名删除
    					while (i < len - 1) // 循环,从列表中删除的位置到列表结束
    					{
    						p_list[i] = p_list[i + 1]; // 将游标所指向的指针列表后的元素向前挪进 1 位
    						i++;
    					}
    					len--; // 列表长度 减 1
    				}
    				else
    				{
    					puts("您所输入的文件编号不存在!");
    				}
    
    				break;
    			case 3: // 打印播放列表
    
    				for (i = 0; i < len; i++)
    				{
    					printf("%d : %s
    ", i + 1, p_list[i]);
    				}
    
    				break;
    			case 5: // 按文件名排序
    
    				if (len > 1)
    				{
    					for (i = 0; i < len - 1; i++)
    					{
    						for (j = i + 1; j < 1; j++)
    						{
    							if (*p_list[i] > *p_list[j]) // 比较 2 个文件名字符串首个字符大小
    							{
    								p_temp = p_list[i];
    								p_list[i] = p_list[j];
    								p_list[j] = p_temp;
    							}
    						}
    					}
    				}
    
    				break;
    			default:
    
    				exit_switch = 0;
    
    				break;
    		}
    
    	} while (exit_switch);
    
    	return EXIT_SUCCESS;
    }

    该代码设置了一个主控制循环,由主控循环反复输入控制提示信息,并等待用户的输入。用户可输入指定的数字来执行对应的操作。

    • 输入数字 1,程序提示键入文件名,文件名并不是按列表的顺序存放在字符数组 f_list 中,而是在遍历数组 f_list 寻找行首为 0 的空位。储存成功后,将字符串在内存中的首地址传送给指针列表 p_list,p_list 则是按列表保存每个文件名字符串的地址。
    • 输入数字 2,程序提示输入文件编号,该编号是从 1 开始的,所以在进行删除处理前,要将保存编号的游标 i 自减1。删除文件名字符串,只需要将该字符串行首的元素置0。然后依次将指针列表中游标所指向位置以后的数值复制到前 1 位,再将列表总长度减去 1。这样,可以删除列表中任何位置的字符串。
    • 输入数字 3,程序将顺序打印播放列表,首先用游标从列表头开始遍历,再用指针列表参照游标的数值间接引用文件名列表。
    • 输入数字 4,程序主操作循环退出标记 exit_switch 被置为 0,操作结束后程序跳出主循环,这样就能退出程序。

    注意:在 do 循环中,scanf() 函数接收一个数字字符作为用户操作菜单的指令。如果用户输入 非法字符,这些字符将进入下一轮循环,并被 scanf()函数接收作为输入。这是由于标准输入的缓冲区缓冲所造成的,形成真正的死循环。如果在 scanf() 函数后用 getchar() 函数接收这些非法字符,即可避免该问题。

    4.10.2 对播放列表排序

    用户在使用媒体播放器时,经常会根据自己的喜好对播放列表进行排序。排序的方法有按名称排序、按播放时长排序、按媒体信息排序。各种排序的原理大同小异,所以这里只选择了按名称排序来演示播放列表排序的程序设计方法。

    排序只有在列表长度大于 1 时才有意义,所以首先要判断列表长度是否大于 1,然后用双层循环变量 *p_list 数组。比较两个数组元素所指向内存中的内容,如果前面的内容大于后者,则交换 *p_list 数组元素的地址。

    具体见上例中的 case 5

  • 相关阅读:
    Windows下如何检测用户修改了系统时间并且把系统时间改回来
    洛谷 1220 关路灯
    洛谷 2279 [HNOI2003]消防局的设立
    洛谷 1498 南蛮图腾
    bzoj 1036 [ZJOI2008]树的统计Count 树链剖分模板
    codevs 1021 玛丽卡 SPFA
    codevs 1077 多源最短路 flyod
    Vijos P1133 装箱问题 01背包
    codevs 1069 关押罪犯 并查集
    codevs 1073 家族 并查集
  • 原文地址:https://www.cnblogs.com/52php/p/5681362.html
Copyright © 2011-2022 走看看