栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C语言笔记(入门)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C语言笔记(入门)

C语言笔记 基础知识 特点
  • 计算机语言:用于人和计算机交流信息,是计算机和人都能识别的语言(机器语言 > 汇编语言 > 高级语言)
  • C语言特点:兼顾了高级语言和汇编语言的特点,简洁、丰富、可移植,程序执行效率高。
  • C语言结构:C语言是结构化,模块化程序设计语言,一个C程序是由一个或多个程序模块组成
  • 运行C语言:编译源程序(.c/.cpp) > 编译(.obj) > 连接处理(.exe) > 运行
文件
  • .c 源文件
  • .h 头文件(head)
基本框架
int main()
//主函数-程序的入口-有且仅有一个
{
  return 0;
}
// int 是整形的意思
// main前面的int表示函数调用返回一个整型值
// return 0;返回0  (前后呼应)
数据类型
char //字符数据型 	 	1

short //短整型		  	 2

int //整型		      4 

long //长整型           4

long long //更长的整型   8

float //单精度浮点型     4

double //双精度浮点型    8

(小数称为浮点型)
基本占位符
%c  // 打印字符格式的数据

%d  // 打印整型十进制的数据

%f  // 打印浮点型——打小数

%p  // 打印地址形式

%s  // 打印字符串
计算机中的单位

bit——比特位

byte-字节

一个字节=八个比特位的大小

变量作用域

变量包括局部变量和全局变量

main内称为局部变量

main外称为全局变量

{}称为代码块

局部变量和全局变量尽量不要相同,当相同时,局部变量优先被选择

变量哪里可以用哪里就是作用域

extern 声明外部符号

常量

一共分为四种:

// 字面常量
int main(int argc, char const *argv[])
{
    3;//字面常量,就是一个直接的值
    100;
    3.1415926;
    return 0;
}
// const修饰常变量:但是本质上还是一个变量,用来创建数组的时候是不能成功的
int main(int argc, char const *argv[])
{
    const int num = 1;
    printf("num = %d", num);
    // num = 3; // 被const修饰的变量就是常量不可以改变
    printf("num = %d", num);

    const int arrlength = 10;
    int arr1[10] = {1, 2, 3}; // 这里的10是常量
    // int arr2[arrlength] = {2, 3, 4}; // 因为被const修饰的变量本质上还是变量,所以会报错

    return 0;
}
// #define定义的标识符常量
#define MAX 10 // 注意使用#define定义的常量不需要写类型也不能写分号
int main(int argc, char const *argv[])
{
    int arr1[MAX] = {1, 2, 3, 4}; // 使用#define定义的常量可以用来创建数组
    return 0;
}
// 枚举常量--一一列举
// 如:
// 性别: 男, 女, 保密
// 三原色: 红, 黄, 蓝
// 星期: 1, 2, 3, 4, 5, 6, 7
// 枚举关键字: enum
enum Sex {
    MALE, // index -> 0
    FEMALE, // index -> 1
    SECRET // index -> 2
};
int main(int argc, char const *argv[])
{
    enum Sex s = MALE;  
    s = FEMALE; // 可以,通过枚举元素创建出来的变量可以改变
    MALE = "男"; // 报错,枚举里的常量也不能改变
    return 0;
}
字符串
int main(int argc, char const *argv[])
{
    // 使用字符数组来存储字符串
    char arr1[] = "abc";
    // char arr2[] = {'a', 'b', 'c'}; //需要在结尾添加一个作为字符串的结束标识,不然会出现乱码
    char arr2[] = {'a', 'b', 'c', ''};
    printf("%s", arr1);
    printf("%s", arr2);
    printf("%d", strlen(arr1)); // 3 strlen(String s) 计算字符串长度
    printf("%d", strlen(arr2)); // 当在数组后面放了的时候,就是3,要是没有则为随机数
    return 0;
}
字符串常见方法
  • putchar()字符输出函数

        int main(int argc, char const *argv[])
        {
            char a = 'm';
            int m = 97;
            putchar('a');  // a
            putchar(a);    // m
            putchar('n');
            putchar('m');  // m
            putchar(65);   //A
            putchar('A' + 1); // B
            putchar('n');
            return 0;
        }
    
  • getchar()字符输入函数

        int main(int argc, char const *argv[])
        {
            char m, n;
            printf("输入");
            m = getchar();
            n = getchar();
            printf("输出");
            putchar(m);
            putchar(n);
            return 0;
        }
    
  • char* strcpy( char* arr1, const char* arr2)字符复制函数 将arr2拷贝到arr1

    int main(int argc, char const *argv[])
    {
        char arr1[] = "arr1内容";
        char arr2[21] = "arr2内容arr2内容a";
        printf("%sn", arr1);   // arr1内容
        printf("%sn", arr2);   // arr2内容arr2内容
        strcpy(arr2, arr1);     // 将arr1的内容复制到arr2
        printf("%sn", arr1);   // arr1内容
        printf("%sn", arr2);   // arr1内容
        return 0;
    }
    
  • void* memset( void* dest, int ch, size_t count )转换值 ch 为 unsigned char 并复制它到 dest 所指向对象的首 count 个字节

    int main(int argc, char const *argv[])
    {
        char arr1[] = "hello world";
        printf("%sn", arr1);   // hello world
        memset(arr1, '*', 5);
        printf("%sn", arr1);   // ***** world
        return 0;
    }
    
