我能拿到鼠标的坐标,你呢?


事实上,今天的内容主要是讲C语言基础的字符类型char和循环结构。然后顺便用EGE图形库的获取鼠标坐标的方法,来取得一下鼠标坐标。

本来今天有好几个更实用且吸引人的可以写的内容,比如之前计划了两个多月的硬件开发的一个内容开始动工了,还有网站建设的服务器方面的内容也准备了几个值得写的了,不过考虑到要抓紧把C语言基础的写完,才有助于更多朋友看懂之后的内容。。。


所以今天还是先写一写这个,对学过的朋友来说简单、无聊的内容吧。


一、新建工程


首先我们还是新建一个工程,并把文件建好,不会的朋友可以参考之前用EGE画爱心的文章。

编写代码:

#include <graphics.h>

#include <stdio.h>


int main(){

initgraph(640, 480);

setfont(48, 0, "宋体");

setcolor(EGERGB(0xFF, 0x00, 0x00));

setbkcolor(EGERGB(0x00, 0x66, 0x00));


/*核心部分*/


closegraph();

return 0;

}

我们使用了EGE图形库来绘制界面和获取鼠标坐标,使用了C语言输入输出头文件来将文本与数字连接在一起(拼接字符串)。

所有内容依旧在主函数main中,一样的初始化窗口和设置背景颜色,就连结束时的关闭图形界面和返回正常结束都和之前一样

不同的是,我们因为要在图形界面中输出文字,所以我们需要设置(set)字体(font),以及设置(set)字体颜色(color),这里同样使用EGERGB来定义颜色。




二、循环与获取鼠标


接下来要实现获取鼠标位置就要用到循环了,我们先来讲解一下循环

我们C语言中常用到的循环有两种形式,分别是for循环while循环。接下来我们就分别讲讲它们。

首先是for循环,for循环的结构是“for(循环前需要执行一次的内容; 进行循环要满足的条件; 循环后要调整的内容){循环的内容}”。

这里“循环前需要执行一次的内容”主要是声明循环时要用到的变量并赋值

进行循环要满足的条件”是每次循环前都要判断的条件,如果不满足那么就不会循环了,而去执行之后的内容。

循环后要调整的内容”是循环后要进行的对循环时用到的变量的值进行调整,比如在开始声明了一个循环时计算循环次数的变量i,这里要进入下一次循环了,就该给这i加上1了。

for的使用方法是:

/*这里是要循环前面的内容*/

for(int i=0; i < 10; i = i+1){

/*这里是要循环的内容*/

}

/*这里是要循环后面的内容*/

这里我们声明了一个循环时要用到的变量i,用来计算循环的次数,我们给定i的初始值为0。

我们每次循环开始前,都需要判断i的值是否是小于10的,如果i不再小于10,那么我们就结束循环。

我们每次循环后都要给i加上1,计算循环的次数。

这个循环执行时,第一次执行要循环的内容时,i的值为0,第二次为1,三次为2,四次为3……这样一直到第十次为9,然后i在第十次循环结束后加上1变为了10,判断i是否小于10时不再满足条件,结束循环,执行循环后面的内容


然后是while循环,while循环的结构是“while(进行循环要满足的条件){循环的内容}”,可以看出while比for精简了不少。

我们先来看看while的使用方式和你想的一不一样。

/*这里是要循环前面的内容*/

while(鼠标在移动){

/*这里是要循环的内容*/

}

/*这里是要循环后面的内容*/

如果鼠标在执行完循环前面的内容时在移动,那么执行要循环的内容,然后鼠标依旧在移动再次执行循环的内容,直到鼠标停下来,才执行循环后面的内容

既然如此,那么while和for通常用在什么场合呢

必须要说明的一点是,这里只讲到了两个最常用的循环方式,其实还有其它的循环的情况,用在一些不常见的场合,比如do...while循环等。这里我们只讲了两种,那么我们就只先说这两种,把这两种学好了,使用中99%的情况都很实用。

我们可以看出,for循环主要的作用就是能方便的计算循环的次数和调整循环用到的参数,而while虽然也能通过一些代码实现,但会麻烦很多。所以很显然,for循环一般用在要计算循环次数的场合,而while则一般用在不关注循环次数的场合

一般要计算循环次数的场合举例:

我们知道需要循环多少次时,比如以后会讲到的数组,我们可以知道里面有多少内容(元素),我们要把里面每个内容检查一遍的话,我们常常的用到for。

我们虽然不知道循环次数,但我们每次循环要知道是第几次循环的情况下,当然,这样的情况很少。

