C语言中的趣味代码(五)

news2025/1/13 15:42:01

我想以此篇结束关于C语言的博客,因为在C语言拖得越久越不能给大家带来新的创作,在此我也相信大家对C语言已经有了一个新的认知。进入正题,在这一篇中我主要编一个“英语单词练习小程序”来给大家展开介绍,从测试版逐步改良,每一步详细讲解让大家能够对学过的知识再有一个全新的认知。

1. 英语练习软件

1.1 单词显示软件

在编写英语学习软件之前,我们先来编写一个只能随机显示单词的程序,我们看下面的代码:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define QNO 12//单词的数量
char* cptr[] = { "动物","汽车","花","家","桌子","书",
				"椅子","爸爸","妈妈","爱","和平","杂志"};
char* eptr[] = { "animal","car","flower","house","desk","book",
                 "chair","father","mother","love","peace","magazine"};
int main()
{
	int nq, pq;//题目编号和上一次的题目编号
	int sw;//选择中文英文
	int retry;//是否接着尝试
	srand(time(NULL));
	pq = QNO;
	do
	{
		do 
		{
			nq = rand() % QNO;
		} while (nq == pq);
		sw = rand() % 2;
		printf("%s\n", sw ? eptr[nq] : cptr[nq]);
		pq = nq;
		printf("再来一次吗?0-否/1-是:");
		scanf("%d", &retry);
	} while (retry == 1);
	return 0;
}

我们简单运行一下看看效果,然后再这个基础上进行改良:

 程序运行。从“动物”,“汽车”.....以及与这些词对应的英语单词“animal”,"car"...这12组共24个单词中随机选出的单词被显示出来,用于存放指向单词字符串的指针的数组有2个,中文单词是cptr,英文单词的数组是eptr,我们把这两个数组的下标成为单词的“编号”。为了随机选择单词,我们需要用到2个变量nq和sw,这2个变量的值都是随机的。变量nq表示要显示的单词的编号。nq的值设为大于等于0小于QNO的随机数。变量nq设定与上一次现实的单词的编号pq不同的值,所以同一个编号的单词不会被连续选中。变量sw表示显示中文或者英文。sw的值为0时显示为中文单词,为1时显示英语单词,值0和1设为随机数。

1.2 向单词学习软件扩展

在刚才的程序中只能显示单词,现在我们要显示单词的时候提供选项,共学习者选择,学习者选完程序进行正误判断。我们呢来实现一下:

#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#define QNO 12
#define CNO 4
char* cptr[] = { "动物","汽车","花","家","桌子","书",
				"椅子","爸爸","妈妈","爱","和平","杂志"};
char* eptr[] = { "animal","car","flower","house","desk","book",
                 "chair","father","mother","love","peace","magazine"};
void print_cand(const int c[], int sw)//显示选项
{
	int i;
	for (i = 0; i < CNO; i++)
		printf("(%d)%s ", i, sw ? cptr[c[i]] : eptr[c[i]]);
	printf(":");
}
int make_cand(int c[], int n)//生成选项并返回正确答案的下标
{
	int i;
	c[0] = n;
	for (i = 1; i < CNO; i++)
		c[i] = rand() % QNO;
	return 0;
}
int main()
{
	int nq, pq;
	int na;
	int sw;
	int retry;
	int cand[CNO];
	srand(time(NULL));
	pq = QNO;
	do
	{
		int no;
		do
		{
			nq = rand() % QNO;
		} while (nq == pq);
		na = make_cand(cand, nq);
		sw = rand() % 2;
		printf("哪一个是%s?\n", sw ? eptr[nq] : cptr[nq]);
		do
		{
			print_cand(cand, sw);
			scanf("%d", &no);
			if (no != na)
				printf("\a回答错误。");
		} while (no != na);
		printf("回答正确。");
		pq = nq;
		printf("再来一次吗?0-否/1-是");
		scanf("%d", &retry);
	} while (retry == 1);
	return 0;
}

我们来运行一下看看效果:

 决定用于出题的单词的方法和上一个程序相同,在这个程序中追加了两个函数,下面我们就一起来学习一下这两个函数。

  1. 函数print_cand:显示选项
  2. 函数make_cand:生成选项

函数print_cand用于显示选项,它将接受下面两个参数:

 c:存有选项编号的数组

参数c接收的是存有选项单词编号的数组。

sw:题目的语言(英文/中文)