循环
// while循环
int main(int argc, char const *argv[])
{
    int index = 0;
    while (index <= 20000)
    {
        printf("这是第%d条代码n", index);
        index++;
    }
    printf("敲够代码了,可以工作了");
    return 0;
}

还有for、do…while循环等

函数
int Add(int x, int y){ // 自定义函数
    int sum = x + y;
    return sum;
}
int main(int argc, char const *argv[]) // 主函数
{
    int a = 10, b = 30;
    int c = Add(a, b);
    printf("%d", c);
    return 0;
}
  • 注意:函数形参要是是数组的话,传递的其实不是数组,而是数组首元素的指针,所以在函数中不能使用sizeof(arr) / sizeof(arr[0])这种方式来获取数组长度
函数详情

​ 函数分为库函数、自定义函数

库函数
  • 不是业务性代码,在开发中每个程序员都有可能用的到,比如printf、scanf等等,可以访问 www.cplusplus.com进行学习

  • 常见库函数:

    • IO函数
    • 字符串操作函数
    • 字符操作函数
    • 内存操作函数
    • 时间/日期函数
    • 数学函数
    • 其他库函数
自定义函数
  • 程序员自己定义的函数

    ret_type fun_name(para1, *)
    {
        statement; // 函数体
    }
    // ret_type // 返回类型
    // fun_name	// 函数名
    // para1 	// 形参:形参实例化之后其实相当于实参的临时拷贝
    
  • 如果函数写在main函数后面, 则需要提前声明函数

    // 函数声明
    int add(int x, int y);
    int main(int argc, char const *argv[])
    {
        // 函数调用
        printf("%d", add(20, 10));
        return 0;
    }
    // 函数定义
    int add(int x, int y)
    {
        return x + y;
    }
    
  • 需要注意的是数组被当成形参的时候只是首元素的地址被传递过去

递归

递归的两个必要条件

  1. 存在限制条件:当满足这个限制条件的时候停止递归

  2. 每次递归调用之后越来越接近这个限制条件

最简单的递归:

int count = 0;
int main()
{
    count++;
    printf("运行%d次n", count);
    if (count < 200)
        main();
    return 0;
}
递归案例
  • 接受一个整型值(无符号),按顺序打印它的每一位。如1234打印成1 2 3 4

    void print(int n){
        if (n > 9)
            print(n / 10); // 使用递归
        printf("%d ", n % 10);
    }
    int main(int argc, char const *argv[])
    {
        unsigned int num = 0;
        scanf("%d", &num);
        print(num);
        return 0;
    }
    
