(2012.01.13)《C程序设计》学习笔记

来源:互联网 发布:士兵突击 知乎 编辑:程序博客网 时间:2024/04/28 04:00

        在有C++基础的前提下,学习C语言,使用了《C程序设计》(第四版)(谭浩强)这本书,了解一下C语言的基础知识。

 

前言

——学习《C程序设计(第四版)》(谭浩强)的原因及感想

        以前没有接触过C语言,都是直接学习C++过来的,然后,看见有些程序在编写的时候,会汲及到那么一两个关于C语言的知识点,但又很多人说,学习了C++的话,就不用学习C语言了,只是,自己还是想系统地了解学习一下,真正地体会一下,我想,从C++转型到学习C语言话,也没有什么难度吧,而且打算粗学,没有打算精学,没打算专攻C语言,只是想了解一下最基本的语法那些,于是,不断地上网找资料,还是决定了购买《C程序设计(第四版)》——谭浩强,用这本书来学习,在2011.12.06和2011.12.07这两天,竟然大概总共只花了五个小时的时候,就将这本书刷完了,刷了一次以后才发觉,原来C++和C语言如果不深研它的话,还真的是大同小异,要说不同,就只有那么几个地方,输入输出语句(包括字符输入输出,文件的输入输出,屏幕的输入输出),类的使用,C语言的类就是结构体,比C++的类简单多了...

        只是,在看谭的这本书的时候,发觉还有另外一个收获,基于这个原因,所以今天(2012.01.12)就再次开始翻阅这本书,因为还没有做总结,上次看过的也没有很深的印象,其中发觉,main的函数参数调用,define与const,程序设计思想,这本书里面的这几个点,对于个人来说,挺有价值的,我想再复习重温一下,顺便再做一些小题目练练手,前段时间一直在复习大学各科的东西,也很久没有写过程序了,好吧,不多说,开工。

 

 

第01章

——程序设计和C语言

    第一章,跳得很快啊,理解性的东西不多,需要记忆的东西,还是记录一下吧,挑一些经典的易忘的,呃,好像只有一个值得记录。

 

100. 程序设计的任务

 

 101. 程序设计,是指从确定任务到得到结果、写出文档的全过程。

 

102. 程序设计经典的五过程:

 

1021. 问题分析 -> 设计算法 -> 编写程序 -> 对源程序进行编辑、编译和连接 -> 运行程序,分析结果

 


 

第02章

——算法,程序的灵魂

200. 怎样表示一个算法

 

202. 用流程图表示算法

 

 

第03章

——顺序程序设计

在第03章中,这本书主要介绍了编写一个顺序程序需要掌握的基本知识,其中包括数据的类型介绍,各运算符的介绍,这些规则基本与C++语言无差异,至于第四节的时候,讲述的是数据的输入与输入,这部分与C++语言有较大差异,需要认真看看,学习一下语法。

 

301. 有关数据输入输出的概念

 

3011. 所谓输入输出是以计算机主机为主体而言的。

 

3012. C语言本并不提供输入输出语句,输入和输出操作是由C标准函数库中的函数来实现的。

 

3013. C语言中的标准输入输出函数主要有putchar,getchar,printf,scanf,puts(字符串),gets(字符串).

 

3014. C语言中,标准输入输出函数标准库头文件为stdio.h  (standard input & output),这与C++的不同点。

 

3015. 简单过一下putchar和getchar的使用。

 

----30151. char a; a = getchar(); 输入’字符’,然后按回车,’字符’会被送到变量a处。(getchar能接收回车\n)

----30152. char b = ‘o’; putchar(b); 将会在屏幕上输出字符’o’.

 

3016. printf与scanf的使用.(详细例子应用见本章习题)

 

----30161.printf的使用.

----------#include <stdio.h>

----------int printf( const char *format, ... );

----------printf()函数根据format(格式)给出的格式打印输出到STDOUT(标准输出)和其它参数中.

----------字符串format(格式)由两类项目组成 - 显示到屏幕上的字符和定义printf()显示的其它参数.

----------即 printf函数的一般格式为:print(格式控制,输出表列).

