为什么嵌入式要用c语言编写[合集5篇]

时间:2019-05-15 10:26:44下载本文作者:会员上传
简介:写写帮文库小编为你整理了多篇相关的《为什么嵌入式要用c语言编写》,但愿对你工作学习有帮助,当然你在写写帮文库还可以找到更多《为什么嵌入式要用c语言编写》。

第一篇:为什么嵌入式要用c语言编写

为什么嵌入式软件要用C语言编写

嵌入式软件一般需着重考虑三个方面:性能、安全性和开发效率(包括代码可移植性等)。性能(运行效率)方面,汇编明显是最高的。但汇编在安全性和开发效率方面明显是最低的(不考虑机器语言--)。所以除非是要求极端高性能的嵌入式平台(或者是系统实在是太简单而没办法支持高级语言,orz--),使用汇编语言的不多。

相对于C,其它高级语言的运行效率一般比较低(C程序运行效率可达汇编的80%,而其它程序可能只有C程序的80%),源代码和目标代码也可能会比较长。对于嵌入式系统,性能的瓶颈是非常致命的,很可能某种用C编写的程序可以达到预期目标,而用其它语言使用同样算法编写的程序就不行。(不过也正因为这个原因,在嵌入式系统上实现的可用编程语言并不多。)

基于系统的用途,安全性设计嵌入式系统也是必须考虑的一个部分(比如说用于医疗卫生设施),必须尽可能在开发期间减少潜在的错误。这方面C不占优势,但如果保证代码严格遵守安全规范,也可以接受(相对而言,汇编就郁闷了--)。

开发效率和安全性类似,也在可接受范围之内。

也可以用汇编编写c语言也好 汇编也好 或者更高级的语言都是跟人看和些的让人的思维能够描述出来

然后通过编译环境编译成计算机能看的懂的东西 不同的语言 编译完以后 逻辑上其实都是一样的然后交给芯片去运行要说效率c没有汇编效率高

举个例子

一个韩国工人(计算机)只会懂韩语(机器语言)领导有一个中国人(程序员)只会说汉语(C语言)另一个日本人(程序员)只会说日语(汇编)还有一个西班牙人(程序员)只会说西班牙语(另一种高级语言比如java)想让韩国人做同样一个事情中国人用汉语说完经过翻译(编译系统)变成韩国语韩国工人明白了要干什么日本人用日语通过翻译 变成韩国语韩国工人也知道要干什么了另一个西班牙人 用西班牙语 翻译成韩国语让韩国人干的是同一个活翻译完的结果是一样的 只是不同语言表达罢了c语言更方便 移植性更强(比汇编)

我目前接触的一般的嵌入式上层软件 c语言就可以搞定

如果遇到比较严格的或者军工的甲方

c语言搭钩框架,然后剩下的全部用汇编语言实现

之所以用c 是因为c比汇编操作简单

调试方便 开发效率较高

但是代码运行效率可能没那么

而且汇编可以精确定时,代码运行时间是可以计算出来的因为C效率高~相对其他高级语言代码所占用的空间少~通用性也不错

所以要用C喽

嵌入式的芯片ROM有限

第二篇:C语言单片机嵌入式软件编写要点

C单片机嵌入式软件

本质是:

在单片机裸机上写一个操作系统。

技术范围:

软件工程。

具体指标:

一,模块化。

二,层次化。

三,可读性,可扩充性(中断程序少做事)。四,可移植性。

五,追求逻辑简单,不追求占用空间最少。

六,条件判断可以重复判断,追求逻辑和时间解耦。七,可以重复清理现场,提高软件抗干扰能力。八,有心得,请继续增加,大家共享。

第三篇:嵌入式开发—C语言面试题

嵌入式开发—C语言面试题

1.用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)

#define SECONDS_PER_YEAR(60 * 60 * 24 * 365)UL 我在这想看到几件事情:

1).#define 语法的基本知识(例如:不能以分号结束,括号的使用,等等)

2).懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的。

3).意识到这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉编译器这个常数是的长整型数。

4).如果你在你的表达式中用到UL(表示无符号长整型),那么你有了一个好的起点。记住,第一印象很重要。

2.写一个“标准”宏MIN,这个宏输入两个参数并返回较小的一个。

#define MIN(A,B)((A)<=(B)(A):))

这个测试是为下面的目的而设的:

1).标识#define在宏中应用的基本知识。这是很重要的,因为直到嵌入(inline)操作符变为标准C的一部分,宏是方便产生嵌入代码的唯一方法,对于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的方法。

2).三重条件操作符的知识。这个操作符存在C语言中的原因是它使得编译器能产生比if-then-else更优化的代码,了解这个用法是很重要的。

3).懂得在宏中小心地把参数用括号括起来

4).我也用这个问题开始讨论宏的副作用,例如:当你写下面的代码时会发生什么事?

least = MIN(*p++, b);

3.预处理器标识#error的目的是什么?

如果你不知道答案,请看参考文献1。这问题对区分一个正常的伙计和一个书呆子是很有用的。只有书呆子才会读C语言课本的附录去找出象这种

问题的答案。当然如果你不是在找一个书呆子,那么应试者最好希望自己不要知道答案。

死循环(Infinite loops)

4.嵌入式系统中经常要用到无限循环,你怎么样用C编写死循环呢?

这个问题用几个解决方案。我首选的方案是:

while(1){ } 一些程序员更喜欢如下方案:

for(;;){ }

这个实现方式让我为难,因为这个语法没有确切表达到底怎么回事。如果一个应试者给出这个作为方案,我将用这个作为一个机会去探究他们这样做的基本原理。如果他们的基本答案是:“我被教着这样做,但从没有想到过为什么。”这会给我留下一个坏印象。

第三个方案是用 goto Loop:...goto Loop;

应试者如给出上面的方案,这说明或者他是一个汇编语言程序员(这也许是好事)或者他是一个想进入新领域的BASIC/FORTRAN程序员。

数据声明(Data declarations)

5.用变量a给出下面的定义

a)一个整型数(An integer)

b)一个指向整型数的指针(A pointer to an integer)

c)一个指向指针的的指针,它指向的指针是指向一个整型数(A pointer to a pointer to an integer)

d)一个有10个整型数的数组(An array of 10 integers)

e)一个有10个指针的数组,该指针是指向一个整型数的(An array of 10 pointers to integers)

f)一个指向有10个整型数数组的指针(A pointer to an array of 10 integers)

g)一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument and returns an integer)

h)一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数(An array of ten pointers to functions that take an integer argument and return an integer)

答案是:

a)int a;// An integer

b)int *a;// A pointer to an integer

c)int **a;// A pointer to a pointer to an integer d)int a[10];// An array of 10 integers

e)int *a[10];// An array of 10 pointers to integers f)int(*a)[10];// A pointer to an array of 10 integers

g)int(*a)(int);// A pointer to a function a that takes an integer argument and returns an integer

h)int(*a[10])(int);// An array of 10 pointers to functions that take an integer argument and return an integer

人们经常声称这里有几个问题是那种要翻一下书才能回答的问题,我同意这种说法。当我写这篇文章时,为了确定语法的正确性,我的确查了一下书。但是当我被面试的时候,我期望被问到这个问题(或者相近的问题)。因为在被面试的这段时间里,我确定我知道这个问题的答案。应试者如果不知道

所有的答案(或至少大部分答案),那么也就没有为这次面试做准备,如果该面试者没有为这次面试做准备,那么他又能为什么出准备呢?

Static

6.关键字static的作用是什么?

这个简单的问题很少有人能回答完全。在C语言中,关键字static有三个明显的作用:

1).在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。

2).在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。

3).在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。

大多数应试者能正确回答第一部分,一部分能正确回答第二部分,同是很少的人能懂得第三部分。这是一个应试者的严重的缺点,因为他显然不懂得本地化数据和代码范围的好处和重要性。

Const

7.关键字const是什么含意?

我只要一听到被面试者说:“const意味着常数”,我就知道我正在和一个业余者打交道。去年Dan Saks已经在他的文章里完全概括了const的所有用法,因此ESP(译者:Embedded Systems Programming)的每一位读者应该非常熟悉const能做什么和不能做什么.如果你从没有读到那篇文章,只要能说出const意味着“只读”就可以了。尽管这个答案不是完全的答案,但我接受它作为一个正确的答案。(如果你想知道更详细的答案,仔细读一下Saks的文章吧。)如果应试者能正确回答这个问题,我将问他一个附加的问题:下面的声明都是什么意思?

const int a;int const a;const int *a;int * const a;

int const * a const;

前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。第四个意识a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。如果应试者能正确回答这些问题,那么他就给我留下了一个好印象。顺带提一句,也许你可能会问,即使不用关键字 const,也还是能很容易写出功能正确的程序,那么我为什么还要如此看重关键字const呢?我也如下的几下理由:

1).关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。如果你曾花很多时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用const的程序员很少会留下的垃圾让别人来清理的。)

2).通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。

3).合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。

Volatile

8.关键字volatile有什么含意 并给出三个不同的例子。

一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:

1).并行设备的硬件寄存器(如:状态寄存器)

2).一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)3).多线程应用中被几个任务共享的变量

回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。嵌入式系统程序员经常同硬件、中断、RTOS等等打交道,所用这些都要求volatile变量。不懂得volatile内容将会带来灾难。

假设被面试者正确地回答了这是问题(嗯,怀疑这否会是这样),我将稍微深究一下,看一下这家伙是不是直正懂得volatile完全的重要性。

1).一个参数既可以是const还可以是volatile吗?解释为什么。

2).一个指针可以是volatile 吗?解释为什么。

3).下面的函数有什么错误:

int square(volatile int *ptr){ return *ptr * *ptr;} 下面是答案:

1).是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。

2).是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。

3).这段代码的有个恶作剧。这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:

int square(volatile int *ptr){ int a,b;a = *ptr;b = *ptr;return a * b;

} 由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:

long square(volatile int *ptr){ int a;a = *ptr;return a * a;}

位操作(Bit manipulation)

9.嵌入式系统总是要用户对变量或寄存器进行位操作。给定一个整型变量a,写两段代码,第一个设置a的bit 3,第二个清除a 的bit 3。在以上两个操作中,要保持其它位不变。

对这个问题有三种基本的反应

1).不知道如何下手。该被面者从没做过任何嵌入式系统的工作。

2).用bit fields。Bit fields是被扔到C语言死角的东西,它保证你的代码在不同编译器之间是不可移植的,同时也保证了的你的代码是不可重用的。我最近不幸看到 Infineon为其较复杂的通信芯片写的驱动程序,它用到了bit fields因此完全对我无用,因为我的编译器用其它的方式来实现bit fields的。从道德讲:永远不要让一个非嵌入式的家伙粘实际硬件的边。

3).用 #defines 和 bit masks 操作。这是一个有极高可移植性的方法,是应该被用到的方法。最佳的解决方案如下:

#define BIT3(0x1<<3)static int a;

void set_bit3(void){ a |= BIT3;

} void clear_bit3(void){ a &= ~BIT3;

} 一些人喜欢为设置和清除值而定义一个掩码同时定义一些说明常数,这也是可以接受的。我希望看到几个要点:说明常数、|=和&=~操作。

10.嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的ANSI编译器。写代码去完成这一任务。

这一问题测试你是否知道为了访问一绝对地址把一个整型数强制转换(typecast)为一指针是合法的。这一问题的实现方式随着个人风格不同而不同。典型的类似代码如下:

