C语言程序设计

一、初识C语言从常量变量开始

1.Bug和Debug为什么叫抓虫?mare2研发中有一只在继电器中,抓出来就可以运行了。

2.sizeof运算符计算变量占用内存空间的大小;sizeof(int)=4;sizeof(a+b);sizeof(a);

3.宏定义与const常量(constant):

(1)宏常量(Macro Constant):用一个标识符号来表示常量

宏定义:#define 标识符 字符串     //#表示这是编译预处理命令

#define PI 3.14159

#define R  5.3

缺点:只是进行简单的字符串替换而不进行类型检查,因此会经常发生意想不到的错误

(2)用const常量来替换宏常量    //放在只读存储器中,在定义的时候赋初值

#include <stdio.h>
int main()
{
    const double pi=3.14159;
    const double r=5.3;
    printf("area=%f\n",pi*r*r);
    return 0;
}

4.数字在计算机中以二进制存储,负数以二进制补码表示(为什么负数在计算机中要以补码的形式表示?)

计算机内部用什么方式表示负数,其实是无所谓的。只要能够保持一一对应的关系,就可以用任意方式表示负数。所以,既然可以任意选择,那么理应选择一种最方便的方式。

2的补码就是最方便的方式。它的便利体现在,所有的加法运算可以使用同一种电路完成。

5.数据和内存

    1字节(byte)=8位(bit)

二、做点计算

1.算术运算

2.赋值运算

3.增1和减1运算符

4.自动类型转换

5.强制类型转换

    (类型)表达式        aver=(float)total/number;

三、键盘输入屏幕输出

1.输出

    包含头文件#include <stdio.h>

    scanf()--接收输入

    printf()--打印输出

2.数据的格式化键盘输入

    scanf(格式控制字符串,输入地址表);

    scanf("%d %f",&a,&b);     //别忘了区地址运算符

    scanf("%2d%2d",&a,&b); //指定位宽2    1234

    scanf("%d,%f",&a,&b);    //12,34

    scanf("a=%d,b=%f",&a,&b); //a=12,b=34

        scanf()的返回值=正确读入的数据项数

  

3.单个字符的输入输出

    字符在内存中以对应的ascii码的二进制值进行存储。a-065 A-097

    字符输出函数putchar()

    putchar(ch)

    字符输入函数getchar()

    ch=getchar()

    从键盘接收的字符作为getchar()的函数值,没有参数

  eg:大写英文字母转换为小写英文字母:

#include <stdio.h>

int main()
{
    char ch;
    ch=getchar();
    ch=ch+32;
    putchar(ch);
    putchar('\n');
    printf("%c,%d\n",ch,ch);
    //以两种格式输出
    return 0;
}


    getchar()使用行缓冲区存储输入的内容    (行缓冲区是一行的缓存)区,把控制台输入内容全部读入

 

4.用%c输入数据存在的问题

 

(1)增加一个getchar(),读掉输入的回车

(2)加一个空格

#include <stdio.h>

int main()
{
    int data1,data2,sum;
    char op;
    scanf("%d %c %d",&data1,&op,&data2);
    printf("%d%c%d=%d\n",data1,op,data2,data1+data2);
    return 0;
}

四、循环分支

1.关系运算符和逻辑运算符

2.条件语句

条件表达式:

    a>b?a:b;

3.开关语句

4.数值溢出和精度损失问题

5.软件测试与错误分析实例

程序测试:给定一组输入,通过运行被测程序,检查程序输出是否与预期结果一致。(测试用例)

    测试过程就像黑客攻击的过程。

    黑盒测试举例:写好了一个判断三角形类型的函数:用各类三角形的值输入。

6.程序=算法+数据结构

    算法:对在数据上的操作的描述,不同的算法可能有不同的时间或空间效率。

    数据结构:定义待操作的数据在计算机内存中是如何存储和组织的,选择恰当的数据结构可以提高程序的运行或存储效率。

    算法的特性:有穷性、确定性、允许没有输入或者多个输入、必须有输出。

    顺序结构、选择结构、

    raptor软件:用于画流程图来运行程序的软件。

c语言生成随机数

#include <stdio.h>
#include <time.h>

int main()
{
    srand(time(NULL));
    //设置随机数种子为时间,不设置时默认为1

    for(int i=0;i<5;i++)
    {
        printf("%d ",rand()%10+1);
    }
    printf("\n");

    return 0;
}

 

五、循环

 

1.计数控制的循环

2.递推

    正向递推与反向递推

3.条件控制的循环

4.嵌套循环

5.穷举

goto END;//无条件转向语句