数组
int main(int argc, char const *argv[])
{
    // 定义一个存放是个int类型的数组
    int arr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    pritnf("%d", arr[5]); // 5
    // 通过arr[index]下标的方式访问
    return 0;
}
数组详情
  • 数组名就是数组首元素地址,但是有两个特殊情况

    • sizeof(数组名):sizeof计算的是整个数组的大小,单位是字节

    • &数组名:取出的是整个数组的地址

      int arr01[4] = {2, 3, 4, 5};
      printf("%pn", arr01);     // 数组首元素的地址
      printf("%pn", &arr01);    // 整个数组的起始位置(也是数组首元素的地址,但是它包含了整个数组,可以通过 &arr01 + 1来区分) 
      printf("%pn", &arr01[0]); // 数组首元素的地址
      printf("%dn", sizeof(arr01)); 
      printf("%dn", *arr01);    // 2
      
常见函数
  • strlen(char[] arr):求字符串长度,但是默认返回的是一个无符号整型,要是想要在for循环中用就要强制类型转换为int类型,例如(int)strlen(charArr) 或者 int len = strlen(charArr) 只有这样才可以使用
int main(int argc, char const *argv[])
{
    char charArr1[] = "abc";
    char charArr2[] = {'a', 'b', 'c'};
    printf("%dn", sizeof(charArr1)); // 4 系统自动加上
    printf("%dn", sizeof(charArr2)); // 3 charArr2的定义方式不会自动添加
    printf("%dn", strlen(charArr1)); // 3
    printf("%dn", strlen(charArr2)); // 随机数charArr2没有结束符,所以依赖系统的随机数
    char charArr3[] = "abcdef";
    printf("%dn", sizeof(charArr3)); // 7 算占用空间,最后还有一个
    printf("%dn", strlen(charArr3)); // 6 求字符串长度,不算
    char charArr4[10] = "ab";
    char charArr5[10] = {'a', 'b'}; // 使用下标超过1的时候显示的都是0
    printf("%dn", sizeof(charArr4)); // 10 字符定义的时候就已经规定了 所以不会添加
    printf("%dn", strlen(charArr4)); // 2 字符串内容长度
    printf("%cn", charArr5[0]);
    printf("%dn", charArr5[4]); // 没有初始化默认为0
    printf("%dn", sizeof(charArr5)); // 10
    printf("%dn", strlen(charArr5)); // 2 默认值但是没有占据数组位置
    // 如果charArr5定义为charArr5[];则sizeof为2,strlen为随机值
    return 0;
}
二维数组
  • 数组创建时的下标为常量
  • 没有被完全初始化的话直接使用会被0自动填充,
  • 二维数组定义可以省略行但是不能省略列
int main(int argc, char const *argv[])
{
    // 定义一个三行四列的数组
    int intArr1[3][4] = {1, 2, 3, 4, 5};// 1234为第一行,第一行满了5自动为第二行
    int intArr2[3][4] = {{1, 2, 3}, {4, 5}}; // 123第一行,45第二行
    // 当二维数组没有全部初始化,后面默认的也是0
    // int intArr3[][] = {1, 2, 3, 4, 5, 6}; // 报错,缺少下标
    // int intArr4[3][] = {1, 2, 3, 4}; // 报错
    int intArr5[][4] = {1, 2, 3, 4}; // 不报错
    return 0;
}
数组排序
// 数组排序
int main(int argc, char const *argv[])
{
    
    int intArr01[] = {1, 5, 6, 7, 8, 9, 2, 3, 4};
    int arrLen = sizeof(intArr01) / sizeof(intArr01[0]);
    int i, j;
    for (i = 0; i < arrLen - 1; i++)
    {
        for ( j = 0; j < arrLen - 1 - i; j++)
        {
            if (intArr01[j] < intArr01[j + 1])
            // 这是从大到小,要改升降序就该 > || <
            {
                int temp = intArr01[j + 1];
                intArr01[j + 1] = intArr01[j];
                intArr01[j] = temp;
            }
        }        
    }
    for ( i = 0; i < arrLen; i++)
    {
        printf("%d,", intArr01[i]);
    }
    return 0;
}
指针

通过指针可以可以找到以指针为地址的内存单元(指针就是变量所对应的内存地址)

  • 在32位系统一个指针占4个字节,64位占8个字节
  • 指针的类型决定了指针能访问几个字节,char*只能访问一个,int*可以访问4个
  • 指针加减整数的时候表示的是内存地址的增加,如:char* + 1表示的是原本地址是0x001变成0x002,int* + 1表示0x001变成0x005
  • 指针减去指针得到的其实是指针之间的元素个数
  • c语言规定只允许数组前面的指针和数组后面的比较,不能数组后面的指针和前面的比较
