语言学习的三个阶段

时间:2024.4.13

语言学习的三个阶段

“人如其食”-流行谚语

在全球资讯时代,这句话或许应该说成“人如其言”。表现各异的语言是人类最典型的成就,语言也是我们的特性。语言可以是社交的、政治的、技术的、实用的、娱乐的、色情的、哲学的,还有更多。在生活的盛宴里,每一门语言都是一道菜。你能更好地使用你的母语和其他语言,你就越能享受这顿盛宴。起码这是我的经验。

我已经在12门语言上达到了不同程度的流利,还期待学更多种语言。对我而言,语言能力的发展有三个自然阶段,我将其概括在此。数十亿美元被浪费在无效的语言和识字辅导课程上,那些辅导课程都忽视了这三个自然阶段。

第一阶段 和外语建立联系 - 60-90小时

我的目标:熟悉陌生的语言

我的量化标准:学会识别1000个单词

主要任务:反复听简短的内容

我的目标语言:(计划中的)捷克语、阿拉伯语、北印度语和土耳其语

开始的时候,我需要与这种新语言建立联系并克服对其奇怪发音和结构的抵制。我不需要讲,不需要理解任何语法,不需要得到任何“正确的”东西。我对掌握一些短语或者简单的问候语不感兴趣。我想习惯这种语言,找到对这种语言的感觉。

下面是麦克基尔大学的费雷德·杰纳西对语言学习开始阶段的描述。

学习行为发生时,神经元之间的神经化学交流得到促进,换句话说,一个神经网络被逐渐建立起来。大脑起初将接收到的不熟悉发音标示为无差别的神经活动。随着持续的接收,听者(以及大脑)学会区分不同发音甚至短的相当于话语或部分话语的发音序列。

我开始的时候反复听短的文章片段。一开始这些片段有30秒长,最后增加到一分钟或更长。为了帮助在大脑中形成新的神经网络,同样的话我要听20遍,甚至更多。这些短片段是一个更长“故事”的一部分,这样就很理想了,这使得整个上下文就有了意义。一心一意听过一个新片段上之后,我复习所有听过的旧片段,这样我就能够消化越来越长的语言累积量。互联网和我的闪存型iPOD使这种文章随手可得并便于携带,这是历史上从来没有过的。

现在,我阅读曾在电脑上听过的所有文本。这样我就可以登录到某个在线词典并创建自己的词汇和短语库,以备用各种方法进行复习。随着我在一门语言上的进步,掌握听和阅读过程中遇到的单词和短语是我的关键衡量目标。

一门语言的新词一开始看起来很奇怪,彼此之间很相似,容易让人混淆。然而,通过反复阅读简单文章,其中的常见词经常出现在不同的上下文中,这些词最终开始在大脑中扎根。我通常把新词及短语同我听过的有这些词的片段联系起来。我将一个词或短语联系的越多,就

越容易记住。

我一开始说的不多,无论如何我的词汇量太小。我很随意地对着自己大声练习重复词汇和短语,我不担心发音。一旦我的大脑在分辨发音方面变得更好,继续学习将更加容易。

我可以说一点,只是为了找乐,试试我学过的东西。通过互联网,我可以轻易找到一个讲母语的家庭教师或语言交流伙伴。因为我不想被其他讲非母语的人搞迷糊了,所以我没去上过外语课。

第二阶段 在大部分情况下变得舒服 180-360小时

我的目标:懂得普通会话和大部分日常用语

我的量化标准:大部分对话中的生词不超过10%

主要任务:听正常会话;背词汇;逐步增加说和写的活动

我的目标语言:俄语、葡萄牙语和韩国语

由于我不再觉得这门语言奇怪,所以我想接触当地人通常说的或写的。有时候这被称为“权威的”语言。

会话是要懂的最简单的“权威的”内容,因为一门语言最常用的单词占会话的90-95%。同样这些单词通常占正式一些的书面材料的70-75%。

每个学习项目现在更长了,差不多3到5分钟。我听每个项目的频率有所降低,为了学更多的单词转而听更多的材料。我利用一些死时间,零零碎碎的学,开车或跑步时听,一遍又一遍。我已知的单词越多,学习新单词就越容易。词汇就像钱,“你有的越多学的就越多”,或者说“富者更富”。

听和读的时候我喜欢找一些有趣的和熟悉的主题,因此我会马上放弃我不感兴趣或者有我不喜欢的有声资料。起初,似乎讲母语者说的很快,但是我的大脑经过足够多的重复后逐渐适应了这种自然流。当我不理解“权威的会话”时,我不觉得沮丧;我理解了之后觉得振奋。

再说一遍,杰纳西教授的意见是有帮助的。当学生的词汇被嵌入到他们很熟悉的真实世界的复杂上下文中时可以得到加强。

有时候我在互联网上和说母语者谈话,开口说帮助我找出缺点、遗漏的词、不会表达的概念以及发音有问题的词。然后我可以自己纠正这些问题。

通过和讲母语者的有限联系、接触,我还写,特别是在互联网博客和论坛上。写对于学来说很重要。我有时间去编辑我的思想,保留我的错误和问题的记录。

在这个阶段,重点还是听和读,以及增加词汇量。

第三阶段 持续改善 180小时-永远

我的目标:继续享受这门语言,学更多的词,更好的使用这门语言

我的量化标准:我感兴趣的文章中的生词不超过10%

我的任务:做我感兴趣的事

我的目标语言:法语、日语、普通话、西班牙、瑞典语、德语、意大利语、广东话和英语

