一、数组

1> 数组的定义和初始化

  1. 定义

    ① 数组定义了同种类型数据的集合
    ② 定义数组时,数组必须有固定的长度
  2. 初始化

    ① 如果在定义数组时,初始化数组,数组元素的个数必须是常量
    ② 如果不在定义数组时初始化,数组元素的个数可以是有确定值的变

    ③ 大括号的初始化方式只能在定义时初始化的情况下使用

2> 数组的内存存储细节

  • 为数组分配内存时是从内存的高地址到低地址,而数组元素的存储是从低地址到高地址
  • 数组名为该数组元素在内存中的首地址,是一个指针常量,类型与数组类型一致
  • 可以用&符号来取得每个数据元素的首地址
  • 数组在内存中所占内存的大小可以用sizeof(数组名)/数组长度来计算

3> 使用注意

  • 数组元素的下标是从0开始的
  • 若要访问数组中的多个元素,一般用for循环
  • 可以通过sizeof来计算数组的长度
  • 可以通过下标直接访问数组,也可以通过指针间接访问数组元素

4> 数组名作为函数参数

  • 数组名作为函数参数是传址参数,传递的是数组的首地址
  • 不同通过sizeof来计算数组长度,此时通过sizeof(数组名),计算的是该编译器中指针的长度
  • 数组的长度必须通过参数传递

5> 示例

  • 步骤

    • 将整型数据10, 6, 23, 8, 15存放在一个数组中
    • 对数组中的元素进行从小到达排序
    • 输出排序后数组中的元素
  • 代码

    #include <stdio.h>
    //将数组按从小到大排序
    void sortTheArray(int array[], int count);
    //逐个输出数组中的元素
    void printTheArray(int array[], int count); int main()
    {
    //定义一个数组并初始化
    int array[]= {10, 6, 23, 8, 15};
    //存储数组元素的个数
    int count; //计算数组的个数
    count = sizeof(array) / sizeof(int); //逐个输出排序前数组中的元素
    printTheArray(array, count); //将数组按从小到大排序
    sortTheArray(array, count); //逐个输出排序后数组中的元素
    printTheArray(array, count); return 0;
    } //将数组按从小到大排序
    void sortTheArray(int array[], int count)
    {
    //用于循环遍历数组
    int i,j,k;
    //中间变量,用于交换数组的两个元素
    int temp; //选择排序
    for (i = 0; i < count-1; i++)
    {
    k = i;
    for (j = i + 1; j < count; j++)
    {
    if (array[j] < array[k])
    {
    temp = array[k];
    array[k] = array[j];
    array[j] = temp;
    }
    }
    }
    } //逐个输出数组中的元素
    void printTheArray(int array[], int count)
    {
    for (int i = 0; i < count; i++)
    {
    printf("%d\t", array[i]);
    }
    printf("\n");
    }

二、字符串

1> 基本使用

  • C语言中用字符数组来表示字符串
  • 字符串用%s格式输出
  • string.h文件中声明了字符串相关的操作函数

2> 字符串的结束标志'\0'

  • 字符串末尾会有'\0'结束标志,其ASCII码值为0
  • 字符串的操作函数是以'\0'为结束符,若没有结束符,这些操作函数可能会操作其他危险的数据
  • 将字符串常量赋值给char类型的指针变量,则该变量存储的是字符串常量的首地址

3> 字符串的输入

  1. scanf函数

    ① scanf函数默认以空格、'\n'和'\t'键作为字符串结束的标志
    ② 可以用格式%[^c]来控制以指定字符c作为字符串结束的标志
  2. gets函数

    ① 可以输入包含空格和'\t'的字符串,以'\n'作为字符串结束标志
    ② gets函数不会判断上限,仅遇到'\n'结束
    ③ 用于接收字符串的缓冲区必须足够大,否则会发生溢出,引发bug
  3. getchar函数

    ① 可以通过循环使用getchar函数来输入任意的字符,来组成字符串
    ② 要对末尾的'\n'进行处理,将其转化为'\0'

三、指针

1> 基本使用

  • 指针变量的内容为内存地址,内存地址是一个机器相关量
  • 指向指针的指针,其内容为所指向指针的地址
  • 通过符号*来访问指针变量所指向地址存储的内容,并可进行修改
  • 指针所指向的内存空间存储变量的类型,与定义指针的类型一致
  • 指针作为函数参数,是一个传址参数
  • 指针可以作为函数参数用于返回函数的执行结果
  • 可以使用指针数组来代替多维数组

2> 使用注意

  • 定义指针变量时的符号*只是一个符号,没有任何实际的意义
  • 定义指针变量时用常量将其初始化,此指针变量的内容将不能被修改
  • 不能间接访问没有初始化的指针变量
  • 若使用一阶指针,不要将地址存储到指针变量所指向的内容
  • 若指针指向的变量类型与定义的类型不一致,可能会影响间接访问的内容
  • sizeof函数的返回值为unsigned long类型,输出格式为%zd
  • 若返回值类型为指针类型,返回值是一个地址