int *ptr;

ptr =(int *)0x67a9;*ptr = 0xaa55;

一个较晦涩的方法是:

*(int * const)(0x67a9)= 0xaa55;

即使你的品味更接近第二种方案,但我建议你在面试时使用第一种方案。

中断(Interrupts)

11.中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展—让标准C支持中断。具代表事实是,产生了一个新的关键字 __interrupt。下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。

__interrupt double compute_area(double radius){ double area = PI * radius * radius;printf(“ Area = %f”, area);return area;}

这个函数有太多的错误了,以至让人不知从何说起了:

1).ISR 不能返回一个值。如果你不懂这个,那么你不会被雇用的。

2).ISR 不能传递参数。如果你没有看到这一点,你被雇用的机会等同第一项。

3).在许多的处理器/编译器中,浮点一般都是不可重入的。有些处理器/编译器需要让额处的寄存器入栈,有些处理器/编译器就是不允许在ISR中做浮点运算。此外,ISR应该是短而有效率的,在ISR中做浮点运算是不明智的。

4).与第三点一脉相承,printf()经常有重入和性能上的问题。如果你丢掉了第三和第四点,我不会太为难你的。不用说,如果你能得到后两点,那么你的被雇用前景越来越光明了。

代码例子(Code examples).下面的代码输出是什么,为什么?

void foo(void)

{ unsigned int a = 6;int b =-20;

(a+b > 6)puts(“> 6”): puts(“<= 6”);}

这个问题测试你是否懂得C语言中的整数自动转换原则,我发现有些开发者懂得极少这些东西。不管如何,这无符号整型问题的答案是输出是“>6”。原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。因此-20变成了一个非常大的正整数,所以该表达式计算出的结果大于6。这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。如果你答错了这个问题,你也就到了得不到这份工作的边缘。

13.评价下面的代码片断:

unsigned int zero = 0;

unsigned int compzero = 0xFFFF;/*1's complement of zero */

对于一个int型不是16位的处理器为说,上面的代码是不正确的。应编写如下:

unsigned int compzero = ~0;

这一问题真正能揭露出应试者是否懂得处理器字长的重要性。在我的经验里,好的嵌入式程序员非常准确地明白硬件的细节和它的局限,然而PC机程序往往把硬件作为一个无法避免的烦恼。

到了这个阶段,应试者或者完全垂头丧气了或者信心满满志在必得。如果显然应试者不是很好,那么这个测试就在这里结束了。但如果显然应试者做得不错,那么我就扔出下面的追加问题,这些问题是比较难的,我想仅仅非常优秀的应试者能做得不错。提出这些问题,我希望更多看到应试者应付问题的方法,而不是答案。不管如何,你就当是这个娱乐吧„

动态内存分配(Dynamic memory allocation)

14.尽管不像非嵌入式计算机那么常见,嵌入式系统还是有从堆(heap)中动态分配内存的过程的。那么嵌入式系统中,动态分配内存可能发生的问题是什么?

这里,我期望应试者能提到内存碎片,碎片收集的问题,变量的持行时间等等。这个主题已经在ESP杂志中被广泛地讨论过了(主要是 P.J.Plauger, 他的解释远远超过我这里能提到的任何解释),所有回过头看一下这些杂志吧!让应试者进入一种虚假的安全感觉后,我拿出这么一个小节目:下面的代码片段的输出是什么,为什么?

char *ptr;

if((ptr =(char *)malloc(0))== NULL)puts(“Got a null pointer”);else

puts(“Got a valid pointer”);

这是一个有趣的问题。最近在我的一个同事不经意把0值传给了函数malloc,得到了一个合法的指针之后,我才想到这个问题。这就是上面的代码,该代码的输出是“Got a valid pointer”。我用这个来开始讨论这样的一问题,看看被面试者是否想到库例程这样做是正确。得到正确的答案固然重要,但解决问题的方法和你做决定的基本原理更重要些。

Typedef

15.Typedef 在C语言中频繁用以声明一个已经存在的数据类型的同义字。也可以用预处理器做类似的事。例如,思考一下下面的例子: #define dPS struct s * typedef struct s * tPS;

以上两种情况的意图都是要定义dPS 和 tPS 作为一个指向结构s指针。哪种方法更好呢?(如果有的话)为什么?

这是一个非常微妙的问题,任何人答对这个问题(正当的原因)是应当被恭喜的。答案是:typedef更好。思考下面的例子:

dPS p1,p2;tPS p3,p4;

第一个扩展为

struct s * p1, p2;

上面的代码定义p1为一个指向结构的指,p2为一个实际的结构,这也许不是你想要的。第二个例子正确地定义了p3 和p4 两个指针。

晦涩的语法

16.C语言同意一些令人震惊的结构,下面的结构是合法的吗,如果是它做些什么?

int a = 5, b = 7, c;c = a+++b;

这个问题将做为这个测验的一个愉快的结尾。不管你相不相信,上面的例子是完全合乎语法的。问题是编译器如何处理它?水平不高的编译作者实际上会争论这个问题,根据最处理原则,编译器应当能处理尽可能所有合法的用法。因此,上面的代码被处理成:

c = a++ + b;

因此, 这段代码持行后a = 6, b = 7, c = 12。

如果你知道答案,或猜出正确答案,做得好。如果你不知道答案,我也不把这个当作问题。我发现这个问题的最大好处是:这是一个关于代码编写风格,代码的可读性,代码的可修改性的好的话题

What will print out?

main()

{ char *p1=“name”;char *p2;

p2=(char*)malloc(20);memset(p2, 0, 20);while(*p2++ = *p1++);printf(“%sn”,p2);

}

Answer:empty string.What will be printed as the result of the operation below:

main()

{ int x=20,y=35;x=y++ + x++;y= ++y + ++x;

printf(“%d%dn”,x,y);}

Answer : 5794

What will be printed as the result of the operation below:

main(){ int x=5;

printf(“%d,%d,%dn”,x,x< <2,x>>2);}

Answer: 5,20,1

What will be printed as the result of the operation below:

#define swap(a,b)a=a+b;b=a-b;a=a-b;void main(){ int x=5, y=10;swap(x,y);

printf(“%d %dn”,x,y);swap2(x,y);

printf(“%d %dn”,x,y);}

int swap2(int a, int b){ int temp;temp=a;b=a;a=temp;return 0;

}

Answer: 10, 5 10, 5

What will be printed as the result of the operation below:

main()

{ char *ptr = ” Cisco Systems”;*ptr++;printf(“%sn”,ptr);ptr++;

printf(“%sn”,ptr);}

Answer:Cisco Systems isco systems

What will be printed as the result of the operation below:

main()

{ char s1[]=“Cisco”;char s2[]= “systems”;printf(“%s”,s1);} Answer: Cisco

What will be printed as the result of the operation below:

main(){ char *p1;char *p2;

p1=(char *)malloc(25);p2=(char *)malloc(25);

strcpy(p1,”Cisco”);strcpy(p2,“systems”);strcat(p1,p2);

printf(“%s”,p1);

}

Answer: Ciscosystems

The following variable is available in file1.c, who can access it?:

static int average;Answer: all the functions in the file1.c can access the variable.WHat will be the result of the following code?

#define TRUE 0 // some code while(TRUE){

// some code

}

Answer: This will not go into the loop as TRUE is defined as 0.What will be printed as the result of the operation below:

int x;

int modifyvalue(){ return(x+=10);

} int changevalue(int x){ return(x+=1);}

void main(){ int x=10;x++;

changevalue(x);x++;

modifyvalue();

printf(“First output:%dn”,x);

x++;

changevalue(x);

printf(“Second output:%dn”,x);modifyvalue();

printf(“Third output:%dn”,x);

}

Answer: 12 , 13 , 13

What will be printed as the result of the operation below:

main(){ int x=10, y=15;x = x++;y = ++y;

printf(“%d %dn”,x,y);}

Answer: 11, 16

What will be printed as the result of the operation below:

main(){ int a=0;if(a==0)

printf(“Cisco Systemsn”);printf(“Cisco Systemsn”);}

Answer: Two lines with “Cisco Systems” will be printed.再次更新C++相关题集

1.以下三条输出语句分别输出什么?[C易] char str1[] = “abc”;char str2[] = “abc”;

const char str3[] = “abc”;const char str4[] = “abc”;const char* str5 = “abc”;const char* str6 = “abc”;

cout << boolalpha <<(str1==str2)<< endl;// 输出什么?

cout << boolalpha <<(str3==str4)<< endl;// 输出什么?

cout << boolalpha <<(str5==str6)<< endl;// 输出什么?

13.非C++内建型别 A 和 B,在哪几种情况下B能隐式转化为A?[C++中等] 答:

a.class B : public A { „„} // B公有继承自A,可以是间接继承的b.class B { operator A();} // B实现了隐式转化为A的转化

c.class A { A(const B&);} // A实现了non-explicit的参数为B(可以有其他带默认值的参数)构造函数

d.A& operator=(const A&);// 赋值操作,虽不是正宗的隐式类型转换,但也可以勉强算一个

12.以下代码中的两个sizeof用法有问题吗?[C易]

void UpperCase(char str[])// 将 str 中的小写字母转换成大写字母

