C primer plus【C语言入门的学习之路】

 想学习的编程的同学可以参考:

             http://tieba.baidu.com/p/1239792581

 C primer plus【PDF】下载地址:

             http://down.51cto.com/data/461794 

 C primer plus【习题答案】:

             http://down.51cto.com/data/461789

 

C语言的输入和输出   input和output;   简称为I/O函数;

 

I/O函数将信息传输您程序中传出信息  printf(),scanf(),getchar和putchar();

 

getchar()和putchar()每次输入和输出一个字符;处理文本的程序的核心。

 

#include <stdio.h>

int main()

{

 char ch;

 while((ch = getchar())!= '#')

      putchar(ch);

 return 0;

}

 

输入的结果就是:

hanyu

hanyu

lishaoli

lishaoli

#

Press any key to continue

 

 ANSIC

 

 

   输入字符立即回显是非缓冲或直接输入的一个实例;  您所键入的字符对正在等待的程序立即变为可用。延迟回显是缓冲输入的实例,情况下键入的字符收集并存储在一个称谓缓冲区buffer的临时存储区域中;

   为什么需要缓冲区? 若干字符作为一个块传输比逐个发送这么字符耗费时间少。如果输入有误的话,可以使用键盘更正功能修正有误的信息!

   一些交互性的程序需要非缓冲输入。

  缓冲:  完全缓冲  fully buffered I/O   行缓冲  line-buffered I/O;

 

 

C语言处理文件的过程:

  

  文件 流和键盘输入;

 file是一块存储信息的存储器区域,文件一般情况下保存在某种类别的永久存储器上,例如软盘,硬盘或磁盘。

  过程是: 编译器打开文件并读取其内容,编译器在结束编译时关闭该文件,C语言有许多用于打开,读,些和关闭文件的库函数。再上一个级别上,它可以使用宿主操作系统的基本文件工具来处理文件。低级I/O.C以第二种级别处理文件,创建用于处理文件的I/O函数的标准模型和标准集;在较高级别上,系统之间差异由特定的C实现来处理。所以打交道的是一个统一的接口。

 

  C语言处理一个流而不是直接处理文件,就是理想化的数据流,实际中的输入和输出映射到这个数据流上,具有不同属性的多种类型的输入由流表示。

 

  键盘上的输入是由一个叫   stidin流表示的

  屏幕显示的输出时:       stout流表示的

  getchar  putchar  printf  scanf 都是标准的i/o包的的成员;

 

 

#definee EOF (-1)    一般的返回值在0到127之间,可能在0到255值 -1不对应任何字符                     可以用它表示文件的结尾

 

重定向   redirect   重定向不同的通信输入和输出,将stdin流重新的分配至文件,                    getchar程序从该流中取数据,不真正的关心流是从何取数据的;

<  符号是unix linux和dos中的重定向运算符。程序所知道的一切就是向它传送一个字符   流,将这些字符独处并一次打印出一个字符,知道晕倒文件结尾。

 

$echo < words 

 

>  输出重定向就是将输出重定向到该文件,将stout从显示折本重定向到mywords文件中

 

$echo_eof > mywords

$

 

组合重定向

制作文件mywords并将其命名为savewords

 

echo_eof < mywords > savewords

 

#include <stdio.h>

#include <stdlib.h>

int main()

{

 int ch;

 FILE * fp;

 char fname[50];

 

 printf ("enter the name file:");

 scanf ("%s",fname);

 fp=fopen(fname,"r");

 if (fp == null)

 {

     printf("failed to open file.\n");

     exit(1);

 }

 while((ch=getc(fp))!=EOF)

        putchar(ch);

        fclose(fp);

return 0;

}

 

 

**************函数****************

function    用于去完成特定任务的程序代码的自包含单元。

 

 

使用函数:

1、省去重复代码的编写,多次使用只需要一个特定的功能就能实现!

2、方便使用,函数的调用!

 

 

函数编写练习:

 

·读入数字

·对数字排序

·找到他们平均值

·打印柱状图

 

 

#include <stdio.h>

#define size 50

int main()

