C语言的用法及特点

阿林老师

C语言的特点

Microsoft.NET(以下简称.NET)框架是微软提出的新一代Web软件开发模型,C#语言是.NET框架中新一代的开发工具。C#语言是一种现代、面向对象的语言,它简化了C++语言在类、命名空间、方法重载和异常处理等方面的操作,它摒弃了C++的复杂性,更易使用,更少出错。它使用组件编程,和VB一样容易使用。C#语法和C++和JAVA语法非常相似,如果读者用过C++和JAVA,学习C#语言应是比较轻松的。

用C语言编写的源程序,必须用C#语言编译器将C#源程序编译为中间语言(MicroSoft Intermediate Language,MSIL)代码,形成扩展名为exe或dll文件。中间语言代码不是CPU可执行的机器码,在程序运行时,必须由通用语言运行环境(Common Language Runtime,CLR)中的既时编译器(JUST IN Time,JIT)将中间语言代码翻译为CPU可执行的机器码,由CPU执行。CLR为C#语言中间语言代码运行提供了一种运行时环境,C语言的'CLR和JAVA语言的虚拟机类似。这种执行方法使运行速度变慢,但带来其它一些好处,主要有:

通用语言规范(Common Language Specification,CLS):.NET系统包括如下语言:C#、C++、VB、J#,他们都遵守通用语言规范。任何遵守通用语言规范的语言源程序,都可编译为相同的中间语言代码,由CLR负责执行。只要为其它操作系统编制相应的CLR,中间语言代码也可在其它系统中运行。

自动内存管理:CLR内建垃圾收集器,当变量实例的生命周期结束时,垃圾收集器负责收回不被使用的实例占用的内存空间。不必象C和C++语言,用语句在堆中建立的实例,必须用语句释放实例占用的内存空间。也就是说,CLR具有自动内存管理功能。

交叉语言处理:由于任何遵守通用语言规范的语言源程序,都可编译为相同的中间语言代码,不同语言设计的组件,可以互相通用,可以从其它语言定义的类派生出本语言的新类。由于中间语言代码由CLR负责执行,因此异常处理方法是一致的,这在调试一种语言调用另一种语言的子程序时,显得特别方便。

增加安全:C#语言不支持指针,一切对内存的访问都必须通过对象的引用变量来实现,只允许访问内存中允许访问的部分,这就防止病毒程序使用非法指针访问私有成员。也避免指针的误操作产生的错误。CLR执行中间语言代码前,要对中间语言代码的安全性,完整性进行验证,防止病毒对中间语言代码的修改。

版本支持:系统中的组件或动态联接库可能要升级,由于这些组件或动态联接库都要在注册表中注册,由此可能带来一系列问题,例如,安装新程序时自动安装新组件替换旧组件,有可能使某些必须使用旧组件才可以运行的程序,使用新组件运行不了。在.NET中这些组件或动态联接库不必在注册表中注册,每个程序都可以使用自带的组件或动态联接库,只要把这些组件或动态联接库放到运行程序所在文件夹的子文件夹bin中,运行程序就自动使用在bin文件夹中的组件或动态联接库。由于不需要在注册表中注册,软件的安装也变得容易了,一般将运行程序及库文件拷贝到指定文件夹中就可以了。

完全面向对象:不象C++语言,即支持面向过程程序设计,又支持面向对象程序设计,C语言是完全面向对象的,在C中不再存在全局函数、全区变量,所有的函数、变量和常量都必须定义在类中,避免了命名冲突。C语言不支持多重继承。

C语言assert的用法

原型定义:

#include

void assert( int expression );

assert的作用是现计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,

然后通过调用 abort 来终止程序运行。

请看下面的程序清单badptr.c:

复制代码 代码如下:

#include

#include

#include

int main( void )

{

FILE *fp;

fp = fopen( "test.txt", "w" );//以可写的方式打开一个文件,如果不存在就创建一个同名文件

assert( fp ); //所以这里不会出错

fclose( fp );

fp = fopen( "noexitfile.txt", "r" );//以只读的方式打开一个文件,如果不存在就打开文件失败

assert( fp ); //所以这里出错

fclose( fp ); //程序永远都执行不到这里来

return 0;

}

