第1章 C入门

helloworld

cat hello.c
#include               //包含标准库的信息
main()                          //定义名为main的函数,它不接受参数值
{                               //main函数的语句都被括在花括号中
        printf("hello,world\n");//main函数调用库函数printf以显示字符序列 \n代表换行符
}

\t 表示制表符;\b 表示回退符;"表示双引号

打印下列华氏温度与摄氏温度对照表

cat huashi.c
#include 
/*
当fahr=0,20,… ,300时,分别
打印华氏温度与摄氏温度对照表*/
main()
{
 int fahr,celsius;
 int lower,upper,step;
 lower = 0;     /* 温度表的下限*/
 upper = 300;   /* 温度表的上限*/
 step = 20;     /* 步长*/
 fahr = lower;
 while (fahr <= upper ){
  celsius = 5 * (fahr-32)/9;
  printf("%d\t%d\n",fahr,celsius);
  fahr = fahr + step;
 }
}

int与float类型的取值范围取决于具体的机器。对于int类型,通常为16 位,其取值范围在-32768~32767 之间,也有用32 位表示的int 类型。float 类
型通常是32位,它至少有6 位有效数字,取值范围一般在10-38~10+38之间。
除 int与float类型之外,C语高还提供了其它一些基本数据类型,例如:
char 字符——一个字节
short 短整型
long 长整型
double 双精度浮点型
这些数据类型对象的大小也取决于具体的机器。另外,还存在这些基本数据类型的数组、结
构、联合,指向这些类型的指针以及返回这些类型值的函教。

改进版
由于我们使用的是整型算术运算,因此经计算得到的摄氏温度值不太精确,例如,与0℉对应的精确的摄氏温度应该为-17.8℃,而不是-17℃。为了得到更精确的结果,应该用浮点算术运算代替上面的整型算术运算。

cat huashi.c
#include 
/*
公式℃=(5/9)(℉-32)打印下列华氏温度与摄氏温度对照表
当fahr=0,20,… ,300时,分别
打印华氏温度与摄氏温度对照表*/
main()
{
 float fahr,celsius;
 float lower,upper,step;
 lower = 0;     /* 温度表的下限*/
 upper = 300;   /* 温度表的上限*/
 step = 20;     /* 步长*/
 fahr = lower;
 while (fahr <= upper ){
  celsius = 5.0 * (fahr-32.0)/9.0;
  printf("%3.0f %6.1f\n",fahr,celsius);
  fahr = fahr + step;
 }
}

printf中的转换说明%3.0f表明待打印的浮点数(即fahr)至少占3个字符宽,且不带小数点和小数部分;%6.1f表明另一个待打印的数(celsius)至少占6个字符宽,且小数点后面有1位数字。

%d 按照十进制整型数打印
%6d 按照十进制整型数打印,至少6个字符宽
%f 按照浮点数打印
%6f 按照浮点数打印,至少6个字符宽
%.2f 按照浮点数打印,小数点后有两位小数
%6.2f 按照浮点数打印,至少6个字符宽,小数点后有两位小数
此外,printf 函数还支持下列格式说明:%o 表示八进制数;%x 表示十六进制数;%c表示字符;%s表示字符串;%%表示百分号(%)本身。

for循环

cat huashi2.c
#include 
main()
{
 int fahr;
 for(fahr = 0;fahr <=300;fahr = fahr +20)
  printf("%3d %6.1f\n",fahr,(5.0/9.0)*(fahr-32));
}

符号常量

cat huashi3.c
#include 
#define  LOWER 0
#define  UPPER 300
#define  STEP 20
main()
{
        int fahr;
        for(fahr = LOWER;fahr <=UPPER;fahr = fahr + STEP)
                printf("%3d %6.1f\n",fahr,(5.0/9.0)*(fahr-32));
}

LOWER、UPPER 与STEP 都是符号常量,而非变量,因此不需要出现在声明中。符号常量名通常用大写字母拼写,这样可以很容易与用小写字母拼写的变量名相区别。注意,#define指令行的末尾没有分号。

字符输入/输出

 cat copy.c
#include 
main()
{
        int c;
        c=getchar();
        while(c!=EOF){
                putchar(c);
                c=getchar();
        }
}

cat copy1.c
#include 
main()
{
        int c;
        while((c=getchar())!=EOF){
                putchar(c);
        }
}

while 循环语句首先读一个字符并将其赋值给c,然后测试该字符是否为文件结束标志。如果该字符不是文件结束标志,则执行while语句体,并打印该字符。随后重复执行while语句。当到达输入的结尾位置时,while循环语句终止执行,从而整个main函数执行结束。