这是最有回报的阶段。我可以到讲这种语言的国家去旅游,或者会见以这种语言为母语的人。我知道我会享受这种经历,即使我会犯错误。我可以保持对这门语言的掌握,即使我长时间不用它。

这是学习语法的最好阶段。我有关于语法的书和音频资料,专供说母语的人使用的。现在我对这门语言足够熟悉,通过不断接触,我可以使用专供母语者使用的风格和使用手册。不过,我的个人兴趣更倾向于历史和文化。我发现,读书听音频资料,主题都是自己感兴趣的,这是最愉快最有效的持续提高的方法,或者提起精神学习一门我还没用过一会儿的语言。

我没有必要去参加任何的语言水平考试。如果我有必要参加考试,我会在这个阶段认真准备考试。取得这种考试成功的关键是快速阅读能力和理解口语能力以及广泛的词汇和短语量,所有这一些我都已经快乐而毫无痛苦的达到了。只有达到这个水平我才会参加这些考试,因为我知道我会得到高分。

这也是学习特殊技能的阶段,比如做演示、写学术论文或者撰写业务报告等。在网上和其他地方找到目标语言的相关资料很容易。目标是模仿某一特定语言和文化中最值得欣赏的措辞、语序以及组织信息的方法。找一个讲母语的专业家庭教师或教师来学习这些技巧非常容易,还是通过网络。

结论:

我已经如此这般许多次了,我知道我能学会一门新语言或者提高一门已经说的不错的语言,包括我的母语在内。任何想这样做的人都可以做到。关键在于激励和享受,而不是一所学校或一个文凭。我又知道,任何一门语言要想追求完美是没有用的,因此我很乐意犯错误,也真地不要求别人给我纠正错误。我就是喜欢饕餮语言盛宴,喝、吃、品尝、咀嚼并消化他们。尽管我会不时有一点陶醉,但从来都没饱过。


第二篇:C语言学习


编译环境设置好以后,就可以正式学习C语言了。

一、变量

(一)、变量类型和表示方法

1.什么是变量?一句话,变量是存储数据的值的空间。由于数值的类型有多种,有整数、小数(浮点数)、字符等等,那么对应的变量就有整型变量、浮点型变量、字符型变量。变量还有其他的具体分类。整型变量还可具体分为无符号型、长整型和短整型。浮点型也可分为单精度型、双精度型和长双精度型。此外还可以分为静态变量、外部变量、寄存器变量和自动存储变量。这些数据类型我们在本节和后面的章节中都会陆陆续续介绍。

那么变量我们总要给它取个名字吧,这个名字我们叫做标识符。

标识符的命名有一定的规则:

(1).标识符只能由字母、数字和下划线三类字符组成

(2).第一个字符必须是字母(第一个字符也可以是下划线,但被视作系统自定义的标识符)

(3).大写字母和小写字母被认为是两个不同的字符,如A和a是两个不同的标识符

(4).标识符可以任意长,但只有前32位有效。有些旧的C版本对外部标识符的限制为6位。这是由于链接程序的限制所总成的,而不是C语言本身的局限性

(5).标识符不能是C的关键字

2.从上面的规则中,有个关键字的概念。那么什么叫关键字呢?

从表面字意上也可以看出,关键字是C语言本身某些特性的一个表示,是唯一的代表某一个意思的。

下面列出ANSI标准定义的32个C语言的关键字,这些关键字在以后的学习中基本上都会用到,到时再说它们的各自用法。

auto break case char const continue default

do double else enum extern float for

goto if int long register return short

signed sizeof static struct switch typedef

union unsigned void volatile while

C语言还包括一些不能用做标识符的扩展关键字。

asm cdecl _cs _ds _es far

huge interrupt near pascal _ss

所以在以后的学习中,在给变量命名时要避开这些关键字。

3. Turbo C2.0规定所有变量在使用前都必须加以说明。一条变量说明语句由数据类型和其后的一个或多个变量名组成。变量说明的形式如下:

类型 <变量表>;

这里类型是指Turbo C2.0的有效数据类型。变量表是一个或多个标识符名,每个标识符之间用,分隔。

(二)、整型变量

整型变量是用来存储整数的。

整型变量又可具体分为好几种,最基本的整型变量是用类型说明符int声明的符号整型,形式如下:

int Counter;

这里int是类型说明符,Counter是变量的名字。

整型变量可以是有符号型、无符号型、长型、短型或象上面定义的普通符号整型。 整型是16位的,长整型是32位,短整型等价于整型。

以下是几种整型变量的声明示例:

long int Amount; /*长整型*/

long Amount; /*长整型,等价于上面*/

signed int Total; /*有符号整型*/

signed Total; /*有符号整型,等价于上面*/

unsigned int Offset; /*无符号整型*/

unsigned Offset; /*无符号整型,等价于上面*/

short int SmallAmt; /*短整型*/

short SmallAmt; /*短整型,等价于上面*/

unsigned short int Month; /*无符号短整型*/

unsigned short Month; /*无符号短整型,等价于上面*/

从上面的示例可以看出,当定义长整型、短整型、符号整型或无符号整型时,可以省略关键字int。

注明:

1.用signed对整型变量进行有符号指定是多余的,因为除非用unsigned指定为无符号型,否则整型都是有符号的。

2.当一个变量有几重特性时,声明关键字的顺序可以任意。以下几种声明是等价的: unsigned long T1;

long unsigned T2;

unsigned long int T3;

unsigned int long T4;

long unsigned int T5;

long int unsigned T6;

int unsigned long T7;

int long unsigned T8;

(三)、浮点类型变量

顾名思义,浮点类型变量是用来存储带有小数的实数的。

C语言中有三种不同的浮点类型,以下是对这三种不同类型的声明示例:

float Amount; /*单精度型*/

double BigAmount; /*双精度型*/

long double ReallyBigAmount; /*长双精度型*/

这里Amount,BigAmount,ReallyBigAmount都是变量名。

浮点型都是有符号的。

(四)、字符型变量

字符型变量中所存放的字符是计算机字符集中的字符。对于PC机上运行的C系统,字符型数据用8位单字节的ASCII码表示。程序用类型说明符char来声明字符型变量: char ch;

这条声明语句声明了一个字符型变量,标识符为ch。当以这种形式声明变量之后,程序可以在表达式中引用这个变量,关于语句和表达式的知识在后面将会介绍。

字符数据类型事实上是8位的整型数据类型,可以用于数值表达式中,与其他的整型数据同样使用。在这种情况下,字符型变量可以是有符号的,也可以是无符号的。对于无符号的字符型变量可以声明为:

unsigned char ch;

除非声明为无符号型,否则在算术运算和比较运算中,字符型变量一般作为8位有符号整型变量处理。

还有其他的如指针型变量,void型变量,以后再介绍。

二、常量

常量的意思就是不可改变的量,是一个常数。同变量一样,常量也分为整型常量、浮点型常量、字符型常量,还有字符串常量、转义字符常量和地址常量。

(一)、整型常量

整型常量可以是长整型、短整型、有符号型、无符号型。在Tubbo C 2.0里有符号整型常量的范围从-32768到32767,无符号整型的为0到65535;有符号长整型的范围为-2147483648到2147483647。无符号长整型的范围为0到4294967295。短整型同字符型。

可以指定一个整型常量为二进制、八进制或十六进制,如以下语句:

-129, 0x12fe, 0177

常量的前面有符号0x,这个符号表示该常量是十六进制表示。如果前面的符号只有一个字母0,那么表示该常量是八进制。

有时我们在常量的后面加上符号L或者U,来表示该常量是长整型或者无符号整型: 22388L, 0x4efb2L, 40000U

后缀可以是大写,也可以是小写。

(二)、浮点型常量

一个浮点型常量由整数和小数两部分构成,中间用十进制的小数点隔开。有些浮点树非常大或者非常小,用普通方法不容易表示,可以用科学计数法或者指数方法表示。下面是一个实例:

3.1416, 1.234E-30, 2.47E201

注意在C语言中,数的大小也有一定的限制。对于float型浮点数,数的表示范围为-3.402823E38到3.402823E38,其中-1.401298E-45到1.401298E-45不可见。double型浮点型常数的表示范围为-1.79E308到1.79E308,其中-4.94E-324到4.94E-324不可见。 在浮点型常量里我们也可以加上后缀。

FloatNumber=1.6E10F; /*有符号浮点型*/

LongDoubleNumber=3.45L; /*长双精度型*/

后缀可大写也可小写。

说明:

1. 浮点常数只有一种进制(十进制)。

2. 所有浮点常数都被默认为double。

3. 绝对值小于1的浮点数, 其小数点前面的零可以省略。如:0.22可写为.22, -0.0015E-3可写为-.0015E-3。

4. Turbo C默认格式输出浮点数时, 最多只保留小数点后六位

(三)、字符型常量

字符型常量所表示的值是字符型变量所能包含的值。我们可以用ASCII表达式来表示一个字符型常量,或者用单引号内加反斜杠表示转义字符。

'A', '\x2f', '\013';

其中:\x表示后面的字符是十六进制数,\0表示后面的字符是八进制数。

注意:在Turbo C 2.0中,字符型常量表示数的范围是-128到127,除非你把它声明为unsigned,这样就是0到255。

(四)、字符串常量

字符串常量就是一串字符,用双引号括起来表示。

Hello,World!

\nEnter selection:

\aError!!!

(五)、转义字符

上面我们见到的\x,\n,\a等等都是叫转义字符,它告诉编译器需要用特殊的方式进行处理。下面给出所有的转义字符和所对应的意义:

转义字符 描述

\' 单引号

\ 双引号

\\ 反斜杠

\0 空字符

\0nnn 八进制数

\a 声音符

\b 退格符

\f 换页符

\n 换行符

\r 回车符

\t 水平制表符

\v 垂直制表符

\x 十六进制符

它们的具体用法我们到讲输出语句时再介绍。

(六)、地址常量

我们前面说的变量是存储数据的空间,它们在内存里都有对应的地址。在C语言里可以用地址常量来引用这些地址,如下:

&Counter, ∑

&是取地址符,作用是取出变量(或者函数)的地址。在后面的输入语句和指针里还会说明。 这一节所讲到的变量和常量知识可以说是在一切程序中都要用到,特别是变量的声明和命名规则。

无论是加减乘除还是大于小于,都需要用到运算符,在C语言中的运算符和我们平时用的基本上都差不多。

运算符包括赋值运算符、算术运算符、逻辑运算符、位逻辑运算符、位移运算符、关系运算符、自增自减运算符。大多数运算符都是二目运算符,即运算符位于两个表达式之间。单目运算符的意思是运算符作用于单个表达式。(具体什么是表达式下一节再说)

一、赋值运算符

赋值语句的作用是把某个常量或变量或表达式的值赋值给另一个变量。符号为‘=’。这里并不是等于的意思,只是赋值,等于用‘==’表示。

注意:赋值语句左边的变量在程序的其他地方必须要声明。

得已赋值的变量我们称为左值,因为它们出现在赋值语句的左边;产生值的表达式我们称为右值,因为她它们出现在赋值语句的右边。常数只能作为右值。 例如:

count=5;

total1=total2=0;