----------格式声明一般形式为: % 附加字符 格式字符

----------常用格式字符有:d (整型带符号), c(字符型),f(浮点型). %%(输出’%’);

-------------如:当int a = 0; printf(“a = %d”, a); 将输出a = 0.

----------附加字符有: -m.n 指占m列,其中包含n个小数位,(-)左对齐.

-------------如:当 float a = 123.678; printf(“a = %-8.2f”, a); 将输出 a = |123.68  |(占8位, ”|”仅用于辨认)

-------------如:当 float a = 123.678; printf(“a = %8.2f”, a); 将输出 a = |  123.68|(占8位,右对齐)

-------------如:当 float a = 123.678; printf(“a = %.1”, a); 将输出 a = |123.7|(字符紧凑合在一起)

 

----30162. scanf的使用.

----------#include <stdio.h>

----------int scanf( const char *format, ... );

----------实际上,scanf与printf的使用是大同小异的,scanf函数的一般形式: scanf(格式控制,地址表列)

---------需要注意的是,这里的地址表列是需要引用变量的地址。

------------如:scanf(“a = %f, b = %f, c = %f”, &a, &b, &c);

------------另外,在输入时,除了要输入变量外,还要根据scanf里面的char *format进行输入.

------------即,该scanf例子的正确输入方法是: “a = 2.3, b = 2, c = 23回车”连同a=,b=这些字符也要输入进去。

 

302. 有关const与define

 

---- #define Pi 3.1415926       // 定义符号常量

---- const float pi = 3.1415926;   // 定义常变量

 

3021. 常变量与常量的异同是:常变量具有变量的基本属性:有类型,占存储单元,只是不允许改变其值。

---------可以说,常变量是有名字的不变量,而常量是没有名字的不变量。

 

3022. 定义符号常量用#define指令,它是预编译指令,它只是用与常量代表一个字符串,在预编译的时候仅是进行字符替换,即,在预编译后,符号常量就不存在了(全部都置换成3.1415926了),对符号常量的名字是不分配存储单元的。

 

3023. 而,常变量要占用存储单元,有变量值,只是该值不改变而己。

 

3024.总的来说:

---- #define Pi 3.1415926       // 定义符号常量,不占内存单元,编译后就将原程序中所有Pi转换成数字

---- const float pi = 3.1415926;   // 定义常变量,占内存单元,相当于一个不变值的变量

 

3025.#define和用const定义还有一个区别是,用const定义的可以指定类型,而#define定义的常量是不分类型的。

 