{ for(size_t i=0;i

} char str[] = “aBcDe”;

cout << “str字符长度为: ” << sizeof(str)/sizeof(str[0])<< endl;UpperCase(str);cout << str << endl;

7.以下代码有什么问题?[C难]

void char2Hex(char c)// 将字符以16进制表示

{ char ch = c/0x10 + '0';if(ch > '9')ch +=('A'-'9'-1);char cl = c%0x10 + '0';if(cl > '9')cl +=('A'-'9'-1);cout << ch << cl << ' ';

} char str[] = “I love 中国”;

for(size_t i=0;i

4.以下代码有什么问题?[C++易] struct Test { Test(int){} Test(){} void fun(){} };

void main(void){ Test a(1);a.fun();Test b();b.fun();}

5.以下代码有什么问题?[C++易] cout <<(true?1:“1”)<< endl;

8.以下代码能够编译通过吗,为什么?[C++易] unsigned int const size1 = 2;char str1[ size1 ];

unsigned int temp = 0;cin >> temp;

unsigned int const size2 = temp;char str2[ size2 ];

9.以下代码中的输出语句输出0吗,为什么?[C++易] struct CLS { int m_i;CLS(int i): m_i(i){} CLS(){ CLS(0);} };

CLS obj;

cout << obj.m_i << endl;

10.C++中的空类,默认产生哪些类成员函数?[C++易] 答:

class Empty { public:

Empty();// 缺省构造函数

Empty(const Empty&);// 拷贝构造函数

~Empty();// 析构函数

Empty& operator=(const Empty&);// 赋值运算符

Empty* operator&();// 取址运算符

const Empty* operator&()const;// 取址运算符 const };

3.以下两条输出语句分别输出什么?[C++难] float a = 1.0f;

cout <<(int)a << endl;cout <<(int&)a << endl;

cout << boolalpha <<((int)a ==(int&)a)<< endl;// 输出什么?

float b = 0.0f;

cout <<(int)b << endl;cout <<(int&)b << endl;

cout << boolalpha <<((int)b ==(int&)b)<< endl;// 输出什么?

2.以下反向遍历array数组的方法有什么错误?[STL易] vector array;

array.push_back(1);array.push_back(2);array.push_back(3);

for(vector::size_type i=array.size()-1;i>=0;--i)// 反向遍历array数组

{ cout << array[i] << endl;}

6.以下代码有什么问题?[STL易] typedef vector IntArray;IntArray array;

array.push_back(1);array.push_back(2);array.push_back(2);array.push_back(3);

// 删除array数组中所有的2

for(IntArray::iterator itor=array.begin();itor!=array.end();++itor){ if(2 == *itor)array.erase(itor);}

11.写一个函数,完成内存之间的拷贝。[考虑问题是否全面] 答:

void* mymemcpy(void *dest, const void *src, size_t count)

{

char* pdest = static_cast(dest);

const char* psrc = static_cast(src);

if(pdest>psrc && pdest

{

for(size_t i=count-1;i!=-1;--i)

pdest[i] = psrc[i];

}

else

{

for(size_t i=0;i

pdest[i] = psrc[i];

}

return dest;

}

int main(void)

{

char str[] = “0123456789”;

mymemcpy(str+1, str+0, 9);

cout << str << endl;

system(“Pause”);

return 0;

}

C语言面试题总汇

C语言面试题总汇

4.static有什么用途?(请至少说明两种)1.限制变量的作用域 2.设置变量的存储域

7.引用与指针有什么区别? 1)引用必须被初始化,指针不必。

2)引用初始化以后不能被改变,指针可以改变所指的对象。

2)不存在指向空值的引用,但是存在指向空值的指针。

8.描述实时系统的基本特性

在特定时间内完成特定的任务,实时性与可靠性

9.全局变量和局部变量在内存中是否有区别?如果有,是什么区别? 全局变量储存在静态数据库,局部变量在堆栈 10.什么是平衡二叉树?

左右子树都是平衡二叉树 且左右子树的深度差值的绝对值不大于1 11.堆栈溢出一般是由什么原因导致的? 没有回收垃圾资源 12.什么函数不能声明为虚函数? constructor 13.冒泡排序算法的时间复杂度是什么? O(n^2)14.写出float x 与“零值”比较的if语句。if(x>0.000001&&x<-0.000001)16.Internet采用哪种网络协议?该协议的主要层次结构? tcp/ip 应用层/传输层/网络层/数据链路层/物理层

17.Internet物理地址和IP地址转换采用什么协议? ARP(Address Resolution Protocol)(地址解析协议)18.IP地址的编码分为哪俩部分?

IP地址由两部分组成,网络号和主机号。不过是要和“子网掩码”按位与上之后才能区分哪些是网络位哪些是主机位。

2.用户输入M,N值,从1至N开始顺序循环数数,每数到M输出该数值,直至全部输出。写出C程序。循环链表,用取余操作做

3.不能做switch()的参数类型是: switch的参数不能为实型。

华为

1、局部变量能否和全局变量重名?

答:能,局部会屏蔽全局。要用全局变量,需要使用“::” 局部变量可以与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。对于有些编译器而言,在同一个函数内可以定义多个同名的局部变量,比如在两个循环体内都定义一个同名的局部变量,而那个局部变量的作用域就在那个循环体内

2、如何引用一个已经定义过的全局变量? 答:extern 可以用引用头文件的方式,也可以用extern关键字,如果用引用头文件方式来引用某个在头文件中声明的全局变理,假定你将那个变写错了,那么在编译期间会报错,如果你用extern方式引用时,假定你犯了同样的错误,那么在编译期间不会报错,而在连接期间报错

3、全局变量可不可以定义在可被多个.C文件包含的头文件中?为什么? 答:可以,在不同的C文件中以static形式来声明同名全局变量。

可以在不同的C文件中声明同名的全局变量,前提是其中只能有一个C文件中对此变量赋初值,此时连接不会出错

4、语句for(;1 ;)有什么问题?它是什么意思? 答:和while(1)相同。

5、do„„while和while„„do有什么区别?

答:前一个循环一遍再判断,后一个判断以后再循环

6、请写出下列代码的输出内容 #i nclude main(){ int a,b,c,d;a=10;b=a++;c=++a;d=10*a++;printf(“b,c,d:%d,%d,%d”,b,c,d);return 0;}

答:10,12,120

1、static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?

全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式。这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。而静态全局变量则限制了其作用域,即只在定义该变量的源文件内有效,在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其它源文件中引起错误。

从以上分析可以看出,把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域,限制了它的使用范围。

static函数与普通函数作用域不同。仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static),内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件

static全局变量与普通的全局变量有什么区别:static全局变量只初使化一次,防止在其他文件单元中被引用;static局部变量和普通局部变量有什么区别:static局部变量只被初始化一次,下一次依据上一次结果值;

static函数与普通函数有什么区别:static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝

2、程序的局部变量存在于(堆栈)中,全局变量存在于(静态区)中,动态申请数据存在于(堆)中。

3、设有以下说明和定义:

typedef union {long i;int k[5];char c;} DATE;struct data { int cat;DATE cow;double dog;} too;DATE max;则语句 printf(“%d”,sizeof(struct date)+sizeof(max));的执行结果是:___52____ 答:DATE是一个union, 变量公用空间.里面最大的变量类型是int[5], 占用20个字节.所以它的大小是20 data是一个struct, 每个变量分开占用空间.依次为int4 + DATE20 + double8 = 32.所以结果是 20 + 32 = 52.当然...在某些16位编辑器下, int可能是2字节,那么结果是 int2 + DATE10 + double8 = 20

4、队列和栈有什么区别? 队列先进先出,栈后进先出

5、写出下列代码的输出内容 #i nclude int inc(int a){ return(++a);} int multi(int*a,int*b,int*c){ return(*c=*a**b);} typedef int(FUNC1)(int in);typedef int(FUNC2)(int*,int*,int*);void show(FUNC2 fun,int arg1, int*arg2){ INCp=&inc;int temp =p(arg1);fun(&temp,&arg1, arg2);printf(“%dn”,*arg2);} main(){ int a;show(multi,10,&a);return 0;} 答:110

7、请找出下面代码中的所以错误

说明:以下代码是把一个字符串倒序,如“abcd”倒序后变为“dcba”

1、#i nclude“string.h”

2、main()

3、{

4、char*src=“hello,world”;

5、char* dest=NULL;

6、int len=strlen(src);

7、dest=(char*)malloc(len);

8、char* d=dest;

9、char* s=src[len];

10、while(len--!=0)

11、d++=s--;

12、printf(“%s”,dest);

13、return 0;

14、} 答: 方法1: int main(){ char* src = “hello,world”;int len = strlen(src);char* dest =(char*)malloc(len+1);//要为分配一个空间 char* d = dest;char* s = &src[len-1];//指向最后一个字符 while(len--!= 0)*d++=*s--;*d = 0;//尾部要加 printf(“%sn”,dest);free(dest);// 使用完,应当释放空间,以免造成内存汇泄露 return 0;} 方法2:

#i nclude #i nclude main(){ char str[]=“hello,world”;int len=strlen(str);char t;for(int i=0;i

str[i]=str[len-i-1];str[len-i-1]=t;} printf(“%s”,str);return 0;} 1.-1,2,7,28,126请问28和126中间那个数是什么?为什么? 第一题的答案应该是4^3-1=63 规律是n^3-1(当n为偶数0,2,4)

n^3+1(当n为奇数1,3,5)答案:63 2.用两个栈实现一个队列的功能?要求给出算法和思路!设2个栈为A,B, 一开始均为空.入队: 将新元素push入栈A;出队:(1)判断栈B是否为空;

(2)如果不为空,则将栈A中所有元素依次pop出并push到栈B;(3)将栈B的栈顶元素pop出;

这样实现的队列入队和出队的平摊复杂度都还是O(1), 比上面的几种方法要好。3.在c语言库函数中将一个字符转换成整型的函数是atool()吗,这个函数的原型是什么? 函数名: atol

功 能: 把字符串转换成长整型数

用 法: long atol(const char *nptr);程序例:

#i nclude #i nclude int main(void){

long l;

char *str = “98765432”;l = atol(lstr);

printf(“string = %s integer = %ldn”, str, l);return(0);} 2.对于一个频繁使用的短小函数,在C语言中应用什么实现,在C++中应用什么实现? c用宏定义,c++用inline

3.直接链接两个信令点的一组链路称作什么? PPP点到点连接

4.接入网用的是什么接口?

5.voip都用了那些协议?

6.软件测试都有那些种类? 黑盒:针对系统功能的测试

白合:测试函数功能,各函数接口

7.确定模块的功能和模块的接口是在软件设计的那个队段完成的? 概要设计阶段

8.enum string

{

x1,x2,x3=10,x4,x5,}x;

问x= 0x801005,0x8010f4;

9.unsigned char *p1;

unsigned long *p2;

p1=(unsigned char *)0x801000;

p2=(unsigned long *)0x810000;

请问p1+5=;

p2+5=;三.选择题:

1.Ethternet链接到Internet用到以下那个协议?

A.HDLC;B.ARP;C.UDP;D.TCP;E.ID

2.属于网络层协议的是:

A.TCP;B.IP;C.ICMP;D.X.25

3.Windows消息调度机制是:

A.指令队列;B.指令堆栈;C.消息队列;D.消息堆栈;

4.unsigned short hash(unsigned short key)

{

return(key>>)%256

}

请问hash(16),hash(256)的值分别是:

A.1.16;B.8.32;C.4.16;D.1.32 四.找错题:

1.请问下面程序有什么错误?

int a[60][250][1000],i,j,k;

for(k=0;k<=1000;k++)

for(j=0;j<250;j++)

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

a[i][j][k]=0;把循环语句内外换一下

2.#define Max_CB 500

void LmiQueryCSmd(Struct MSgCB * pmsg)