第一个赋值语句大家都能理解。

第二个赋值语句的意思是把0同时赋值给两个变量。这是因为赋值语句是从右向左运算的,也就是说从右端开始计算。这样它先total2=0;然后total1=total2;那么我们这样行不行呢?

(total1=total2)=0;

这样是不可以的,因为先要算括号里面的,这时total1=total2是一个表达式,而赋值语句的左边是不允许表达式存在的。

二、算术运算符

在C语言中有两个单目和五个双目运算符。

符号 功能

+ 单目正

- 单目负

* 乘法

/ 除法

% 取模

+ 加法

- 减法

下面是一些赋值语句的例子, 在赋值运算符右侧的表达式中就使用了上面的算术运算符:

Area=Height*Width;

num=num1+num2/num3-num4;

运算符也有个运算顺序问题,先算乘除再算加减。单目正和单目负最先运算。 取模运算符(%)用于计算两个整数相除所得的余数。例如:

a=7%4;

最终a的结果是3,因为7%4的余数是3。

那么有人要问了,我要想求它们的商怎么办呢?

b=7/4;

这样b就是它们的商了,应该是1。

也许有人就不明白了,7/4应该是1.75,怎么会是1呢?这里需要说明的是,当两个整数相除时,所得到的结果仍然是整数,没有小数部分。要想也得到小数部分,可以这样写7.0/4或者7/4.0,也即把其中一个数变为非整数。

那么怎样由一个实数得到它的整数部分呢?这就需要用强制类型转换了。例如: a=(int) (7.0/4);

因为7.0/4的值为1.75,如果在前面加上(int)就表示把结果强制转换成整型,这就得到了1。那么思考一下a=(float) (7/4);最终a的结果是多少?

单目减运算符相当于取相反值,若是正值就变为负值,若是负数就变为正值。 单目加运算符没有意义,纯粹是和单目减构成一对用的。

三、逻辑运算符

逻辑运算符是根据表达式的值来返回真值或是假值。其实在C语言中没有所谓的真值和假值,只是认为非0为真值,0为假值。

符号 功能

&& 逻辑与

|| 逻辑或

! 逻辑非

例如:

5!3;

0||-2&&5;

!4;

当表达式进行&&运算时,只要有一个为假,总的表达式就为假,只有当所有都为真时,总的式子才为真。当表达式进行||运算时,只要有一个为真,总的值就为真,只有当所有的都为假时,总的式子才为假。逻辑非(!)运算是把相应的变量数据转换为相应的真/假值。若原先为假,则逻辑非以后为真,若原先为真,则逻辑非以后为假。 还有一点很重要,当一个逻辑表达式的后一部分的取值不会影响整个表达式的值时,后一部分就不会进行运算了。例如:

a=2,b=1;

a||b-1;

因为a=2,为真值,所以不管b-1是不是真值,总的表达式一定为真值,这时后面的表达式就不会再计算了。

四、关系运算符

关系运算符是对两个表达式进行比较,返回一个真/假值。

符号 功能

> 大于

< 小于

>= 大于等于

<= 小于等于

== 等于

!= 不等于

这些运算符大家都能明白,主要问题就是等于==和赋值=的区别了。

一些刚开始学习C语言的人总是对这两个运算符弄不明白,经常在一些简单问题上出错,自己检查时还找不出来。看下面的代码:

if(Amount=123) ……

很多新人都理解为如果Amount等于123,就怎么样。其实这行代码的意思是先赋值Amount=123,然后判断这个表达式是不是真值,因为结果为123,是真值,那么就做后面的。如果想让当Amount等于123才运行时,应该if(Amount==123) ……

五、自增自减运算符

这是一类特殊的运算符,自增运算符++和自减运算符--对变量的操作结果是增加1和减少1。例如:

--Couter;

Couter--;

++Amount;

Amount++;

看这些例子里,运算符在前面还是在后面对本身的影响都是一样的,都是加1或者

减1,但是当把他们作为其他表达式的一部分,两者就有区别了。运算符放在变量前面,那么在运算之前,变量先完成自增或自减运算;如果运算符放在后面,那么自增自减运算是在变量参加表达式的运算后再运算。这样讲可能不太清楚,看下面的例子:

num1=4;

num2=8;

a=++num1;

b=num2++;

a=++num1;这总的来看是一个赋值,把++num1的值赋给a,因为自增运算符在变量的前面,所以num1先自增加1变为5,然后赋值给a,最终a也为5。b=num2++;这是把num2++的值赋给b,因为自增运算符在变量的后面,所以先把num2赋值给b,b应该为8,然后num2自增加1变为9。

那么如果出现这样的情况我们怎么处理呢?

c=num1+++num2;

到底是c=(num1++)+num2;还是c=num1+(++num2);这要根据编译器来决定,不同的编译器可能有不同的结果。所以我们在以后的编程当中,应该尽量避免出现上面复杂的情况。

六、复合赋值运算符

在赋值运算符当中,还有一类C/C++独有的复合赋值运算符。它们实际上是一种缩写形式,使得对变量的改变更为简洁。

Total=Total+3;

乍一看这行代码,似乎有问题,这是不可能成立的。其实还是老样子,'='是赋值不是等于。它的意思是本身的值加3,然后在赋值给本身。为了简化,上面的代码也可以写成:

Total+=3;

复合赋值运算符有下列这些:

符号 功能

+= 加法赋值

-= 减法赋值

*= 乘法赋值

/= 除法赋值

%= 模运算赋值

<<= 左移赋值

>>= 右移赋值

&= 位逻辑与赋值

|= 位逻辑或赋值

^= 位逻辑异或赋值