{

 float list[SIZE];

 

 readlist(list,SIZE);

 sort(list,SIZE);

 average(list,SIZE);

 bargraph(list,SIZE);

 return 0;

}

 

 

 

#include <stdio.h>      

#define N "hanyu"

#define A "love "

#define P "lishaoli"

#define W 30         \\一直到上面的#include这五行都是函数的预处理指令;

 

void han();

int main()

{

 han();

 printf ("%s\n",N);

 printf ("%s\n",A);

 printf ("%s\n",P);

 han();

 return 0;

void han()

{

 int c;

     for (c=1;c<=W;c++)

       putchar('@');

      printf "\n";

}

 

执行的结果

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

hanyu

love

lishaoli

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Press any key to continue

 

 

 

 

 

#include <stdio.h>

#include <string.h>

#define N "han"

#define A "love "

#define P "lishaoli"

#define W 40      

#define S ' '

void han(char ch,int num);

 

int main()

{

  int spaces;

  han('*',W);

  printf ("\n");

  han(S,12);

  printf("%s\n",N);

  spaces=(W-strlen(A))/2;

 

  han(S,spaces);

  printf("%s\n",A);

  han(S,(W-strlen(P))/2);

   

  printf("%s\n",P);

  han("*",W);

  putchar('\n');

 

  return 0;

}

 

void han(char ch ,int num)

{

 int c;

 for (c=1;c<=num;c++)

 putchar(ch);

}

执行的结果:

****************************************

                  han

                  li

                lishaoli

****************************************

Press any key to continue

 

 

 

 

 

比较两个输入数的大小;

 

#include <stdio.h>

int han(int a,int b);

int main()

{

  int num1,num2;

  printf ("enter a pair of tow num(quit to 'q'):\n");

  while (scanf("%d %d",&num1,&num2) == 2)

  {

  printf ("the two num is %d  %d, the min is %d\n",num1,num2,han(num1,num2));

  }

  return 0;

}

 

int han(int a,int b)

{

  int min;

 if(a<b)

    min=a;

 else 

    min=b;

 return min;

}

 

 

执行的结果:

 

enter a pair of tow num(quit to 'q'):

12 111

the two num is 12  111, the min is 12

q

Press any key to continue

 

 

 

 

 

 

 

 

starbar标示符在不同位置被使用3次:   函数原型(function prototype)告知编译器starbar()的函数类型

 

 

终止循环  break;

 

int p,q;

scanf ("%d",&p);

while (p > 0)

{

 printf ("%d\n",p);

 scanf ("%d",&q);

 

 while(q>0)

{

 printf ("%d\n",p*q);

  if(q>100)

    break;   //跳出里面(里层)的循环!

   scanf ("%d",&q);

}

if (q>100)

 break;      //跳出外层的循环

scanf ("%d",&p);

}

 

 

break       终止!

continue    继续执行!

 

 

 

使用switch

 

while ((ch=getchar())='#')

{

 if('\n'== ch)

    continue;

 if(islower(ch))

    switch(ch)

     {

       case 'a';

         printf("a,hi! Asia\n");

       break;

       case 'b';

         printf("b,hi! \n");

       default;

         printf("that's a stumper");    //语句的结束!     

}

else 

  printf ("i agress the letters.\n");

  while(getchar()!='\n')

   continue;

  printf ("please type another letter #.\n");

}

 

 

 

   紧跟在单词switch后的圆括号里的表达式被求值,就是输入给ch的值,然后程序扫描标签列表;直到搜索到一个与该值相匹配的标签。然后程序跳到那一行,如果有标记为default标签的行,程序就跳到改行!否则的话程序继续处理switch语句之后的语句。

 

   break语句导致程序脱离switch语句,跳到switch之后的下一个语句。如果没有break语句,从相匹配的标签到switch末尾的每一条语句都要被处理。

 

 

 

    switch(number)

   {

    case 1: statement 1;

             break;

    case 2: statement 2;

             break;

    default:statement 3;

   }

    statement4;            如果执行的number匹配的话就执行扫描匹配,之后执                           行break语句;然后跳出循环执行statement4语句;

 

 

 

 

#include <stdio.h>

int main()

{

  char ch;

  int a,b,c,d;

  a=b=c=d=0;

  printf ("enter some text:enter ! to quit.\n");

  while ((ch=getchar())!='#')

  {

      switch (ch)

      {

        case 'a':

        case 'A':  a;

        break;

        case 'b':

        case 'B':  b;

        break;

        case 'c':

        case 'C':   c;

        break;

        case 'd':   d;

        case 'D':

        break;

        default: break;

       }

   }

 printf ("ABCD\n");

 printf ("%d%d%d%d\n",a,b,c,d);

 return 0;

}

   

 

条件运算符  (?:)

if (a<x<z)    错误的代码   没有逻辑运算符

if (a<x && x<z)   使用&&组合两个表达式;

 

 

打印出的代码:

 

#include <stdio.h>

int main()

{

 int num;

 for (num=1;num<=11;num++)

 {

 if(num%3 == 0)

 putchar('$');

 else 

    putchar('*');

    putchar('#');

  putchar('%');

 }

putchar('\n');

return 0;

}

 

执行的结果:

 

*#% *#% $#% *#% *#% $#% *#% *#% $#% *#% *#%

Press any key to continue

 

 

#include <stdio.h>

int main()

{

 int i=0;

 while(i<3){

   switch(i++){

             case 0:printf("fat");

             case 1:printf("hat");

             case 2:printf("cat");

             default:printf("no no");

}

putchar ('\n');

}

return 0;

}

 

执行的结果是:

fathatcatno no

hatcatno no

catno no

Press any key to continue

 

 

 

int age = 20;

   while(age++ <= 65)

{

     if ((age%20)==0)

        printf("you are %d.\n",age);

     if (age=65)

        printf ("you are %d.here is your!\n")

}

 

 

int main()

{

 char ch;

 while 

}

#include <stdio.h>

int data[2]={10,20};

int more[2]={30,40};

int main()

{

 int *p1,*p2,*p3;

 

 p1=p2=data;

 p3=more;

 printf (" *p1=%d,*p2=%d,*p3=%d\n",*p1,*p2,*p3);

 printf (" *p1++ =%d,*++p2=%d,(*p3)++ =%d\n",*p1++,*++p2,(*p3)++);

 printf (" *p1=%d,*p2=%d,*p3=%d\n",*p1,*p2,*p3);

return 0;

}

 

 

 

执行的结果:

 

 *p1=10,*p2=10,*p3=30

 *p1++ =10,*++p2=20,(*p3)++ =30

 *p1=20,*p2=20,*p3=31

Press any key to continue

 

 

表达式 a[i]和*(a+i)的意义是一样的;不管a是一个数组名还是一个指针变量,两个表达式都可以工作。只有当a是一个指针变量时,才可以使用a++这样的表达式;

 

 

int a[3]={132,123,456};

int *p1,*p2,*p3;

p1=a;

p2=&a[2];

 

printf("pointer value dereferenced pointer pointer address:\n");

printf("%p,%d %p",p1,*p1,&p1);

 

p3=p1+4;

printf("%p %d\n",p1+4,*(p1+3));

 

p1++;

printf("%p %d %p\n",p1,*p1,&p1);

 

p2--;

printf("%p %d %p",p2,*p2,&p2);

 

--p1;

++p2;

printf("%p %p %d",p2,p1,p2-p1);

printf("%p %p",p3,p3-2);

return 0;

 

执行的结果:

pointer value dereferenced pointer pointer address:

0018FF3C,132 0018FF380018FF4C 1638280

0018FF40 123 0018FF38

0018FF40 123 0018FF34

0018FF44 0018FF3C 2

0018FF4C 0018FF44

Press any key to continue

 

 

 

赋值      可以吧一个地址赋给指针,使用数组名或地址运算符&来进行地址赋值,地址          应该和指针类型兼容。

 

求值[value-finding]或取值[dereferencing]    运算符*可取出指针指向地址中存储的          数值。一般都是去的指针中首值;

 

取值针地址 指针变量具有地址和数值,使用运算符&可以得到存储指针本身的地址

 

将一个整数加给指针      使用+运算符   

 

 

 

 

对初始化指针取值:

 

int *pt;    未初始化的指针;

*pt =5;     严重的错误;

 

如果把数值存储在pt指向的地址,没有初始化所以值是随机的,所以5也不知道存储在上面位置,

 

创建一个指针时,系统只分配用来存储指针本身的内存空间,并不分配用来存储数据的内存空间;因此在使用指针之前,必须给它赋予一个已分配的内存地址。  

 

可以把一个已存在的变量地址赋给指针(当您使用带有一个指针参量的函数时,属于这一个情况)

 

 

合法的语句:

 

 

ptrl++;    

ptr2=ptrl+2;

ptr2=urn+1;

 

 

 

void add_to(double ar[],int n,double val)

{

  int i;

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

     ar[i] += val;

 }

 

add_to(prices,100,2.50);

 

函数调用将使数组prices里的每个元素增加2.5;

 

int sum(const int ar[],int n);

 

使用const并不要求原始数组固定不变,只是说明函数在处理数组时,应把数组当作是固定不变的。使用const可以对数组提供保护一样;

 

 

一个函数显示数组,另一个函数对数组的每个元素乘上一个给定的数值;

 

 

#include <stdio.h>

#define size 5

void show_array (const double ar[],int n);

void mult_array(double ar[],int n,double mult);

int main(void)

{

   double dip[size] = {20.1,13.5,1.1,3.5,6.4};

 

   printf("the original dip array:\n");

   show_array(dip,size);

   mult_array(dip,size,2.5);

   

   printf("the dip array after calling mult_array():\n");

   show_array(dip,size);

   return 0;

}

 

void show_array(const double ar[],int n)

{

 int i;

   

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

   printf("%10.2f",ar[i]);

 putchar('\n');

}

 

void mult_array(double ar[],int n,double mult)

{

  int i;

  

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

   ar[i] *=mult;

 }

 

 

执行的结果是:

the original dip array:

     20.10     13.50      1.10      3.50      6.40

the dip array after calling mult_array():

     50.25     33.75      2.75      8.75     16.00

Press any key to continue

 

 

 

 

const double *pd = rates;

使用pd指向数组开始处;

pd++;     让pd指向rates[1]

 

只想指向常量的指针用作函数参数,表明函数不会用这个指针来修改数据;

 

只有非常量数据的地址才可以赋给普通的指针;

 

double a[2]={10,20};

const double b[2]={30,40};

const double *c=a;

c=b;

c=&b[1];

 

double *c=a;

c=&b[1];

 

 

 

int (*pz)[2];     pz指向一个包含2个int值的数组;

 

int * pax[2];

   pax包含两个某种元素数组   pax两个指针组成的数组,由两个指向int值 的指针构成的数组

 

 

 

通过变量获取有关的信息:

 

int a[4][2]={{2,4},{6,8},{1,3},{5,7}};

int (*c)[2];

c=a;

 

printf ("c=%p c+1=%p\n",c,c+1);

printf ("c[0]=%p c[0]+1=%p\n",c[0],c[0]+1);

printf ("*c=%p *c+1=%p\n",*c,*c+1);

printf ("c[0][0]=%d\n",c[0][0]);

printf ("c[0]=%d\n",*c[0]);

printf ("c[0]=%p c[0]+1=%p\n",**c);

printf ("c[2][1]=%d\n",c[2][1]);

printf ("*(*(c+2)+1)=%d\n",*(*(c+2)+1));

return 0;

 

 

 

执行的结果:

 

c=0018FF28 c+1=0018FF30

c[0]=0018FF28 c[0]+1=0018FF2C

*c=0018FF28 *c+1=0018FF2C

c[0][0]=2

c[0]=2

c[0]=00000002 c[0]+1=00000000

c[2][1]=3

*(*(c+2)+1)=3

Press any key to continue

 

c[m][n] == *(*(c+m)+n)

c[m][n] == *(*(c+m)+n)

 

 

#define rows 3

#define cols 4

void sum_rows (int ar[][cols],int rows);

void sum_cols (int [][cols],int);

int sum2d (int(*ar)[cols],int rows);

int main()

{

 int junk[rows][cols] = {

               {2,4,6,8},

               {3,5,7,9},

               {12,10,8,6}

 };

 

 sum_rows(junk,rows);

 sum_cols(junk,rows);

 printf("sum of all = %d\n",sum2d(junk,rows));

 

 return 0;

 }

void sum_rows(int ar[][cols],int rows)

 int r;

 int c;

 int tot;

  

 for (r=0;r<rows;r++)

 {

  tot += ar[r][c];

  printf("row %d:sum=%d\n",r,tot);

  }

 }