参数sw的值表示用来出题的单词的语言。若用的是英语,则sw为1,若为中文,则sw为0。for语句 中则显示与题目相反的单词。

函数make_cand用于生成要提示的4个选项,他将接收下面两个参数:

c:存有选项编号的数组

参数c接收的是存有选项单词编号的数组。

n:题目(正确答案)的编号

参数n接收的是正确答案(用于出题的单词)的编号。

运行程序我们会发现,这个程序存在两个隐藏问题:正确答案一定位于选项开头的位置,这让一来学习者就知道答案了。由于后面3个选项设为大小等于0小于QNO的随机数,因此可能会生成相同的随机数值,此时就会出现重复的选项。

1.3 生成选项(改良版本)

为了解决上面程序中的隐藏问题,我们可以将make_cand函数修改成下面这样:

int make_cand(int c[],int n)
{
  int i,j,n;
  c[0]=n;
  for(i=1;i<CNO;i++)
   {
     do
     {
       n=rand()%QNO;
       for(j=0;j<i;j++)
        if(c[j]==n)
          break;
     }while(i!=j);
     c[i]=n;
   }
  j=rand()%CNO;
  if(j!=0)
   swap(int,c[0],c[j]);
  return j;
}

此项的操作和上一个程序相同,把正确答案的编号n赋给数组的开头元素c[0]。这个for语句负责生成剩下的3个选项,把变量i的值增量给1,2,3,进行3次循环。这里和前面程序的不同之处在于,for语句的循环体里面加入了do...while语句,形成了二重循环的结构,在内侧的do...while语句的作用下,程序会一直重复生成随机数直到出现没有选过的选项值为止,这样一来就避免了选项出现重复,接下来我们要做的是移动正确答案,首先生成随机数0~3,把该值设为j,如果生成的随机数刚好为0,那么就变成了c[0]和c[0],这是程序会通过if语句跳过交换处理(正确答案的移动操作)。此外,用随机数生成的j的值的范围必须设为0~3而不能是1~3,因为正确答案绝不能位于开头。

1.4 单词文件的读取

如果用于出题的单词只有12个,学习者很容易就能记住,下面我们来让程序能够处理更多的单词。如果单词达到了一定的数量,那么就应该提供一个单词专用文件,以便追加和删除单词,但是在这种情况下,程序方面单词数量就会变得不明确,也就无法把单词存入“数组”,因此在声明时数组的元素个数必须是已知的,因此我们需要在运行程序时为任意元素个数的数组动态分配空间。

#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#include<string.h>
#define CNO 4
#define swap(type,x,y) do{type t=x;x=y;y=t;}while(0)
int QNO;
char** cptr;
char** eptr;
void print_cand(const int c[], int sw)//显示选项
{
	int i;
	for (i = 0; i < CNO; i++)
		printf("(%d)%s ", i, sw ? cptr[c[i]] : eptr[c[i]]);
	printf(":");
}
int make_cand(int c[], int n)
{
    int i, j, x;
    c[0] = n;
    for (i = 1; i < CNO; i++)
    {
        do
        {
            x = rand() % QNO;
            for (j = 0; j < i; j++)
                if (c[j] == x)
                    break;
        } while (i != j);
        c[i] = x;
    }
    j = rand() % CNO;
    if (j != 0)
        swap(int, c[0], c[j]);
    return j;
}
int read_tango()
{
    int i;
    FILE* fp;
    if ((fp = fopen("TANGO.txt","r")) == NULL)
        return 1;
    fscanf(fp, "%d", &QNO);
    if ((cptr = calloc(QNO, sizeof(char*))) == NULL)
        return 1;
    if ((eptr = calloc(QNO, sizeof(char*))) == NULL)
        return 1;
    for (i = 0; i < QNO; i++)
    {
        char etemp[1024];
        char ctemp[1024];
        fscanf(fp, "%s%s", etemp, ctemp);
        if ((eptr[i] = malloc(strlen(etemp) + 1)) == NULL)
            return 1;
        if ((cptr[i] = malloc(strlen(ctemp) + 1)) == NULL)
            return 1;
        strcpy(eptr[i], etemp);
        strcpy(cptr[i], ctemp);
    }
    fclose(fp);
    return 0;
}
int main()
{
    int i;
    int nq, pq;
    int na;
    int sw;
    int retry;
    int cand[CNO];
    if (read_tango() == 1)
    {
        printf("\a单词获取失败。\n");
        return 1;
    }
    srand(time(NULL));
    pq = QNO;
    do
    {
        int no;
        do
        {
            nq = rand() % QNO;
        } while (nq == pq);
        na = make_cand(cand, nq);
        sw = rand() % 2;
        printf("哪一个是%s?\n", sw ? eptr[nq] : cptr[nq]);
        do
        {
            print_cand(cand, sw);
            scanf("%d", &no);
            if (no != na)
                printf("回答错误。");
        } while (no != na);
        printf("回答正确。");
        pq = nq;
        printf("再来一次吗?0-否/1-是:");
        scanf("%d", &retry);
    } while (retry == 1);
    for (i = 0; i < QNO; i++)
    {
        free(eptr[i]);
        free(cptr[i]);
    }
    free(eptr);
    free(cptr);
    return 0;
}