上面的十个复合赋值运算符中,后面五个我们到以后位运算时再说明。

那么看了上面的复合赋值运算符,有人就会问,到底Total=Total+3;与Total+=3;有没有区别?答案是有的,对于A=A+1,表达式A被计算了两次,对于复合运算符A+=1,表达式A仅计算了一次。一般的来说,这种区别对于程序的运行没有多大影响,但是当表达式作为函数的返回值时,函数就被调用了两次(以后再说明),而且

如果使用普通的赋值运算符,也会加大程序的开销,使效率降低。

七、条件运算符

条件运算符(?:)是C语言中唯一的一个三目运算符,它是对第一个表达式作真/假检测,然后根据结果返回两外两个表达式中的一个。

<表达式1>?<表达式2>:<表达式3>

在运算中,首先对第一个表达式进行检验,如果为真,则返回表达式2的值;如果为假,则返回表达式3的值。

例如:

a=(b>0)?b:-b;

当b>0时,a=b;当b不大于0时,a=-b;这就是条件表达式。其实上面的意思就是把b的绝对值赋值给a。

八、逗号运算符

在C语言中,多个表达式可以用逗号分开,其中用逗号分开的表达式的值分别结算,但整个表达式的值是最后一个表达式的值。

假设b=2,c=7,d=5,

a1=(++b,c--,d+3);

a2=++b,c--,d+3;

对于第一行代码,有三个表达式,用逗号分开,所以最终的值应该是最后一个表达式的值,也就是d+3,为8,所以a=8。对于第二行代码,那么也是有三个表达式,这时的三个表达式为a2=++b、c--、d+3,(这是因为赋值运算符比逗号运算符优先级高)所以最终表达式的值虽然也为8,但a2=3。

还有其他的如位逻辑运算符,位移运算符等等,我们等到讲位运算时再说明。

九、优先级和结合性

从上面的逗号运算符那个例子可以看出,这些运算符计算时都有一定的顺序,就好象先要算乘除后算加减一样。优先级和结合性是运算符两个重要的特性,结合性又称为计算顺序,它决定组成表达式的各个部分是否参与计算以及什么时候计算。 下面是C语言中所使用的运算符的优先级和结合性:

优先级 运算符 结合性

(最高) () [] -> . 自左向右

! ~ ++ -- + - * & sizeof 自右向左

* / % 自左向右

+ - 自左向右

<< >> 自左向右

< <= > >= 自左向右

== != 自左向右

& 自左向右

^ 自左向右

| 自左向右

&& 自左向右

|| 自左向右

?: 自右向左

= += -= *= /= %= &= ^= |= <<= >>= 自右向左

(最低) , 自左向右

在该表中,还有一些运算符我们没有介绍,如指针运算符、sizeof运算符、数组运算符[]等等,这些在以后的学习中会陆续说明的。

11xxxxxxxxxxxx11xxxxxxxxxxxx1111111111111

求数组平均值

#include <stdio.h>

void main()

{

int a[6],i;

float average=0.0;

float sum=0.0;

printf("input 6 datas\n");

for(i=0;i<6;i++)

scanf("%d",&a[i]);

for(i=0;i<6;i++)

sum=sum+a[i];

average=sum/6;

printf("average=%f\n",average);

}//你的返回值错了,至于conversion from 'double ' to 'float ', possible loss of data,上面sum可以定义成float型,后面average=sum/6;而不是6.0,因为sum的类型是float.

追问

为什么是6,而不是6.0.visual运行是按照6, 6.0有警告

回答

因为数组的定义里面a[6],是整数,方括号里面(数组的下标)只能是整数和整形表达式。

222222222222222222222222222222222222222

可以用下面的冒泡排序做任意大小的数组,只需要在函数调用的时候,把要排序的数组传进来就行了

int fun(int a[])

{

int i,t,b;

int size = sizeof(a)/sizeof(int); //求数组长度

for(b=1;b<size;b++)

{

for(i=0;i<size -b;i++) //数组下标是从0开始的

if(a[i]>a[i+1]) { t=a[i];a[i]=a[i+1];a[i+1]=t;}

}

for(i=0;i<size;i++) printf("%d",a[i]);

}

3333333333333333333333333333333333333333333333333

====================================================

算法思想简单描述:

在要排序的一组数中,对当前还未排好序的范围内的全部数,自上

而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较

小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要

求相反时,就将它们互换。

下面是一种改进的冒泡算法,它记录了每一遍扫描后最后下沉数的

位置k,这样可以减少外层循环扫描的次数。

冒泡排序是稳定的。算法时间复杂度O(n2)--[n的平方]

=====================================================

*

void bubble_sort(int *x, int n)

{

int j, k, h, t;

for (h=n-1; h>0; h=k) /*循环到没有比较范围*/

{

for (j=0, k=0; j<h; j++) /*每次预置k=0,循环扫描后更新k*/

{

if (*(x+j) > *(x+j+1)) /*大的放在后面,小的放到前面*/

{

t = *(x+j);

*(x+j) = *(x+j+1);

*(x+j+1) = t; /*完成交换*/

k = j; /*保存最后下沉的位置。这样k后面的都是排序排好了的。*/ }

}

}

}

/*

/***************************************************************** 液晶接法:GND:0 VCC:1 VO:NC PSB:1 RST:NC VOUT: NC A:1 *****************************************************************/

#include<reg52.h>

#include<intrins.h>

#include<stdlib.h>

#define uchar unsigned char

#define uint unsigned int

#define lcd_bus P0

sbit lcd_rs=P1^0;

sbit lcd_rw=P1^1;

sbit lcd_e=P1^2;