3> 指向函数的指针

  • 定义格式 void (*p)(int ),这是定义一个无返回值,有一个整型参数的指向函数的指针变量

  • 通常用函数名为指向函数的指针变量赋值,函数名表示函数在内存中存储的首地址

  • 通过指针变量调用函数的两种方式

     ① p( );
    ② (*p)();

四、指针与数组

1> 基本使用

  1. 通常定义一个与数组同类型的指针变量来指向数组的首地址
  2. 通过指针的自增自减运算来间接访问数组元素
  3. 可以用指针变量加上下表来访问数组元素

2> 使用注意

  1. 指针运算是以定义指针类型在内存中所占存储空间的字节数为单位的
  2. 下标绝不会比指针更有效率,但指针有时可能比下标更有效率
  3. 数组名和指针不能等同

四、结构体

1> 基本使用

  • 结构体定义了多个不同类型数据的集合,是构造类型的一种
  • 结构体可以将某个对象的一组属性组合在一起
  • 结构体的成员可以是基本数据类型,也可以是其他构造类型,如结构体
  • 可以在定义结构体时用大括号为其初始化,用点语法可以实现机构提成员的乱序赋值
  • 结构体数组用于定义具有多个属性的多个同种类型的对象

2> 使用注意

  • 定义结构体不会分配内存空间,只有定义结构体变量时才会为变量分配内存空间
  • 结构体变量所占内存空间的大小为所有成员变量中占内存空间最大的变量所占内存空间的整数倍
  • 结构体变量之间可以赋值,实际上是全部成员变量之间的赋值
  • 结构体变量的名字是该结构体在内存中的首地址
  • 不能定义同名结构体
  • 尽量不要再代码块内定义结构体,避免造成作用域问题

3> 定义结构体变量的三种方式

  • 在定义结构体的同时定义结构体变量,重用性差
  • 先定义结构体,在用这种类型定义结构体变量
  • 用typedef为结构体定义一个新的类型名,用这个新类型名定义这种类型的结构体变量

4> 指向结构体的指针

  • 可以定义一个结构体类型的指针来指向该种类型的结构体变量

  • 通过指针间接访问结构体指针变量的两种方式

     ① (*p).name,(p为指向结构体变量的指针,name为结构体变量的成
    员变量的名字)
    ② p->name

五、枚举

1> 基本使用

  • 用于定义一个具有固定取值的变量
  • 枚举类型变量的定义与结构体类型变量的定义相似

2> 使用注意

  • 枚举类型的成员变量实际上存储的是整型常量,默认从0开始编号
  • 可以指定枚举类型的成员变量的编号规则

六、综合示例

  • 步骤

    • 定义一个Person结构体,属性包含:名字、性别
    • 名字用字符串表示
    • 性别用枚举表示
    • 定义一个函数输出结构体变量的信息
  • 代码

    #include <stdio.h>
    #include <string.h>
    //定义一个枚举类型,用于存储性别
    typedef enum
    {
    sexMan, sexWoman, sexUnknown
    } Sex; //定义一个结构体类型,用于存储某个人的姓名和性别属性
    typedef struct
    {
    char name[20]; //姓名
    Sex sex; //性别
    } Person; //声明一个函数,用于打印某个人的信息
    void printThePerson(Person *p); int main()
    {
    //定义一个结构体变量p
    Person p; //输入姓名,存放到结构体的name属性中
    printf("请输入一个人的姓名\n");
    //使用%[^\n]控制一'\n'字符作为字符串的结束字符
    scanf("%[^\n]", p.name); //输入性别,存放到结构体的sex属性中
    printf("请输入一个人得性别(0:Man,1:Woman,2:Unknown)\n");
    scanf("%d", &p.sex); //打印结构体变量p的相关信息
    printThePerson(&p); return 0;
    } void printThePerson(Person *p)
    {
    char *str = NULL;
    //将枚举值sex转换成相应的字符串
    switch (p->sex)
    {
    case 0:
    str = "Man";
    break;
    case 1:
    str = "Woman";
    break;
    case 2:
    str = "Unknown";
    break; default:
    break;
    }
    printf("这个人的姓名为:%s\t性别为:%s\n", p->name, str);
    }