{

unsigned char ucCmdNum;

......for(ucCmdNum=0;ucCmdNum

{

......;

} 死循环

3.以下是求一个数的平方的程序,请找出错误:

#define SQUARE(a)((a)*(a))

int a=5;

int b;

b=SQUARE(a++);

4.typedef unsigned char BYTE

int examply_fun(BYTE gt_len;BYTE *gt_code)

{

BYTE *gt_buf;

gt_buf=(BYTE *)MALLOC(Max_GT_Length);

......if(gt_len>Max_GT_Length)

{

return GT_Length_ERROR;

}

.......} 五.问答题:

1.IP Phone的原理是什么? IPV6

2.TCP/IP通信建立的过程怎样,端口有什么作用? 三次握手,确定是哪个应用程序使用该协议

3.1号信令和7号信令有什么区别,我国某前广泛使用的是那一种?

4.列举5种以上的电话新业务?

微软亚洲技术中心的面试题!!1.进程和线程的差别。

线程是指进程内的一个执行单元,也是进程内的可调度实体.与进程的区别:(1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位

(2)并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行

(3)拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源.(4)系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销。2.测试方法

人工测试:个人复查、抽查和会审 机器测试:黑盒测试和白盒测试

2.Heap与stack的差别。Heap是堆,stack是栈。

Stack的空间由操作系统自动分配/释放,Heap上的空间手动分配/释放。Stack空间有限,Heap是很大的自由存储区

C中的malloc函数分配的内存空间即在堆上,C++中对应的是new操作符。

程序在编译期对变量和函数分配内存都在栈上进行,且程序运行过程中函数调用时参数的传递也在栈上进行

3.Windows下的内存是如何管理的? 4.介绍.Net和.Net的安全性。

5.客户端如何访问.Net组件实现Web Service? 6.C/C++编译器中虚表是如何完成的?

7.谈谈COM的线程模型。然后讨论进程内/外组件的差别。8.谈谈IA32下的分页机制

小页(4K)两级分页模式,大页(4M)一级

9.给两个变量,如何找出一个带环单链表中是什么地方出现环的? 一个递增一,一个递增二,他们指向同一个接点时就是环出现的地方 10.在IA32中一共有多少种办法从用户态跳到内核态?

通过调用门,从ring3到ring0,中断从ring3到ring0,进入vm86等等 11.如果只想让程序有一个实例运行,不能运行两个。像winamp一样,只能开一个窗口,怎样实现?

用内存映射或全局原子(互斥变量)、查找窗口句柄..FindWindow,互斥,写标志到文件或注册表,共享内存。.12.如何截取键盘的响应,让所有的‘a’变成‘b’? 键盘钩子SetWindowsHookEx 13.Apartment在COM中有什么用?为什么要引入?

14.存储过程是什么?有什么用?有什么优点?

我的理解就是一堆sql的集合,可以建立非常复杂的查询,编译运行,所以运行一次后,以后再运行速度比单独执行SQL快很多

15.Template有什么特点?什么时候用? 16.谈谈Windows DNA结构的特点和优点。

网络编程中设计并发服务器,使用多进程 与 多线程,请问有什么区别? 1,进程:子进程是父进程的复制品。子进程获得父进程数据空间、堆和栈的复制品。

2,线程:相对与进程而言,线程是一个更加接近与执行体的概念,它可以与同进程的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。两者都可以提高程序的并发度,提高程序运行效率和响应时间。

线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源管理和保护;而进程正相反。同时,线程适合于在SMP机器上运行,而进程则可以跨机器迁移。

思科

1.用宏定义写出swap(x,y)#define swap(x, y)x = x + y;y = xy;2.数组a[N],存放了1至N-1个数,其中某个数重复一次。写一个函数,找出被重复的数字.时间复杂度必须为o(N)函数原型: int do_dup(int a[],int N)3 一语句实现x是否为2的若干次幂的判断 int i = 512;cout << boolalpha <<((i &(ib;a = a1 = 0111,正好是原数取反。这就是原理。用这种方法来求1的个数是很效率很高的。不必去一个一个地移位。循环次数最少。

int a,b,c 请写函数实现C=a+b ,不可以改变数据类型,如将c改为long int,关键是如何处理溢出问题

bool add(int a, int b,int *c){ *c=a+b;return(a>0 && b>0 &&(*ca || *c>b)));}

分析: struct bit {

int a:3;

int b:2;

int c:3;};

int main(){

bit s;

char *c=(char*)&s;

cout<

*c=0x99;

cout << s.a <

int a=-1;

printf(“%x”,a);

return 0;}

输出为什么是 4 1-1-4 ffffffff 因为0x99在内存中表示为 100 11 001 , a = 001, b = 11, c = 100 当c为有符合数时, c = 100, 最高1为表示c为负数,负数在计算机用补码表示,所以c =-4;同理

b =-1;当c为有符合数时, c = 100,即 c = 4,同理 b = 3

位域 :

有些信息在存储时,并不需要占用一个完整的字节,而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态,用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。这样就可以把几个不同的对象用一个字节的二进制位域来表示。

一、位域的定义和位域变量的说明位域定义与结构定义相仿,其形式为:

struct 位域结构名

{ 位域列表 };

其中位域列表的形式为: 类型说明符 位域名:位域长度

例如:

struct bs

{

int a:8;

int b:2;

int c:6;

};

位域变量的说明与结构变量说明的方式相同。可采用先定义后说明,同时定义说明或者直接说明这三种方式。例如:

struct bs

{

int a:8;

int b:2;

int c:6;

}data;

说明data为bs变量,共占两个字节。其中位域a占8位,位域b占2位,位域c占6位。对于位域的定义尚有以下几点说明:

1.一个位域必须存储在同一个字节中,不能跨两个字节。如一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域。也可以有意使某位域从下一单元开始。例如:

struct bs

{

unsigned a:4

unsigned :0 /*空域*/

unsigned b:4 /*从下一单元开始存放*/

unsigned c:4

}

在这个位域定义中,a占第一字节的4位,后4位填0表示不使用,b从第二字节开始,占用4位,c占用4位。

2.由于位域不允许跨两个字节,因此位域的长度不能大于一个字节的长度,也就是说不能超过8位二进位。

3.位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。例如:

struct k

{

int a:1

int :2 /*该2位不能使用*/

int b:3

int c:2

};

从以上分析可以看出,位域在本质上就是一种结构类型,不过其成员是按二进位分配的。

二、位域的使用位域的使用和结构成员的使用相同,其一般形式为: 位域变量名•位域名 位域允许用各种格式输出。

main(){

struct bs

{

unsigned a:1;

unsigned b:3;

unsigned c:4;

} bit,*pbit;

bit.a=1;

bit.b=7;

bit.c=15;

pri 改错:

#i nclude int main(void){

int **p;

int arr[100];

p = &arr;

return 0;} 解答:

搞错了,是指针类型不同, int **p;//二级指针

&arr;//得到的是指向第一维为100的数组的指针 #i nclude int main(void){ int **p, *q;int arr[100];q = arr;p = &q;return 0;}

下面这个程序执行后会有什么错误或者效果: #define MAX 255 int main(){

unsigned char A[MAX],i;//i被定义为unsigned char

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

A[i]=i;} 解答:死循环加数组越界访问(C/C++不进行数组越界检查)MAX=255

数组A的下标范围为:0..MAX-1,这是其一..其二.当i循环到255时,循环内执行:

A[255]=255;这句本身没有问题..但是返回for(i=0;i<=MAX;i++)语句时, 由于unsigned char的取值范围在(0..255),i++以后i又为0了..无限循环下去.struct name1{

char str;

short x;

int

num;}

struct name2{

char str;

int num;

short x;}

sizeof(struct name1)=8,sizeof(struct name2)=12 在第二个结构中,为保证num按四个字节对齐,char后必须留出3字节的空间;同时为保证整个结构的自然对齐(这里是4字节对齐),在x后还要补齐2个字节,这样就是12字节。

intel:

A.c 和B.c两个c文件中使用了两个相同名字的static变量,编译的时候会不会有问题?这两个static变量会保存到哪里(栈还是堆或者其他的)? static的全局变量,表明这个变量仅在本模块中有意义,不会影响其他模块。他们都放在数据区,但是编译器对他们的命名是不同的。

如果要使变量在其他模块也有意义的话,需要使用extern关键字。

struct s1 {

int i: 8;

int j: 4;

int a: 3;

double b;};

struct s2 {

int i: 8;

int j: 4;

double b;

int a:3;};

printf(“sizeof(s1)= %dn”, sizeof(s1));printf(“sizeof(s2)= %dn”, sizeof(s2));result: 16, 24 第一个struct s1 {

int i: 8;

int j: 4;

int a: 3;

double b;};理论上是这样的,首先是i在相对0的位置,占8位一个字节,然后,j就在相对一个字节的位置,由于一个位置的字节数是4位的倍数,因此不用对齐,就放在那里了,然后是a,要在3位的倍数关系的位置上,因此要移一位,在15位的位置上放下,目前总共是18位,折算过来是2字节2位的样子,由于double是8字节的,因此要在相对0要是8个字节的位置上放下,因此从18位开始到8个字节之间的位置被忽略,直接放在8字节的位置了,因此,总共是16字节。

第二个最后会对照是不是结构体内最大数据的倍数,不是的话,会补成是最大数据的倍数上面是基本问题,接下来是编程问题:

本人很弱,这几个题也搞不定,特来求救: 1)读文件file1.txt的内容(例如): 12 34 56 输出到file2.txt: 56 34 12(逆序)

2)输出和为一个给定整数的所有组合 例如n=5 5=1+4;5=2+3(相加的数不能重复)则输出

1,4;2,3。望高手赐教!

第一题,注意可增长数组的应用.#i nclude #i nclude int main(void){

int MAX = 10;int *a =(int *)malloc(MAX * sizeof(int));int *b;

FILE *fp1;FILE *fp2;

fp1 = fopen(“a.txt”,“r”);if(fp1 == NULL){printf(“error1”);

exit(-1);}

fp2 = fopen(“b.txt”,“w”);if(fp2 == NULL){printf(“error2”);

exit(-1);}

int i = 0;

int j = 0;

while(fscanf(fp1,“%d”,&a[i])!= EOF){ i++;j++;if(i >= MAX){ MAX = 2 * MAX;b =(int*)realloc(a,MAX * sizeof(int));if(b == NULL){ printf(“error3”);exit(-1);} a = b;} }

for(;--j >= 0;)

fprintf(fp2,“%dn”,a[j]);fclose(fp1);fclose(fp2);return 0;

}

第二题.#i nclude int main(void){ unsigned long int i,j,k;

printf(“please input the numbern”);scanf(“%d”,&i);

if(i % 2 == 0)

j = i / 2;else j = i / 2 + 1;

printf(“The result is n”);

for(k = 0;k < j;k++)

printf(“%d = %d + %dn”,i,k,i1);QSort(L,pl + 1,high);} }