// c0305.c -- C语言第03章第05题/** * 题目: * 用下面的scanf函数输入数据,使a = 3, b = 7, x = 8.5, y = 71.82, c1 = 'A', c2 = 'a'. **/// 该题可帮助了解怎样正确对数进行输入,熟悉使用scanf函数。#include <stdio.h>int main(){printf("请输入数据,使a = 3, b = 7, x = 8.5, y = 71.82, c1 = 'A', c2 = 'a'\n");int a, b;float x, y;char c1, c2;scanf("a=%db=%d", &a, &b);scanf("%f%f", &x, &y);scanf("%c%c", &c1, &c2);     void checkprint(int, int, float, float, char, char);  // 此函数非原题上,编写函数为验证结果 checkprint(a, b, x, y, c1, c2);// 函数调用    while(1);return 0;}// 为了验证其输入的正确性,特意多写下列的输出函数// checkprint函数功能,输入六个变量的值。void checkprint(int a, int b, float x, float y, char c1, char c2){// 输出刚刚输入的结果。printf("\n下面是输出结果:\na = %-12d, b= %-12d", a, b);printf("\nx = %-12.1f, y = %-12.2e", x, y);printf ("\nc1 = %-12c, c2 = %-12c\n", c1, c2);// 检查其正确性并提示信息//if(3 == a && 7 == b && 8.5 == x && 71.82 == y && 'A' == c1 && 'a' == c2)// 在判断浮点型数据时,不能直接这样等于,判断两者之差,一般在 1e-6范围内认为相等。      if(3 == a && 7 == b && (x-8.5<1e-6) && (y-71.82<1e-6) && 'A' == c1 && 'a' == c2){printf("\n输出结果正确,与题目相符合!\n");}elseprintf("\n输出结果错误,请检查输入的方式。\n");return;}// 本程序使用 Microsoft Visual C++ 6.0 验证正常。// 第一次尝试输入时:/************************************************请输入数据,使a = 3, b = 7, x = 8.5, y = 71.82, c1 = 'A', c2 = 'a'a=3b=78.571.82Aa     // <-这里在输入71.82前,输入了回车,出错下面是输出结果:a = 3           , b= 7x = 8.500000    , y = 7.182000e+001  c1 = A           , c2 = a输出结果错误,请检查输入的方式。 // <-这里出错了Press any key to continue************************************************/// 修改过程: /**原:if(3 == a && 7 == b && 8.5 == x && 71.82 == y && 'A' == c1 && 'a' == c2)因: 在判断浮点型数据时,不能直接这样等于,判断两者之差,一般在 1e-6范围内认为相等。 改: if(3 == a && 7 == b && (x-8.5<1e-6) && (y-71.82<1e-6) && 'A' == c1 && 'a' == c2)*/// 修改后输入:/************************************************请输入数据,使a = 3, b = 7, x = 8.5, y = 71.82, c1 = 'A', c2 = 'a'a=3b=78.5 71.82Aa下面是输出结果:a = 3           , b= 7x = 8.5         , y = 7.18e+001c1 = A           , c2 = a输出结果正确,与题目相符合!************************************************/// 总结:// 从这个程序的编写调试运行过程中可以知道,// 在scanf函数中,需严格按照格式控制进行输入。// 在float比较时,注意不要直接使用==比较,而要将其设定在1e-6范围内 


 

// c0307.c -- C语言第03章第07题/** * 题目: * 设圆半径r = 1.5, 圆柱高h = 3, 求圆周长、圆面积、圆柱体积。 * 用scanf输入数据,输出计算结果,输出时要求有文字说明,取小数点后2位数字。请编程序。 **/// 做题目的,练习C语言中printf和scanf的使用。/** * 做题思路: * 这题目并不难,按照一般的思路就行了,先用一个函数输入数据,然后再分别用两个函数计算出结果。 * 整个过程,共有四个函数,一个主函数,一个用于输入数据的函数,两个用于计算的函数。 **/#include <stdio.h>int main(){// 声明变量float r;// 圆的半径float h;// 圆的高printf("-> 请根据提示输入圆的半径及高,系统将自动计算出圆的周长,面积及圆柱的体积。\n");void valueInput(float & r, float & h);// 声明函数,在该函数中输入数值valueInput(r, h);// 调用函数void roundness(float r);// 声明函数,该函数实现计算并显示圆周长,圆面积的功能void column(float r, float h);// 声明函数,该函数实现计算圆柱体积的功能roundness(r);// 调用函数,计算圆周长及圆面积column(r, h);// 调用函数,计算圆柱体体积return 0;}// 在该函数中输入r 和 h 的数值void valueInput(float & r, float & h){printf("-> 请输入该圆的半径(输入后按回车结束):");scanf("%f", &r);printf("-> 请输入该圆柱的高(输入后按回车结束):");scanf("%f", &h);printf("\n输入完毕。。。\n");return;}// 该函数实现计算并显示圆周长,圆面积的功能void roundness(float r){printf("-> 该圆的周长为:%-.2f", 3.14 * r * 2);printf("\n-> 该圆的面积为:%-.2f", 3.14 * r * r);return;}// 该函数实现计算圆柱体积的功能void column(float r, float h){printf("\n-> 该圆柱的体积为:%-.2f", 2 * 3.14 * h * r);printf("\n");return;}// 运行测试/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** -> 请根据提示输入圆的半径及高,系统将自动计算出圆的周长,面积及圆柱的体积。-> 请输入该圆的半径(输入后按回车结束):34.23-> 请输入该圆柱的高(输入后按回车结束):34.2输入完毕。。。-> 该圆的周长为:214.96-> 该圆的面积为:3679.12-> 该圆柱的体积为:7351.78Press any key to continue**********************************************************/


 

 