END:    ;    //标号(标识符)后面必须有语句,哪怕是空语句

#include <stdio.h>

int main()
{
    int x;
    for(x=1;;x++){
        if(x%5==1&&x%6==5&&x%7==4&&x%11==10){
            printf("%d",x);
            goto END;
        }
    }
    END:;
    return 0;
}

break与exit(0)--<stdlib.h>与使用标志变量tag(可读性更好)

尽量避免使用goto语句,在跳出多重循环和跳向共同的出口位置。

穷举法也叫枚举法:密码的破译、暴力搜索法

6.软件调试与错误实例分析

程序中常见的出错原因:

(1)编译错误:语法错误

(2)链接错误:缺少包含文件、或者包含文件的路径错误等

(3)运行时错误:运行结果与预期不一致程序无法正常运行

        调试一个错误的程序能够极大提高我们的调试能力。

7.循环结构

循环结构的两种实现方法:

    (1)当型循环:先检票后上车

    (2)直到型循环:先上车后检票

六、函数:分而治之

1.函数的定义、调用、参数传递和函数原型

(1)标准库函数

    ISO C定义的标准库函数

    第三方库函数

(2)用户自定义函数

函数的定义:返回值类型、形式参数、return返回值(函数的出口)

函数原型: 就是函数先声明    --在函数开头定义函数的原型是一种良好的编程习惯

2.函数封装与程序的健壮性

(防御性程序设计)程序的健壮性:对非法输入进行判断

函数设计的基本原则

    *检查入口参数的有效性、合法性

    *检查函数调用成功与否

(1)函数规模要小

(2)函数功能要单一

(3)函数接口定义要清楚

3.断言与防御性编程

断言:assert(只在debug版本中有用,在relase版本中不起作用)

    仅用于调试程序,不能作为程序的功能。

何时适合使用断言?

    检查程序中的各种假设的正确性

    证实或测试某种不可能发生的状况确实不会发生

使用断言的基本原则

    使用断言捕获不应该或者不可能发生的情况

    每个assert只检验一个条件

防御性编程

    养成良好的编程风格

    避免闪电式编程,用怀疑的眼光审视

    简单就是一种美,不要滥用技巧,让你的代码过于复杂

    编译时打开所有警告,不要忽略它们

    使用安全的数据结构和函数调用

    做内存的“好管家”

4.代码风格

花括号不跟在函数后面,另起一行写

变量名:小写字母开头,“名词”或者“形容词+名词”

            oldValue    ,    newValue

函数名:大写字母开头,“动词”或者“动词+名词”

            GetValue()    ,    SetValue()

宏和const常量全用大写字母,并用下划线分割单词

            #define    ARRAY_LEN    10

            const    int    MAX_LEN=100;        

5.自顶向下、逐步求精的结构化程序设计方法

七.递归

1.从嵌套调用到递归调用

    递归调用:直接或间接调用自己。

2.递归是如何执行的

    汉诺塔(Hanoi)问题:

#include <stdio.h>
void Hanoi(int n,char a,char b,char c);
void Move(int n,char a,char b);
int main()
{
    int n;
    printf("Input the number of disks:");
    scanf("%d",&n);
    printf("steps of moving %d disks from A to B by means of C:\n",n);
    Hanoi(n,'A','B','C');
    return 0;
}
void Hanoi(int n,char a,char b,char c)
{
    if(n==1)
    {
       Move(n,a,b);
    }
    else
    {
        Hanoi(n-1,a,c,b);
        Move(n,a,b);
        Hanoi(n-1,c,b,a);
    }
}
void Move(int n,char a,char b)
{
    printf("Move %d:from %c to %c\n",n,a,b);
}

拓展:递归调用时的函数调用栈。

递归方法的优缺点:

优点:

    简单、直观、精炼,易编、易懂、逻辑清晰、可读性好,更符合人的思维习惯,逼近数学公式的表示。

缺点:

    函数调用开销大,耗费更多的时间和栈空间,时空效率偏低。

    易产生大量的重复计算。

3.尾递归是什么?(与普通递归的区别)
    在递归返回阶段直接返回给主函数。

4.变量的作用域
    局部变量与全局变量

5.变量的生存期

声明变量的存储类型:    存储类型    数据类型    变量名;

C存储类型关键字

    auto(自动变量)    //离开函数,值就消失

    static(静态变量)    //离开函数,值仍保留

    extern(外部变量)    

    register(寄存器变量)    //频繁访问的变量放到寄存器中,无需我们特别声明

6.分治与迭代

分治:分而治之

迭代:

7.多文件结构

    在本目录中新建一个.c文件就可以了