void sum_clos(int ar[][cols];int rows)

{

  int r;

  int c;

  int tot;

  

 for (c=0;c<cols;c++)

 {

   tot=0;

   for (r=0;r<rows;r++)

      tot += ar[r][c];

   printf("col%d: sum=%d\n",c,tot);

  }

 }

int sum2d(int ar[][cols],int rows)

{

  int r;

  int c;

  int tot=0;

  

  for(r=0;r<rows;r++)

    for(c=0;c<cols;c++)

      tot += ar[r][c];

  return tot;

 }

 

 

数组的列只能被预置在函数内部;

 

#define a 4

int sum(int abc[][c],int d)

{

 int e;

 int f;

 int t=0;

 

 for (r=0;r<d;r++)

   for (f=0;f<a;f++)

     t += abc[r][f];

 

 return t;

 }

 

 

 

 

 

二维变长数组

 

int sum(int a,int b,int abc[a][b]);

 

 

 

处理数组时   函数必须知道数组的地址和元素的个数。

             数组地址直接传递给函数,数组元素的个数信息需要内建于函数内部或被             做为独立的参数传递给函数;

 

type name[size]    数组类型  数组名字 size元素的个数;

                   数组名和指向首元素的指针是等价的

           a[i]   *(a+i)

 

8月1号

 