二级指针
int main(int argc, char const *argv[])
{
    int a = 10;
    int *pa = &a;
    int **ppa = &pa; // pa是指针,指针也有地址,将pa的地址放在ppa就需要使用**来定义指针变量
    printf("%d,%d,%d,%d,%d", &pa, &ppa, &a, pa, *ppa);
    // pa是a的内存地址,ppa是pa的内存地址,*ppa是pa的值(内存地址),**ppa是a的值
    return 0;
}
指针数组

指针数组是存放指针的数组,数组指针是存放数组的指针

int main(int argc, char const *argv[])
{
    int a = 10, b = 20, c = 30;
    int arr[10] = {a, b, c};    // 整形数组
    int *parr[] = {&a, &b, &c}; // 指针数组
    printf("%d, %d", parr[1], *(parr[1]));
    return 0;
}
结构体

结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量

声明结构体 简单结构体
struct tag          // struct关键字 tag是标识符
{
    member-list;    // 成员列表
}variable-list;     // 变量列表

要注意是否有typedef关键字修饰

// 定义一个学生类型
struct Student
{
    char name[20];  // 名字
    short age;      // 年龄
    char tele[12];  // 电话
    char sex[5];    // 性别
}student1, student2, student3; // 创建完结构体后直接创建三个全局的结构体变量,可以直接使用了,但是不建议使用
// typedef 给Stud重新起名为Stu,之后创建变量可以不使用struct关键字,并且使用Stu别名
typedef struct Stud
{
    char name[20];  // 名字
    short age;      // 年龄
    char tele[12];  // 电话
    char sex[5];    // 性别
}Stu;
int main(int argc, char const *argv[])
{
    // 初始化Student
    // struct Student student;
    // 初始化stud,被typedef修饰后不需要关键字struct
    // Stu stu1;
    
    // 给结构体内部赋值
    Stu s = {"张三", 20, "12345678910", "男"};
    // 通过元素名.属性名使用变量
    printf("%s", s.name);
    return 0;
}
复杂结构体
struct S
{
    int a;
    char c;
    char arr[20];
    double d;
};
struct T
{
    char ch[10];
    struct S s;     // 使用结构体S
    char *pc;
};
int main(int argc, char const *argv[])
{
    char arr[] = "Hello Cn";
    // 初始化结构体T,其中要使用到结构体S
    struct T t = {"hehe", {100, 'c', "helloWorld", 3.14}, arr}; // 数组的名字就是地址,所以不用加&
    printf("%d", t.s.a);
    return 0;
}
结构体成员的访问
  • 结构体变量访问成员是通过.操作符访问
  • 有时候得到的不是一个结构体变量,而是指向结构体的指针,则使用->操作符访问
typedef struct Student
{
    char name[20];
    short age;
    char tele[12];
    char sex[5];
} Stu;
void Print1(Stu s)
{
    printf("name: %sn", s.name);
    printf(" age: %dn", s.age);
    printf("tele: %sn", s.tele);
    printf(" sex: %sn", s.sex);
}
void Print2(Stu *s)
{
    printf("name: %sn", s->name); // 完全等效于下面
    // printf("name: %sn", (*s).name); 
    printf(" age: %dn", s->age);
    printf("tele: %sn", s->tele);
    printf(" sex: %sn", s->sex);
}
int main(int argc, char const *argv[])
{
    Stu s = {"李四", 40, "123123123", "男"};
    // 定义Print1函数 使用.操作符 传值
    Print1(s);
    // 定义Print2函数 使用->操作符 传址
    Print2(&s);
    return 0;
}
常见关键字
  • typedef:类型定义,这里应该理解为类型的重命名
  • static:用来修饰变量和函数(局部变量/全局变量/函数->静态局部变量/全局变量/函数)
    • 修饰局部变量 -> 局部变量生命周期变长
    • 修饰全局变量 -> 让静态的全局变量只能在自己所在的源文件内部使用
    • 修饰函数 -> 也是改变了函数的作用域(正式说法:改变了函数的链接属性 外部链接 -> 内部链接)
  • #define:定义常量和宏
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/889945.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号