头图

1. 运算符和表达式

1.1 赋值

左边的 = 右边的;
赋值的含义 是 将右边的值,存储到左边中。
左边必须是一个 变量。
右边可以是变量,也可以是常量,也可以是一个算式,最终是一个值。
int a = 0;
int b = 100;
a = b;
a = 200;
a = b+200;
复合赋值:
比如: a+=b; 等价于 a = a+b;

1.2 算术运算符

基本的:+ - * / %
自增自减:++ --
主要注意的重点:
/ 两个整数相除 只能得到整数部分

1.2.1 除法

/ 两个整数相除 只能得到整数部分

  有浮点数参与的除法,才能得到小数部分

图片.png

1.2.2 取模

% 获取余数 10%3 得到的余数是 1

   取模(取余)参与运算的数据只能是  整数
   10.8%3  这个语法是错误的

图片.png
图片.png

1.2.3 自增自减

前置还是后置的问题

#include <stdio.h>
#include <stdlib.h>
int main()
{
    //基本使用
    int nNum1 = 10;
    nNum1++;
    printf("%d\n", nNum1);
    int nNum2 = 10;
    ++nNum2;
    printf("%d\n", nNum2);
    //前置和后置有什么区别呢???
    //区别在于,自增的同时还要参与其他运算,
    //前置 是 先自增,再进行其他运算
    //后置 是 先参与其他运算,然后再自增
    //基本使用
    int nNum3 = 10;
    printf("%d\n", nNum3++);
    printf("%d\n", nNum3);
    int nNum4 = 10;
    printf("%d\n", ++nNum4);
    printf("%d\n", nNum4);
    //下面这个会输出什么
    int nNum5 = 10;
    printf("%d\n", nNum5--);
    printf("%d\n", --nNum5);
    printf("%d\n", nNum5);

    return 0;
}

1.3 取地址运算符

获取变量的地址
比如一个int变量是 4个字节 每个字节都有自己的地址,取地址符获取到的是 第1个字节的地址。

1.4 sizeof运算符

求变量或者某一个数据类型,所占用的字节数
图片.png

1.5 逗号运算符

起到了一个分隔的作用
逗号优先级最低
int a = 10,20; 运算完之后 a是10
int a = (10,20); 运算玩之后 a是20 为什么 因为 先算了逗号表达式的值是最右边的数值

1.6 优先级与结合性

图片.png
先算优先级高的,如果一样高,看结合性
3+5+8 先算左边,再算右边, 叫做左结合
c =100
a =b =c 先算右边

2. 数组

2.1 基本的定义和使用

相同数据类型的一个集合
定义方式:
数据类型 数组名[数组长度] = {,,,,,,,,,,};

#include <stdio.h>
#include <stdlib.h>
int main()
{
    //1. 定义数组
    //[]里面的数字,代表数组元素的个数(数组的长度)
    int arrTest[5] = { 10,20,30 };

    //2. 怎么使用数组
    //数组名[下标],此时[]中的数字,代表元素在数组中的位置
    //数组名[下标] 表示的是数组中的某一个元素
    //这个数组一共有5个元素,分别:
    //arrTest[0],arrTest[1],arrTest[2],arrTest[3],arrTest[4]
    //使用这些元素的时候,和普通int类型的变量是一样的。

    arrTest[0] = 100;
    arrTest[2] = arrTest[0];
    int a = 500;
    arrTest[3] = a;
    printf("%d", arrTest[3]);
    scanf_s("%d", &arrTest[3]);

    //3. 数组的初始化问题
    //不初始化是一个不好的习惯
    int arrTest2[5];
    //前3个元素 是10 20 30 后两个元素,自动初始化为0
    int arrTest3[5] = { 10,20,30 };
    //所有的元素都是0
    int arrTest4[5] = {};
    //4. 数组只能在初始化的时候,整体给数据
    //一旦错过了初始化,就只能一个元素一个元素的给数据
    //以下都是错的:
    //arrTest2 = { 1,2,3,4,5 };
    //arrTest2 = arrTest3;
    //arrTest2 = 0;
    //只能一个一个赋值了
    arrTest2[0] = 1;
    arrTest2[1] = 2;

    //5. 在数组写了初始化的情况下,数组的长度可以省略
    //这么写的话,相当于[]里面填充了一个 3
    //编译器会根据初始化元素的个数,自动推断出长度是3
    int arrTest5[] = { 10,20,30 };
    //int arrTest6[];不写长度的话,就必须初始化了

    //6. 定义数组的时候,长度只能是一个常量
    //   使用数组的时候,下标可以是常量,也可以是变量
    int n = 10;
    scanf_s("%d", &n);
    //int arrTest[n] = {};错误的,长度不能是变量
    int arrTest7[10] = {};
    //数组的下标可以是常量,也可以是变量,也可是是表达式
    n = 8;
    arrTest7[n - 5] = 0;
    arrTest7[n] = 0;
    arrTest[6] = 0;

    return 0;
}

