首页
大事记
友情链接
留言板
关于
Search
1
无界拷贝文件在线传输系统开始公测
941 阅读
2
宝塔BT面板PHP防CC
921 阅读
3
解决SSH登录卡在"Last login"问题
797 阅读
4
高考作文论证方法之“广深高铁”
404 阅读
5
Linux环境安装Dlib——以Centos7为例
394 阅读
默认分类
新鲜科技
时事热点
学无止境
Python
Arduino
作文素材
C语言
踩坑记录
机器学习
资源分享
站长杂谈
登录
Search
标签搜索
机器学习
Datawhale
C语言
git
python
组队学习
物联网
esp8266
PHP
云顶书院
Linux
LLM
建站
网站
宝塔
开学
清明节
VPS
Arduino
开源硬件
MoyiTech
累计撰写
55
篇文章
累计收到
37
条评论
首页
栏目
默认分类
新鲜科技
时事热点
学无止境
Python
Arduino
作文素材
C语言
踩坑记录
机器学习
资源分享
站长杂谈
页面
大事记
友情链接
留言板
关于
搜索到
2
篇与
的结果
2022-11-05
「云顶书院」C语言复习笔记
前言说真的,在云顶书院的四周适应期简直太快太快了。就感觉好像还没开始学啥呢,但转头一看,之前对于C语言还是萌新的我已经学会了好多好多了......C语言的基本语法网上都有,在这就不再整理了,那就写点儿不一样的吧!作为强迫症 在这几周的编码过程中时时刻刻都想着优化自己的代码:怎么写更快、更美、更易读、更可续。甚至有的代码只写了1个小时,但优化它的时间甚至都接近了10个小时。在这儿主要是想梳理一些近期写过/遇到的比较有趣的代码Amazing codeLet's enjoy it!通过数组调用函数在完成本周作业时,需要一个随机生成+-*/的功能,但是对生成的数字都有一定的范围要求(1~100),那么在生成随机数后 首先想到的是先把四个运算生成器封装成函数,再返回是否答对,但是到了这里,使用连续的if-else就显得不够那么“优雅”。于是就想到了将四个函数放到一个数组里,由于函数名并不能通过整数型和字符型这些来表示,于是就想到了指针:将函数的地址储存到一个长度为4的数组中。调用时就可以先使用随机数作为数组索引进行调用。具体实现方式如下:int (*exam_container[4]) (int i) = {add_exam, sub_exam, mul_exam, div_exam};其中第一个int表示函数的返回值是int类型,*表示该数组储存的为指针,int i表示这四个函数的形参都是int i,后面大括号里面则是定义的四个函数的名称(注意不加括号)接着又发现了一个弊端,以加法生成器add_exam()为例//加法 int add_exam (int i) { //加法题目生成采用答案倒推法,避免使用while过多消耗系统资源 int input; int res = random (1, 100); int add2 = random (1, res - 1); //保证add1 > 0 int add1 = res - add2; printf ("%d + %d =", add1, add2); scanf ("%d", &input); exam_log[i][0] = add1; exam_log[i][1] = '+';//自动转化为ASCII码 exam_log[i][2] = add2; exam_log[i][3] = res; exam_log[i][4] = input; if (input == res) { return 10; } else { return 0; } }其中int类型exam_log负责储存本次考试每道题的详情,这段代码显然在四个函数里是重复的,scanf和input==res同样也是。这里就需要用函数返回一个数组,交由上层函数统一进行调用,于是就用到了指针函数: C 从函数返回数组 再经过一番修改,函数就变成这样了//加法 int *add_exam () { static int outcome[4]; //加法题目生成采用答案倒推法,避免使用while过多消耗系统资源 int res = random (1, 100); int add2 = random (1, res - 1); //保证add1 > 0 int add1 = res - add2; printf ("%d + %d =", add1, add2); outcome[0] = add1; outcome[1] = '+';//相当于返回的ASCII码 outcome[2] = add2; outcome[3] = res; return outcome; }由于函数变为了指针函数,且无需参数了,那么定义储存函数指针的数组就变成这样了int * (*exam_container[4]) () = {add_exam, sub_exam, mul_exam, div_exam};很恐怖对不对?完整代码待作业提交结束后奉上~//written by moyi //2022-11-04 #include<stdio.h> #include<time.h> #include<stdlib.h> #include<string.h> char data[100][3][20]; int count = 0; int exam_log[10][5]; char user_id[50]; int login(); void initialize(); void read_file(); void write_file (char *user_id, int mark, int time); int random (int start, int end); int random_except (int start, int end, int except_num); int print_info (char *user_id); void exam (char *user_id); void menu(); int *add_exam (); int *sub_exam (); int *mul_exam (); int *div_exam (); //把四种运算生成器放到数组里 //前面的*代表里面函数返回指针(这个试了好几分钟才发现的问题) //后面的星号代表函数的地址 int * (*exam_container[4]) () = {add_exam, sub_exam, mul_exam, div_exam}; int main() { initialize(); menu(); return 0; } void menu(){ while (1) { char input[50]; printf ("\nMenu:\n1.开始测试\n2.检查分数\n3.退出\n\n请输入指令(1/2/3):"); scanf ("%s", input); if (!strcmp (input, "1") ) { exam (user_id); } else if (!strcmp (input, "2") ) { if(!print_info (user_id)){ printf("你没考过试!\n"); } } else if (!strcmp (input, "3") ) { return; } else { system ("cls"); printf ("看看你写的啥!\n\n"); } } } //初始化 void initialize(){ srand ( (unsigned int) time (NULL) ); while(!login()){ printf("\n格式错误!请重新输入!\n"); } } //登录 int login(){ printf ("What is your ID:"); scanf ("%s", user_id); if (strlen (user_id) != 6) { return 0; } int i; for (i = 0; i < 6; i++) { if (i < 2) { if (user_id[i] > 'Z' || user_id[i] < 'A') { return 0; } } else { if (user_id[i] > '9' || user_id[i] < '0') { return 0; } } } system("cls"); printf ("Login success!\nHello:%s\n", user_id); return 1; } //读文件 void read_file() { //r:文件不存在会报错 //w+:文件被清空 //a:只写在最后面 //a+:读写,不会覆盖文件,没有文件也可以自动创建 FILE *fp = fopen ("record.txt", "a+"); char row[80]; char *token; int i = 0; count = 0;//读取前重置计数器 while (fgets (row, 80, fp) != NULL) { count++; token = strtok (row, ","); int j = 0; while (token != NULL) { if (j == 2) { token = strtok (token, "\n"); } strcpy (data[i][j], token); token = strtok (NULL, ","); j++; } i++; } fclose (fp); } //写入文件 void write_file (char *user_id, int mark, int time) { FILE *fp = fopen ("record.txt", "a"); //a:追加到文件结尾,节省IO资源 if (fp == NULL) { fprintf (stderr, "fopen() failed.\n"); exit (EXIT_FAILURE); } fprintf (fp, "%s,%d,%d\n", user_id, mark, time); fclose (fp); return; } int random (int start, int end) { return rand() % (end - start + 1) + start; } //生成随机数时不包含某数 int random_except (int start, int end, int except_num) { int tmp; do { tmp = random(start, end); } while (tmp == except_num); //注意是取等才循环 return tmp; } //加法 int *add_exam () { static int outcome[4]; //加法题目生成采用答案倒推法,避免使用while过多消耗系统资源 int res = random (1, 100); int add2 = random (1, res - 1); //保证add1 > 0 int add1 = res - add2; printf ("%d + %d =", add1, add2); outcome[0] = add1; outcome[1] = '+';//相当于返回的ASCII码 outcome[2] = add2; outcome[3] = res; return outcome; } //减法 int *sub_exam () { static int outcome[4]; int sum = random (1, 100); int x = random (1, sum - 1); //保证res > 0 int res = sum - x; printf ("%d - %d =", sum, x); outcome[0] = sum; outcome[1] = '-';//相当于返回的ASCII码 outcome[2] = x; outcome[3] = res; return outcome; } //乘法 int *mul_exam () { static int outcome[4]; //下面同样利用了100/a <= 100.0/a的限制,避免了使用while int res, a, b; a = random (1, 51); b = random (1, 100 / a); res = a * b; printf ("%d * %d =", a, b); outcome[0] = a; outcome[1] = '*';//相当于返回的ASCII码 outcome[2] = b; outcome[3] = res; return outcome; } //除法 int *div_exam () { static int outcome[4]; //除法跟乘法生成方式一样,换个参数就行 int res, Divisor, Dividend; res = random (1, 51); Divisor = random (1, 100 / res); Dividend = res * Divisor; printf ("%d / %d =", Dividend, Divisor); outcome[0] = Dividend; outcome[1] = '/';//相当于返回的ASCII码 outcome[2] = Divisor; outcome[3] = res; return outcome; } //考试函数 void exam (char *user_id) { int random_log[4];//已经出过的赋值1 int input; int *p; int i, tmp; int mark = 0;//初始分数 int start_time = time (0);//初始时间 tmp = random (0, 3);//确保random_expect函数正确执行 for (i = 0; i < 10; i++) { //用了个不太妙的方法 //对后3个题目进行操作,保证四中运算均出现 int flag=0; if(i > 6){ int j; for(j=0;j<4;j++){ if(!random_log[j]){ tmp = j; flag = 1; } } } if(!flag){ tmp = random_except (0, 3, tmp);//保证每次题目不同 } random_log[tmp] = 1; p = exam_container[tmp] ();//调用出题函数获取数组 scanf ("%d", &input); //判断答案是否正确 if (input == * (p + 3) ) { mark += 10; } //赋值到exam_log,便于考试结束后输出 exam_log[i][0] = *p; exam_log[i][1] = *++p; exam_log[i][2] = *++p; exam_log[i][3] = *++p; exam_log[i][4] = input; } int end_time = time (0); //写入数据 write_file (user_id, mark, end_time - start_time); //输出考试详情 printf ("\n\n 问题 | 正确答案 | 你的答案"); for (i = 0; i < 10; i++) { printf ("\n%3d%3c%3d=?|%10d|%d", exam_log[i][0], exam_log[i][1], exam_log[i][2], exam_log[i][3], exam_log[i][4]); } printf ("\n\n本次得分:%d\n时间:%d秒\n\n\n", mark, end_time - start_time); } //输出该ID的考试记录 int print_info (char *user_id) { system("cls"); printf ("你以前的记录是:"); read_file(); int res = 0; int i; for (i = 0; i < count; i++) { if (!strcmp (user_id, data[i][0]) ) { printf ("\n%s %3s %s秒", data[i][0], data[i][1], data[i][2]); res = 1; } } return res; } C语言随机数生成:rand和srand函数原文链接关于杨辉三角的一些思考原文链接超市老板那道题原文链接结语保持学习,保持热爱!
2022年11月05日
140 阅读
1 评论
0 点赞
2022-10-24
「云顶书院」适应期第二阶段学习总结与思考
作业任务超市老板题目你是一个超市的老板,超市里面有很多的商品,包括{"牛奶","面包","方便面","矿泉水","火腿肠","溜溜梅","薄荷糖","豆腐干","辣条","纸巾"},对应的价格是:{3,2,5,1,1.5,5,10,1,0.5,1}要求:试编写一个程序,要求输入对应的商品名称可以查询该商品的单价拓展要求1:自行输入购买的商品种类和数量(不可以预先设定)可以自动实现对商品的总价进行清算拓展要求2:并列出购物的小票(购买的商品名称 单价 购买个数 总价)要求对于小票中的商品进行同种商品的合并,比如多次输入“面包”的时候,可以在小票中只显示一次合并的数量拓展要求3:增加 添加商品 的功能添加新商品后,输入对应的商品名称可以查询该商品的单价,并满足以上拓展要求示例小票如下:商品名 单价 数量面包 2 2牛奶 3 6总价 22 而不是小票如下:商品名 单价 数量面包 2 2牛奶 3 6面包 2 1分析整体分析 本题的基本要求是求商品单价,可以定义两个数组为全局变量分别存储商品名和价格,其中商品名为字符串,应使用char类型的二维数组存储;价格为存在小数,应使用float类型的一维数组存储。再看拓展要求中的1、2项的要求可以用局部变量解决,第3项涉及到了数据的增加,那么就需要再定义一个全局变量count用于记录数组长度。 不难发现,无论是在基本要求还是在拓展要求中,程序都要进行一个相同的过程:在已有商品中查找,那么我们就可以定义一个函数check_name用于查找指定商品名并返回相应结果:在找到商品时,返回对应索引;在找不到商品时就返回-1(为什么不返回0,这样不是更方便使用if对0和非0进行判断了吗?因为查找到第一个时会返回索引0,而负数不是任何商品的索引!) 本程序功能较多,故可以在一个主菜单的死循环while(1)中添加各个功能,而开始菜单就写在主菜单循环的开头:1.单价查询 2.商品结算 3.添加商品 0.退出程序需要的知识标准输入/输入函数scanf和printf(stdio.h)DOS指令函数system(stdlib.h) cls用于清屏、pause可用于程序退出时字符串操作函数strcmp、strcpy(string.h)if-else判断、for while循环语句函数的定义解题首先是库的导入#include<stdio.h> #include<string.h> #include<stdlib.h>定义全局变量char goods_names[256][256] = {"牛奶","面包","方便面","矿泉水","火腿肠","溜溜梅","薄荷糖","豆腐干","辣条","纸巾"}; float goods_price[256] = {3,2,5,1,1.5,5,10,1,0.5,1}; int count=10;定义查找函数//查找商品:找到返回索引,否则返回 -1 int check_name(char name[]){ int i; for(i=0;i<count;i++){ if(!(strcmp(name, goods_names[i]))){ return i; } } return -1; }由于程序需要进行多次字符串的输入,就定义一个函数内变量char input_str[256];在循环开始时输出主菜单,并读取用户输入的数据{collapse}{collapse-item label="思考:为什么不使用int类型的输入?"}由于用户输入的数据具有不确定性——可能是一个数字、好几个数字、字母、汉字等,故使用字符串进行判别更加安全{/collapse-item}{/collapse}printf("菜单:\n1.单价查询\n2.商品结算并列出小票\n3.添加商品\n0.退出程序\n\n请输入指令(1/2/3/0):"); scanf("%s", &input_str);在查询完商品后使用进行清屏system("cls");判断进入购物车指令else if(!(strcmp(input_str, "2")))定义局部变量//定义购物车 {索引:数量} x 256 int cart[256][2]; int cart_count=0;搜索商品system("cls"); printf("请输入要购买的商品名称:"); scanf("%s", &input_str); int resp = check_name(input_str); while(resp == -1){ printf("查询无此商品,请重新输入:"); scanf("%s", &input_str); resp = check_name(input_str); }输入数量printf("请输入要购买的%s数量:", input_str); int item_count; scanf("%d", &item_count); while(item_count <= 0 ){ printf("数量需大于0,请重新输入要购买的%s数量:", input_str); scanf("%d", &item_count); }遍历购物车是否有重复商品 ,如果有则添加,并改变flag的值int i; int flag=1; for(i=0;i<cart_count;i++){ if(resp==cart[i][0]){ cart[i][1] += item_count; flag = 0; break; } }如果找不到重复商品则向购物车内添加项目if(flag){ cart[cart_count][0] = resp; cart[cart_count][1] = item_count; cart_count++; }一个二级菜单printf("添加成功!\n输入1继续添加商品输入其他内容退出(1/Others):"); scanf("%s", &input_str); if(strcmp(input_str, "1")){ break; }清屏并输出购物明细system("cls"); printf("您的购物详单如下:"); int i; float total_cost=0; for(i=0;i<cart_count;i++){ printf("\n商品名:%s,数量:%d,单价:%.2f,小计:%.2f", goods_names[cart[i][0]], cart[i][1], goods_price[cart[i][0]], cart[i][1]*goods_price[cart[i][0]]); total_cost += cart[i][1]*goods_price[cart[i][0]]; } printf("\n\n总计消费%.2f元\n\n~~~~~~~~~~~~~~~~~~~~~~~~\n", total_cost);新增商品else if(!(strcmp(input_str, "3")))清屏并输入商品名,存在则直接进入下一次循环输入商品名{collapse}{collapse-item label="思考:为什么不用break"}待更新···{/collapse-item}{/collapse}system("cls"); printf("请输入要添加商品的名称:"); scanf("%s", &input_str); int resp=check_name(input_str); if(resp!=-1){ printf("\n该商品已存在,添加失败!\n\n"); continue; }读入价格,并保留两位然后count自增使用%.2f可以保留两位小数输出printf("请输入商品价格(最小位数为:分,即小数点后两位):"); float input_price; scanf("%f", &input_price); input_price = ((int)(input_price*100))/100.0; strcpy(goods_names[count], input_str); goods_price[count] = input_price; count++; printf("添加成功!商品名:%s,价格:%.2f\n\n", input_str, input_price);完整代码//Shop program written by moyi //Date: 2020/10/21 #include<stdio.h> #include<string.h> #include<stdlib.h> char goods_names[256][256] = {"牛奶","面包","方便面","矿泉水","火腿肠","溜溜梅","薄荷糖","豆腐干","辣条","纸巾"}; float goods_price[256] = {3,2,5,1,1.5,5,10,1,0.5,1}; int count=10; //查找商品:找到返回索引,否则返回 -1 int check_name(char name[]){ int i; for(i=0;i<count;i++){ if(!(strcmp(name, goods_names[i]))){ return i; } } return -1; } int main(){ //程序启动 char input_str[256]; printf("This is a shop program\nWritten by moyi\nDate:2022/10/20\n\n"); //主菜单循环 while(1){ printf("菜单:\n1.单价查询\n2.商品结算并列出小票\n3.添加商品\n0.退出程序\n\n请输入指令(1/2/3/0):"); scanf("%s", &input_str); //查询价格 if(!(strcmp(input_str, "1"))){ system("cls"); printf("请输入你要查询商品的名称:"); scanf("%s", &input_str); system("cls"); int resp=check_name(input_str); if(resp == -1){ printf("查无此商品\n\n"); }else{ printf("找到商品:%s,价格为:%.2f\n\n", input_str, goods_price[resp]); } //二级菜单 }else if(!(strcmp(input_str, "2"))){ //定义购物车 {索引:数量} x 256 int cart[256][2]; int cart_count=0; //循环添加预购买的商品 while(1){ //清屏 system("cls"); printf("请输入要购买的商品名称:"); scanf("%s", &input_str); int resp = check_name(input_str); while(resp == -1){ printf("查询无此商品,请重新输入:"); scanf("%s", &input_str); resp = check_name(input_str); } printf("请输入要购买的%s数量:", input_str); int item_count; scanf("%d", &item_count); while(item_count <= 0 ){ printf("数量需大于0,请重新输入要购买的%s数量:", input_str); scanf("%d", &item_count); } //遍历购物车是否有重复商品 int i; int flag=1; for(i=0;i<cart_count;i++){ if(resp==cart[i][0]){ cart[i][1] += item_count; flag = 0; break; } } //没找到 if(flag){ cart[cart_count][0] = resp; cart[cart_count][1] = item_count; cart_count++; } printf("添加成功!\n输入1继续添加商品输入其他内容退出(1/Others):"); scanf("%s", &input_str); if(strcmp(input_str, "1")){ break; } } system("cls"); printf("您的购物详单如下:"); int i; float total_cost=0; for(i=0;i<cart_count;i++){ printf("\n商品名:%s,数量:%d,单价:%.2f,小计:%.2f", goods_names[cart[i][0]], cart[i][1], goods_price[cart[i][0]], cart[i][1]*goods_price[cart[i][0]]); total_cost += cart[i][1]*goods_price[cart[i][0]]; } printf("\n\n总计消费%.2f元\n\n~~~~~~~~~~~~~~~~~~~~~~~~\n", total_cost); //添加商品 }else if(!(strcmp(input_str, "3"))){ system("cls"); printf("请输入要添加商品的名称:"); scanf("%s", &input_str); int resp=check_name(input_str); if(resp!=-1){ printf("\n该商品已存在,添加失败!\n\n"); continue; } printf("请输入商品价格(最小位数为:分,即小数点后两位):"); float input_price; scanf("%f", &input_price); input_price = ((int)(input_price*100))/100.0; strcpy(goods_names[count], input_str); goods_price[count] = input_price; count++; printf("添加成功!商品名:%s,价格:%.2f\n\n", input_str, input_price); //退出 }else if(!(strcmp(input_str, "0"))){ break; }else{ //清屏、错误提示 system("cls"); printf("输入错误,请重新输入!\n\n"); } } return 0; }未完待续...字典题目题目解释1、预先设定50组英语词汇(附件txt文件),和与其对应的50组词、50组中文解释。2、通过查询英语词汇,可得到其【中文翻译】。拓展要求:1、程序能进行循环。2、增加 添加词汇 的功能添加新词汇后可以查到该词汇的中文翻译和解释。分析解题排序题目题目解释用户需输入10个整数,程序对其进行排序。要求:奇数全在前面,偶数全在后面,并且按照从小到大的顺序输出。拓展要求:1、 增加循环;2、 输出后,可以添加新数字,仍要求奇数全在前面,偶数全在后面,并且按照从小到大的顺序输出。示例:输入:9 96 23 21 6 200 2 28 92 10输出:9 21 23 2 6 10 28 92 96 200分析解题写在最后祝各位未来的程序员节日快乐!
2022年10月24日
125 阅读
0 评论
3 点赞