intmain(){ intnarry[100],addr[100];intsum = 1,t;

cout << “Input number:” << endl;cin >> t;while(t!=-1){ narry[sum] = t;addr[sumkk] << endl;cout << “And it's place is:”;for(i = 0;i < sum;i++){ if(addr[i] == narry[sum-kk])cout << i << 't';}

return0;}

1、找错 Void test1(){ char string[10];char* str1=“0123456789”;strcpy(string, str1);// 溢出,应该包括一个存放''的字符string[11] }

Void test2(){ char string[10], str1[10];for(I=0;I<10;I++){ str1[i] ='a';} strcpy(string, str1);// I,i没有声明。}

Void test3(char* str1){ char string[10];if(strlen(str1)<=10)// 改成<10,字符溢出,将strlen改为sizeof也可以 { strcpy(string, str1);} } 2.void g(int**);int main(){ int line[10],i;int *p=line;//p是地址的地址 for(i=0;i<10;i++){ *p=i;g(&p);//数组对应的值加1 } for(i=0;i<10;i++)printf(“%dn”,line[i]);return 0;}

void g(int**p){(**p)++;(*p)++;// 无效 } 输出: 1 2 3 4 5 6 7 8 9 10 3.写出程序运行结果

int sum(int a){ auto int c=0;static int b=3;c+=1;b+=2;return(a+b+c);}

void main(){ int I;int a=2;for(I=0;I<5;I++){ printf(“%d,”, sum(a));} } // static会保存上次结果,记住这一点,剩下的自己写 输出:8,10,12,14,16,4.int func(int a){ int b;switch(a){ case 1: 30;case 2: 20;case 3: 16;default: 0 } return b;} 则func(1)=? // b定义后就没有赋值。

5: int a[3];a[0]=0;a[1]=1;a[2]=2;int *p, *q;p=a;q=&a[2];则a[q-p]=a[2] 解释:指针一次移动一个int但计数为1

第四篇:C语言编写俄罗斯方块论文

俄罗斯方块

学 号:

班 级:

姓 名:

指导教师:

完成日期:2012年5月

1.引言..............................................................................................................................................1

1.1开发工具............................................................................................................................1 1.1.1 C是中级预言......................................................................................................1

1.1.2 C是结构化语言..................................................................................................1 1.1.3 C语言功能齐全..................................................................................................1 1.1.4 C语言可移植性好..............................................................................................1 游戏设计......................................................................................................................................2

2.1游戏设计要求....................................................................................................................2

2.1.1.设计题目:俄罗斯方块游戏.............................................................................2

2.1.2.设计内容:.........................................................................................................2 2.1.3.功能模块划分:.................................................................................................2 2.2 游戏设计思想...................................................................................................................2

2.2.1游戏界面:............................................................................................................2 2.2.2 设计思路.......................................................................................................................2 2.3:游戏功能......................................................................................................................3 2.3.1:开始部分...........................................................................................................3

2.3.2.运行部分...............................................................................................................3

3.实验总结:..................................................................................................................................4

3.1 开发背景与需求分析.......................................................................................................4 3.2 系统功能介绍...................................................................................................................4 4.核心代码:................................................................................................................................8 总结................................................................................................................................................21 参考文献:....................................................................................................................................22

基于C语言的俄罗斯方块游戏

[摘要]:俄罗斯方块是一款风靡全球的电视游戏机和掌上游戏机游戏。俄罗斯方块的基本规则是移动、旋转和摆放游戏自动输出的各种方块,使之排列成完整的一行或多行并且消除得分。由于上手简单、老少皆宜,从而家喻户晓,风靡世界。[关键词]:C语言;心得体会;影响

1.引言 随着社会的发展,人们生活的步调日益加快,越来越多的人加入了全球化的世界.人们不在拘泥于一小块天地.加班,出差成了现代人不可避免的公务.而此时一款可以随时随地娱乐的游戏成了必需品.在手机和电脑成为人们日用品的社会,一款能在其上能便捷运行的游戏成为买家的参考点.现在我们所要设计的这一款基于C语言的游戏——贪吃蛇,就是满足以上要求而设计出来的,希望能给玩家带来娱乐.贪吃蛇这一游戏简单易行,操作方便,娱乐性较强,吸引了不少人.这一款游戏紧紧地抓住了人们的心理,虽然简单,却起乐无穷,在人们不断追求更多的欲望下,该游戏给人们带来了追逐的快感,以及成功后的满足感,对于一直处于高压下的现代人是很好的放松工具.1.1开发工具

《C/C++程序设计学习与试验系统》

该系统继承了Turbo C2.0/C++3.0、GCC、Visua C++6.0这四种常见的编译器,可以很好满足目前主流的C语言教材的实验需求。

C语言具有下列特点:

1.1.1 C是中级预言

它把高级语言的基本结构和语句与低级语言的实用性结合起来,C语言可以像汇编语言一样对位、字节和地址进行操作,通常还是称C为高级语言。

1.1.2 C是结构化语言

结构化语言的特点是程序的各个部分除了必要地数据交流外彼此独立。这种结构化方式可使程序层次清晰,便于使用,维护及调试。

1.1.3 C语言功能齐全

C语言具有多种数据类型,并引入了指针概念,可使程序效率更高;C语言也具有强大的图形功能;具有较强的计算功能、逻辑判断功能。

1.1.4 C语言可移植性好

与汇编语言相比,C语言程序适用范围大,可用于各种操作系统和各种型号的计算机。游戏设计

2.1游戏设计要求

2.1.1.设计题目:俄罗斯方块游戏 2.1.2.设计内容:

一组由4个小型正方形组成的规则图形,中文通称为方块共有7种,分别以S、Z、L、J、I、O、T这7个字母的形状来命名。通过设计者预先设置的随机发生器不断地输出单个方块到场地顶部,以一定的规则进行移动、旋转、下落和摆放,锁定并填充到场地中。每次摆放如果将场地的一行或多行完全填满,则组成这些行的所有小正方形将被消除,并且以此来换取一定的积分或者其他形式的奖励。而未被消除的方块会一直累积,并对后来的方块摆放造成各种影响。如果未被消除的方块堆放的高度超过场地所规定的最大高度则游戏结束。

2.1.3.功能模块划分:

系统功能模块

2.2 游戏设计思想

2.2.1游戏界面:

方块堆积。遇整则消。

2.2.2 设计思路

1、一个用于摆放小型正方形的平面虚拟场地,其标准大小:行宽为10,列高为20,以每个小正方形为单位。2.、一组由4个小型正方形组成的规则图形,英文称为Tetromino,中文通称为方块共有7种,分别以S、Z、L、J、I、O、T这7个字母的形状来命名。I:一次最多消除四层

J(左右):最多消除三层,或消除二层

L:最多消除三层,或消除二层

O:消除一至二层

S(左右):最多二层,容易造成孔洞

Z(左右):最多二层,容易造成孔洞

T:最多二层

(1)部分游戏有单格方块,可以穿透固定的方块到达最下层空位。其他的改版中出现更多特别的造型。

方块会从区域上方开始缓慢继续落下。

(2)玩家可以做的操作有:以90度为单位旋转方块,以格子为单位左右移动方块,让方块加速落下。

(3)方块移到区域最下方或是着地到其他方块上无法移动时,就会固定在该处,而新的方块出现在区域上方开始落下。

(4)当区域中某一列横向格子全部由方块填满,则该列会消失并成为玩家的得分。同时删除的列数越多,得分指数上升。

(5)当固定的方块堆到区域最上方而无法消除层数时,则游戏结束。

(6)一般来说,游戏还会提示下一个要落下的方块,熟练的玩家会计算到下一个方块,评估现在要如何进行。由于游戏能不断进行下去对商业用游戏不太理想,所以一般还会随着游戏的进行而加速提高难度。

3、通过设计者预先设置的随机发生器不断地输出单个方块到场地顶部,以一定的规则进行移动、旋转、下落和摆放,锁定并填充到场地中。每次摆放如果将场地的一行或多行完全填满,则组成这些行的所有小正方形将被消除,并且以此来换取一定的积分或者其他形式的奖励。而未被消除的方块会一直累积,并对后来的方块摆放造成各种影响。

4、如果未被消除的方块堆放的高度超过场地所规定的最大高度(并不一定是20或者玩家所能见到的高度),则游戏结束。

具体到每一款不同的游戏,其中的细节规则都可能有千差万别,但是以上的基本规则是相同的。

2.3:游戏功能

2.3.1:开始部分

游戏是运行在图形模式下的,所以第一步一定是初始化图形模式,接着要有开始的界面,就像书有封面一样,我设置了一个游戏的标题画面,除了游戏标题画面我还设置了一个欢迎画面。标题画面以后,还要为游戏的运行部分作初始化,包括绘制游戏运行时的背景,对游戏某些重 要变量的初始化。

2.3.2.运行部分

俄罗斯方块的要求为:不同形状组合的方块从界面上方落下。通过键盘上的四个光标控制方块下落时的形状转换和下落方向。方块堆积在一起,将区域占满时则会消除以增加

游戏分数。

整个游戏过程分为三个步骤:

1、按游戏界面的“开始”按钮或者F2键来开始游戏,自己使用右边的窗口,对手使用左边的窗口

2、键盘操作:系统缺省设置使用右边的窗口,用光标操作,“←”左移一格;“→”右移一格;“↑”旋转方块;↓ 方块丢下(方块下落到底),“End”健可以一格格的下落,用户还可以自定义习惯的按键来操作游戏。

3、计分牌显示的内容:“分数”为双方本局的分数,计分标准为下落一个块10分,一次消一行100分、2行200分、3行400分、4行800分。等级”为双方的游戏设置等级,当分数达到一定的值,等级就会提升、速度加快。“行数”第一行为双方消的行数,第二行是送给对方的行数。“比分”为双方赢的局数。2.3.3:结束部分:

游戏结束时,显示“GAME OVER”

3.实验总结:

3.1 开发背景与需求分析

随着网络技术的发展,人们的生活越来越离不开网络,网络给人们带来了各种各样的信息和更多更新的娱乐。据统计。每天上网的人群中75%的人用来丰富自己的生活。其中游戏最为常见和普遍。所以,这次课程设计我想实现一个小游戏:俄罗斯方块。需求分析

1)游戏面板(画布)GameCanvas类,完成游戏显示; 2)方块绘画drawUnit类,方块下落过程中的各种形态;

3)主界面实现游戏的开始,退出,暂停,提高级数,降低级数功能及图像界面排版;

4)通过键盘按键实现游戏,并且可以调节游戏速度。

3.2 系统功能介绍

俄罗斯方块是一个非常复杂但比较有趣并且耐玩的游戏,相信很多人对俄罗斯方块并不陌生,如下图所示,游戏中共有七种方块,每种方块都有四个方格组成。

这七种方块可以旋转90度、180度、270度,因此每种方块有四种状态,七种方块总有28种状态,这28种状态的方块随机产生,自由下落,落下时可由玩家通过键盘上的上、下、左、右控制键来控制方块的反转、移动和加速下落。如果下落时,方块填满某一行则这一行消失,同时给玩家加分,若由存在空格的方块填满整个窗口,则游戏结束。

图1-1 初始状态

图1-2 开始游戏

图1-3 消除一行

图1-4 消除两行

图1-5 消除四行

图1-6 游戏结束

4.核心代码:

import java.awt.*;import java.awt.event.*;

//俄罗斯方块类

public class computer extends Frame { public static boolean isPlay = false;public static int level = 1, score = 0;public static TextField scoreField, levelField;

public static MyTimer timer;GameCanvas gameScr;//声明一个属于画布类得变量 public static void main(String[] argus){ computer ers = new computer(“俄罗斯方块游戏 V1.0 Author:Vincent”);//运用构造方法为框架名

WindowListener win_listener = new WinListener();//定义一个窗口监听事件对象

ers.addWindowListener(win_listener);//为框架添加该监听器 }

computer(String title)// 俄罗斯方块类的构造方法 { super(title);//调用父类得构造方法

setSize(600, 480);//设置框架的尺寸

setLayout(new GridLayout(1, 2));//设置框架的布局流

gameScr = new GameCanvas();gameScr.addKeyListener(gameScr);//为该对象注册键盘点击监听器

timer = new MyTimer(gameScr);timer.setDaemon(true);timer.start();timer.suspend();

add(gameScr);

Panel rightScr = new Panel();rightScr.setLayout(new GridLayout(2, 1, 0, 30));rightScr.setSize(120, 500);add(rightScr);

// 右边信息窗体的布局

MyPanel infoScr = new MyPanel();infoScr.setLayout(new GridLayout(4, 1, 0, 5));infoScr.setSize(120, 300);rightScr.add(infoScr);

// 定义标签和初始值

Label scorep = new Label(“分数:”, Label.LEFT);Label levelp = new Label(“级数:”, Label.LEFT);scoreField = new TextField(8);levelField = new TextField(8);scoreField.setEditable(false);levelField.setEditable(false);infoScr.add(scorep);

infoScr.add(scoreField);infoScr.add(levelp);infoScr.add(levelField);scorep.setSize(new Dimension(20, 60));scoreField.setSize(new Dimension(20, 60));levelp.setSize(new Dimension(20, 60));levelField.setSize(new Dimension(20, 60));scoreField.setText(“0”);levelField.setText(“1”);

// 右边控制按钮窗体的布局

MyPanel controlScr = new MyPanel();controlScr.setLayout(new GridLayout(5, 1, 0, 5));rightScr.add(controlScr);

// 定义按钮play Button play_b = new Button(“开始游戏”);play_b.setSize(new Dimension(50, 200));play_b.addActionListener(new Command(Command.button_play, gameScr));

// 定义按钮Level UP Button level_up_b = new Button(“提高级数”);level_up_b.setSize(new Dimension(50, 200));level_up_b.addActionListener(new Command(Command.button_levelup, gameScr));

// 定义按钮Level Down Button level_down_b = new Button(“降低级数”);level_down_b.setSize(new Dimension(50, 200));level_down_b.addActionListener(new Command(Command.button_leveldown, gameScr));

// 定义按钮Level Pause Button pause_b = new Button(“游戏暂停”);pause_b.setSize(new Dimension(50, 200));pause_b.addActionListener(new

Command(Command.button_pause,gameScr));

// 定义按钮Quit Button quit_b = new Button(“退出游戏”);quit_b.setSize(new Dimension(50, 200));quit_b.addActionListener(new Command(Command.button_quit, gameScr));

controlScr.add(play_b);controlScr.add(level_up_b);controlScr.add(level_down_b);controlScr.add(pause_b);controlScr.add(quit_b);setVisible(true);gameScr.requestFocus();} }