2.2 数组在内存中的形式

图片.png

2.3 一些常见的数组相关的用语

遍历数组:
遍历是指数组中的元素 挨个访问一下,访问一下做什么,不一定。

数组的越界:
编译器不会检查数组的越界访问,但是越界访问是一个错误的事情。产生这样的错误,报错的位置距离错误的代码,有可能很远。这样的错误是非常难以寻找的。
而且 有可能报错,有可能不报错

#include <stdio.h>
#include <stdlib.h>
int main()
{
    int arrTest[5] = { 1,2,3,4 };
    arrTest[0] = 0x10;
    arrTest[1] = 0x20;
    arrTest[2] = 0x30;
    arrTest[3] = 0x40;
    arrTest[4] = 0x50;
    //arrTest[5] = 0x80;
    //arrTest[6] = 0x80;
    //arrTest[7] = 0x80;
    //arrTest[8] = 0x80;
    arrTest[9] = 0x80;
    return 0;
}

3. 字符数组

3.1 char类型数组

#include <stdio.h>
#include <stdlib.h>
int main()
{
    //普通用法,用于存储字符
    char arrTest1[5] = { 'a','b','c','d','e' };
    arrTest1[0] = 'm';
    //它的特殊用法
    //char arrTest2[5] = { "abcde" };
    char arrTest2[6] = { "abcde" }; //因为字符串结尾有一个0,所以是6个元素
    arrTest2[0] = 'm';
    printf("%s\n", arrTest1);
    arrTest1[3] = 0;
    printf("%s\n", arrTest1);
    printf("%s\n", arrTest2);

    return 0;
}

3.2 wchar_t类型

#include <stdio.h>
#include <stdlib.h>
int main()
{
    //普通用法,用于存储字符
    wchar_t arrTest1[5] = { L'a',L'b',L'c',L'd',L'e' };
    arrTest1[0] = L'm';
    //它的特殊用法
    //char arrTest2[5] = { "abcde" };
    wchar_t arrTest2[6] = { L"abcde" }; //因为字符串结尾有一个0,所以是6个元素
    arrTest2[0] = L'm';
    printf("%S\n", arrTest1);
    arrTest1[3] = 0;
    printf("%S\n", arrTest1);
    printf("%S\n", arrTest2);

    return 0;
}

3.3 关于字符串的输入

我们将字符串输入到数组中要注意安全版函数,需要一个长度。
数组名是数组的 起始地址。

#include <stdio.h>
#include <stdlib.h>
int main()
{

    char arrTest1[20] = { };
    //arrTest1就是代表数组的起始地址
    //数组名就是代表数组的起始地址。
    //arrTest1[1]这个代表的是数组的某一个元素
    scanf_s("%s", arrTest1, 20);
    return 0;
}

3.4 几个字符串处理函数

因为我们是借助于数组存储字符串的
数组不能赋值,也不能一次操作好多元素。所以C语言提供了一些字符串处理函数供我们使用
strlen 获取字符串长度
strcpy 字符串拷贝函数 相当于是赋值的感觉
strcat 字符串拼接
strcmp 比较两个字符串是否完全相同
设置使用非安全版函数的位置:

图片.png

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    char arrTest1[10] = { "hello" };
    char arrTest2[10] = {};
    int arrTest3[10] = {};

    int nLenth1 = 0;
    int nLenth2 = 0;
    int nLenth3 = 0;
    int nLenth4 = 0;
    //1.求字符串长度
    //  字符串长度指的是 字符串中除了结尾0之外的字符的个数。
    nLenth1 = strlen(arrTest1);
    printf("%d\n", nLenth1);
    //sizoef求得的就是数据类型占用的字节数
    nLenth2 = sizeof(arrTest1);
    printf("%d\n", nLenth2);
    nLenth3 = sizeof(arrTest3);
    printf("%d\n", nLenth3);
    //wcslen也是求字符串长度
    //字符串长度指的是 字符串中除了结尾0之外的字符的个数。
    wchar_t arrTest[10] = L"hello";
    nLenth4 = wcslen(arrTest);
    printf("%d\n", nLenth4);
    printf("%d\n", sizeof(arrTest));

    //2. 字符串拷贝函数
    char arrTest4[20] = {"Hello"};
    char arrTest5[20] = {"World"};
    char arrTest6[3] = {  };
    //假如我想要将arrTest4放到arrTest6
    //arrTest6 = arrTest4;//数组不能直接赋值
    //strcpy(arrTest6, arrTest4);//默认这个函数是不能用的
    //要求我们使用安全版函数
    //安全版函数,指的都是在处理字符串问题的时候,避免出现安全问题
    //比如  scanf_s 输入字符串的时候,需要加上一个  【缓冲区长度】
    //函数的作用,将右边缓冲区内的字符串拷贝到左边参数缓冲区中
    //strcpy_s(arrTest6, 3, arrTest4);
    //安全版和非安全版有什么区别呢????
    //3. 字符拼接函数
    //功能,就是将第三个参数代表的缓冲区拼接到第一个参数缓冲区字符串的后面去
    //拼接完了之后,就应该是HelloWorld
    strcat_s(arrTest4, 20, arrTest5);

    //4. 字符串比较函数
    //如果两个字符串相等,那么返回值是0
    //如果两个字符串不相等,那么返回值是非0(1或者-1)
    int n = strcmp(arrTest4, "HellWorld");


    return 0;
}

3.5 几个字符串处理函数

因为我们是借助于数组存储字符串的
数组不能赋值,也不能一次操作好多元素。所以C语言提供了一些字符串处理函数供我们使用
strlen 获取字符串长度
strcpy 字符串拷贝函数 相当于是赋值的感觉
strcat 字符串拼接
strcmp 比较两个字符串是否完全相同
设置使用非安全版函数的位置:
图片.png

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    char arrTest1[10] = { "hello" };
    char arrTest2[10] = {};
    int arrTest3[10] = {};

    int nLenth1 = 0;
    int nLenth2 = 0;
    int nLenth3 = 0;
    int nLenth4 = 0;
    //1.求字符串长度
    //  字符串长度指的是 字符串中除了结尾0之外的字符的个数。
    nLenth1 = strlen(arrTest1);
    printf("%d\n", nLenth1);
    //sizoef求得的就是数据类型占用的字节数
    nLenth2 = sizeof(arrTest1);
    printf("%d\n", nLenth2);
    nLenth3 = sizeof(arrTest3);
    printf("%d\n", nLenth3);
    //wcslen也是求字符串长度
    //字符串长度指的是 字符串中除了结尾0之外的字符的个数。
    wchar_t arrTest[10] = L"hello";
    nLenth4 = wcslen(arrTest);
    printf("%d\n", nLenth4);
    printf("%d\n", sizeof(arrTest));

    //2. 字符串拷贝函数
    char arrTest4[20] = {"Hello"};
    char arrTest5[20] = {"World"};
    char arrTest6[3] = {  };
    //假如我想要将arrTest4放到arrTest6
    //arrTest6 = arrTest4;//数组不能直接赋值
    //strcpy(arrTest6, arrTest4);//默认这个函数是不能用的
    //要求我们使用安全版函数
    //安全版函数,指的都是在处理字符串问题的时候,避免出现安全问题
    //比如  scanf_s 输入字符串的时候,需要加上一个  【缓冲区长度】
    //函数的作用,将右边缓冲区内的字符串拷贝到左边参数缓冲区中
    //strcpy_s(arrTest6, 3, arrTest4);
    //安全版和非安全版有什么区别呢????
    //3. 字符拼接函数
    //功能,就是将第三个参数代表的缓冲区拼接到第一个参数缓冲区字符串的后面去
    //拼接完了之后,就应该是HelloWorld
    strcat_s(arrTest4, 20, arrTest5);

    //4. 字符串比较函数
    //如果两个字符串相等,那么返回值是0
    //如果两个字符串不相等,那么返回值是非0(1或者-1)
    int n = strcmp(arrTest4, "HellWorld");


    return 0;
}