C语言-06-复杂数据类型的更多相关文章

  1. C语言-06复杂数据类型-04 结构体

    结构体的说明(构造类型) 数组:只能由多个相同类型的数据构成 结构体:可以由多个不同类型的数据构成 ,结构体的类型是不存在的,自己定义 int main() { // 1.定义结构体类型 定义类型的时 ...

  2. C语言-06复杂数据类型-03指针

    指针变量的定义 变量类型 *变量名; #include <stdio.h> int main() { // 指针就一个作用:能够根据一个地址值,访问对应的存储空间 // 指针变量p前面的i ...

  3. C语言-06复杂数据类型-02字符串

    #include <stdio.h> int main() { //char name[] = {'i', 't', 'c', 'H', 's', 't', '\0'}; char nam ...

  4. C语言-06复杂数据类型-01数组

    01-数组 #include <stdio.h> int main() { // 使用注意 // 都是正确写法 //int ages[5] = {10 , 11, 12, 67, 56}; ...

  5. C语言的基本数据类型长度

    PS:以下内容是在Xcode的编辑器64位环境下的测试结果,网上有关于64位和32位各数据类型存在的差异,请自行online search. main.m #import <Foundation ...

  6. Go 语言的基本数据类型

    Go 语言的基本数据类型 0)变量声明 var 变量名字 类型 = 表达式 例: 其中“类型”或“= 表达式”两个部分可以省略其中的一个. 1)根据初始化表达式来推导类型信息 2)默认值初始化为0. ...

  7. Android For JNI(二)——C语言中的数据类型,输出,输入函数以及操作内存地址,内存修改器

    Android For JNI(二)--C语言中的数据类型,输出,输入函数以及操作内存地址,内存修改器 当我们把Hello World写完之后,我们就可以迈入C的大门了,今天就来讲讲基本的一些数据类型 ...

  8. Go语言基础之数据类型

    Go语言基础之数据类型 Go语言中有丰富的数据类型,除了基本的整型.浮点型.布尔型.字符串外,还有数组.切片.结构体.函数.map.通道(channel)等.Go 语言的基本类型和其他语言大同小异. ...

  9. [日常] Go语言圣经--复合数据类型,数组习题

    go语言圣经-复合数据类型 1.以不同的方式组合基本类型可以构造出来的复合数据类型 2.四种类型——数组.slice.map和结构体 3.数组是由同构的元素组成——每个数组元素都是完全相同的类型——结 ...

  10. C语言复习————基本数据类型、运算符和表达式

    数据类型/运算符/表达式 主要分两部分介绍,第一部分介绍常用的数据类型,例如:常量和变量/整型/实型/字符型:第二部分介绍算数运算符和算数表达式以及赋值运算符和逗号运算符. 一. 常用的数据类型 1. ...

随机推荐

  1. Android之startActivityForResult的使用

    在Android中startActivityForResult主要作用就是: A-Activity需要在B-Activtiy中执行一些数据操作,而B-Activity又要将,执行操作数据的结果返回给A ...

  2. 菜鸟学Windows Phone 8开发(1)——创建第一个应用程序

    本系列文章来源MSDN的 面向完全新手的 Windows Phone 8 开发 主要是想通过翻译本系列文章来巩固下基础知识顺带学习下英语和练习下自己的毅力(因为打算每天翻译一篇,但是发现翻译这篇花费了 ...

  3. [Python] Symbol Review

    From:http://learnpythonthehardway.org/book/ex37.html 1. with X as Y: pass 1.1 yield 2. exec 2.1 name ...

  4. 关于完整解答Leo C.W博客中名为“我们公司的ASP.NET 笔试题,你觉得难度如何”的所有题目

    关于完整解答Leo C.W博客中名为“我们公司的ASP.NET 笔试题,你觉得难度如何”的所有题目,请大家鉴定,不足之处,敬请指教! 第1到3题解答如下: public enum QuestionTy ...

  5. C#序列化JSON

    public static string ConvertToJsonString<T>(T instance) {             using (MemoryStream stre ...

  6. [JS] JavaScript由浅入深(2) 进阶

    本节,将围绕以下几点来讲. 知识点:多线程.作用域.闭包.this 先顶后看 1.多线程 在不支持H5的浏览器中.使用Concurrent.Thread.js. 在支持H5中,使用WebWork. 在 ...

  7. 复利计算v6.0--web版--软件工程

    一.结对同伴 姓名:蔡舜 学号: 博客园地址:http://www.cnblogs.com/caishun/ http://www.cnblogs.com/caishun/p/5392896.html ...

  8. C#设计模式——命令模式(Command Pattern)

    一.概述通常来说,“行为请求者”与“行为实现者”是紧耦合的.但在某些场合,比如要对行为进行“记录.撤销/重做.事务”等处理,这种无法抵御变化的紧耦合是不合适的.在这些情况下,将“行为请求者”与“行为实 ...

  9. 小白学Linux(五)--VI/VIM编辑器

    我们操作文件,终究离不开编辑文件,对文件内容的编辑,Linux系统下,我们通常使用VI/VIM来编辑文件.VI是每个Linux都会自带的文本编辑器,VIM是VI的增强版,可能有些发行版本没有自带,可以 ...

  10. Webhooks PHP

    Webhooks/Parse When webhooks are triggered in the gateway, a notification is sent as a POST request ...