// 重写MyPanel类,使Panel的四周留空间 class MyPanel extends Panel { public Insets getInsets(){ return new Insets(30, 50, 30, 50);} }

// 游戏画布类

class GameCanvas extends Canvas implements KeyListener { final int unitSize = 30;// 小方块边长 int rowNum;// 正方格的行数 int columnNum;// 正方格的列数

int maxAllowRowNum;// 允许有多少行未削 int blockInitRow;// 新出现块的起始行坐标 int blockInitCol;// 新出现块的起始列坐标 int[][] scrArr;// 屏幕数组 Block b;// 对方快的引用

// 画布类的构造方法 GameCanvas(){ rowNum = 15;columnNum = 10;maxAllowRowNum = rowNum1;blockInitCol = columnNum / 2(row + 1)* unitSize, unitSize, unitSize, true);g.dispose();}

public Block getBlock(){ return b;// 返回block实例的引用 }

// 返回屏幕数组中(row,col)位置的属性值 public int getScrArrXY(int row, int col){ if(row < 0 || row >= rowNum || col < 0 || col >= columnNum)return(-1);else return(scrArr[row][col]);}

// 返回新块的初始行坐标方法 public int getInitRow(){ return(blockInitRow);// 返回新块的初始行坐标 }

// 返回新块的初始列坐标方法 public int getInitCol(){ return(blockInitCol);// 返回新块的初始列坐标 }

// 满行删除方法

void deleteFullLine(){ int full_line_num = 0;int k = 0;

for(int i = 0;i < rowNum;i++){ boolean isfull = true;

L1: for(int j = 0;j < columnNum;j++)if(scrArr[i][j] == 0){ k++;isfull = false;break L1;} if(isfull)full_line_num++;if(k!= 0 && k1, j, 0);else drawUnit(k1][j] = scrArr[i][j];} } for(int i = k1)){

dispBlock(0);col--;dispBlock(1);} }

// 实现块的右移

public void rightMove(){ if(assertValid(blockType, turnState, row, col + 1)){ dispBlock(0);col++;dispBlock(1);} }

// 实现块落下的操作的方法 public boolean fallDown(){ if(blockState == 2)return(false);if(assertValid(blockType, turnState, rowi, col + j);if(temp < 0 || temp == 2)return false;} k = k >> 1;} } return true;}

// 同步显示的方法

public synchronized void dispBlock(int s){ int k = 0x8000;for(int i = 0;i < 4;i++){ for(int j = 0;j < 4;j++){ if(((int)pattern[blockType][turnState] & k)!= 0){ scr.drawUnit(rowcomputer.level + 1)* 100);} catch(InterruptedException e){ } if(!scr.getBlock().fallDown()){ scr.deleteFullLine();if(scr.isGameEnd()){ computer.isPlay = false;suspend();} else scr.getBlock().reset();} } } }

class WinListener extends WindowAdapter { public void windowClosing(WindowEvent l){ System.exit(0);} } 总结

1感悟:当今计算机应用在生活中可以说得是无处不在。因此作为二十一世纪的大学来说掌握程序开发技术是十分重要的,而C语言又是最常见,功能最强大的一种高级语言,因此做好C语言课程设计是十分必要的。回顾起此次课程设计,至今我们仍感慨颇多,的确,自从拿到题目到完成整个编程,从理论到实践,在这么长的时间里,可以学到很多很多的东西,同时不仅可以巩固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识。通过这次课程设计使我们懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。在设计的过程中遇到问题,可以说得是困难重重,这毕竟第一次做的,难免会遇到过各种各样的问题,同时在设计的过程中发现了自己的不足之处,对一些前面学过的知识理解得不够深刻,掌握得不够牢固,比如说结构体,指针,链表……通过这次课程设计之后,我们把前面所学过的知识又重新温故了一遍。

我做的是做俄罗斯方块游戏。简单的一个,但对我来说却是一个很大的困难。更加是第一次做基于C语言的课程设计,所以连续几天翻阅书籍或是参考网上内容却丝毫没有进展,最主要是不知从何开始,这个时候才知道上课老师们不厌其烦的教导是多么的宝贵,这个时候才后悔上课的时候

没有认真的听讲。可是现在一切都晚了,还好时间还算是充裕,只好拿出书本重新复习一下。不过经过几天的努力,大体上把课本上的知识点看了一遍,知识点也都基本是撑握了,所以一下一步就是开始正式的编程序了。不过毕竟水平有限,还是不知如何下手,于是就在网上下了一篇类似的程序,经过仔细的研究,终于读懂了C语言编程的基本过程和方法。经过一波三折,终于开始正式编程。

而且编程是一件高精度、模范化的事情,稍有疏乎都会影响全局,也可能因为某一处的小的错误而导致整个程序的无法运行。所以认真仔细就是非常重要的了。开始的时候真的感觉编程是一件很无聊的事情,所以就在网上下载的程序的基础上开始行动了,不过当一个程序运行成功的时候那种喜悦是无法言语的,那种成就感是无法比拟的。又经过几天的努力,终于把程序完成了,尽管程序还是有很多错误和漏洞,不过还是很高兴的。无论如何是自己的劳动成果,是自己经过努力得到的成绩,同时也是学习C语言的一次实践作业,自己进步的证明。

通过这次课程设计,使我对C语言有了更进一步的认识和了解,要想学好它要重在实践,要通过不断的上机操作才能更好地学习它,我也发现我的好多不足之处,首先是自己在指法上还不行,经常按错字母,通过学习也有所改进;再有对C语言的一些标准库函数不太了解,还有对函数调用的正确使用不够熟悉,还有对C语言中经常出现的错误也不了解,通过实践的学习,我认识到学好计算机要重视实践操作,不仅仅是学习C语言,还是其它的语言,以及其它的计算机方面的知识都要重在实践,所以后在学习过程中,我会更加注视实践操作,使自己便好地学好计算机。

在该游戏设计过程中,收获知识,提高能力的同时,我也学到了很多人生的哲理,懂得怎么样去制定计划,怎么样去实现这个计划,并掌握了在执行过程中怎么样去克服心理上的不良情绪。

2感谢:经过两个星期的苦心钻研,系统终于制作完毕。在本次课程设计中困难遇到不少,也让我学到了很多。在这次系统开发的过程中,我深深地体会到了做一个系统,首先进行需求分析的重要性。了解了一个系统的制作,从功能分析到功能模块分析,与其他系统的关系,这些都有待以后进一步的改进。通过实践对我以后的学习是一笔不小的财富!

在此,感谢班上同学对我的帮助和指点,没有他们所提供的资料,仅凭我个人力量,在短短的两周时间里是很难完成这个设计的。更要感谢的是我的老师,感谢老师孜孜不倦的教诲,一丝不苟的精神和一视同仁的教学风格。我会仅记老师的教诲,一步一个脚印的完成自己的学业!

参考文献:

[1].裘宗燕 著,从问题到程序科学出版社,北京大学出版社,1999年4月。[2].《C程序设计(第二版)》,谭浩强编,清华大学出版社,1999年12月。[3].《C语言编程常见问题解答》,[美]Paul S.R.Chishohm等著,张芳妮 吕波译,清华大学出版社,11996年12月。[4].《The C Programming Language》,by Brian W.Kernighan and Dennis M.Ritchie.,Pubilished by Prentice-Hall in 1988。

[5].朱若愚.数据结构[M].北京: 电子工业出版社, 2006.1

[6].傅清祥,王晓东.数据结构与算法设计[M].北京: 电子工业出版社, 2006.3 [7].李春葆.数据结构(C语言版)习题与解析[M].北京:清华大学出版社, 2006.1 [8].刘大有.数据结构[M].北京: 高等教育出版社, 2006.3 [9].王敬华,陈静.C语言程序设计[M].北京: 清华大学出版社, 2007.10 [10].徐孝凯.数据结构简明教程.[M].北京: 清华大学出版社, 2006.04

课程设计俄罗斯方块游戏源代码

本程序共三个类,建一个包 square。把三个类都封装到一个包里面,三个类分别是

Controller,Main,Square

package square;import javax.swing.JPanel;import java.awt.Color;

// 事倒入java程序所需要的类库文件。如果不倒入相应的文件。java程序是会报错的。import javax.swing.JLabel;public class Controller extends Thread //Controller类从定义从父类继承来来的某些成员变量和成员方法,游戏控制线程

private int x;

//方块左上角的坐标

private int y;

private Square sq;

//方块对象的引用当前

private Square next;

//下一个方块的引用

private JPanel[][] sc;

//显示

private boolean[][] state;

//填充状态

private int sorce;

//分值

private int speed;

//下落速度

private JLabel jl1;

//分数速度提示

private JLabel jl2;

private JPanel jp;

//下一个方块提示

private JPanel[][] sc2;

private int sleepTime;

//等待时间

public Controller(int x, int y, JPanel[][] sc, boolean[][] state,//构造器

传递引用

int sorce, int speed, JLabel jl1, JLabel jl2,JPanel jp, JPanel[][] sc2){

this.x = x;

this.y = y;

this.sc = sc;

this.state = state;

this.sorce = sorce;

this.speed = speed;

this.jl1 = jl1;

this.jl2 = jl2;

this.jp = jp;

this.sc2 = sc2;

this.sleepTime = 200;

sq = new Square((int)(Math.random()* 4)+ 1);

next = new Square((int)(Math.random()* 4)+ 1);

}

public void init(){

for(int i = 0;i < state.length;i++){

for(int j = 0;j < state[i].length;j++){

state[i][j] = false;

}

}

update();

}

@Override

public void run()

//重设run()方法

{

while(true){

try {

if(!isGameOver()){

if(isHit()){

set();

} else {

fall();

}

check();

update();

Thread.sleep(sleepTime);

} else {

break;

}

} catch(InterruptedException e){

e.printStackTrace();

}

}

}

private void set()

//码放方块

{

for(int i = 0;i < 4;i++){

for(int j = 0;j < 4;j++){

if(sq.getState(i, j)== true){

state[i + x][y + j] = true;

}

}

}

x = 0;

y = 0;

sq = next;

next = new Square((int)(Math.random()* 4)+ 1);

sleepTime = 1000 /(speed + 2);

}

private void update()

//更新数据