第08章

——指针

801. 指针数组作main函数的形参

----int main(int argc, char * argv[])  argc 和 argv 是main函数的形参,是“命令行参数”。

8011. argc = argument count; // 参数个数

8012. argv = argument vector; // 参数向量

8013. main函数是操作系统调用的,实参只能由操作系统给出。命令行参数都是字符串。

8014. 命令行的一般形式: 命令名 参数1 参数2 参数3 ... 参数n

-----如: file1.exe[这个属于命令] HaHa(这个属于第一个参数) HeiHei(这个属于第二个参数)

-----这里此时, argv[0] = ”file1.exe \0” argv[1]= “HaHa\0” argv[2] = “HeiHei\0”.

-----如果使用了这个命令行参数后,再执行以下程序的话,估计就能理解这个参数的意思了。

-----void main( int argc, char * argv[])

----{ while (*argv != NULL)

----   cout << *argv ++ << endl;

----}

8015.其实,main函数中的形参不一定命名为argc和argv,可以是任意的名字,argc和argv只是习惯。

8016.总的来说,通过指针数组,可以对main传递命令行参数,使用指定的功能。

 

802. 动态内存分配与指向它的指针变量

 

8021. 内存的存储区域(稍归纳一下,其实内存里面就三个区)

-----静态存储区:是在程序编译时就已经分配好的,在整个运行期间都存在,如全局变量、常量。

-----动态存储区(栈(stack)区)函数内的局部变量就是从这分配的,但分配的内存容易有限。

-----自由存储区(堆(heap)区)也称动态分配,如new,malloc分配内存,delete,free释放内存。

 

8022. 建立内存的动态分配(系统提供的库函数,malloc, calloc, free, realloc)

 

80221. 使用malloc函数: void * malloc(unsigned int size)

--------在内存的动态存储区中分配一个长度为size的连续空间。

---------如: int * p = malloc(100); // 开辟一个100字节的空间,函数值为第1个字节的地址。

 

80222. 使用calloc函数:void * calloc(unsigned n, unsigned size);

--------在内存的动态存储区中分配n个长度为size的连续空间,空间大小足以存放一个数组。

---------p = calloc(50, 4);  // 开辟50 * 4个字节的临时分配域,把起始地址赋给指针变量p

 

80223. 使用free函数: void free (void * p);

---------其作用是释放指针变量p所指向的动态空间,使这部分空间能重新被其他变量使用。free(p);

 

80224. 使用realloc函数:void * realloc(void * p, unsigned int size);

--------改变指针变量在动态空间所占大小,使用realloc重新分配。

--------realloc(p, 50);

---------// 将p所指向的已分配的动态空间改为50字节,分配后,p值不变,若失败,返回NULL。

 

 

第09章

——用户自己建立数据类型(类)

901.建立结构体类型

-----声明一个结构体类型的一般形式

-----struct 结构体名{成员表列};

 

902.定义结构体类型变量

-----假如已经声明了一个结构体类型 struct Student{};

------现在用它来定义变量。   struct Student student1, student2; // 变量student1, student2

-------还可以 struct Student{成员表列}变量名表列;

--------如:struct Student{int num} student1, student2; // 变量student1, student2

 

903.用typedef声明新类型名

-----命名一个新的类型名代表结构体类型:

------typedef struct{int month;}Data;

-------Data a; // 则a 的类型为 Data与原来的直接用struct定义不同的是一个少写了struct.

-----再如: typedef int Num[100]; Num a; // a 相当于 int [100]

 

 

 

第10章

——对文件的输入输出

1001.文件的分类

――――根据数据的组织形式,数据文件可以分为ASCII文件和二进制文件。

 

10011.二进制文件

------数据在内存中是以二进制形式存储的,如果不加转换地输出到外存,就是二进制文件。

------也可以认为它是存储在内存的数据映像,所以也称作映像文件(image file)。

 

10012.文本文件(text file)

------ASCII文件又称为文本文件。当要求在外存上以ASCII形式存储,则需要在存储前进行转换。

 

 

1002.对文件的操作及两语言操作的不同比较