我们来运行一下看看效果:

用于存放中文单词的cptr和用于存放英语单词的eptr这两个指针指向的都是指向char型的指针,即指向“指向已动态分配的字符串的”指针的数组。我们准备的单词数据是以“TANGO”为名称的文本文档形式,如下图:

第一行写入了一个整数值表示单词数量,从第二行起准备了英语单词和对应的中文释义,函数read_tango用于打开文本文件“TANGO”,并在分配存储空间的同时读取单词,当文件无法打开时或者存储空间分配失败时返回1,正常读取时返回0。在这里读取文件会常遇到一个问题那就是中文会出现乱码的情况,如下图:

那怎么解决这种问题呢?我只需要找到文本文件点击另存为,将其编码改为ASNI即可:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1635385.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言入门课程学习笔记-7

C语言入门课程学习笔记-7 第31课 - 初探程序中的函数实验-函数调用实验-函数求前n个正整数和 第32课 - 深入浅出函数调用第33课 - 函数定义细节剖析实验-返回int实验-返回void 第34课 - 函数参数深度剖析实验-形参实参实验-数组元素作为函数形参小结 第35课 - 编写函数对数组排…

前端: 浏览器调试小技巧

1. 如何禁止某个网站跳转: 用于拦截网站地址 2. 如何在线上环境调试源代码, 给源代码打断点 3. 如何在线编写代码 线上调试代码: network -> 找到加载的html文件 -> 右击 -> 选择override content (浏览器的代理调试程序) -> 可以在线写代码啦 4. 如何通过浏览器…

电脑提示msvcr110.dll文件丢失的常见问题以及解决方案

在使用电脑时突然提示msvcr110.dll文件丢失的问题&#xff0c;这是一个的常见问题接下俩这篇文章将教大家几种以及msvcr110.dll丢失的解决方案&#xff0c;用户可能会遇到一些常见问题&#xff0c;这些问题可能会影响他们的软件运行或系统稳定性。以下是一些常见问题及其解决方…

R语言的学习——day1

将数据框中某一列数据改成行名 代码 结果

可平滑替代FTP的FTP替代解决方案,具有哪些强大功能?

FTP是一种广泛使用的文件传输协议&#xff0c;主要用于在网络上的计算机之间传输文件。具有以下特点&#xff1a; 1.简单易用&#xff1a;FTP协议相对简单&#xff0c;易于设置和使用&#xff0c;许多操作系统和应用程序都内置了对FTP的支持。 2.广泛的客户端支持&#xff1a…

C++三大特性及应用

C三大特性 面向对象程序设计&#xff08;OOP&#xff09;是一种编程范式&#xff0c;它使用“对象”来设计软件。在OOP中&#xff0c;对象是类的实例&#xff0c;类包含数据&#xff08;属性&#xff09;和可以对数据执行操作的方法&#xff08;行为&#xff09;。 面向对象的…

Ieetcode——21.合并两个有序链表

21. 合并两个有序链表 - 力扣&#xff08;LeetCode&#xff09; 合并两个有序链表我们的思路是创建一个新链表&#xff0c;然后遍历已知的两个有序链表&#xff0c;并比较其节点的val值&#xff0c;将小的尾插到新链表中&#xff0c;然后继续遍历&#xff0c;直到将该两个链表…

请求路径引发的http308错误

记录一个请求路径输错引发的问题。 正确路径&#xff1a; /user/bind-email 请求路径我们如果输错故意多打一个s /user/bind-emails 正常预检请求会报错404未找到&#xff0c;我们下意识的就去排查路径是不是写错了 但是如果多打一个/ /user//bind-email 此时预检请求会报308永…

【iOS】消息流程分析