1、打印

 

#include <stdio.h>

int main()

{

 int a[]={8,4,0,2};

 int *b;

 int c;

 

 for(c=0,b=a;c<4;c++,b++)

   printf("%d %d\n",a[c],*b);

 return 0;

 }

 

 

执行的结果:

 

8 8

4 4

0 0

2 2

Press any key to continue

 

 

[一]、

*a,*(a+1)和*(a+2)的数值:

#include <stdio.h>

int main()

{

 int *a;

 int b[2][2]={12,14,16};

 a=b[0];

   printf("%d %d\n",*a,*(a+1));

 return 0;

 }

 

执行的结果:

12 14 16

Press any key to continue

 

[二]、

 

*a,*(a+1)和*(a+2)的数值:

#include <stdio.h>

int main()

{

 int *a;

 int b[2][2]={{12},{14,16}};

 a=b[0];

   printf("%d %d\n",*a,*(a+1));

 return 0;

 }

 

执行结果:

12 0 14

Press any key to continue

 

[三]、

 

#include <stdio.h>

int main()

{

  int (*a)[2];

    int b[2][2]={12,14,16};

    a=b;

    printf("%d %d \n",**a,**(a+1));

    return 0;

}

 

执行结果:

12 16

Press any key to continue

 

[四]、

 

