zoukankan      html  css  js  c++  java
  • [啃书] 第2篇

    说在前面

    既然周末,就再来一篇吧,之后隔一天更一篇。

    本篇总结自《算法笔记》2.5-2.7

    正文

    知识点1:数组(一维)

    数据类型 数组名[数组大小]

    数组大小不能是变量,所以该定义要求定死了。

    数组初始化

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

    上方数组没有全部初始化,未初始化部分默认值为很大的随机数或0(看编译器不同赋值不同)。

    若完全不初始化如int a[10],数组中每个元素都可能是随机数,不一定默认为0。

    所以需要整个数组都赋初值为0,则只要把第一个赋为0即可,如int a[10] = {0};


    知识点2:冒泡排序

    总体说:进行n-1轮排序,忽略上一轮的最大值,每轮都把最大的“沉底”后移,其它的数像“冒泡”一样前移。

    具体说:

    比如5个数,从第1位第2位开始两两比较,前者大则交换,一直到第4位第5位比较算一轮,得到第5位为最大;

    继续下一轮两两比较不过到第3位和第4位比较完为止,因为第5位已经是最大值了;

    继续下一轮两两比较到第2位第3位为止,因为第4位也已经确定了;

    继续下一轮两两比较第1位第2位。

    程序员不知道这个就有点说不过去了,直接上代码吧


    知识点3:数组(二维)

    数据类型 数组名[第一维大小][第二维大小]

    数组初始化

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

    代码示例:两个数组对应值累加,存入第一个数组。

    输入两个3×3的矩阵,输出一个3×3的结果矩阵。

    注:如果数组长度过大超过106则将其定义在主函数外(静态存储区),否则在主函数中申明(系统栈)程序会异常退出。

    三维数组及更高维度的数组与二维类似,定义要三个[],赋值要三层循环。如int a[3][3][3];

    这一部分比较简单就不自己敲了,后面难的部分手打代码。


    知识点4:memset对数组每个元素赋相同值(需string.h头文件)

    memset(数组名, 值, sizeof(数组名));

    建议只赋值为0或-1(因为memset按字节赋值,组成int的四个字节会被赋成相同值,而0和-1的二进制补码全为0和1,不容易出错,如果赋别的数则会不准确,所以别的数用fill函数,后面会讲)

    memset速度快于fill


    知识点5:字符数组

    字符数组定义和初始化和普通数组一样

    char str[15] = {'G', 'o', 'o', 'd', '', 's', 't', 'o', 'r', 'y', '!'};

    也可以直接初始化字符串给字符数组(仅限初始化,其他地方赋值不行)

    char str[15] = "Good Story!"

    输入输出:

    scanf,getchar,gets

    printf,putchar,puts

    gets

    用来输入一行字符串;

    gets识别换行符 作为输入结束;

    若前面有整数等输入则要先使用getchar把换行符接受掉,再进行gets,否则读空了;

    存放于一维数组/二维数组的一维中;

    puts

    用来输出一行字符串;

    将一维数组/二维数组的一维输出在界面上(并拼上一个换行符);

    说明:二维字符数组可以当作字符串数组

    字符数组的存放方式

    一维字符数组/二维字符数组的二维末尾都有一个空字符表示存放字符串的结尾(作用是给puts和printf识别输出结束)

    特别注意1:

    的ASCII码为0即空字符NULL,占用一个字符位,因此开字符串数组要记得比字符串长度至少多1

    不是空格,空格的ASCII码是32,切勿混淆。

    特别注意2:

    scanf和gets输入的字符串自带,而getchar等其它方法得到的字符数组一定要自己在末尾加上否则乱码。


    知识点6:字符数组常用方法(string.h头文件)

    strlen(字符数组);

    返回第一个前字符的个数

    strcmp(字符数组1,字符数组2);

    返回两个字符串大小比较结果(字典序。正数:前者大,负数:前者小,零:一样大)

    strcpy(字符数组1,字符数组2);  

    2复制给1,包括也复制了

    strcat(字符数组1,字符数组2);

    2接到1后面


    知识点7:sscanf和sprintf(stdio.h)

    sscanf(str, "%d", &n);

    把字符数组str中的内容以%d的格式写到n中(从左到右)

    sprintf(str, "%d", n);

    把n以%d的格式写入到str字符数组中(从右到左)

    类比记忆:scanf相当于scanf(screen, "%d", &n)把屏幕内容输到n中,而sscanf则把screen变成了字符串,同样的类比printf。

    应用

    int n;
    double db; char str[100] = "2048:3.14,hello", str2[100] sscanf(str, "%d:%lf,%s", &n, &db, str2);
    //分别取到n=2048,db=3.14,str2=hello
    int n = 12;
    double db = 3.1415;
    char str[100], str2[100] = "good";
    sprintf(str, "%d:%.2f,%s", n, db, str2);
    //str得到12:3.14,good

    字符串处理问题的利器。 


    知识点8:函数

    返回类型 函数名称(参数类型 参数){
      函数主体
    }

    局部变量、形参只是实参的副本、int main()返回0在于告诉系统程序正常结束

    数组作为参数 void change(int a[], int b[][5]){ }

    函数的嵌套、递归


    知识点9:指针

    计算机中每个字节都有一个地址,指针可以理解为变量的地址。

    变量的地址一般是它占用的字节中第一个字节的地址(比如一个int占了四个字节,其中第一个字节的地址)

    对变量进行&取地址操作即可获得变量的地址。

    指针是一个unsigned类型的整数


    知识点10:指针变量

    用专门定义的类型来存放指针,

    int* p;
    double* p;
    char* p;
    int* p1, p2; //p1是int*型,p2是int型
    int *p1, *p2, *p3; //都是int*型
    int a; int* p = &a; //指针类型赋值
    int a; int* p; p = &a;//效果同上
    int a,b; int *p1 = &a, *p2 = &b;//多个指针变量初始化
    //星号可以跟着类型也可以贴着变量,除了多个定义时跟着变量,但具体是p存储了指针而不是*p
    //*p中的星号是找到p地址对应的变量,是一个对p的操作。
    //int* p中的星号则是和int构成一个int*指针类型,不是独立的。
    //所以为什么int* p更有利于理解而不是int *p
    //改变变量内容不影响地址

    对于int*型的指针变量p来说,p+1是指p所指的int型变量的下一个int型变量地址(跨越了一整个int型即4Byte,如果是double*型的指针变量p则跨越了一整个double型是8Byte)


    知识点11:指针与数组

    数组名称也作为数组的首地址使用,即 a==&a[0]

    *a表示数组第一个数

    *(a+1)表示数组第二个数(因为指针后移了再用星号取地址)

    *(a+i)表示数组第i-1个数

    示例代码:读取一整个数组并输出

    遍历数组(指针方法)

      

    指针的减法

     

    因为是int*型,所以距离以int为单位,输出5而不是20。


    知识点12:指针作函数参数

    #include<stdio.h>
    
    void change(int* p){
      *p = 233;
    }
    int main(){
      int a = 1;
      int* p = &a;
      change(p);
      printf("%d
    ", a);
      return 0;
    }

    输出结果:233

    传入了指针(p),通过指针把找到它所指向内容,把该内容(变量a)改变了。

    交换两个数(指针做参数)

    #include<stdio.h>
    
    void swap(int* a, int* b){
      int temp = *a; //temp是存放指针指向的内容的,所以是int型而不是int*型
      *a = *b;
      *b = temp;
    }
    
    int main(){
      int a = 1, b = 2;
      int *p1 = &a, *p2 = &b;
      swap(p1, p2);
      printf("a = %d, b = %d
    ", *p1, *p2);
      return 0;
    }

    常见错误1:int* temp没赋初值直接*temp = *a,错在没赋初值的指针可能会指向系统工作区。

    如果定义int* temp指针作为中间值,则使用*temp来暂存内容。

    则一定记得要指针变量要赋初值,写成如下

    常见错误2:int* temp直接暂存地址,把两个地址进行交换。

    错在传过来的指针类型(也就是变量的地址)是一个副本,我们现在拿到的是变量a,b的地址,所以我们可以去找到他们修改,就可以实现交换;而我们不知道地址的地址,即我们只知道地址的内容(副本),无法找到地址,也就无法修改地址,不能修改就无法交换地址。


     知识点13:引用

    给某变量起个别名,该别名同样能访问到这个变量。

    代替指针实现修改传入参数的功能,引用在实战中很常用。

    #include<stdio.h>
    
    void change(int &x){ //可以贴着int,也可贴着x(注意区分取地址符&)
      x=1;
    }
    
    int main(){
      int x = 10;
      change(x);
      printf("%d
    ", x);
      return 0;
    }

    输出结果:1

    应用:交换地址

    对指针的引用(对地址的引用,也就是给地址起个别名,可以直接访问到地址)

    #include<stdio.h>
    
    void swap(int* &p1, int* &p2){ //对int*型指针的引用
      int* temp = p1;
      p1 = p2;
      p2 = temp;
    }
    
    int main(){
      int a = 1, b = 2;
      int *p1 = &a, *p2 = &b;
      swap(p1, p2);
      printf("a = %d, b = %d
    ", *p1, *p2);
      return 0;
    }

    原理是因为,int*可以理解为unsigned int型,所以就像一个普通变量取地址一样,而这里的普通变量碰巧也是地址,也就是地址的地址。


    有点长了,分开再写一篇吧。

    第二章剩下结构体、补充内容及黑盒测试,下一篇继续。

    加油。

  • 相关阅读:
    Educational Codeforces Round 85 D. Minimum Euler Cycle(模拟/数学/图)
    Educational Codeforces Round 85 C. Circle of Monsters(贪心)
    NOIP 2017 提高组 DAY1 T1小凯的疑惑(二元一次不定方程)
    Educational Codeforces Round 85 B. Middle Class(排序/贪心/水题)
    Educational Codeforces Round 85 A. Level Statistics(水题)
    IOS中的三大事件
    用Quartz 2D画小黄人
    strong、weak、copy、assign 在命名属性时候怎么用
    用代码生成UINavigationController 与UITabBarController相结合的简单QQ框架(部分)
    Attempting to badge the application icon but haven't received permission from the user to badge the application错误解决办法
  • 原文地址:https://www.cnblogs.com/cc1997/p/12943864.html
Copyright © 2011-2022 走看看