语法技巧与注意事项

  1. 二维数组行列均从0开始,先行后列

  2. 转置二维数组时只遍历上三角阵,如if(i<=j)和for(j=i;j<n;j++)

  3. 按矩阵输出,外循环内要包含换行

  4. 输入字符串以回车结尾时,

    1
    2
    while((name[n]=getchar())!='\n')n++; 
    name[n]='\0';
  5. str[i]-'0'将数字字符转换成数字

  6. gets()能读空格,gets(str);
    scanf("%s",str);不能读空格
    puts()输出字符串后会自动换行,而printf("%s",str);不会自动换行

  7. 用C++有关东西的时候头文件得包括这些

    1
    2
    #include <iostream> 
    using namespace std;
  8. #define For(x,a,b) for(x=a;x<=b;x++)
    方便的宏定义函数

  9. int *p=&i;等价于int i,*p; p=&i;

  10. 自定义函数在传递参数时,数组的实参是a,形参是a[]

  11. int a[100],*p;p=a;p=&a[0];等价;同理,p=a+1;p=&a[1];等价

  12. 以下语句对数组求和

    1
    2
    3
    4
    sum=0; 
    for(p=a;p<=&a[99];p++)
    (也可写作p<=a+99)
    sum+=*p;

    或:

    1
    2
    for(i=0;i<100;i++) 
    sum+=*(a+i);

    或:

    1
    2
    3
    4
    p=a; 
    sum=0;
    for(i=0;i<100;++i)
    sum+=p[i];
  13. 两个相同类型的指针相减,表示他们之间相隔的数组元素数目;两个指针不能相加、相乘或相除

  14. 自定义函数的函数声明里面int a[]等价于int*a

  15. pow(double,int),是求一个double的数的int次方

  16. 最后用指针回传某种特定的字符串的时候,要逐位复制

  17. int a[10(可省略)]={1,2,3};
    char b[10(可省略)]={"Happy"};
    char b[10]="Happy";

  18. 指针传回东西的时候要用*m(指针)=p(要传的东西)

  19. system("CLS");用于清屏;对于Windows来说使用DOS命令,DOS不区分大小写即可以写成cls;对于Linux来说区分大小写。

  20. size_t和unsigned int
        size_t是一些C/C++标准在stddef.h中定义的。这个类型足以用来表示对象的大小。size_t的真实类型与操作系统有关。
    在32位架构中被普遍定义为:
    typedef   unsigned int size_t;
    而在64位架构中被定义为:
    typedef  unsigned long size_t;
        size_t在32位架构上是4字节,在64位架构上是8字节,在不同架构上进行编译时需要注意这个问题。而int在不同架构下都是4字节,与size_t不同;且int为带符号数,size_t为无符号数。
    为什么有时候不用int,而是用size_type或者size_t:
       与int固定四个字节不同有所不同,size_t的取值range是目标平台下最大可能的数组尺寸,一些平台下size_t的范围小于int的正数范围,又或者大于unsigned int. 使用Int既有可能浪费,又有可能范围不够大。

  21. 布尔类型(bool)
    布尔类型只有两个值,false和true,通常用来判断条件是否成立。如果变量值为 0 就是 false,否则为 true,布尔变量只有这两个值。如:
      例1:bool pb= -1.5; // pb=true;
      例2:bool pt=0; // pt=false;

  22. vector是向量类型,可以容纳许多类型的数据,因此也被称为容器(可以理解为动态数组,是封装好了的类)。进行vector操作前应添加头文件#include <vector>
    vector初始化:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    1. //定义具有10个整型元素的向量(尖括号为元素类型名,它可以是任何合法的数据类型),不具有初值,其值不确定
    vector<int>a(10);
    2. //定义具有10个整型元素的向量,且给出的每个元素初值为1
    vector<int>a(10,1);
    3. //用向量b给向量a赋值,a的值完全等价于b的值
    vector<int>a(b);
    4. //将向量b中从0-2(共三个)的元素赋值给a,a的类型为int型
    vector<int>a(b.begin(),b.begin+3);
    5. //从数组中获得初值
    int b[7]={1,2,3,4,5,6,7};
    vector<int> a(b,b+7);
  23. C语言计算算法运行时间:C/C++中的计时函数是clock(),而与其相关的数据类型是clock_t(一个长整型数)。
    CLOCKS_PER_SEC:标准C的time.h头函数中宏定义的一个常数,表示一秒钟内CPU运行的时钟周期数,用于将clock()函数的结果转化为以秒为单位的量,但是这个量的具体值是与操作系统相关的。
    应用举例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
      int main( void )  
    {
    long i = 10000000L;
    clock_t start, finish;
    double duration;
    /* 测量一个事件持续的时间*/
    printf( "Time to do %ld empty loops is ", i );
    start = clock();
    while( i-- ) ;
    finish = clock();
    duration = (double)(finish - start) / CLOCKS_PER_SEC;
    printf( "%f seconds\n", duration );
    system("pause");
    }
  24. 按位与(&)和,或(丨),异或(^)运算都是属于位运算符
    是在二进制形式上进行的运算符
    ①按位与运算:同1则1。
    只有当两个二进制数同位上的都是1时才可以为1,否则为0。例子↓
    与(&)运算:
    1010      
    0110      
    结果:0010
    ②按位或运算:同0则0。
    只有当两个二进制数同位上的都是0时才是0,否则为1。例子↓
    或(丨)运算:
    1010
    0110
    结果:1110
    ③按位异或运算:相同则0,不同则1。
    只有当同位上的两个数都同时为1或者为0时结果是0,否则为1例子↓
    异或运算(^):  
    1010       0110
    1110       1100
    结果:0100       1010

  25. 动态分配内存相关
    malloc: void *malloc (unsigned size) 动态分配一长度为size的连续空间,成功则返回起始地址的指针,失败则返回NULL。
    例如:

    1
    2
    int *p;
    if((p=(int *)malloc(n*sizeof(int)))==NULL) exit(1);

    calloc: void *calloc (unsigned n, unsigned size) 分配n个连续空间,长度为size,并且之后还把存储块里全部初始化位0。申请成功失败与malloc相同。
    例如:

    1
    2
    char *q;
    if((q=(char *)calloc(n,sizeof(char)))==NULL) exit(1);

    分配的时候有些情况下一定要记得+1,比如给字符串最后放’\0’的空间,如果没有+1就会导致’\0’没地方放,从而导致字符串处理出错,如输出时无法正常结束,调试时提示Program received signal SIGTRAP, Trace/breakpoint trap.等等。
    同时,len*sizeof(char)+1len*(sizeof(char)+1)是一样的,因为sizeof(char)=1,即char只占一个字节(8个二进制位),int啥的就不一样了。

  26. strstr(str1,str2)函数用于判断字符串str2是否是str1的子串。如果是,则该函数返回str1字符串从str2第一次出现的位置开始到str1结尾的字符串;否则,返回NULL。

  27. 一种连接两个数字的小技巧
    a>>2是指将a所对应的二进制数向右移位2位(a可以是字符,数字等)(其实字符也算一种数字?只不过是字符的呈现形式),前面空余出来的地方补0,即原本10100111向右移位两位后变为00101001;同理,a<<3是将a所对应的二进制数向左移3位,后面多出来的部分补零,即10100111变为1010011100(当特殊情况时丢弃前几位,如本来它只能存储八位,这下前几位越界了,就只能把前几位丢掉了)
    之前在24条处学习了与运算、或运算,在这里也有很大的用处。&,按位与,可以把两个数或者字符等的二进制数字按位取与。于是,可以使用这种方法取出两者中的一者的二进制数的后几位。比如a=77,其对应二进制数为01001101;0x3是16进制数字,对应二进制数为00000011。那么,运行a & 0x3,也就是01001101&00000011,由于0与1或0取与均为0,所以就可以得到a的二进制字符的后两位,即00000001。同理,a & 0xf就是01001101&00001111,也就是将a的后四位取出来,即00001101。然后,我们再使用移位符……比如(a & 0xf)<<4呢?当然是能得到000011010000了,暂时不看前面的无用的0(起码在这里无用),就成了11010000了。这看似并没有什么用处。但是,再加上或运算呢?就可以把两个二进制数首尾拼接起来了啊。比如a=01001101,b=11101001,现在要取a的后两位和b的前六位重新组合形成一个二进制数,就要先使用a & 0x3取出最后两位,然后(a & 0x3)<<6为后面留出一个六位的空间,随后再取出b的前六位,即b>>2,最后两位就没了,b被它的前六位覆盖。随后使用(a & 0x3)<<6 | b>>2,即可把二者和为一体。
    总的来说,&负责取出数字的后几位,<<负责移动数字为待拼接的数字腾出空间,|则负责拼接数字。

  28. getchar()getch()的区别:
    getchar();从键盘读取一个字符并输出,该函数的返回值是输入第一个字符的ASCII码;若用户输入的是一连串字符,函数直到用户输入回车时结束,输入的字符连同回车一起存入键盘缓冲区。若程序中有后继的getchar();函数,则直接从缓冲区逐个读取已输入的字符并输出,直到缓冲区为空时才重新读取用户的键盘输入。
    getch();接受一个任意键的输入,不用按回车就返回。该函数的返回值是所输入字符的ASCII码,且该函数的输入不会自动显示在屏幕上,需要putchar();函数输出显示。getch();函数常用于中途暂停程序方便调试和查看。
    getchar();getch();的另一个区别就是所需要包含的头文件不同。
    getchar();#include<stdio.h>
    getch();#include<conio.h>

  29. 在Windows下,方向键由两个字节组成,分别为:’\244’和
    ‘\72’ up
    ‘\80’ down
    ‘\75’ left
    ‘\77’ right

  30. 波兰数学家Jan Lukasiewicz提出了另一种数学表示法——波兰表达式,它有两种表示形式:
    把运算符写在操作数之前,称为波兰表达式(Polish Expression)或前缀表达式(Prefix Expression),如+AB;把运算符写在操作数之后,称为逆波兰表达式(Reverse Polish Expression)或后缀表达式(Suffix Expression),如AB+;前后缀表达式的出现是为了方便计算机处理,它的运算符是按照一定的顺序出现,所以求值过程中并不需要使用括号来指定运算顺序,也不需要考虑运算符号(比如加减乘除)的优先级。
    先介绍中简单的人工转化方法:
    假设有一个中缀表达式a+b*c-(d+e)
    ①首先将这个中缀表达式的所有运算加括号((a+(b*c))-(d+e))
    ②然后将所有运算符放到括号后面,这样就变成了((a(bc)*)+(de)+)-
    ③把所有括号去掉abc*+de+-,最后得出的结果就是后缀表达式。

  31. 为一个n×m的二维数组分配动态内存
    首先需要注意的是,不要这样一次性分配为数组内存空间:
    int **arr = (int**)malloc(n *m * sizeof(int));
    正确的做法是先分配行,再分配列。释放内存的时候,也要先释放列,再释放行。
    注意,顺序反了的话,会把列的地址擦除,导致释放列时内存时找不到地址,程序崩溃。
    正确的分配空间代码如下:

    1
    2
    3
    int **arr = (int **)malloc(n*sizeof(int *));
    for(i=0;i<n;i++)
    arr[i] = (int *)malloc(m*sizeof(int));

    正确的释放空间代码如下:

    1
    2
    3
    for(i=0;i<n;i++)
    free(arr[i]);/*释放列*/
    free(arr);/*释放行*/

    注:这种分配方式得到的其实并不是真正意义上的二维数组,因为其行与行之间的内存并不连续,虽然可以用下标arr[i][j]的方式访问,但当用指向该二维数组的指针来访问时候,不能通过指针值的增加来跨行获取元素,不过这种情况一般用的也不多,因此上述分配方式在大多数情况下的操作都能得到正确的结果。

  32. 记录一些没见过的ASCII码(以下记录的均为十进制)。
    ESC:27
    Backspace:8
    方向键:由两个ASCII码组成,具体见29
    Shift:19
    CapsLock:20
    Tab:9
    Enter:13

  33. 转义字符
    \a 响铃(BEL) 007
    \b 退格(BS) 008
    \f 换页(FF) 012
    \n 换行(LF) 010
    \r 回车(CR) 013
    \t 水平制表(表示空四个字符,也称缩进,相当于按一下Tab键)(HT) 009
    \v 垂直制表(VT) 011
    \\ 反斜杠 092
    \' 单引号字符 039
    \" 双引号字符 034
    \0 空字符(NULL) 000
    \ddd 任意字符 三位八进制
    \xhh 任意字符 二位十六进制

  34. 文件打开方式r+与a+的区别
    如果仅仅是读:r+就可以读取到原文件内容(使用read);a+是追加模式,读的时候是将指针已经放在文件末尾了,所以读取到的文件是空的。
    如果仅仅是写:r+是从头开始写的,你写了多少就会覆盖原文件多少;a+因为指针已经放在文件末尾了,所以你写的时候就是追加在后面的。
    如果是先读在写:这样就有点麻烦了。r+当你使用read读完之后再使用write写的时候,指针已经在文件末尾了,所以你再写的时候就感觉是追加在末尾似的。a+因为你先读的时候指针已经在末尾了,读不到任何内容。

  35. 以w方式打开已存在的文件然后不做改动再直接关闭,会清除文件的全部内容。

  36. scanf和fscanf使用%s读取字符串时,能读取中文,但是不能读取空格。

  37. #ifndef是”if not defined”的简写,是宏定义的一种,它是可以根据是否已经定义了一个变量来进行分支选择,一般用于调试等。
    #ifndef 标识1 //判断”标识1”是否定义,如果被定义则返回假,如果没有被定义则返回真。
    例如:
    语句1 #ifndef 标识1
    语句2 #define 标识1
    语句3 #endif
    语句4 ……
    语句5 ……
    该段代码意思是:如果标识1没有被定义,则重定义标识1,即执行语句2、语句3;如果标识1已经被定义,则直接跳过语句2、语句3,直接执行语句4、语句5、……
    备注:#ifndef#endif 要一起使用,如果丢失#endif,可能会报错。

  38. typedef为C语言的关键字,作用是为一种数据类型定义一个新名字。这里的数据类型包括内部数据类型(int,char等)和自定义的数据类型(struct等)。
    在编程中使用typedef目的一般有两个,一个是给变量一个易记且意义明确的新名字,另一个是简化一些比较复杂的类型声明。
    例如:

    1
    2
    3
    typedef char Line[81];
    Line text,line;
    getline(text);

    相当于

    1
    2
    char line[81];
    char text[81];
  39. i++是先赋值,然后再自增;++i是先自增,后赋值。
    用代码表示就是:
    a = i++;则等价于 a=i;i=i+1;
    a = ++i;则等价于 i=i+1;a=i;

Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2020-2024 Minato Xeon Microsoft
  • Visitors: | Views:

别和金钱过不去。

支付宝
微信