八、一堆数据

1.数组Array的定义和初始化

    保存大量同类型数据

    为什么数组下标从0开始?

        --使编译器的实现简化一点,且下标的运算速度少量提高。
不能用变量n声明数组,最好用宏定义

int a[5]={62,74,56,88,90};

int a[5]={62,74};

int a[ ]={62,74,56,88,90};

一维数组元素的赋值

二维数组第二位不能省略

2.向函数传递数组

    数组作为函数参数(call by value)与简单变量作为函数参数(call by reference)的区别

    **传递的是形参数组的首地址

#include <stdio.h>
#define N 40
int Average(int score[],int n);
void ReadScore(int score[],int n);

int main()
{
    int score[N],aver,n;
    printf("Input n:");
    scanf("%d",&n);
    ReadScore(score,n);
    //传入数组的第一个索引

    aver=Average(score,n);
    printf("Average score is %d\n",aver);
    return 0;
}

void ReadScore(int score[],int n)
{
    int i;
    printf("Input score:");
    for(i=0;i<n;i++)
    {
        scanf("%d",&score[i]);
    }
}

int Average(int score[],int n)
{
    int i,sum=0;
    for(i=0;i<n;i++)
    {
        sum+=score[i];
    }
    return sum/n;
}

#include <stdio.h>
#define N 40
int Average(int score[],int n);
int ReadScore(int score[]);
int main()
{
    int score[N],aver,n;

    n=ReadScore(score);
    //传入数组的第一个索引

    printf("Total students are %d\n",n);

    aver=Average(score,n);
    printf("Average score is %d\n",aver);
    return 0;
}
int ReadScore(int score[])
{
    int i=-1;
    do{
        i++;
        printf("Input score:");
        scanf("%d",&score[i]);
    }while(score[i]>=0);
    //输入负数结束
    return i;
}
int Average(int score[],int n)
{
    int i,sum=0;
    for(i=0;i<n;i++)
    {
        sum+=score[i];
    }
    return sum/n;
}

3.查找算法

  (1)查找最大值

  (2)线性查找LinSearch

(3)二分查找Binary Search(折半查找)

#include <stdio.h>
#define N 40
int ReadScore(long num[],int score[]);
int BinSearch(long num[],long x,int n);
int main()
{
    int score[N],n,pos;
    long num[N],x;
    n=ReadScore(num,score);
    //传入数组的第一个索引

    printf("Input the searching ID:");
    scanf("%ld",&x);
    pos=BinSearch(num,x,n);
    if(pos!=-1)
    {
        printf("score=%d\n",score[pos]);
    }
    else
    {
        printf("Not found!\n");
    }
    return 0;
}
int ReadScore(long num[],int score[])
{
    int i=-1;
    do{
        i++;
        printf("Input num,score:");
        scanf("%ld%d",&num[i],&score[i]);
    }while(score[i]>=0);
    //输入负数结束
    return i;
}
int BinSearch(long num[],long x,int n)
{
    int low=0,high=n-1,mid;
    while(low<=high)
    {
        mid=(high+low)/2;
        if(x>num[mid])
        {
            low=mid+1;
        }
        else if(x<num[mid])
        {
            high=mid-1;
        }
        else
        {
            return mid;
        }
    }
    return -1;
}

4.排序算法

(1)冒泡法排序    BubbleSort    外层n-1,内层n-i-1

#include <stdio.h>
#define N 40
int ReadScore(int score[]);
void BubbleSort(int score[],int n);

int main()
{
    int score[N],n,pos;
    long num[N],x;
    n=ReadScore(score);
    //传入数组的第一个索引

    BubbleSort(score,n);
    for(int i=0;i<n;i++)
    {
        printf("%d",score[i]);
    }
    return 0;
}

void BubbleSort(int score[],int n)
{
    int i,j,temp;
    for(i=0;i<n-1;i++)
    {
        for(j=1;j<n-i;j++)
        {
            if(score[j]<score[j-1])
            {
                temp=score[j];
                score[j]=score[j-1];
                score[j-1]=temp;
            }
        }
    }
}

int ReadScore(int score[])
{
    int i=-1;
    do{
        i++;
        printf("Input score:");
        scanf("%d",&score[i]);
    }while(score[i]>=0);
    //输入负数结束
    return i;
}

(2)交换排序    ChangeSort

#include <stdio.h>
#define N 40
int ReadScore(int score[]);
void ChangeSort(int score[],int n);

