首页 > 代码库 > 复习C语言:第一章

复习C语言:第一章

  复习C语言中的5中基本类型,以及各个类型占用了多少个字节:

#include <stdio.h>int main(void) {    printf("int=%d\n", sizeof(short int));    printf("int=%d\n", sizeof(int));    printf("int=%d\n", sizeof(long int));    printf("char=%d\n", sizeof(char));    printf("float=%d\n", sizeof(float));    printf("float=%d\n", sizeof(double));    return 0;}

技术分享

 

 

 

   复习数组, 常量指针, 变量指针, 常量指针的指向地址是不能改变的, 但是变量指针的指向地址是可以改变的:

#include <stdio.h>int main() {    int i;    //a为常量指针    int a[] = {4,5,6,7};    int len = sizeof(a)/sizeof(a[0]);    //循环数组,并获取数组中的值;    for(i=0 ;i<len; i++) {        printf("%d\n",a[i]);    };    for(i=0 ;i<len; i++) {        printf("%d\n",*(a+i));    };    //定义一个指针, 指向数组, 此时的指针pa为变量指针    int* pa;    pa = a;    for(i=0 ;i<len; i++) {        printf("%d\n", pa[i]);    }    for(i=0 ;i<len; i++) {        printf("%d\n", *(pa+i));    }    //让指针 pa++ ,输出数组的指针    printf("%d\n", *(pa++));    //让数组 a++ ,输出结果, 会报错, 因为a是常量指针, 无法改变的;    //printf("%d\n", a++);    return 0;}

   通过指针修改数组, 和直接修改数组的方式:

#include <stdio.h>int main() {    int ar[] = {1,2,3,4};    int* p;    p = ar;    //*p = 0; //*p指向p的第一个元素;    p[0] = 0; //这个上一行的代码效果一模一样;    //*(p+1) = 0; //这一行和上面一行效果也是一样的    p[1] = 0;    printf("%d\n",ar[0]);    printf("%d\n",ar[1]);    return 0;}

  在调用函数的时候,可以传值:

#include <stdio.h>void Exchg1(int x, int y){    int tmp;    tmp=x;    x=y;    y=tmp;    printf("x=%d,y=%d\n",x,y);}int main(){    int a=4,b=6;    Exchg1 (a,b) ;    printf("a=%d,b=%d\n",a,b);    return 0;}

  也可以传指针, 指针的话就变成后面的回调函数了: 

#include <stdio.h>void Exchg2(int *px, int *py){    int tmp=*px;    *px=*py;    *py=tmp;    printf("*px=%d,*py=%d\n",*px,*py);}int main(){    int a=4;    int b=6;    Exchg2( &a,&b);    printf("a=%d,b=%d\n", a, b);    return 0;}

  指针是c中的一大玩点,  但是指针终究是指针 , 如果参数为一个数组, 指针是无法获取到指针对应的值的长度的, 所以要把数组给一个函数, 都要把数组的长度作为参数传递?这个有待考证

#include <stdio.h>void run(int *p, int *p1) {    printf("p 的长度是%d\n", (int)sizeof(*p));}int main() {    int a[] = {1,2,3,4,5,6,7,8};    run(a, b);    printf("a 的长度是 : %d\n", (int)sizeof(a));    return 0;}//输出://p 的长度是 : 4//a 的长度是 : 32
#include <stdio.h>//float average( int*p 一样 ,int len) {float average( int a[] ,int len) {    float val;    int sum = 0;    //printf("%d\n", a);    for(int i=0; a[i]!=9999; i++) {        printf("%d\n", a[i]);    };    a[0] = 9;    return  val;}int main() {    int x[] = {1,2,3,4,5,6,7,8,9,10,9999};    float av;    //c语言中的指针不带有长度信息, 必须把长度作为参数;    av = average(x, sizeof(x)/4);    printf("%d\n", x[0]);    return 0;}

  定义数组的变量,即为这个数组的首地址, 把数组作为参数的时候, 被调用的函数中的参数为这个数字的引用:

#include <stdio.h>void average( int a[] ) {    a[0] = 9;}int main() {    int x[] = {1,2,3,4,5,6,7,8,9,10,9999};    average(x);    //x的第一个值是 : 9    printf("x的第一个值是 : %d", x[0]);    return 0;}

  接受参数的时候, 可以定义一个数组作为形参数:

#include <stdio.h>void average( int* p ) {    p[0] = 9;}int main() {    int x[] = {1,2,3,4,5,6,7,8,9,10,9999};    average(x);    //输出:x的第一个值是 : 9    printf("x的第一个值是 : %d", x[0]);    return 0;}

  一个字符或者数字只是一个变量, 把以上两种类型作为参数的时候, 实际上传递的只是一个原始值的复制品:

#include <stdio.h>void test( int p ) {    p = 9;}int main() {    int x = 0;    test(x);    //输出:x的第一个值是 : 0    printf("x的值是 : %d", x);    return 0;}

  也可以把字符或者数字作为一个指针,传递给函数, 函数定义的时候接收, 在调用的函数中修改指针, 对应的变量会发生改变:

#include <stdio.h>void test( int* p ) {    *p = 9;}int main() {    int x = 0;    test(&x);    //输出:x的第一个值是 : 9    printf("x的值是 : %d", x);    return 0;}

   搞笑的数组和指针:

#include <stdio.h>int main() {    int a[10];    int *p;    int i;    for(p = a; p<a+10; p++){        printf("p is %d \n", p);    }    return 0;}

 

  循环输入学生的分数,冒泡排序以后重新输出分数, malloc(Byte):

#include <stdlib.h>#include <stdio.h>void sort( int *s , int len) {    int i = 0, j = 0;    //冒泡排序    for(i=0; i<len; i++) {        for(j=i; j<len; j++) {            if( s+j>s+i ) {                int temp = 0;                temp = *(s+i);                *(s+i) = *(s+j);                *(s+j) = temp;            }        }    }}int main() {    int *a , j , n;    scanf("%d\n",&n);    a = (int *)malloc(10);    for(j=0; j<n; j++) {        scanf("%d",a+j);    }    printf("puts trings\n");    sort(a, n);    for(j=0; j<n; j++) {        printf("%d\n",*(a+j));    }    free(a);    return 0;}

  实现一个命令行的投票功能, 输入li或者zhang, 投的票数会自动增加 :

#include <stdio.h>#include <string.h>struct per {    char name[20];    int count;}leader[2] = {{"li",0},{"zhang",0}};int main() {    int i , j;    int p;    char name[20];    printf("enter ‘li‘ or ‘zhang‘ : \n");    for(i = 0; i<6; i++) {        scanf("%s\n", name);        for(j = 0; j<2; j++) {            if(strcmp(leader[j].name, name) == 0) {                leader[j].count = leader[j].count+1;            };        }    }    for(i = 0; i<2 ; i++) {        printf("user %s, count is %d\n", leader[i].name, leader[i].count);    }    return 0;}

技术分享

  

  字符串的复制需要strcpy, 原始类型的复制可以使用左值直接赋值:

#include <stdio.h>#include <string.h>struct st{    char name[10];    int age;}s2;int main() {    char c[] = "abcd";    char b[4];    strcpy(b,c);    printf("string is : %s\n",b);    struct st s1 = {"nono",28};    s2.age = s1.age;    printf("s2 age is : %d\n", s2.age);    strcpy(s2.name, s1.name);    printf("s2 name is : %s\n", s2.name);    return 0;}

  技术分享

  利用结构体实现简易的用户查询系统,  包含用户的添加以及查询:

#include <stdio.h>#include <string.h>#include <stdlib.h>struct user{    int id;    char name[20];    char descript[20];}s[20];//预置20个用户int count = 0;void find() {    printf("please to enter user id:\n");    int id = 0, i;    scanf("%d", &id);    for(i=0 ;i <count; i++) {        if(s[i].id == id) {            printf("user id is %d\n user name is %s \nuser desciprtion %s\n", s[i].id, s[i].name, s[i].descript);        }    }}void all() {    int i = 0;    for(i=0 ; i<count; i++) {        printf("user name : %d\n", s[i].id );        printf("user name : %s\n", s[i].name );        printf("user desciprtion : %s\n", s[i].descript );    }}void add() {    char name[20];    char descript[20];    printf("input user name :\n");    scanf("%s",name);    printf("input user desciprtion:\n");    scanf("%s",descript);    user s1; //= { count , *name, *descript};    s1.id = count;    strcpy(s1.name, name);    strcpy(s1.descript, descript);    s[count] = s1;    count++;}int main() {    //用户的输入:    char ipt[10];    //循环获取用户的输入    printf("%d\n", (int)(sizeof(s)/sizeof(s[0])));    while(1) {        printf("\n\n\n\n输入查询:\n ");        printf("查询所有输入:all \n 增加用户输入:add\n 查询详细输入:find\n");        //获取用的输入        scanf("%s", ipt);        printf("%s", ipt);        //查看所有的用户        if(strcmp(ipt, "all")==0) {            all();        }        //增加一个用户        if(strcmp(ipt,"add")==0) {            add();        }        //根据用户ID, 返回查询用户消息        if(strcmp(ipt,"find")==0) {            find();        }    }    return 0;}

   内存管理(MM), 通过malloc申请内存,以及使用free返还内存:

#include <stdio.h>#include <stdlib.h>int main() {    char *p;    p = (char *)malloc(8);    int i;    for(i=0; i<8; i++) {        p[i] = i;    }    for(i=0; i<8; i++) {        printf("address is %p;content is %c\n",&p[i],p[i]);    }    free(p);    return 0;}

 

#include <stdio.h>#include <stdlib.h>int main() {    char *p;    p = (char *)malloc(8);    int i;    for(i=0; i<8; i++) {        p[i] = i;    }    for(i=0; i<8; i++) {        printf("address is %p;content is %c\n",&p[i],p[i]);    }    free(p);    return 0;}

 

  买车的实现:

#include <stdio.h>#include <string.h>#include <stdlib.h>struct car{    char maker[10];    int deposit;};struct people{    char name[10];    int deposit;    car *c;};void buy(people *p) {    car *c = (car *)malloc(sizeof(car));    strcpy(c->maker, "bench");    c->deposit = 10;    p->deposit -= c->deposit;    p->c = c;;}void discard(people *p) {    free(p->c);    p->c = NULL;}int main() {    people p = {"nono",100,NULL};    printf("people name is : %s\n", p.name);    printf("people deposit is : %d\n", p.deposit);    buy(&p);    printf("after buy it , people deposit is : %d\n", p.deposit);    printf("%s has a car, the car name is %s\n",p.name, p.c->maker);    discard(&p);    return 0;}

技术分享

  链表的使用, 链表和数组的区别以及各自不同的使用场景,有头节点和无头节点的区别和区别:

  链表是动态生成的, 可控性比数组好非常多, 数组的长度是固定的,但是链表可以无限延长, 对于链表的操作也比较灵活, 可以往链表的中间插入数据, 但是数组的插入是非常繁琐的;

  有头链表保障了链表起码有一个开始, 对于数据的操作更灵活, 无头链表必须保证,头部有一个数据, 否者无法做后续操作:

#include <stdio.h>#include <string.h>#include <stdlib.h>/**网吧用户管理系统*/struct User {    //用户名    char name[10];    //用户密码    char pass[10];    //用户金额    int deposit;    User* next;};//察看所有void showAll(User *user) {    User *curr = user;    while(curr->next) {        curr = curr->next;        printf("user : %s\ndeposit:%d\n",curr->name,curr->deposit);    }}//添加用户void add(User *user) {    //局部创建的变量, 在离开该函数的作用域后, 会被自动清空;    char name[10];    char pass[10];    int deposit = 0;    printf("please enter user name :\n");    scanf("%s",name);    printf("please enter user pass :\n");    scanf("%s",pass);    printf("please enter user deposit :\n");    scanf("%d",&deposit);    //必须使用MM申请空间, 然后再往user下添加数据    User *u = (User*)malloc(sizeof(User));    u->deposit = deposit;    strcpy(u->name, name);    strcpy(u->pass, pass);    u->next = NULL;    //循环,直到,user没有下一个数据;    while(user->next){        user = user->next;        printf("find next\n");    };    user->next = u;    //printf("next is :%p\n",user->next);}void find(User *user) {    char name[10];    printf("enter user name to find : \n");    scanf("%s", name);    User *curr = user;    while(curr->next) {        if( strcmp(curr->next->name, name) == 0 ) {            printf("user is %s\ndeposit is %d\n", curr->next->name, curr->next->deposit);            return ;        }        curr = curr->next;    }}//删除用户void remove(User *user) {    char name[10];    printf("enter user name to rmove : \n");    //数组的话只要传name,因为name本来就是一个地址    //字符和数字要加&因为,他们本身是数据,要根据地址改数据;    scanf("%s", name);    User* curr = user->next;    while( curr->next ) {        if( strcmp(curr->next->name, name) == 0 ) {            User *now = curr->next;            curr->next = now->next;            free(now);            printf("removed\n");            return ;        }        user = user->next;     }}int main() {    User user = {"","",0,NULL};    char  cmdline[10];    while(1) {        //输出查看,添加,删除命令        printf("查看所有:all\n添加用户:add\n删除用户:remove\n查找用户信息:find\n");        scanf("%s",cmdline);        printf("you are enter : %s\n", cmdline);        //如果是察看        if(strcmp("all",cmdline) == 0) {            showAll(&user);        };        //如果是添加        if(strcmp("add",cmdline)==0) {            add(&user);        }        //如果是删除        if(strcmp("remove",cmdline)==0) {            remove(&user);        }        //如果是删除        if(strcmp("find",cmdline)==0) {            find(&user);        }    }        return 0;}

  引用相关, 定义一个引用的时候, 必须初始化, 但是定义指针不要强制初始化, 定义完毕引用以后,无法解绑,被强制绑定, 无法重新赋值 :

#include <stdio.h>struct stu {    char name[16];    int age;};int main() {    //refference引用是强化版的指针    int a = 100;    //定义一个引用的时候, 必须初始化, 但是定义指针不要强制初始化    //定义完毕引用以后,无法解绑,被强制绑定, 无法重新赋值    int&b = a;    printf("b = %d, address : %p\n", b,&b);    printf("a = %d, address : %p", a,&a);    stu s = {"nono",10};    stu& s1 = s;    printf("把s1的age改成100");    s1.age = 100;    printf("s的age is %d\n", s.age);    return 0;}

   引用可以作为返回值:

#include <stdio.h>int b = 1000;int& test() {    //如果我把b定义在test函数内部, 会报错, 因为函数执行完毕以后, 内部的所有变量都会被销毁;    int& a = b;    return a;}int main() {    int& a = test();    printf("The a is %d\n", a);    return 0;}

  可以把引用作为返回值, 但是这种写法不太好阅读, 不方便阅读理解:

#include <stdio.h>int number = 0;int& test() {    return number;}int main() {    test() = 4;    printf("%d\n", number);    return 0;}

 

    

  done

  参考:

复习C语言:第一章