文章目录 前言动态类型动态绑定动态语言消息发送objc_msgSendSEL&#xff08;selector&#xff09;IMP&#xff08;implementation&#xff09;IMP高级用法 MethodSEL、IMP、Method总结流程概述 快速查找消息发送快速查找的总结buckets 慢速查找动态方法解析resolveInstanceMet…

做国外数据采集,更改ip后还被封是ip质量的原因吗?

IP质量低确实会出现封锁情况&#xff0c;但不是唯一的因素。 高质量的IP地址通常不容易被锁定&#xff0c;因为他们往往是由正规的ISP&#xff08;互联网服务商&#xff09;。但是&#xff0c;即使是高质量的IP地址&#xff0c;也有可能受其他因素影响导致封锁&#xff0c;如滥…

详解封装,继承,多态

java是一种面向对象的编程语言。 面向对象&#xff1a;是把构成问题的事务分解成各个对象&#xff0c;而建立对象的目的也不是为了完成一个个步骤&#xff0c;而是为了描述某个事物在解决整个问题的过程中所发生的行为。面向对象有封装、继承、多态的特性&#xff0c;所以易维…

肝了半年,我整理出了这篇云计算学习路线(新手必备,从入门到精通)

大家好&#xff01;我是凯哥&#xff0c;今天给大家分享一下云计算学习路线图。这是我按照自己最开始学习云计算的时候的学习路线&#xff0c;并且结合自己从业多年所涉及的知识精心总结的云计算的思维导图。这是凯哥精心总结的&#xff0c;花费了不少精力哦&#xff0c;希望对…

【论文阅读】ChipNeMo中的领域适配检索模型

前面先总体学习了《ChipNeMo: Domain-Adapted LLMs for Chip Design》。然后发现文章中还有细节需要继续学习&#xff0c;前一篇看了领域适配分词&#xff0c;今天接着看领域数据微调的预训练检索模型。 领域适配检索模型 众所周知&#xff0c;LLM 可以生成不准确的文本&…

DVWA靶场

DVWA是指Damn Vulnerable Web Application&#xff0c;是一个用于教育和训练网络安全人员的虚拟漏洞应用程序。DVWA模拟了一个包含了多种常见Web安全漏洞的虚拟环境&#xff0c;包括SQL注入、XSS攻击、CSRF攻击等等。通过使用DVWA&#xff0c;安全人员可以学习和实践各种Web安全…

科研学习|论文解读——CVPR 2021 人脸造假检测(论文合集)

随着图像合成技术的成熟&#xff0c;利用一张人脸照片合成假视频/不良视频现象越来越多&#xff0c;严重侵犯个人隐私、妨碍司法公正&#xff0c;所以人脸造假检测越来越重要&#xff0c;学术界的论文也越来越多。 一、研究1 1.1 论文题目 Multi-attentional Deepfake Detecti…

从零开始构建大语言模型(MEAP)

原文&#xff1a;annas-archive.org/md5/c19a4ef8ab1664a3c5a59d52651430e2 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 一、理解大型语言模型 本章包括 大型语言模型&#xff08;LLM&#xff09;背后的基本概念的高层次解释 探索 ChatGPT 类 LLM 源自的 Transfo…

第二证券投资参考:汽车以旧换新细则发布 云厂商AI投资持续加码

上星期五&#xff0c;A股放量大涨。两市股指盘中单边上行&#xff0c;午后再度攀升&#xff0c;沪指涨超1%&#xff0c;创业板指大涨超3%&#xff1b;到收盘&#xff0c;沪指涨1.17%报3088.64点&#xff0c;深证成指涨2.15%报9463.91点&#xff1b;创业板指涨3.34%报1823.74点&…

git 的迁移

现象是gitlab经常会挂掉&#xff0c;linux会显示磁盘空间不足&#xff0c;实际上&#xff0c;我们linux某个目录的空间是4T。这个空间应该是足够的。猜测是gitlab的安装目录不对导致的空间不足。 1、查找原因 用rpm 安装gitlab会有自己的目录&#xff0c;很多安装文件会在opt…

当非遗遇上全身动作捕捉设备,创新非遗文化传承形式

随着全身动作捕捉设备不断革新&#xff0c;越来越多行业运用全身动作捕捉设备保护并传承非遗文化&#xff0c;如越剧、戏曲、武术等非遗项目&#xff0c;可以通过全身动作捕捉设备实时动态采集非遗演绎数据&#xff0c;搭建非遗数据框架&#xff0c;使传统戏剧、游艺与杂技等多…