字符计数

cat test/calchar.c
#include 
main()
{
        long nc;
        nc=0;
        while(getchar()!=EOF){
                ++nc;
                printf("%ld\n",nc);
        }
}

运算符++,其功能是执行加1 操作。

行计数

$ cat calline.c
#include 
main(){
        int c,nl;
        nl=0;
        while((c=getchar())!=EOF){
                if(c=='\n'){
                        ++nl;
                }
        }
        printf("%d\n",nl);
}

编写一个统计空格、制表符与换行符个数的程序

cat cal.c
#include 
main(){
        int c,emptyChar,tableChar,changeChar;
        emptyChar=0,tableChar=0,changeChar=0;
        while((c=getchar())!=EOF){v
                if(c==' '){
                        ++emptyChar;
                }else if(c=='\t'){
                        ++tableChar;
                }else if(c=='\n'){
                        ++changeChar;
                }
        }
        printf("空格有%d\n",emptyChar);
        printf("制表符有%d\n",tableChar);
        printf("换行符有%d\n",changeChar);
}

编写一个将输入复制到输出的程序,并将其中连续的多个空格用一个空格代替。

 cat skipempty.c
#include 
main(){
        int c,temp;
        while((c=getchar())!=EOF){
                if(c==' '){
                        if(temp!=' '){
                           putchar(c);
                        }
                        temp=' ';
                }else{
                        putchar(c);
                        temp=c;
                }
        }
}

编写一个将输入复制到输出的程序,并将其中的制表符替换为\t,把回退符替换为\b,把反斜杠替按为\。这样可以将制表符和回退符以可见的方式显示出来。

cat showorigin.c
#include 
main()
{
        int c;
        while((c=getchar())!=EOF){
                if(c=='\t'){
                        printf("\t");
                }else if(c=='\\'){
                        printf("\\");
                }else if(c=='\b'){
                        printf("\b");
                }else{
                        putchar(c);
                }

        }
}

程序用于统计行数、单词数与字符

cat cal1.c
#include 
#define IN 1 /*在单词里*/
#define OUT 0 /*在单词之间*/
main(){
        int c,nc,nl,nw,state;
        c=nc=nl=nw=0;
        state=OUT;
        while((c=getchar())!=EOF){
                ++nc;
                if(c=='\n'){
                        ++nl;
                }
                if(c==' ' || c=='\t' || c=='\n'){
                        state=OUT;
                }else if (state==OUT){
                        ++nw;
                        state=IN;
                }
        }
        printf("共有%d个字符\n %d行\n %d个单词\n",nc,nl,nw);
}

程序执行时,每当遇到单词的第一个字符,它就作为一个新单词加以统计。state 变量记录程序当前是否正位于一个单词之中,它的初值是“不在单词中”,即初值被赋为OUT。我们在这里使用了符号常量IN与OUT,而没有使用其对应的数值1 与0,这样程序更易读。

编写一个程序,以每行一个单词的形式打印其输入

 cat printw.c
#include 
main(){
        int c, temp;
        while((c=getchar())!=EOF){
                if(c==' '){
                        if(temp!=' '){
                                putchar('\n');
                        }
                        temp=' ';
                }else{
                        putchar(c);
                        temp=c;
                }
        }

}

编写一个程序,以统计各个数字、空白符(包括空格符、制表符及换行符)以及所有其它字符出现的次数

cat cal2.c
#include 
main()
{
        int digest[10];
        int i,c,whiteC,otherC;
        whiteC=otherC=0;
        for(i=0;i<10;i++)
        {
                digest[i]=0;
        }
        while((c=getchar())!=EOF)
        {
                if(c>='0' && c<='9')
                        ++digest[c-'0'];
                else if(c==' '||c=='\t'||c=='\n')
                        ++whiteC;
                else
                        ++otherC;
        }
        printf("数字 ");
        for(i=0;i<10;i++)
                printf("%d ",digest[i]);

        printf("\n空白字符%d",whiteC);
        printf("\n其它字符%d\n",otherC);
}

函数

cat testpow.c
#include 
int power(int m,int n);
main()
{
        int i;
        for(i=0;i<10;i++)
                printf("2的%d次幂是%d, -3的%d次幂是%d\n",i,power(2,i),i,power(-3,i));
        return 0;
}
int power(int m,int n)
{
        int i,total;
        total=1;
        for(i=1;i<=n;i++)
                total=total*m;
        return total;
}