int main()
{
    int score[N],n,pos;
    long num[N],x;
    n=ReadScore(score);
    //传入数组的第一个索引

    ChangeSort(score,n);
    for(int i=0;i<n;i++)
    {
        printf("%d",score[i]);
    }
    return 0;
}

int ReadScore(int score[])
{
    int i=-1;
    do{
        i++;
        printf("Input score:");
        scanf("%d",&score[i]);
    }while(score[i]>=0);
    //输入负数结束
    return i;
}

void ChangeSort(int score[],int n)
{
    int i,j,temp;
    for(i=0;i<n-1;i++)
    {
        for(j=i+1;j<n;j++)
        {
            if(score[j]<score[i])
            {
                temp=score[j];
                score[j]=score[i];
                score[i]=temp;
            }
        }
    }
}

(3)选择法排序    

#include <stdio.h>
#define N 40
int ReadScore(int score[]);
void SelectionSort(int score[],int n);

int main()
{
    int score[N],n,pos;
    long num[N],x;
    n=ReadScore(score);
    //传入数组的第一个索引

    SelectionSort(score,n);
    //选择排序

    for(int i=0;i<n;i++)
    {
        printf("%d",score[i]);
    }
    return 0;
}

int ReadScore(int score[])
{
    int i=-1;
    do{
        i++;
        printf("Input score:");
        scanf("%d",&score[i]);
    }while(score[i]>=0);
    //输入负数结束
    return i;
}

void SelectionSort(int score[],int n)
{
    int i,j,k,temp;
    for(i=0;i<n-1;i++)
    {
        k=i;
        for(j=i+1;j<n;j++)
        {
            if(score[j]<score[k])
            {
                k=j;
            }
        }
        if(k!=i)
        {
            temp=score[k];
            score[k]=score[i];
            score[i]=temp;
        }
    }
}

九、指针

1.指针变量的定义、初始化及其解引用

    NULL是空指针,无效指针

声明指针时最好先赋值,如果不知道指向谁,则设置为NULL

2.指针变量作为函数参数

(1)参数传递方式

(2)典型实例--两数交换

3.函数指针及其应用

(1)什么是函数指针?

(2)函数指针的典型应用--通用的排序函数

(3)函数指针的典型应用--计算任意函数的定积分

4.数组的趣味应用

(1)筛法求素数

(2)文曲星猜数字游戏

(3)螺旋矩阵

十、字符串

1.字符串的存储与表示

(1)字符串的输入和输出

(2)字符串的表示与存储

2.字符串处理操作

3.向函数传递和从函数返回字符串

(1)向函数传递字符串

(2)从函数返回字符串

4.缓存区溢出与缓存区溢出攻击

如下:存在缓冲区溢出的代码

#include <stdio.h>
#include <string.h>
int main()
{
    char password[8]="secret",input[8];
    while(1)
    {
        printf("Enter your password:");
        gets(input);
        if(strcmp(input,password)==0)
        {
            printf("Welcome!\n");
            break;
        }
        else
        {
            printf("Sorry!\n");
        }
    }
    return 0;
}

安全的输入更改:

十一、指针的孪生兄弟

1.指针的算术运算

2、指针和一维数组间的关系

3、指针和二维数组间的关系

4.指针数组及其应用

(1)用指针数组表示多个字符串

(2)用指针数组表示命令行参数

十二--结构体

1.结构体类型

2、结构体与数组的嵌套

 

3、结构体的相关计算和操作

(1)结构体所占内存的字节数

(2)对结构体的操作

4.向参数传递一堆不同类型的数据

(1)结构体指针

(2)向函数传递结构体

5.枚举类型和共用体类型有什么不同

(1)枚举类型

(2)共用体类型

6.典型应用实例--洗发牌模拟

十三、内存

1.何为动态内存分配

(1)C程序的内存镜像

(2)动态内存分配函数

2.动态数组

(1)动态数组的特点及基本操作

(2)动态数组的创建

(3)动态数组的增长和释放

3.常见的内存错误及其解决对策

十四、结构设计的艺术

1.单向链表

(1)基本概念

2.其他数据结构简介

十五、学会保存数据(文件操作)

1.二进制文件与文本文件

2.文件的打开和关闭

3.格式化数据的文件读写

4.字符和字符串的文件读写

(1)按字符读写文件

(2)fgetc(),fputc(),feof()的程序实例

fputc()向文本中写文件

fgetc()从文本中读取文件,EFO为结束标识符

feof()判读是否到了文件尾

(3)feof()函数在应用中存在的问题原因分析

(4)按行读写文件

5.内存数据块的文件读写

6.随机读写与文件缓存

 

 

 

 

 

 

 

 




 

  • 14
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kerven_HKW

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值