sbit down=P1^3;

sbit up=P1^4;

sbit left=P1^5; K:0

sbit right=P1^6;

#define PASSSCORE 10

uchar flag=0,n;

uchar idata speed=1;

uchar idata score=1;

static unsigned long idata Seed = 1;

#define A 48271L

#define M 2147483647L

#define Q (M / A)

#define R (M % A)

/************************************ 伪随机数发生器

*************************************/ double Random(void)

{

long idata TmpSeed;

TmpSeed=A*(Seed%Q)-R*(Seed/Q);

if(TmpSeed>=0)

Seed=TmpSeed;

else

Seed=TmpSeed+M;

return (double)Seed/M;

}

/************************************** 为伪随机数发生器播种

***************************************/ void InitRandom(unsigned long InitVal)

{

Seed=InitVal;

}

#define N 25

/***********蛇结构体**************************/ struct snake

{

uchar life;

uchar x[N];

uchar y[N];

uchar node_x[N];

uchar node_y[N];

uchar node;

}snake;//蛇结构体

//snake.life=1;

/*************食物结构体***********************/ struct food

{

uchar yes;

uchar x;

uchar y;

}food;//snake结构体

/**********延时1ms函数**********************/ void delay(int z)

{

int x,y;

for(x=z;x>0;x--)

for(y=110;y>0;y--);

}

/*************

测试LCD是否处于忙状态

如果忙则返回0x80,否则返回0

**************/

unsigned char Lcd_CheckBusy(void)

{

unsigned char Busy;

lcd_bus=0xff;

lcd_rs=0;

lcd_rw=1;

lcd_e=1;

//delay(5);

Busy=lcd_bus&0x80;

lcd_e=0;

return Busy;

}

/********************************************* 写入一个字节的数据

**********************************************/ void lcd_write_data(uchar Data)

{while(Lcd_CheckBusy());

lcd_rs=1;

lcd_rw=0;

lcd_bus=Data;

lcd_e=1;

lcd_e=0;

}

/********************************************* 读出一个字节的数据

*********************************************/ uchar lcd_read_data()

{

uchar temp;

while(Lcd_CheckBusy());

lcd_bus=0xff;

lcd_rs=1;

lcd_rw=1;

lcd_e=1;

temp=lcd_bus;

lcd_e=0;

return temp;

}

/********************************************* 写入一个字节的命令

**********************************************/ void lcd_write_com(uchar com)

{while(Lcd_CheckBusy());

lcd_rs=0;

lcd_rw=0;

lcd_bus=com;

lcd_e=1;

lcd_e=0;

}

/*********************************************** 为了位的计算方便,而设置一个掩码表,实际上是 牺牲c52的内存空间,换取计算速度的一种方法

*******************************************/

uint code MaskTab[]=

{

0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080, 0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000 };

/************************************************* 指定的位置写入一个像素,1代表有显示,0代表无显示

************************************************/

void lcd_put_Pixel(unsigned char x,unsigned char y,unsigned char Color) {

unsigned char z,w;

unsigned int Temp;

if(x>=128||y>=64)

return;

Color=Color%2;

w=15-x%16;//确定对这个字的第多少位进行操作

x=x/16;//确定为一行上的第几字

if(y<32) //如果为上页

z=0x80;

else //否则如果为下页

z=0x88;

y=y%32;

EA=0;

lcd_write_com(0x36);

lcd_write_com(y+0x80); //行地址

lcd_write_com(x+z); //列地址

Temp=lcd_read_data();//先空读一次

Temp=(unsigned int)lcd_read_data()<<8;//再读出高8位 Temp|=(unsigned int)lcd_read_data();//再读出低8位

EA=1;

if(Color==1) //如果写入颜色为1

Temp|=MaskTab[w];//在此处查表实现加速

else //如果写入颜色为0

Temp&=~MaskTab[w];//在此处查表实现加速

EA=0;

lcd_write_com(y+0x80); //行地址

lcd_write_com(x+z); //列地址

lcd_write_data(Temp>>8);//先写入高8位,再写入低8位 lcd_write_data(Temp&0x00ff);

lcd_write_com(0x30);

EA=1;

}

/************************************************ 指定位置,指定长度,指定颜色的垂线

**********************************************/ void lcd_VertLine(uchar x,uchar y,uchar length,uchar color ) {

uchar i;

if(length==0)

return;

for(i=0;i<length;i++)

{

lcd_put_Pixel(x,y++,color);

}

}

/************************************************ 指定位置,指定长度,指定颜色的水平线

**********************************************/ void lcd_HoriLine(uchar x,uchar y,uchar length,uchar color ) {

uchar i;

if(length==0)

return;

for(i=0;i<length;i++)

{

lcd_put_Pixel(x+i,y,color);

}

}

/**************************************************** 以指定的4个坐标点,画出一个矩形 ,颜色为color

**************************************************/

void lcd_Rectangle(uchar x0,uchar y0,uchar x1,uchar y1,uchar color) {

uchar temp;

if(x0>x1)

{

temp=x0;

x0=x1;

x1=temp;

}

if(y0>y1)

{

temp=y0;

y0=y1;

y1=temp;

}

lcd_VertLine(x0,y0,y1-y0+1,color);

lcd_VertLine(x1,y0,y1-y0+1,color);

lcd_HoriLine(x0,y0,x1-x0+1,color);

lcd_HoriLine(x0,y1,x1-x0+1,color);

}

/*******************************************************

在随机的位置,画出食物,颜色为color

*******************************************************/

/*------------------清屏命令--------------------------*/

void clrscreen()

{

lcd_write_com(0x01);

}