{

for(int i = 0;i < sc.length;i++){

for(int j = 0;j < sc[i].length;j++){

if(state[i][j] == true){

sc[i][j].setBackground(Color.BLUE);

} else {

sc[i][j].setBackground(Color.WHITE);}

}

for(int i = 0;i < 4;i++){

for(int j = 0;j < 4;j++){

if(sq.getState(i, j)){

sc[i + x][j + y].setBackground(Color.BLUE);

}

}

}

for(int i = 0;i < sc2.length;i++){

for(int j = 0;j < sc2[i].length;j++){

if(next.getState(i, j)){

sc2[i][j].setBackground(Color.BLUE);

} else {

sc2[i][j].setBackground(Color.WHITE);

}

}

}

}

private boolean isHit()

//下落碰撞判断

{

for(int i = 0;i < 4;i++){

for(int j = 0;j < 4;j++){

if(sq.getState(i, j)&&(x + i == 19 || state[i + x + 1][j + y])){

return true;

}

}

}

return false;

}

private void fall()

//下落

{

x++;

}

private boolean isLeftHit()

//左移碰撞判断

{

if(y == 0){

return true;

}

for(int i = 0;i < 3;i++){

for(int j = 0;j < 3;j++){

if(sq.getState(i, j)&& state[x + i][y + j1][j];

}

}

sorce += 10;

speed = sorce / 100;

jl1.setText(String.valueOf(sorce));

jl2.setText(String.valueOf(speed));

sleepTime = 1000 /(speed + 2);

} catch(InterruptedException e){

e.printStackTrace();

}

}

}

}

public void moveLeft()

//向左

{

if(!isLeftHit()){

state[x][y] = false;

y--;

}

}

private boolean isRightHit()

//右移碰撞判断

{

for(int i = 0;i < 3;i++){

for(int j = 0;j < 3;j++){

if(sq.getState(i, j)&&(y + j >= 9 || state[x + i][y + j + 1])){

return true;

}

}

}

return false;

}

public void moveRight()//向右

{

if(!isRightHit()){

state[x][y] = false;

y++;

}

}

public void rot()

//旋转

{

sq.rot();

}

public void down()

//加速向下

{

sleepTime = 20;}

}

package square;import javax.swing.*;import java.awt.*;public class Main extends javax.swing.JFrame { private static final long serialVersionUID = 1L;private JPanel sc[][];

private JPanel sc2[][];

private boolean state[][];

Controller t;

/** Creates new form Square */

public Main()

{

initComponents();

sc = new JPanel[20][10];

sc2 = new JPanel[4][4];

state = new boolean[25][15];

jPanel1.setLayout(new GridLayout(20, 10, 2, 2));

jPanel3.setLayout(new GridLayout(4, 4, 2, 2));

jPanel3.setSize(150, 150);

for(int i = 0;i < sc.length;i++){

for(int j = 0;j < sc[i].length;j++){

sc[i][j] = new JPanel();

// sc[i][j].setSize(20, 20);

sc[i][j].setBackground(Color.WHITE);

jPanel1.add(sc[i][j]);

}

}

for(int i = 0;i < sc2.length;i++){

for(int j = 0;j < sc2[i].length;j++){

sc2[i][j] = new JPanel();

// sc2[i][j].setSize(20, 20);

sc2[i][j].setBackground(Color.WHITE);

jPanel3.add(sc2[i][j]);

}

}

jLabel3.setText(“0”);

jLabel4.setText(“0”);

this.setSize(460, 650);

}

/** This method is called from within the constructor to

* initialize the form.* WARNING: Do NOT modify this code.The content of this method is

* always regenerated by the Form Editor.*/

private void initComponents(){

jPanel2 = new javax.swing.JPanel();

jLabel1 = new javax.swing.JLabel();

jLabel2 = new javax.swing.JLabel();

jLabel3 = new javax.swing.JLabel();

jLabel4 = new javax.swing.JLabel();

jButton1 = new javax.swing.JButton();

jPanel1 = new javax.swing.JPanel();

jButton2 = new javax.swing.JButton();

jButton3 = new javax.swing.JButton();

jMenuBar1 = new javax.swing.JMenuBar();

jMenu1 = new javax.swing.JMenu();

jMenuItem1 = new javax.swing.JMenuItem();

jMenu2 = new javax.swing.JMenu();

jMenuBar2 = new javax.swing.JMenuBar();

jMenu3 = new javax.swing.JMenu();

jMenuItem2 = new javax.swing.JMenuItem();

jMenu4 = new javax.swing.JMenu();

jPanel3 = new javax.swing.JPanel();

jButton4 = new javax.swing.JButton();

jMenuBar3 = new javax.swing.JMenuBar();

jMenu5 = new javax.swing.JMenu();

jMenuItem3 = new javax.swing.JMenuItem();

jMenu6 = new javax.swing.JMenu();

jButton5 = new javax.swing.JButton();

jMenuBar4 = new javax.swing.JMenuBar();

jMenu7 = new javax.swing.JMenu();

jMenuItem4 = new javax.swing.JMenuItem();

jMenu8 = new javax.swing.JMenu();

setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

setMinimumSize(new java.awt.Dimension(400, 550));

jPanel2.setBorder(javax.swing.BorderFactory.createEtchedBorder());

jLabel1.setText(“Score”);

jLabel2.setText(“Speed”);

jLabel3.setText(“jLabel3”);

jLabel4.setText(“jLabel4”);

javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);

jPanel2.setLayout(jPanel2Layout);

jPanel2Layout.setHorizontalGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

.addGroup(jPanel2Layout.createSequentialGroup()

.addContainerGap()

.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

.addGroup(jPanel2Layout.createSequentialGroup()

.addComponent(jLabel1)

.addGap(18, 18, 18)

.addComponent(jLabel3))

.addGroup(jPanel2Layout.createSequentialGroup()

.addComponent(jLabel2)

.addGap(18, 18, 18)

.addComponent(jLabel4)))

.addContainerGap(35, Short.MAX_VALUE)));

jPanel2Layout.setVerticalGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

.addGroup(jPanel2Layout.createSequentialGroup()

.addContainerGap()

.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)

.addComponent(jLabel1)

.addComponent(jLabel3))

.addGap(18, 18, 18)

.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)

.addComponent(jLabel2)

.addComponent(jLabel4))

.addContainerGap(84, Short.MAX_VALUE)));

jButton1.setText(“Start”);

jButton1.addActionListener(new java.awt.event.ActionListener(){

public void actionPerformed(java.awt.event.ActionEvent evt){

jButton1ActionPerformed(evt);

}

});

jPanel1.setBorder(javax.swing.BorderFactory.createEtchedBorder());

jPanel1.setMinimumSize(new java.awt.Dimension(300, 500));

javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);

jPanel1.setLayout(jPanel1Layout);

jPanel1Layout.setHorizontalGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

.addGap(0, 291, Short.MAX_VALUE));

jPanel1Layout.setVerticalGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

.addGap(0, 504, Short.MAX_VALUE));

jButton2.setText(“L”);

jButton2.addActionListener(new java.awt.event.ActionListener(){

public void actionPerformed(java.awt.event.ActionEvent evt){

jButton2ActionPerformed(evt);

}

});

jButton3.setText(“R”);

jButton3.addActionListener(new java.awt.event.ActionListener(){

public void actionPerformed(java.awt.event.ActionEvent evt){

jButton3ActionPerformed(evt);

}

});

jMenu1.setText(“File”);

jMenuItem1.setText(“Start”);

jMenu1.add(jMenuItem1);

jMenuBar1.add(jMenu1);

jMenu2.setText(“Edit”);

jMenuBar1.add(jMenu2);

jMenu3.setText(“File”);

jMenuItem2.setText(“Start”);

jMenu3.add(jMenuItem2);

jMenuBar2.add(jMenu3);

jMenu4.setText(“Edit”);

jMenuBar2.add(jMenu4);

jPanel3.setBorder(javax.swing.BorderFactory.createEtchedBorder());

jPanel3.setMinimumSize(new java.awt.Dimension(120, 120));

jPanel3.setPreferredSize(new java.awt.Dimension(120, 120));

javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);

jPanel3.setLayout(jPanel3Layout);

jPanel3Layout.setHorizontalGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

.addGap(0, 135, Short.MAX_VALUE));

jPanel3Layout.setVerticalGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

.addGap(0, 116, Short.MAX_VALUE));

jButton4.setText(“Rot”);

jButton4.addActionListener(new java.awt.event.ActionListener(){

public void actionPerformed(java.awt.event.ActionEvent evt){

jButton4ActionPerformed(evt);

}

});

jMenu5.setText(“File”);

jMenuItem3.setText(“Start”);

jMenu5.add(jMenuItem3);

jMenuBar3.add(jMenu5);

jMenu6.setText(“Edit”);

jMenuBar3.add(jMenu6);

jButton5.setText(“D”);

jButton5.addActionListener(new java.awt.event.ActionListener(){

public void actionPerformed(java.awt.event.ActionEvent evt){

jButton5ActionPerformed(evt);

}

});

jMenu7.setText(“File”);

jMenu7.addActionListener(new java.awt.event.ActionListener(){

public void actionPerformed(java.awt.event.ActionEvent evt){

jMenu7ActionPerformed(evt);

}

});

jMenuItem4.setText(“Start”);

jMenu7.add(jMenuItem4);

jMenuBar4.add(jMenu7);

jMenu8.setText(“Edit”);

jMenuBar4.add(jMenu8);

setJMenuBar(jMenuBar4);

javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());

getContentPane().setLayout(layout);

layout.setHorizontalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()

.addComponent(jPanel1,javax.swing.GroupLayout.PREFERRED_SIZE,295, javax.swing.GroupLayout.PREFERRED_SIZE)

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

.addComponent(jPanel2,javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)

.addComponent(jPanel3, Short.MAX_VALUE)

.addComponent(jButton4,javax.swing.GroupLayout.DEFAULT_SIZE, 139,javax.swing.GroupLayout.PREFERRED_SIZE, 132, javax.swing.GroupLayout.PREFERRED_SIZE)

.addGroup(layout.createSequentialGroup()

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)

.addComponent(jButton1, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)

.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()

.addComponent(jButton2)

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)

.addComponent(jButton5)

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)

.addComponent(jButton3)))

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, Short.MAX_VALUE)))

.addContainerGap()));

layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

.addGroup(layout.createSequentialGroup()

.addContainerGap()

.addComponent(jPanel2,javax.swing.GroupLayout.PREFERRED_SIZE,10,javax.swing.GroupLayout.Alignment.LEADING,javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)

.addComponent(jPanel3,javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)

.addGap(44, 44, 44)

.addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE)

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)

javax.swing.GroupLayout.PREFERRED_SIZE,33,.addComponent(jButton2, javax.swing.GroupLayout.PREFERRED_SIZE, 36, javax.swing.GroupLayout.PREFERRED_SIZE)

.addComponent(jButton5, javax.swing.GroupLayout.PREFERRED_SIZE, 35, javax.swing.GroupLayout.PREFERRED_SIZE)

.addComponent(jButton3, javax.swing.GroupLayout.PREFERRED_SIZE, 34, javax.swing.GroupLayout.PREFERRED_SIZE))

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)

.addComponent(jButton4, javax.swing.GroupLayout.PREFERRED_SIZE)

.addContainerGap(63, Short.MAX_VALUE))

.addComponent(jPanel1,javax.swing.GroupLayout.DEFAULT_SIZE,javax.swing.GroupLayout.PREFERRED_SIZE,38, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE));

pack();

}

//

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt){

// TODO add your handling code here:

t = new Controller(0, 0, sc, state, 0, 0, jLabel3, jLabel4, jPanel3, sc2);

t.init();

t.start();}