一般不关注循环次数的场合举例:

我们有一个不确定要处理多少次的内容,比如硬盘里的一篇文章需要读取时,我们只能判断它有没有到结尾,而不能判断它数量,这时常常要用到while。

我们有一件事不知道要做多久,比如鼠标的移动,我们不知道要移动多久,我们只能判断它有没有在移动,那么我们也常使用while。

我们程序的主循环,在没使用循环的程序中,程序打开往往很快就自己关闭了,而一般应用软件和游戏,都是长时间运行的,因此我们要循环并且一直循环,直到用户要求关闭才停止。这时我们while判断条件一般就要一直设置为真,写法也就是“while(true){循环内容}”。

当然,这里又涉及到一个问题就是一直循环到一定程度时要跳出循环怎么办的问题,这个问题我们在讲选择时一并讨论。现在我们已经讲了最常用的判断(if,else)和循环(for,while)了,再加上之前讲到的整数(int)再加上待会的字符串(char,也就相当于我们常见的文本),然后再来点简单的数组,我们就可以写小游戏了。当然要实现实用的软件还有比较长的一段路要走,毕竟,我们这之前讲的也只是最常用的情况,还有其它的循环等的方式,而且之后还有函数,指针,结构体,预处理等。

下面我们就把这次代码的核心部分循环写出来吧。




代码:

while(is_run()){


int x, y;

mousepos(&x, &y);


delay_fps(60);

}

这里我们因为不知道要循环多久(同时又是主循环,满足while使用的两个场合),所以我们选用while循环。

我们判断如果窗口没有关闭,就执行循环。

我们声明了两个整数类型的变量名,但都没给定值,用来存储鼠标的坐标位置。

我们使用EGE图形库的获取鼠标(mouse)位置(pos)的函数,传入存储鼠标位置的两个变量的地址(这是指针的内容,先可以不管,知道结果就行),然后在这个函数运行后,得到的结果就是,我们的存储鼠标位置的这两个变量有了记录的鼠标位置坐标

在经过文本的处理(待会马上讲一小部分)后,我们延迟(delay)60毫秒,然后再次循环。

这里为什么要延迟呢,其实每个程序主循环都应该有或多或少的延迟,以便让电脑CPU休息,给其它程序运行的空间(虽然不同程序且不同线程基本互不干扰,但一个程序长时间占满CPU还是会对其它程序构成影响),当然其实我们现在编写的程序都是通过CPU在处理运行,所以也不存在显卡烂照成画面卡的情况,画面卡,也基本是CPU和代码的问题,这小程序中内存也影响不大。至于显卡影响画面的情况,那要我讲到3D处理去了,还早着呢,再怎么,几百篇文章也才可能讲得过去(不排除每周日补坑的文章会涉及的情况)


三、文本处理


好了好了,接下来讲讲文本的处理,也就是字符串,抓紧讲完这篇无聊的内容。

说到字符串,涉及到的光常用的都有点多,这里先讲今天用得到的部分内容,首先肯定是字符串的声明与赋值

字符串的声明是使用char来声明的(某朋友让我说String或var,我这讲的是C语言。。。谢谢,无语),而C语言的字符串又基本可以说是字符串数组,(看着今天写的代码上火一时语塞,不知道如何描述比较好,数组扯得有点远,又不得不扯),今天代码中用到的字符串声明的形式是“char 字符串名[字符串最多存储的字符数]”(这样解释字符串数组希望大家别介意,因为要具体解释,又要很长的文章讲数组然后讲与字符串关系等等了,上面这个形式只是这里便于理解今天代码,这个形式的解释是错误的!在讲到数组后纠正)。

今天我们声明字符串后不赋值,然后使用sprintf()来实现拼接字符串(怎么感觉又得讲指针。。。今天代码坑真多,我尽量绕开,以后回头分析)。

sprintf函数的使用方法是“sprintf(存储拼接后的字符串的变量, 拼接字符串, 拼接字符串用到的参数多个时用英文逗号隔开)”使用情况看待会的代码即可。

然后要说的一点是print的%这个格式控制符号。首先sprintf这个函数是由s加上print加上f组成的,printf在helloworld中就用过,是控制台程序的输出字符串,而前面加上s就变成了拼接字符串。sprintf与printf在参数上来说,仅仅是sprintf多了第一个参数“存储拼接后的字符串的变量”,其它都一样的。所以这里讲的%对printf也适用

要说明的是,%在这里是格式控制符,后面跟上d表示整数这个整数后面“拼接字符串用到的参数”必须提供,并且多个参数时要按出现顺序提供完整。在%和d的中间可以加入数字,这在待会的代码里的数字4表示这个数据所占列数为4。