/*****************************************

清除Lcd全屏,如果清除模式Mode为0,则为全屏清除为颜色0(无任何显示) 否则为全屏清除为颜色1(全屏填充显示)

******************************************/

void Lcd_Clear(unsigned char Mode)

{

unsigned char x,y,ii;

unsigned char Temp;

if(Mode%2==0)

Temp=0x00;

else

Temp=0xff;

lcd_write_com(0x36);//扩充指令 绘图显示

for(ii=0;ii<9;ii+=8)

for(y=0;y<0x20;y++)

for(x=0;x<8;x++)

{

EA=0;

lcd_write_com(y+0x80); //行地址

lcd_write_com(x+0x80+ii); //列地址 lcd_write_data(Temp); //写数据 D15-D8 lcd_write_data(Temp); //写数据 D7-D0 EA=1;

}

lcd_write_com(0x30);

}

/******************************************

指定位置写入字符串

*******************************************/

void lcd_Write_string(uchar x,uchar y,uchar *str)

{

if((x>7)||(y>3))

return;

EA=0;

switch(y)

{

case 0:

lcd_write_com(0x80+x);

break;

case 1:

lcd_write_com(0x90+x);

break;

case 2:

lcd_write_com(0x88+x);

break;

case 3:

lcd_write_com(0x98+x);

break;

}

while(*str>0)

{

lcd_write_data(*str);

str++;

}

EA=1;

}

/***************************************

初始化界面

******************************************/ void DrawBoard()

{

// uchar idata n;

for(n=0;n<31;n++)

{

lcd_Rectangle(3*n,0,3*n+2,2,1); lcd_Rectangle(3*n,60,3*n+2,62,1); }

for(n=0;n<21;n++)

{

lcd_Rectangle(0,3*n,2,3*n+2,1); lcd_Rectangle(90,3*n,92,3*n+2,1); }

lcd_HoriLine(93,31,35,1);

lcd_HoriLine(93,63,35,1);

}

/***************************

打印成绩

****************************/

void PrintScore(void)

{

unsigned char idata Str[3];

lcd_Write_string(6,0,"成绩");

Str[0]=(score/10)|0x30;//十位

Str[1]=(score%10)|0x30;//个位

Str[2]=0;

lcd_Write_string(7,1,Str);

}

/******************************** 打印速度级别

*********************************/ void PrintSpeed(void)

{

unsigned char idata Str[2];

lcd_Write_string(6,2,"级别");

Str[0]=speed|0x30;

Str[1]=0;

lcd_Write_string(7,3,Str);

}

/***********************************************

游戏结束处理

*************************************************/ void Game_Over()

{

if(snake.life==0)

lcd_Write_string(2,1,"GOOD");

else

{

Lcd_Clear(0);

clrscreen();

lcd_Write_string(0,0,"failed the game!"); lcd_Write_string(0,1,"失败是成功之母!"); //lcd_Write_string(2,1,"得分: ");

//PrintScore();

//PrintSpeed();

}

}

void set_speed()

{

while(flag!=1);

while(1)

{

flag=0;

if(flag==3)

{

speed=speed+1;

if(speed==10)

speed=1;

flag=0;

PrintSpeed();

//continue;

}

if(flag==4)

{

speed--;

if(speed==0)

speed=9;

flag=0;

PrintSpeed();

//continue;

}

if(flag==2)

{

break;

}

}

}

/****************************************

LCD初始化

*****************************************/

void Lcd_Reset()

{

//PSB=1;

lcd_write_com(0x30); //选择基本指令集

lcd_write_com(0x0c); //开显示(无游标、不反白)

lcd_write_com(0x01); //清除显示,并且设定地址指针为00H

lcd_write_com(0x06); //指定在资料的读取及写入时,设定游标的移动方向及指定显示的移位

}

/********************************************************

初始化定时器0

**************************************************/

void init_Timer0()

{

TMOD=0x02;

TH0=0;

TL0=0;

EA=1;

ET0=1;

TR0=1;

}

/*******************************************************

开始游戏 ,玩游戏

************************************************************/

void Game_Play()