#include <stdio.h>

int main()

{

  int (*a)[2];

    int b[2][2]={{12},{14,16}};

    a=b;

    printf("%d %d \n",**a,**(a+1));

    return 0;

}

 

执行结果

12 14

 

 

初始化一个double数组,把数组内容复制到另外两个数组

【有问题!!!!】

#include <stdio.h>

#define M 5

double copy_atob(double a[],double b[],int M );

double copy_atoc(double a[],double c[],int M);

int main()

{

double a[M]={1.1,2.2,3.3,4.4,5.5};

double b[M];

double c[M];

    copy_atob(a,b,M);

    copy_atoc(a,c,M);

    return 0;

}

 

double copy_atob(double a[],double b[],int M )

{

  int e=0;

  for (e;e<M;e++)

  b[e]=a[e];

   printf ("b[5]is: %f\n",b[e]);

}  

  

double copy_atoc(double a[],double c[],int M )

{

 double *aa,*cc;

 aa=a,cc=c;

 int f=0;

 for(f;f<M;f++)

 *(aa+f)=*(cc+f);

     printf("c[5]is: %f",*(cc+f);)

}

 

 

 

double a[5]={1.1,2.2,3.3,4.4,5.5};

double b[5];

double c[5];

copy_atob(a,b,5)

copy_atoc(a,c,5)

 

 