宏名: assert

功 能: 测试一个条件并可能使程序终止

用 法: void assert(int test);

程序例:

复制代码 代码如下:

#include

#include

#include

struct ITEM {

int key;

int value;

};

/* add item to list, make sure list is not null */

void additem(struct ITEM *itemptr) {

assert(itemptr != NULL);

/* add item to list */

}

int main(void)

{

additem(NULL);

return 0;

}

assert() 宏用法

注意:assert是宏,而不是函数。在C的assert.h头文件中。

assert宏的原型定义在中,其作用是如果它的`条件返回错误,则终止程序执行,原型定义:

复制代码 代码如下:

#include

void assert( int expression );

assert的作用是先计算表达式expression,如果其值为假(即为0),那么它先向标准错误流stderr打印一条出错信息,然后通过调用abort来终止程序运行;否则,assert()无任何作用。宏assert()一般用于确认程序的正常操作,其中表达式构造无错时才为真值。完成调试后,不必从源代码中删除assert()语句,因为宏NDEBUG有定义时,宏assert()的定义为空。

C语言怎样输出菱形

适有同学问起一些C语言题目,本想上网搜索了事,但网上的方法都是分为上下部分用两个嵌套for循环输出。我想有没有合起来输出的呢,这样符合简洁又美观的要求呢?答案是有的。

题目:输出行列都相等的菱形,如5行5列:

行列 12345

1 *

2 ***

3 *****

4 ***

5 *

分析:

当行数等于总行数的一半时,'*'是递增的,递增为2。

当行数大于总行数的一半时,'*'是递减的,递增为2。

设有一个行列为n的菱形,

我们用变量i作为行数,以0开始,i

k作为n菱第i行要输出的'*'个数。

则i<=n的中值(用m表示,m=(n-1)/2)时,k递增,i>m时,k递减。

因为k相对于m行对称,所以:

当i>m时,i每增加i-m时的k值就和第m-i行的.k值相等,即第i-m行和第m-(i-m)相对称。

所以得出结果:

当i<=m时,k=2i+1

当i>m时,k=2(m-(i-m))+1,(m=(n-1)/2)。即k=2n-2i-1

由于我们只需要输出'*'左边的空格即可,所以每行'*'左边的空格的个数为:(n-每行的k)/2。

每行循环输出空格,再循环输出每行的'*',再输出回车,结束一行。

这样我们就可以开始编程了。

#include

int main()

{

int i,j,k,n;//定义四个变量:i是行,j每行*号前的空格数,k每行的*号数

printf("please input odd n:");

scanf("%d",&n); //输入奇数n

for (i=0;i

{

if(n>=2*i+1) //判断k值

k=2*i+1;

else

k=2*n-2*i-1;

for(j=(n-k)/2;j>0;j--) //循环输出空格

printf(" ");

for(;k>0;k--) //循环输出*号

printf("*");

printf("n"); //输出回车结束一行

}

本来呢题目就到止结束了,但上面的程序还不够完美

比如说,别人输入n值为偶数怎么办?输入非数值呢?

我们加一点东西进去:

#include

int main()

{

int i,j,k,n=0; //这里给n赋初值,即使输入非数值,n也可有确切的值。

do{ //增加一个大循环,可以令n可以输入多次以观察不同的结果。

printf("please input odd n, 0 to exit:");//当输入0的时候,退出大循环,结束程序。

scanf("%d",&n);

if (!(n%2)) //增加对输入偶数的判断。

{

printf("you input a even, please input again.n");

continue;

}

for (i=0;i

{

if(n>=2*i+1)

k=2*i+1;

else

k=2*n-2*i-1;

j=(n-k)/2;

for(;j>0;j--)

printf(" ");

for(;k>0;k--)

printf("*");

printf("n");

}

}while(n);

return 0;

}