private void jButton2ActionPerformed(java.awt.event.ActionEvent evt){

// TODO add your handling code here:

t.moveLeft();}

private void jButton3ActionPerformed(java.awt.event.ActionEvent evt){

// TODO add your handling code here:

t.moveRight();}

private void jButton4ActionPerformed(java.awt.event.ActionEvent evt){

// TODO add your handling code here:

t.rot();}

private void jButton5ActionPerformed(java.awt.event.ActionEvent evt){

// TODO add your handling code here:

t.down();

}

private void jMenu7ActionPerformed(java.awt.event.ActionEvent evt){

// TODO add your handling code here:

t.init();}

/**

* @param args the command line arguments

*/

public static void main(String args[]){

java.awt.EventQueue.invokeLater(new Runnable(){

public void run(){

new Main().setVisible(true);

}

});

}

// Variables declaration-do not modify

private javax.swing.JButton jButton1;

private javax.swing.JButton jButton2;

private javax.swing.JButton jButton3;

private javax.swing.JButton jButton4;

private javax.swing.JButton jButton5;

private javax.swing.JLabel jLabel1;

private javax.swing.JLabel jLabel2;

private javax.swing.JLabel jLabel3;

private javax.swing.JLabel jLabel4;

private javax.swing.JMenu jMenu1;

private javax.swing.JMenu jMenu2;

private javax.swing.JMenu jMenu3;

private javax.swing.JMenu jMenu4;

private javax.swing.JMenu jMenu5;

private javax.swing.JMenu jMenu6;

private javax.swing.JMenu jMenu7;

private javax.swing.JMenu jMenu8;

private javax.swing.JMenuBar jMenuBar1;

private javax.swing.JMenuBar jMenuBar2;

private javax.swing.JMenuBar jMenuBar3;

private javax.swing.JMenuBar jMenuBar4;

private javax.swing.JMenuItem jMenuItem1;

private javax.swing.JMenuItem jMenuItem2;

private javax.swing.JMenuItem jMenuItem3;

private javax.swing.JMenuItem jMenuItem4;

private javax.swing.JPanel jPanel1;

private javax.swing.JPanel jPanel2;

private javax.swing.JPanel jPanel3;

// End of variables declaration

}

package square;public class Square {

boolean[][][] state;

int condition;

//定义多种情况

public Square(int kind)

//

定义多种类型

{

state = new boolean[4][4][4];

condition = 0;

switch(kind){

case 1:

//方形

每个case之后应该有个break;否则在满足条件之后会继续向后进行会跳出

state[0][0][0] = true;

state[0][0][1] = true;

state[0][1][0] = true;

state[0][1][1] = true;

state[1][0][0] = true;

state[1][0][1] = true;

state[1][1][0] = true;

state[1][1][1] = true;

state[2][0][0] = true;

state[2][0][1] = true;

state[2][1][0] = true;

state[2][1][1] = true;

state[3][0][0] = true;

state[3][0][1] = true;

state[3][1][0] = true;

state[3][1][1] = true;

break;

case 2:

//I型

state[0][0][0] = true;

state[0][1][0] = true;

state[0][2][0] = true;

state[0][3][0] = true;

state[1][0][0] = true;

state[1][0][1] = true;

state[1][0][2] = true;

state[1][0][3] = true;

state[2][0][0] = true;

state[2][1][0] = true;

state[2][2][0] = true;

state[2][3][0] = true;

state[3][0][0] = true;

state[3][0][1] = true;

state[3][0][2] = true;

state[3][0][3] = true;

break;

case 3:

//L型

state[0][0][0] = true;

state[0][1][0] = true;

state[0][2][0] = true;

state[0][2][1] = true;

state[1][0][2] = true;

state[1][1][0] = true;

state[1][1][1] = true;

state[1][1][2] = true;

state[2][0][0] = true;

state[2][0][1] = true;

state[2][1][1] = true;

state[2][2][1] = true;

state[3][0][0] = true;

state[3][0][1] = true;

state[3][0][2] = true;

state[3][1][0] = true;

break;

case 4:

//T型

state[0][0][0] = true;

state[0][0][1] = true;

state[0][0][2] = true;

state[0][1][1] = true;

state[1][0][1] = true;

state[1][1][0] = true;

state[1][1][1] = true;

state[1][2][1] = true;

state[2][0][1] = true;

state[2][1][0] = true;

state[2][1][1] = true;

state[2][1][2] = true;

state[3][0][0] = true;

state[3][1][0] = true;

state[3][1][1] = true;

state[3][2][0] = true;

break;

}

}

public boolean getState(int i, int j)//获得是否为声明的i,j变量的值

{

return state[condition][i][j];

}

public void rot(){

condition =(condition + 1)% 4;

} }

第五篇:C语言 程序代码编写规范

C语言 程序代码编写规范

(初级程序员 讨论版)

前言

一个好的程序编写规范是编写高质量程序的保证。清晰、规范的源程序不仅仅是方便阅读,更重要的是能够便于检查错误,提高调试效率,从而最终保证软件的质量和可维护性。

说明

此文挡还在完善改进中,如有不足,欢迎指正。本文档主要适用于刚刚开始接触编程的初学者。

对于具有一定工程项目开发经验的程序员,建议学习C语言程序代码编写规范—高级版。

目录 代码书写规范 2 注释书写规范 3 命名规范内容代码书写规范

1.1函数定义

每个函数的定义和说明应该从第1列开始书写。函数名(包括参数表)和函数体的花括号(“{”和“}”)应该各占一行。在函数体结尾的括号(“}”)后面应该加上注释,注释中应该包括函数名,这样比较方便进行括号配对检查,也可以清晰地看出来函数是否结束。

范例1:函数的声明

void matMyFunction(int n){ …… } /* matMyFunction*/ 1.2空格的使用

使用空格分割所有演算符号和操作数。

这条规则的例外是“->”,““.”, “()”和“[]”,这些操作符和操作数之间不空格。当需要把一个程序行的内容分成几行写时,操作符号应该放在行末,而不是下一行的开头。

1.3缩进的设置

代码书写应该遵从结构化的要求,采用缩进的格式。最小缩进量为4个空格,整个文件内部应该统一,不要混用Tab键和4个空格这两种情况,因为不同的编辑器对Tab键的处理方法不同。

1.4折行的使用

每行的长度不要超过80个字符,当程序行太长时,应该分行书写。分行时应该按照自然的逻辑关系进行,例如:不要把一个简单的逻辑判断写在两行上。

分行后的缩进应该按照程序的逻辑关系进行对齐。例如:参数表折行后,下面的行应该在参数表左括号的下方。

范例2:折行的格式dwNewShape = matAffineTransform(coords, translation,rotation);

if(((new_shape.x > left_border)&&

(new_shape.x < right_border))&&

((new_shape.y > bottom_border)&&

(new_shape.y < top_border))){

draw(new_shape);}

1.5嵌套语句(语句块)的格式

对于嵌套式的语句--即语句块(如,if、while、switch等)应该包括在花括号中。花括号的左括号应该单独占一行,并与关键字对齐。建议即使语句块中只有一条语句,也应该使用花括号包括,这样可以使程序结构更清晰,也可以避免出错。建议对比较长的块,在末尾的花括号后加上注释以表明该语言块结束。

范例3:嵌套语句格式 if(value < max){

if(value!= 0)

{

func(value);

} } } else {

error(“The value is too big.”);} /* if(value < max)*/ 注释书写规范

注释必须做到清晰,准确地描述内容。对于程序中复杂的部分必须有注释加以说明。注释量要适中,过多或过少都易导致阅读困难。

2.1注释风格

语言中使用一组(/* … */)作为注释界定符。注释内容尽量用英语方式表述。

注释的基本样式参考范例4。

注释应该出现在要说明的内容之前,而不应该出现在其后。

除了说明变量的用途和语言块末尾使用的注释,尽量不使用行末的注释方式。

范例4:几种注释样式

/*

* ************************************************* 强调注释

* ************************************************ */ /* * 块注释 */

/* 单行注释 */

int i;/*行末注释*/ 2.2何时需要注释

如果变量的名字不能完全说明其用途,应该使用注释加以说明。

如果为了提高性能而使某些代码变得难懂,应该使用注释加以说明。对于一个比较长的程序段落,应该加注释予以说明。如果设计文档中有流程图,则程序中对应的位置应该加注释予以说明。

如果程序中使用了某个复杂的算法,建议注明其出处。

如果在调试中发现某段落容易出现错误,应该注明。命名规范

3.1常量、变量命名

用#define定义的符号常量全部采用大写。

变量命名的基本原则:

可以选择有意义的英文(小写字母)组成变量名,使人看到该变量就能大致清 楚其含义。

不要使用人名、地名和汉语拼音。

如果使用缩写,应该使用那些约定俗成的,而不是自己编造的。

多个单词组成的变量名,每个单词的首字母应该大写。如:dwUserInputValue。

3.2函数命名

函数命名原则与变量命名原则基本相同。对于初学者,函数命名可以采用 “FunctionName”的形式。

下载为什么嵌入式要用c语言编写[合集5篇]word格式文档
下载为什么嵌入式要用c语言编写[合集5篇].doc
将本文档下载到自己电脑,方便修改和收藏,请勿使用迅雷等下载。
点此处下载文档

文档为doc格式


声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:645879355@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。

相关范文推荐

    c语言编写单片机感想

    用C语言对单片机编程感想 起先接触单片机,单片机的程序是用汇编语言编写的。汇编语言是面向机器的低级语言,保持了机器语言的优点,具有直接和简捷的特点,目标代码简短,占用内存少......

    嵌入式程序员C语言笔试题目

    华硕_嵌入式程序员C语言笔试题目 预处理器(Preprocessor) 1 . 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题) #define SECONDS_PER_YEAR (60 * 6......

    嵌入式C语言编程心得(合集5篇)

    一、.H文件与.C文件的关系: 迄今为止,写过的程序都是一些很简单的程序,从来没有想到要自己写.H文件,也不知道.H文件到底什么用,与.C文件什么关系。只是最近写键盘程序,参考别人的......

    嵌入式程序员C语言笔试经典题

    新一篇: 存储过程,无限级分类 | 旧一篇: 类继承中构造函数和析构函数的调用 这个测试适于不同水平的应试者,大多数初级水平的应试者的成绩会很差,经验丰富的程序员应该有很好......

    C语言嵌入式系统编程修炼之道

    C语言嵌入式系统编程修炼之道收藏C语言嵌入式系统编程修炼之道——背景篇... 1 C语言嵌入式系统编程修炼之道——软件架构篇... 4 1.模块划分... 4 2.多任务还是单任务... 5......

    编写一个以C 语言为基础的DSP程序

    实验1.2 : 编写一个以C 语言为基础的DSP程序 一.实验目的 1.学习用标准C语言编制程序;了解常用的C语言程序设计方法和组成部分。 2.学习编制连接命令文件,并用来控制代码的连接。......

    C语言于单片机的编写感想

    C语言于单片机的编写感想                 Y=max(m,n) 这指的是y=m和n中最大的 这就是C语言和单片机语言的一个思想 C语言和单片机主要是靠逻辑思想来编程。 但两者之间也有......

    嵌入式系统c语言编程该怎么学?

    雪中悍刀行 http://bmdqw.com/嵌入式系统c语言编程该怎么学?C语言博大精深,玩了很长时间了,一直徘徊在入门处。看了很多别人的编程经验,加上项目程序越做越大,直到这半年来突然有......