以文本方式查看主题

-  计算机科学论坛  (http://bbs.xml.org.cn/index.asp)
--  『 C/C++编程思想 』  (http://bbs.xml.org.cn/list.asp?boardid=61)
----  [转帖]C 的杂谈(原创)『连载1』--初识C  (http://bbs.xml.org.cn/dispbbs.asp?boardid=61&rootid=&id=22753)


--  作者:anchen0617
--  发布时间:10/5/2005 12:52:00 AM

--  [转帖]C 的杂谈(原创)『连载1』--初识C
C语言是大多数朋友们学习的第一门编程语言。然而C语言是一门怎样的语言呢?它有
        什么特点呢?三年前,大专编程的第一门语言是C,谁想得到现在在RMIT又要再次学习
        C了。好吧,写一点想法,献给已经、正在或将要学习C的朋友们吧。
        
        C是一个相当强大的语言,UNIX系统就是用C写的。C是学习C++和JAVA的基础。好吧
        我们上路吧。经典的C教材中,hello.c总是作为第一个程序,请看程序
        

        #include <stdio.h>
        
        int main( )
        {  
            printf( "Hello world  \n");
                    return 0;
         }
         
         这就是我们的第一个C程序,是不是很简单啊:)好吧,我们来分析一下吧
         int main( ) 这是main函数,中文叫主函数,所有的C语言都要包括这个函数。int 给出了函数
         返回值的类型,main函数的返回值一般为0,通常情况,main函数省略了返回值的类型,
         即以main( ) 代替 int main( )。 我个人认为应该保留,这样当你学习到函数时会很好的理解。
         printf( "Hello world  \n"); 这是程序执行的主要过程--即调用printf函数。printf函数的作用在于
         将给定的参数输出。在( )之间的称为参数。那printf函数为什么可以直接使用呢?这个问题
         问得很好。C语言是一门基于函数的语言,每一个函数都完成一个特定的功能。随着C的
         不断完善,C给出了一个标准的函数库,供编程者使用。应此在程序的开头有
         #include <stdio.h> 这就告诉编译器,我的程序将使用到标准的输入输出函数库。好吧,关于
         第一个程序就先说这么多呢。
        
        
        
        第一个程序"Hello World"并不是一个典型的编程结构,典型的编程结果应当由三模块组成。也就是
输入、执行和输出。C中的模块由函数构成,当然对于简单的程序。我们没有必要建立很多的函数,
但我们应当有函数和模块思想。好吧,我门就写一个包含以上三个模块的程序吧

        /*  求两个数的和*/
        
        #include <stdio.h>
        int main( )
        {
           int a, b,sum;                /*声明变量*/
           printf("please input the frist number \n");    /*显示输入提示*/
           scanf("%d", &a);                 /*输入数值a*/
           
           printf("please input the second number \n");
           scanf("%d", &b);
           
           sum=a+b;  /*运算过程*/
           
           printf("The sum is:");  /*输出结果*/
           printf("%d\n", sum);
                   return 0;

          }
           
我们来分析一下吧。int a, b,sum;    声明变量。现在我们遇到变量了。变量是编程中相当重要的一个概念。
变量究竟是什么呢?你口袋里的现金就是变量,应为它会取款后增加,花费后减少。声明时,要给出
变量的类型,根据不同的类型系统会分配不同大小的空间,在这里,我们只要求两个整数的和,所以,
我们声明变量类型为整形的。在以后的编程中要根据不同的需求使用不同类型的变量。变量还有一个
作用域的范围。这很好理解,如同现金一样,这现金是谁的,是国家、集体还是个人的。以后遇到多个
函数时,再具体解释什么是全局变量,什么是局部变量。C语言规定变量的声明要再赋值之前,当大家
学到C++ 是,就会发现C++在这方面比C灵活。
scanf("%d", &a);    scanf函数,标准输入输出函数之一,%d说明以十进制的形式输入,&a取得a的地址,并
将输入的值存入a。P.S双引号的意思是原样输入输出,%d表示将以什么样的形式输入输出变量。
   sum=a+b;一个赋值语句,把a+b的值赋给变量sum。刚开始学习编程的在这最容易出问题的,好吧,
   我们来具体地分析一下这个语句的执行过程:
   在执行这个语句之前,我们知道a和b在执行scanf函数
   是已经赋了值。假设a为5,b为8。编译器执行a+b即得出13,必将13赋给变量sum
   后面的语句我已经讲过了,就不重复了。:)


--  作者:anchen0617
--  发布时间:10/5/2005 12:53:00 AM

--  
今天我想谈谈变量(variable)的类型(type)。让我们先来看看什么是变量吧。变量是一个存储单元,这个单元可读可写。也就是说,我们可以访问这个单元,也可以改变单元里的值。

        回到变量的类型来吧。先让我们看看为什么要有类型的区别?我们知道不同类型在内存中所占的空间的大小不同。不同的变量用来存储不同类型的数据。因此,在程序的规划期间,变量的类型应当要有所考虑。

        变量在内存中的储存是有一个范围,如果超过了这个范围就会出现溢出,因此,对于要选择适当的变量。

        对于变量的理解,一直是困扰初学者的一个概念,因为大多数人过去的经验多是停留在静态的。要理解好变量,我们应该谈一些跟底层的东西。在以前的文章中我有提到过,一个经典的程序要有输入(input)、处理(processing)、输出(output)这三个模块。要实现数据的处理,我们要有空间来存放数据,这就是内存(处理器只能从内存读入数据)。应此变量是存在内存中的。好吧,回到变量上来吧,当你声明一个变量时,编译器会在内存中开辟一个空间来。比如int num;从编写者的角度来看,我们声明了一个整形变量,叫num。编译器会在内存中开辟一个四字节(byte)的空间,用来存放一个整形数据。当然这个空间的首地址我实可以知道的&num,并且C语言中有一专门的一个类型来存放地址,就是指针(pointer)。赋值运算赋“=”,也是一个让初学者晕头的东西。一段经典的代码,用来解释吧
a=a+b;
b=a-b;
a=a-b;
上面是一段交换a和b值的代码,为了便于解释,我们设a的初值为A,b的初值为B。首先,a=a+b;我们把a和b的和存到a中,因此,变量a的值为A+B,b=a-b,因此变量b的值为(A+B-B),为A。a=a-b;a的值为(A+B-A)为B。


--  作者:anchen0617
--  发布时间:10/5/2005 12:53:00 AM

--  
今天继续讨论变量,并扩展一些。对于一个变量系统会分配一个内存空间,它有地址。我们可以用&来访问地址。

#include <stdio.h>
int  main( )
{
int num=2;
printf("%d \n", num);
printf("%p",&num);
}

你发现不同的。C语言有专门的变量存放变量的地址,就是指针。指针的存在使得C可以很好的控制内存。我们用*来访问指针的变量。
#include <stdio.h>
int  main( )
{
int num=2;
int  *numAdd;
numAdd=&num;
printf("%d \n", num);
printf("%p\n",&num);
    printf("%d\n",*numAdd);
printf("%p\n",numAdd);
}
比较一下,用指针如何访问变量的。指针的事先提到这吧,目前。

电脑事如何存储变量的呢??我们都知道计算机只懂得0和1这两个数字。因此变量在内存重也是以0和1存在的。由于2进制数太长了,因此我们常用16进制数来表达内存地址。十六进制数书写上以0x开头。在编译其中以0开头的数值,编译器将它当作八进制数,以0x开头的数值,编译器当作十六进制数。

字符也是以代码的方式存储的。这就要提到ASCII码了,字符通过特定的代码存储。因此我们有可能对字符排序啊。
#include <stdio.h>
int main ()
{ char char1;
char1='a';
printf("%c\n",char1);
printf("%d",char1);

return 0;

}


--  作者:anchen0617
--  发布时间:10/5/2005 12:54:00 AM

--  
好久没有继续C的杂谈了。这段忙啊,一边学网络基础,一
边学习面向对象,追梦说要去看看IPv6。弄得我是晕头转向的。
好了,回到C的杂谈吧。今天我想通过一个例子来简单说一说
怎样选择算法。好吧,我们今天要解决的问题是从N个数中找出
一个最大值来。首先是两个数的,我们有以下的代码
if(num1>num2)
        printf("The greater number is %d\n",num1);
else
        printf("The greater number is%d\n",num2);

这是一个相当正常的逻辑,并且在N=2时,是相当高效的。然而当
N=3时,我们有一下代码
if(num1>num2)
        if(num1>num3)
                printf("The greatest number is %d\n",num1);
        else
                printf("The greatest number is %d\n",num3);
else if(num2>num3)
                printf("The greatest number is %d\n",num2);
        else
                printf("The greatest number is %d\n",num3);
我们可以预见,当N继续增大,代码的长度会急剧增加。因此这样的
算法时,不可取的。

        我们怎样去选择算法呢,去生活中发现。我们可以发现上面的算法
很像比赛中的单循环赛,那我继续考虑一下就会发现,淘汰赛是最快的
因此我们有一下代码
#include <stdio.h>
int main( )
{
        int max,num, count,time;
        max=0;
        printf("Enter the how many time you want to enter: ");
        scanf("%d",&time);
        for(count=1;count<=time;count++)
                {        printf("Enter number %d",count);
                        scanf("%d",&num);
                        if(max<num)
                                max=num;
                }
        printf("The greatest the number is %d",max);
        return 0;
}
因此我们在选择算法时要多多思考。


--  作者:anchen0617
--  发布时间:10/5/2005 12:54:00 AM

--  
scanf函数是C语言中相当常用的一个函数了,然而在使用它输入字符时,要千万的小心
因为它隐含着陷阱的。我用一个实例来说明吧。
要求:输入姓和名的第一个字母及年龄,程序输出你的姓和名的第一个字母,并告诉你,你
活了多少天了(假设一年365天)一般人会有一下程序
#include <stdio.h>
int main()
{
char c1,c2;
int age, date;
printf("Please enter you first name's frist letter:");
scanf("%c",&c1);
printf("\nPlease enter you second name's frist letter:");
scanf("%c",&c2);
printf("\nPlese enter you age:");
scanf("%d",&age);
date=365*age;
printf("\n %c %c  you have lived %d dates",c1,c2,date);
return 0;
}

如果是这样,你一定会有问题,不信,运行试试。
想想我们是怎么操作的,你输入一个字符、回车???为什么第二行我没法输入???
打住,你不是输了回车了??回车也是字符啊,所以,程序要改进的
#include <stdio.h>
int main()
{
char c1,c2,temp;
int age, date;
printf("Please enter you first name's frist letter:");
scanf("%c",&c1);

printf("\nPlease enter you second name's frist letter:");
scanf("%c,",&temp);  //用temp存回车,就可以结局的
scanf("%c",&c2);
  printf("\nPlese enter you age:");
scanf("%d",&age);
  date=365*age;
printf(" \n%c %c  you have lived %d dates",c1,c2,date);
return 0;
}


--  作者:anchen0617
--  发布时间:10/5/2005 12:55:00 AM

--  
昨天有人问我数组的问题,其实我对数组的理解不是十分的深刻,写一点肤浅的看法吧。
        本应当先写循环,可是没思路:(。数组是C自带的一个结构,编译器会分配一块固定的内存
        给数组使用,这块空间是不可以动态分配的。数组的表的方式  数组名[下标]。 说到数组不得
        不再提一下指针和sizeof( )函数了。对于数组的内存如何分配,我是这样理解的。对于给定的
        数组a[n],n是确定的,编译器先测定数组的类型,我们可以用sizeof( )函数知道这个类型的长
        度,假设为l。编译器可以利用数组的首地址,我们假设为p,那么a[i],(0<=i<=n)可以通p+i*l,
        来访问。经过上面的解释,对于数组名是指向数组首地址的指针就可以很好的理解了。要记得
        在C语言中,下标是从0开始的。
        
                数组的引入,可以简化大量重复的类似赋值运算。看看对100个用户的读入年龄。
        #include <stdio.h>
        int main( )
        {
                int a[100];
                int j;
                for(j=0;j<=100;j++)
                {
                        printf("Please enter your age:");
                        scanf("%d",&a[j]);
                return 0;
        }
                在C语言中,你不可以将一个数组的值赋给另一个数组,一下的语句是非法的
        int a[10],b[10];
        ``````
        ``````
        a=b;
                但数组的元素之间可以赋值,一下代码是正确的
        for(i=0;i<10;i++) a[i]=b[i];
        
                在C里面,编译器不会检查数组的长度,我们来分析一下以下这段代码
                int crash[10],i;
                for(i=0;i<100;i++) crash[i]=i;
        crash[10]以后的90个内存单位会被覆盖,这是我们应当注意到这个的。


--  作者:anchen0617
--  发布时间:10/5/2005 12:56:00 AM

--  
今天我想说一说函数,函数的地位在C语言中太重要了。可以说不了解函数,你还没掌握C语言。介于函数的重要性,我将分几个部分来介绍她(究竟多少部分,现在还不清楚)今天。我重点谈谈是么是函数,和怎样使用函数。
         
         在我最早的文章里。提到过模块的思想。把一个大的程序细化为若个个小的程序来编写,这个已经在软件业得到了默认的。在C语言中,模块是以函数的形式表现的。在C语言中函数又分为标准的库函数和程序员自己的函数。
         
         函数在使用过程中是通过调用来实现的。调用函数提供了被调用函数的函数名和该函数所需的参数。调用函数不关心被调用的函数如何完成工作的。
         
         在一个C程序中,至少包含了一个main()函数。对于一个给定的函数,通常包含了两个部分。一是函数的头部分,一个是函数的实体部分。在函数的头部分。我们规定了该函数的返回值类型,函数名和参数列表(包括了参数的数量和各个参数的类型)。在函数的实体部分,我们包含了执行该函数的代码和返回值。下面看一个例子。
         
         int                            max        (int n1,int n2)   //; -------------------------函数头部分
      //返回值类型        函数名     参数列表
      {
                      int max;
                      if(n1>n2) max=n1;
                      else max=n2;
                      return max;//返回值
              }
      如果函数没用返回值,要用void关键字。
      
      函数的原型,它是从C++中吸取来的。上例的函数原型是 int max (int ,int); 我们可以看到函数的原型和函数的头部分很相识的。使用函数原型的好处是编译器会检测被调用的函数的参数和返回值类型是否正确。函数的原型要紧跟着预处理。看一看例子。
      
     #include <stdio.h>
           int max (int, int); //函数原型
     
           int main( )
           {
                       int n1,n2,big;
                       printf("Enter the frist number:");
                       scanf("%d",&n1);
                        printf("Enter the second number:");
                       scanf("%d",&n2);
                       big=max(n1,n2); //调用max( )函数
                       printf("The greater number is %d\n",big);
                       return 0;
               }
     
     
               int max (int n1, int n2)
           {
                                     int big;
                                     if(n1>n2) big=n1;
                                     else big=n2;
                                     return big;//返回值
                   }

大家有没有发现在main( )和 max( )里面都有变量big啊。这个问题我会在下一部分函数的作用域中解释的。


--  作者:anchen0617
--  发布时间:10/5/2005 12:56:00 AM

--  
因为一下私人的原因,最近很久没有写东西了,不好意思啊。上次数组讲的不全,今天继续讲。
        数组是使用静态内存来存储多个类型相同的变量。首先,看看声明一个数组,编译器都做了什么事情。(不了解编译器是怎么执行语句的,我认为是还没入门的)。比如 int num[10],这个个声明语句,当编译器执行到这一语句时,它会可以的可用内存中去寻找一块相邻的区域,这个区域要可以存放下10个整形变量。并且开辟了一个指向整形变量的指针变量*num,并把这个数组的0号元素的地址放在着指针里. 也就是相当执行这个几个语句 int *num; num=&num[0];大家可以去编译运行了一下者两段代码
代码1
#include <stdio.h>

int main()
{
        int num[3]={1,2,3};
        int i;

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

        printf("%d ",*(num+i));

        return 0;
}

代码2
#include <stdio.h>

int main()
{
        int num[3]={1,2,3};
        int i;
        int  *p;
        p=&num[0];

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

        printf("%d ",*(p+i));

        return 0;
}

结果是一样的。

数组还可以作为参数传递个函数,在这里实际上传递的是数组名,也就是指向数组首个元素的地址。
一个简单的例子,说明一下

#include <stdio.h>

void max( int [ ]);

int main()
{
        int num[2]={1,2};
        max(num);

        printf("The max number is %d", num[0]);

        return 0;
}

void max (int arrNum[2])
{
        int big;
        arrNum[0]=arrNum[0]>arrNum[1]?arrNum[0]:arrNum[1];
}

在这里数组num和数组arrNum是一样的,你可以看到,我在函数改变了arrNum[0]的值,在main函数中,可以看见num[0]的值是改变了的。

最后,我说一些关于多维数组。多维数组完全可以看成一维数值。解释一下。比如有十个人如果站一排就是一维的(1~10),如果站两派就是二维的(1,1)~(2,5),其实6和(2,1)是一样的。多维数组是对开发者而言的,为的是好管理变量,其实在内存中,它是连续的。


--  作者:binaryluo
--  发布时间:10/5/2005 10:16:00 AM

--  
up
--  作者:fanqingsong
--  发布时间:10/11/2005 2:27:00 PM

--  
可以搞个c语言入门教程
--  作者:qzlzj
--  发布时间:2/7/2006 9:09:00 PM

--  
studying .....
--  作者:qingye
--  发布时间:3/3/2006 7:05:00 PM

--  
很想知道,开始的:return 0;   是干什么用的,有什么作用?
--  作者:红衣男孩-孤行者
--  发布时间:3/18/2006 1:15:00 PM

--  
我们这学期刚开始学 C程序设计

谢谢指教哦!!


--  作者:renzhelhllong
--  发布时间:3/23/2006 7:44:00 PM

--  
Good~!
--  作者:society
--  发布时间:5/28/2006 8:14:00 PM

--  
初次造访,很好呀!对初学者很有帮助,为什么不继续写下去呢?
--  作者:wlyxz
--  发布时间:6/1/2006 4:58:00 AM

--  
对呀,再把结构写上,就差不多了!
--  作者:wlyxz
--  发布时间:6/1/2006 5:00:00 AM

--  
#include <stdio.h>
        
        int main( )
        {  
            printf( "Hello world  \n");
                    return 0;
         }


return 0;是返回int main( ),int的值为0;也可以用void


--  作者:xmczr
--  发布时间:8/2/2006 8:34:00 PM

--  
int 的main() 可以不用返回的
不过为了标准还是返回一个0
W 3 C h i n a ( since 2003 ) 旗 下 站 点
苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
234.009ms