2、编写函数  返回int数组中存储最大数值;

 

int a[b];

int i=0,j=0;

 

int max_ab(const int a[],int n);

void show_a(const int a[],int n);

 

int main()

{

  int max;

  b[5]={1,2,3,4,5};

  show_a(b,5);

  max=max_ab(b,5);

  printf("the max value is:%d\n",max);

}

int max_ab(const int a[],int n)

{

 int j;

 int max=a[0];

 for (j=1;j<n;j++)

  if(max<a[j])

     max=a[j];

  return max; 

}

 

void show_a(const int a[],int n)

{

 int i;

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

   printf("%d \n",a[i]);

 }

 

简单的比较大小:

 

程序代码:

 

#include <stdio.h>

int max_ab(int a[],int n);

int main()

{

int b[5]={1,2,3,4,5};

int max;

max=max_ab(b,5);

printf("the max of b[5] is:%d\n",max);

return 0;

}

int max_ab(int a[],int n)

{

int i,max;

max=a[0];

for (i=1;i<n;i++)

if (max<a[i])

max=a[i];

return max;

}

 

执行的结果

the max of b[5] is:5

Press any key to continue

 

函数的调用和使用:

 

 

3、返回一个double数组,存储最大数值索引;

 

#include <stdio.h>

int max_ab(int a[],int n);

int main()

{

       

return 0;

}

 

 

int cmp(double * array,int size)

{

 int index=0;

 for(int i=1;i<size;i++)

 {

  if(array[i]>array[index])

  index=i;

  }

 return index+1;

 }

 

int main()

{

 double test[10]={2,5,10,3,7,4,6,9,1,11};

 cmp(test,9);

 return 0;

}

 

 

 

正确地求解:

#include <stdio.h>

#define S 5

int result(double ar[],int size);

int main()

{

double a[S];

int i;

printf("enter you want array:\n");

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

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

printf("the result is:\n");

    result (a,S);     //执行但是没有输出到显示器上;

printf("%d\n",result(a,S));

return 0;

}

int result (double ar[],int size) 

{

double index=ar[0];

int i;

int j=0;             //首元素的索引为0;

 

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

{

if(index<ar[i])

index=ar[i];

j++;              //比较之后索引值自加;

}

return j; 

}

 

 

执行结果:

enter you want array:

1 2 3 4 5

the result is:

4

Press any key to continue    最大值5的索引值为4;

 

 

【4、求数组中最大和最小数的差值;】

 

 

int   result()

 

int main()

{

  double a[5];

  int i;

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

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

  

  result();

}

 

int result()

{

  int re;

  int i,max,min;

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

    {

      if  (a[0]<a[max])

       a[max]=a[0];

     } 

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

    {

      if  (a[min]<a[0])

       a[min]=a[0];

     }

  re=a[man]-a[min];

  printf("%d",re);

}

 

正确地写法:

#include <stdio.h>

int result(float ar[],int size);

int main()

{

  float a[5];

  int i;

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

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

  result(a,5);

  printf ("%d\n",result(a,5));

  return 0;

}

 

int result(float ar[],int size)

{

  float max=ar[0];    

  float min=ar[0];

  for (int i=1;i<size;i++)

    {

      if  (max < ar[i])

         max=ar[i];                \\求出最大值                

      else if (min > ar[i])

         min=ar[i];                \\求出最小值

}

  return max-min;

 }

 

执行的结果:

1 2 3 4 5

4

Press any key to continue