4. 三大结构与选择结构

#include <stdio.h>
int main()
{
    //1. 从键盘输入一个数,如果大于0,就输出yes,不大于0,就输出no
    //if (表达式)
    //{
    //    //语句序列
    //}
    //int nNum = 0;
    //printf("请输入一个整数:");
    //scanf_s("%d", &nNum);
    //if (nNum>0)
    //{
    //    printf("Yes");
    //}
    //if (nNum<=0)
    //{
    //    printf("No");
    //}
    //2. 请判断输入的一个整数是否能被2整除,能输出yes,不能输出no
    //if (表达式)
    //{
    //    //语句序列
    //}
    //else
    //{
    //    //语句序列
    //}
    //int nNum2 = 0;
    //printf("请输入一个数字:");
    //scanf_s("%d", &nNum2);
    //if (nNum2%2 == 0)
    //{
    //    printf("能整除");
    //}
    //else
    //{
    //    printf("不能整除");
    //}
    //3. 题目:
    //    请完这样一个功能,
    //    输入1~7之间的数字,
    //    输入几,就输出星期几
    //int nDay = 0;
    //printf("请输入1到7之间的数字:");
    //scanf_s("%d", &nDay);
    //if (nDay ==1)
    //{
    //    printf("星期一\n");
    //}
    //else if(nDay == 2)
    //{
    //    printf("星期二\n");
    //}
    //else if (nDay == 3)
    //{
    //    printf("星期三\n");
    //}
    //else if (nDay == 4)
    //{
    //    printf("星期四\n");
    //}
    //else if (nDay == 5)
    //{
    //    printf("星期五\n");
    //}
    //else if (nDay == 6)
    //{
    //    printf("星期六\n");
    //}
    //else if (nDay == 7)
    //{
    //    printf("星期日\n");
    //}
    //else
    //{
    //    printf("输入有误\n");
    //}
    //和单IF的区别在于,if-else 有一个进入了,就不会再判断其他的了
    //if (nDay == 1)
    //{
    //    printf("星期一\n");
    //}
    //if (nDay == 2)
    //{
    //    printf("星期二\n");
    //}
    //if (nDay == 3)
    //{
    //    printf("星期三\n");
    //}
    //if (nDay == 4)
    //{
    //    printf("星期四\n");
    //}
    //if (nDay == 5)
    //{
    //    printf("星期五\n");
    //}
    //if (nDay == 6)
    //{
    //    printf("星期六\n");
    //}
    //if (nDay == 7)
    //{
    //    printf("星期日\n");
    //}
    //4. switch-case结构
    int nDay = 0;
    printf("请输入1到7之间的数字:");
    scanf_s("%d", &nDay);
    switch (nDay)
    {
    case 1:
    {
        //假如这个case需要定义变量的话,必须在case中定义一个复合语句
        int a = 10;
        printf("星期一%d\n", a);
        break;
    }
    case 2:
        printf("星期二\n");
        break;
    case 3:
        printf("星期三\n");
        break;
    case 4:
        printf("星期四\n");
        break;
    case 5:
        printf("星期五\n");
        break;
    case 6:
        printf("星期六\n");
        break;
    case 7:
        printf("星期日\n");
        break;
    default:
        printf("输入有误\n");
        break;
    }

    return 0;
}

N 关于内存窗口

VS允许我们查看程序的内存,在调试状态下,可以调出内存窗口:

图片

图片

(持续更新,已更新至8月25日)C语言经典题集合


瞿小凯
1.3k 声望593 粉丝