函数定义的一般形式为:
返回值类型函数名(0个或多个参数声明)
{
声明部分
语句序列
}
main函数的末尾有一个return语句。由于main本身也是函数,因此也可以向其调用者返回一个值,该调用者实际上就是程序的执行环境。一般来说,返回值为0 表示正常终止,返回值为非0 表示出现异常情况或出错结束条件。为简洁起见,前面的main 函数都省略了return 语句,但我们将在以后的main 函数中包含return 语句,以提醒大家注意,程序还要向其执行环境返回状态。

字符数组

cat str.c
#include 
#define MAXLINE 1000
int getoneline(char line[], int lmt);
void copy(char to[], char from[]);
main()
{
        int len; /*目前的长度*/
        int max; /*目前为目最大的字符长度*/
        char line[MAXLINE];/*当前输入的字符串*/
        char longest[MAXLINE];/*当前存储的最长字符串*/
        max=0;
        while((len=getoneline(line,MAXLINE))>0)
        {
                if(len>max){
                        max=len;
                        copy(longest,line);
                }
        }
        if(max>0)
                printf("%s\n",longest);
        return 0;

}
int getoneline(char line[],int lmt)
{
        int c,i;
        for(i=0;i < lmt-1 && (c=getchar()) != EOF && c != '\n';++i)
        {
                line[i]=c;
        }
        if (c=='\n')
        {
                line[i]=c;
                ++i;
        }
        line[i]='\0';
        return i;
}
void copy(char to[], char from[])
{
        int i;
        i=0;
        while((to[i]=from[i])!='\0')
                ++i;
}

首先,我们编写一个独立的函数getline,它读取输入的下一行。我们尽量保持该函数在其它场台也有用。至少getline 函数应该在读到文件末尾时返回一个信号;更为有用的设计是它能够在读入文本行时返回该行的长度,而在遇到文件结束符时返回0。由于0 不是有效的行长度,因此可以作为标志文件结束的返回值。每一行至少包括一个字符,只包含换行符的行,其长度为1。当发现某个新读入的行比以前读入的最长行还要长时,就需要把该行保存起来。也就是说,我们需要用另一个函数copy把新行复制到一个安全的位置。

外部变量与作用域

人们通常把变量和函数的extern 声明放在一个单独的文件中(习惯上称之为头文件),并在每个源文件的开头使用#include 语句把所要用的头文件包含进来。后缀名.h约定为头文件名的扩展名。

cat str1.h
#ifndef CTR1_H_
#define CTR1_H_

#define MAXLINE 1000
char line[MAXLINE];
int max;
char longest[MAXLINE];
int getoneline(void);
void copy(void);

#endif

外部变量时谨慎地使用了定义(define)与声明(declaration)这两个词。“定义”表示创建变量或分配存储单元,而“声明”指的是说明变量的性质,但并不分配存储单元。

cat str1.c
#include 
#include "str1.h"
int getoneline(void);
void copy(void);
main()
{
        int len; /*目前的长度*/
        extern int max; /*目前为目最大的字符长度*/
        extern char longest[];/*当前存储的最长字符串*/
        max=0;
        while((len=getoneline())>0)
        {
                if(len>max){
                        max=len;
                        copy();
                }
        }
        if(max>0)
                printf("%s\n",longest);
        return 0;

}
int getoneline(void)
{
        extern char line[];
        int c,i;
        for(i=0;i < MAXLINE-1 && (c=getchar()) != EOF && c != '\n';++i)
        {
                line[i]=c;
        }
        if (c=='\n')
        {
                line[i]=c;
                ++i;
        }
        line[i]='\0';
        return i;
}
void copy(void)
{
        extern char line[],longest[];
        int i;
        i=0;
        while((longest[i]=line[i])!='\0')
                ++i;

}

前几行定义了main、getline 与copy 函数使用的几个外部变量,声明了各外部变量的类型,这样编译程序将为它们分配存储单元。从语法角度看,外部变量的定义与局部变量的定义是相同的,但由于它们位于各函数的外部,因此这些变量是外部变量。
函数在使用外部变量之前,必须要知道外部变量的名字。要达到该目的,一种方式是在函数中使用extern 类型的声明。这种类型的声明除了在前面加了一个关键字extern 外,其它方面与普通变量的声明相同。
某些情况下可以省略extern 声明。在源文件中,如果外部变量的定义出现在使用它的函数之前,那么在那个函数中就没有必要使用extern声明。因此,main、getline及copy中的几个extern 声明都是多余的。在通常的做法中,所有外部变量的定义都放在源文件的开始处,这样就可以省略extern声明。

你可能感兴趣的:(第1章 C入门)