下面摘录一段本上火之前发在某c4IDE的资料库中的内容供参考,因为这里接着讲下去长篇大论一堆就说不到代码了。


格式声明说明备注
%d输出一个十进制整数可以使用%5d这种形式指定输出数据的列数(域宽),如这里的5表示5列
%c输出一个字符可以使用%5c这种形式指定输出数据的列数(域宽),如这里的5表示5列. 可以使用ASCII码作为参数,输出ASCII字符.
%s输出一个字符串如printf("%s","hello world");也可以输出hello world
%f输出一个小数可以使用%5.2f这种形式指定输出数据的列数(域宽),如printf("%1.2f",1.0/3);输出1.0除以3的结果为0.33
%e或%E以指数形式输出实数此格式不常用,同样可指定域宽,如果格式中字母大写,则输出的字母为大写
%i输出一个十进制整数作用与%d类似,一般使用%d
%o以8进制整数形式输出此格式不常用
%x或%X以16进制整数形式输出此格式不常用,如果格式中字母大写,则输出的字母为大写
%u以十进制形式输出无符号数据此格式不常用
%g或%G输出浮点数(小数)此格式不常用,由系统自行选择小数以%f或%e形式输出,如果格式中字母大写,则输出的字母为大写


今天字符串这块本来想讲点什么,但结果发现涉及很多后面的知识,就算讲,小白也听不明白,会的无论讲不讲,都要嫌弃今天这篇内容已经是肯定的了,那不会的我们今天也就先讲少点,能懂则懂,把上面循环搞清楚就好,字符串这块参考参考即可。下面发这段字符串处理的代码(没涉及转义字符也就不管了)。

char str[32];


outtextxy(0, 40, "鼠标位置:");

sprintf(str, " X坐标:%4d", x);

outtextxy(0, 180, str);

sprintf(str, " Y坐标:%4d", y);

outtextxy(0, 320, str);




这里声明了一个存储字符串的变量str它最多存32个字符。

使用EGE函数指定XY坐标输出(out)文本(text)来在图形界面绘制文本,这里前两个参数是XY坐标,然后是要绘制的文本。

使用sprintf拼接字符串,第一个参数是存拼接结果字符串的变量,第二个参数是拼接字符串的形式,然后是这个形式中用到的参数,这里只有一个整数参数,也就是这个坐标。

依旧是绘制文本,这里参数Y坐标变大了,避免文本重叠,然后绘制的文本是那个拼接的字符串变量的内容。

再一次重复,实现Y坐标。

以下是今天代码运行效果:




好的。。。今天这篇文章上火自我感觉相当糟糕,可算把比较重要的,循环的主要的两个形式讲了,然后说了下字符串的声明用char和格式字符(其它的好多东西涉及以后的内容,现在难以讲清除。那些涉及后面的内容的东西,总感觉现在讲,有种只可意会不可言传的感觉,但实际上,我在之前写的几篇发在别处的,没考虑新人基础能力的文章反到感觉表达很清楚,只是用了一堆新人可能听不懂的名词。。),现在还是来总结一下吧。

好了,还是说说整个程序,虽然这个内容实际没多少用途,但至少这个程序在EGE图形库开发的程序上,还是有用的。

1、首先引用了EGE图形库和输入输出头文件,然后主函数里初始化图形界面,定义了字体和颜色。

2、循环,这是今天内容的重点,我们判断窗口存在就一直循环,这也相当于主循环

3、声明字符串,这涉及以后的字符串数组。

4、声明存储鼠标位置的整数。

5、获取鼠标位置,这涉及以后的指针。

6、在绘图界面上绘制文字,这没什么,就是EGE的API应用。

7、拼接字符串,涉及到的东西太多了,指针,可变参数,格式字符,伪正则等等一堆东西,这里只提了一下格式字符,而且感觉还没讲清楚。

8、延时函数,这里是60毫秒,补充一句1000毫秒等于1秒。

9、结束程序。


今天内容上火自我感觉很糟糕,特别是字符串这块特别糟糕。看不懂的话请联系我,各位会的认为这文章不好也尽管联系我,我都接受另外还有个事就是,按目前进度,接下来如果把基础讲全再讲后面的话,可以避免以后出这种糟糕的文章,但接下来几篇这系列的会不太吸引人;如果按某几个关注这文章的的朋友的要求,标题和内容吸引人的话,这样糟糕的可能还有两到三篇,直到把数组和字符串解决掉,请各位朋友给出一下主意,您们想让怎么写。