{

//uchar n=0;

snake.node=2;

flag=1;

PrintScore(); PrintSpeed(); for(n=0;n<snake.node;n++) { snake.x[0]=6; snake.y[0]=6; snake.x[n]=snake.x[0]-3*n; snake.y[n]=snake.y[0]; lcd_Rectangle(snake.x[n],snake.y[n],snake.x[n]+2,snake.y[n]+2,1); } delay((int)(100/speed)); food.yes=1; while(1) { InitRandom(TL0); //1表示需要出现新事物,0表示已经存在食物尚未吃掉 if(food.yes==1) { while(1) { food.x=Random()*85+3; food.y=Random()*55+3;//获得随机数 } while(food.x%3!=0) food.x++; while(food.y%3!=0) food.y++; for(n=0;n<snake.node;n++)//判断产生的食物坐标是否和蛇身重合 { if((food.x==snake.x[n])&&(food.y==snake.y[n])) break; } if(n==snake.node) { food.yes=0; break;//产生有效的食物坐标 } }

for(n=0;n<snake.node;n++) { snake.node_x[n]=snake.x[n]; snake.node_y[n]=snake.y[n]; } n=1; for(n=1;n<(snake.node+1);n++) { snake.x[n]=snake.node_x[n-1]; snake.y[n]=snake.node_y[n-1]; lcd_Rectangle(snake.x[n],snake.y[n],snake.x[n]+2,snake.y[n]+2,1); } if(food.yes==0) { lcd_Rectangle(food.x,food.y,food.x+2,food.y+2,1); } DrawBoard(); if(flag==1) { snake.x[0]+=3; } if(flag==2) { snake.x[0]-=3; } if(flag==3) { snake.y[0]+=3; } if(flag==4) { snake.y[0]-=3; }

lcd_Rectangle(snake.x[0],snake.y[0],snake.x[0]+2,snake.y[0]+2,1);

lcd_Rectangle(snake.x[snake.node],snake.y[snake.node],snake.x[snake.node]+2,snake.y[snake.node]+2,0);

//Lcd_Clear(0);

if(food.yes==0)

{

lcd_Rectangle(food.x,food.y,food.x+2,food.y+2,1);

}

DrawBoard();

for(n=3;n<snake.node;n++)/////////从第三节开始判断蛇头是否咬到自己

{

if(snake.x[n]==snake.x[0]&&snake.y[n]==snake.y[0])

{

//Game_Over()

snake.life=1;

break;

}

}

if(snake.x[0]<3||snake.x[0]>=90||snake.y[0]<3||snake.y[0]>=60)//判蛇头是否撞到墙壁 {

//Game_Over()

snake.life=1;

}

if(snake.life==1)

break;//蛇死,则跳出while(1)循*/

//Game_Over();

if(snake.x[0]==food.x&&snake.y[0]==food.y)//判蛇是否吃到食物

{

lcd_Rectangle(food.x,food.y,food.x+2,food.y+2,0);//消隐食物

snake.x[snake.node]=200;

snake.y[snake.node]=200;//产生蛇新的节坐标先放在看不见的位置

snake.node++;//蛇节数加1

food.yes=1;//食物标志置1

if(++score>=PASSSCORE)

{

speed++;

PrintScore();

PrintSpeed();

//Game_Over();

//break;

}

PrintScore();

}

/*DrawBoard(); rintScore(); PrintSpeed();*/

delay((int)(100/speed));

Lcd_Clear(0); //Lcd_Clear(0); //clrscreen(); }

//Lcd_Clear(0);

//clrscreen();

}

void main()

{

Lcd_Reset();

init_Timer0();

Lcd_Clear(0);

clrscreen();

while(1)

{

DrawBoard(); PrintScore(); PrintSpeed();

set_speed(); Game_Play(); Game_Over();

while(1);

}

}

/*********************************************** 定时器0中断 用 方式2

************************************************/ void Timer0() interrupt 1

{

if((flag!=1)&&(up==0))

{

_nop_();

_nop_();

if((flag!=1)&&(up==0))

while(!up);

flag=2;

}

if((flag!=2)&&(down==0))

{

_nop_();

_nop_();

if((flag!=2)&&(down==0))

while(!down);

flag=1;

}

if((flag!=4)&&(left==0))

{

_nop_();

_nop_();

if((flag!=4)&&(left==0))

while(!left);

flag=3;

}

if((flag!=3)&&(right==0))

{

_nop_();

} } _nop_(); if((flag!=3)&&(right==0)) while(!right); flag=4;

C语言学习

1.初始化人机界面

C语言学习

.2.调节速度.

C语言学习

3.玩游戏.

C语言学习

4.游戏输了,结束游戏.

更多相关推荐:
关于学习名言(英文)

关于学习读书励志的名言警句PeoplediebutbooksneverdieNomanandnoforcecanabolishmemoryFranklinRoosevelt人会死亡书却无朽没有任何人可以丢弃记忆...

关于学习的英语名言

关于学习的英语名言学习英语总是一件不容易的事,但想收获还得坚持。对于学习,我们该抱着怎么样的态度?什么样的目标?下面分享学习的英语名言,给大家照亮学习的路:Allthingsaredifficultbefore…

英语学习名言

英语学习者的经典名言10句20xx1225094949分类标签字号大中小订阅1WhatislanguageforSomepeopleseemtothinkitsforpracticinggrammarrules...

关于英语学习的名言

激励学习英语的吧名言1WhatislanguageforSomepeopleseemtothinkit39sforpracticinggrammarrulesandlearninglistsofwordsthe...

英语学习_名人名言(中英文对照)(英语版)_必备

弃我去者昨日之日不可留乱我心者今日之日多烦忧名人名言中英文对照励志篇名人名言奋斗1Geniusonlymeanshardworkingallone39slifeMendeleyerRussianChemist天...

100句值得学习的英语名言

100句值得学习的英语名言1Truthandroseshavethornsaboutthem真理和玫瑰身旁都有刺2Thebraveandthewisecanbothpityandexcusewhencoward...

关于英语学习的名言

激励学习英语的吧名言1WhatislanguageforSomepeopleseemtothinkit39sforpracticinggrammarrulesandlearninglistsofwordsthe...

英语名言警句学习(带中文翻译)

英语名言警句Abadconscienceisasnakeinone39sheart做贼心虚Abadworkmanquarrelswithhistools拙匠常怨工具差Abirdinthehandiswortht...

整理好的英语名言

AllthingsintheirbeingaregoodforsomethingDifficultcircumstancesserveasatextbookoflifeforpeople困难坎坷是人们的生活教科...

英语有关的名言

1Abosomfriendafarbringsadistantlandnear海内存知己天涯若比邻2Acommondangercausescommonaction同舟共济3Acontentedmindisaco...

关于大学的英语名言

1WhatislanguageforSomepeopleseemtothinkit39sforpracticinggrammarrulesandlearninglistsofwordsthelongerthew...

中英文有关名言的名言警句

中英文有关责任的名言警句责任的名言Therelevantresponsiblesayingone1责任就是对自己要求去做的事情有一种爱歌德1theresponsibilityistoownrequesttodo...

学习的英语名言(18篇)