数据类型(Data Types)

一、整型

整型分为整形常量和整形变量 常量就是我们平时所看到的准确的数字 例如:1、20、333等等 变量则按我的理解是我向内存去申请一个存储空间 告诉内存空间我申请了这个地方用来存放一个整形的数据 但是什么时候放并没有直接确定 一般占4个字节(32位) 最高位代表符号 0表示正数 1表示负数 取值是-2147483648~2147483647 在内存中的存储顺序是低位在前 高位在后 例如0x12345678

同时整型分为有符号整数类型(整型 短整型 长整型)和无符号整数类型(无符号整型 无符号短整型 无符号长整形)在说明符前由“signed”与“unsigned”区分开 但有符号整型前的“signed”通常省略

1、有符号整数类型

类型存储字节表示范围格式说明符
int4-231~231-1%d、%u、%o、%#o、%x、%#x
short int2-215~215-1%hd、%hu、%ho、%#ho、%hx、%#hx
long int4/8-231~231-1/-263~263-1%ld、%lu、%lo、%#lo、%lx、%#lx
long long8-263~263-1%lld、%llu、%llo、%#llo、%llx、%#llx

(1)整型int(long int) (4字节)int 即 “integer”意为 整数
long是**long int **的简写
在C语言中,根据C标准规范,long int至少占据4个字节(32位)。这是因为C标准规定:

  • int类型的大小必须大于或等于16位;
  • long int类型的大小必须大于或等于int类型。

虽然C标准规定了这些最小要求,但具体的实现可能会有所不同。在不同的编译器和操作系统中,long int类型的大小可能是32位(4字节),也可能是64位(8字节)或其他大小。
要确定在特定的编译器和操作系统中long int的确切大小,可以使用sizeof运算符来获取它的字节数。

取值范围:-2147483648 ~ +2147483647 (4 Bytes)

int main(){
    int Integer = -10;
    long int LongInteger = 10;
}

(2)短整型 short(内存中占2个字节)
short int 的简写
取值范围:-32768 ~ + 32767 (2 Bytes)

int main(){
    short int ShortInteger = 18;
}

(3)长整型long long (8字节)
取值范围:-9223372036854775808~+9223372036854775807(8 Bytes)

int main(){
    long long int LongLongInteger = 1937897132;
}

C语言规定 int最少16位(2字节) long不能比int短 short不能比int长 具体位长由编译器开发商根据各种情况自己决定
32位平台下long 是4个字节 long long 是8字节 但是64位平台下则全是8字节 因此为了保证平台的通用性 程序中尽量不要使用long数据类型

#include<stdio.h>
int main(){
    int num1 = 42;
    printf("num1: %d\n", num1);     // 输出num1的值
    return 0;
}

image.png

2、无符号整数类型

无符号整数类型只包含正数 这样就能将二进制的符号位作为整数位 使得最小取值为0 最大值大了一倍
在有符号整数类型说明符前添加前缀unsigned 即构成对应的无符号正数类型说明符 在无符号整数类型后要加后缀字母

  • 无符号整型:后缀字母uU
  • 无符号短整型:后缀字母usUS
  • 无符号长整型:后缀字母ulUL
  • 无符号长长整型:后缀字母ullULL
    | 类型 | 存储字节 | 表示范围 | 格式说明符 |
    | — | — | — | — |
    | unsigned int | 4 | 0~2^32-1 | %d、%u、%o、%#o、%x、%#x |
    | unsigned short int | 2 | 0~2^16-1 | %hd、%hu、%ho、%#ho、%hx、%#hx |
    | unsigned long int | 4 | 0~2^32-1 | %ld、%lu、%lo、%#lo、%lx、%#lx |
    | unsigned long long | 8 | 0~2^64-1 | %lld、%llu、%llo、%#llo、%llx、%#llx |
int main(){
    unsigned int num1 = 42u; // 使用后缀字母'u'表示无符号整数
    unsigned short num2 = 65535u; // 使用后缀字母'u'表示无符号短整数
    unsigned long int num3 = 1234567890ul; // 使用后缀字母'ul'表示无符号长整型
    unsigned long long num4 = 1234567890ULL; // 使用后缀字母'ULL'表示无符号长长整数
}

当处理的数据只有正整数时 此时使用无符号整数类型数据可以更好的利用计算机的储存空间 从而提高计算效率

#include<stdio.h>
int main(){
    unsigned int num2 = 123456789;
    printf("num2: %u\n", num2);     // 输出num2的值
    return 0;
}

image.png

3、整型数据的溢出

整型数据的溢出(Integer Overflow)是指在计算过程中,整数类型变量的值超过了该类型所能表示的范围,从而导致结果不准确或无法正确存储。
在C语言中,整型数据可以分为有符号和无符号两种类型。对于有符号整型,最高位用于表示正负号,因此有限的位数可以表示的数值范围会减半。而无符号整型则没有正负号,能够表示更大的正整数范围。
以下是关于整型数据溢出的一些重要概念和实例:

  1. 有符号整型溢出:
    • 如果一个有符号整型变量达到了其最大值,再进行加1操作,将会产生溢出,并且变量的值会变为最小值。
int i = INT_MAX; // i的初始值为INT_MAX
i = i + 1; // 整型溢出,i的值变为INT_MIN
  • 如果一个有符号整型变量达到了其最小值,再进行减1操作,同样会产生溢出,变量的值会变为最大值。
int j = INT_MIN; // j的初始值为INT_MIN
j = j - 1; // 整型溢出,j的值变为INT_MAX
  1. 无符号整型溢出:
    • 无符号整型变量只能表示非负数,当其值达到了最大值时,再进行加1操作将会产生溢出,并且变量的值会变为0。
unsigned int x = UINT_MAX; // x的初始值为UINT_MAX
x = x + 1; // 整型溢出,x的值变为0
  • 当无符号整型变量的值为0时,再进行减1操作也会产生溢出,变量的值会变为最大值。
unsigned int y = 0; // y的初始值为0
y = y - 1; // 整型溢出,y的值变为UINT_MAX

需要注意的是,整型数据溢出可能导致计算结果错误,甚至引发未定义行为。在编写C代码时,应当谨慎处理整型数据溢出情况,避免出现不确定的结果。

二、实型(浮点型)

浮点型是一种用于表示带有小数部分的数值的数据类型 它在计算机中以科学记数法的形式存储 由两个部分组成:尾数(mantissa)和指数(exponent) 这种表示方法使得浮点型能够表示非常大或非常小的数值
浮点型主要有两种类型:单精度浮点型(float)和双精度浮点型(double) 单精度浮点型使用4字节(32位)来存储浮点数 而双精度浮点型使用8字节(64位)

类型存储字节表示范围格式说明符
float4约1.17549e-383.40282e+38,-1.17549e-38-3.40282e+38%f、%e、%a
double8约2.22507e-3081.79769e+308,-2.22507e-308-1.79769e+308%f、%e、%a

需要注意的是 这些取值范围是近似值 实际的取值范围可能会根据编译器的实现略有不同 此外 浮点数的可表示精度也会随着数值的大小变化而减小 因此在进行非常大或非常小的计算时 可能会涉及到精度失的问题。
当需要更大范围和更高精确度的浮点数时 可以选择使用 double 类型 对于一般的计算 float 类型通常足够 并且在存储空间上更为节省 具体选择何种类型取决于应用的需求和数值范围的大小

#include<stdio.h>
int main(){
    float num1 = 3.14;
    double num2 = 123.456;
    printf("num1: %.2f\n", num1);   // 输出num1,保留两位小数
    printf("num2: %.3lf\n", num2);  // 输出num2,保留三位小数,并用lf后缀指定双精度格式
    return 0;
}

image.png
浮点数的比较应该避免使用**==**运算符 因为在计算机内部 浮点数的表示是近似的 应该使用范围或误差判断来进行比较
浮点数的运算可能会存在舍入误差 因此在比较浮点数相等性时应该考虑到这一点

三、字符型

字符型在其本质上就是整形 我们在C语言中使用char表示一个字符型 他占用一个字符的存储空间 字符型在存储时其内部存储的依旧是二进制数据 当我们读出时将会得到一个整形数据 而我们输出时会得到一个字符是因为我们人为的定义了ASCII码表 这个表规定字符a的数值就是97 所以当我们遇到97时我们有两种读出方式 第一种以整数形式读出就是97 另一种就是以字符型读出 使用%c指定读出形式 按表对照则为a

printf("将c按整数形式读出:%d\n", c);
printf("将c按字符形式读出:%c\n", c);

image.png

1、字符常量(Character Constants)

  • 字符常量是用单引号括起来的单个字符
  • 例如:‘A’、‘b’、'5’等ASCII字符集中的字符都是字符常量
  • 字符常量可以包含ASCII码对应的字符 也可以包含特殊字符 如转义字符’\n’表示换行符

2、字符串常量

  • 字符串常量是由一系列字符组成的常量 使用双引号括起来
  • 例如:"hello,world!"就是一个字符串常量
  • 字符串常量通常以空字符 ‘\0’(ASCII码值为0)结尾 表示字符串的结束
  • 可以通过字符数组来存储字符串常量 并通过下标(即索引)访问每个字符

3、转义字符

以下是常见的转义字符、它们的含义和示例:

  1. - 单引号:
    • 含义:表示一个单引号字符。
char ch = '\''

image.png

  1. " - 双引号:
    • 含义:表示一个双引号字符。
printf("Hello, \"World!\"\n");

image.png

  1. \ - 反斜杠:
    • 含义:表示一个反斜杠字符。
printf("C:\\Program Files\\");

image.png

  1. \n - 换行符:
    • 含义:表示换行。在输出中插入一个新行。
printf("Hello\nWorld");

image.png

  1. \r - 回车符:
    • 含义:将光标移到当前行的起始位置。
printf("Hello\rWorld");

在运行该代码时,输出的结果为 “World”,因为光标先打印了 “Hello”,然后通过回车符 “\r” 将光标移动到最左边,再输出 “World”。因此最终的输出结果为 “World”。
image.png

  1. \t - 制表符:
    • 含义:表示水平制表符,用于在输出中插入一个制表符。
printf("Name\tAge");

image.png

  1. \b - 退格符:
    • 含义:表示退格,将光标回退一个位置。
printf("Hello\bWorld");

image.png

  1. \f - 换页符:
    • 含义:表示换页,在输出中插入一个换页符。
printf("Page 1\fPage 2");
  • 示例:printf(“Page 1\fPage 2”); 输出结果会在 “Page 1” 和 “Page 2” 之间进行分页。

image.png

  1. \0 - 空字符(字符串结束标志):

    • 含义:表示字符串的结束符。在C语言中,字符串以空字符结尾。
    • 示例:char str[5] = “Hello”; 字符数组 str 的长度为5,最后一个元素为空字符。
      在C语言中,一个字符数组的最后一个元素是空字符(‘\0’)是为了表示字符串的结束。字符串在C语言中是使用字符数组来表示的,以字符数组的形式存储在内存中。而在字符数组中,每个字符占据一个内存位置。为了区分字符串的实际内容和字符串的结束,我们需要一种特殊的字符来表示字符串的结束点。这个特殊的字符就是空字符。
      空字符是ASCII码表中的一个字符,其对应的数值为0。当遇到一个字符数组,并且该数组用作字符串时,我们可以通过检查数组中的每个元素,直到找到空字符为止,确定字符串的长度和结束位置
  2. \xhh - 以十六进制表示的ASCII码:

  • 含义:表示一个特定的ASCII码值,其中 hh 是两个十六进制数字。
  • 示例:char ch = ‘\x41’; 表示将十六进制值0x41(65的十进制值,对应大写字母’A’的ASCII码)赋给字符变量 ch。

其中,\xhh 是一个通用的转义字符格式,其中 hh 表示两个十六进制数字,用于表示任意的ASCII码值。

4、字符变量

字符变量用于存储单个字符 使用char类型声明
可以通过赋值操作来存储具体的字符
例如:

char ch = 'B';

5、字节型数据与整型数据的相关运算

当涉及到char类型和int类型的相关运算时,有一些原理和注意事项需要考虑。

  1. char类型:
  • char类型是用来存储单个字符的数据类型,在内存中占据1字节的空间。
  • 在C语言中,char类型可以表示ASCII码表中的字符,范围从0到255或-128到127(取决于是否使用有符号或无符号)。
  • 当进行数值运算时,char类型会被隐式转换为整数类型,即按照对应的ASCII码值进行计算。
  1. int类型:
  • int类型是用来表示整数的数据类型,在大多数平台上占据4字节的空间(取决于具体的系统架构)。
  • int类型可以表示整数范围内的数值,通常在-2147483648到2147483647之间。

char类型和int类型的相关运算中,需要注意以下几点:

  • 隐式类型转换:在表达式中混合使用char类型和int类型时,编译器会根据规则进行隐式类型转换。通常情况下,char类型会自动转换为int类型进行运算。
  • 精度丢失:如果将一个超出char类型表示范围的整数值赋给char类型变量,或者将int类型的值赋给char类型变量,可能会导致精度丢失。超出char类型表示范围的值会被截断为有效范围内的值。
  • 符号扩展:如果将一个带有符号位的char类型转换为int类型时,会进行符号扩展,即符号位会扩展到更高位上。
  • 数值溢出:在进行运算时,特别是涉及到加法和乘法等操作,需要注意数值溢出问题。当结果超出目标数据类型的表示范围时,会发生溢出,并产生不正确的结果。

为了确保运算的正确性和避免潜在的问题,在涉及char类型和int类型的运算时,建议:

  • 明确处理类型转换,可以使用显式类型转换来指定所需的类型。
  • 当对字符进行数值运算时,需要注意ASCII码值与字符之间的关系。
  • 了解并掌握不同数据类型的表示范围,以避免溢出和精度问题。

总之,在使用char类型和int类型进行运算时,要小心处理类型转换、数值溢出和精度问题,以确保正确性和可靠性。
以下是一些示例:

示例1:隐式类型转换

#include <stdio.h>
int main() {
    char c = 'A';
    int num = 10;
    
    int result = c + num;
    
    printf("Result: %d\n", result);
    
    return 0;
}

在这个示例中,将一个char类型的变量 c 初始化为字符 ‘A’,然后将一个 int 类型的变量 num 初始化为 10。然后,我们将 c 和 num 相加并将结果赋给 result 变量。由于在表达式中混合使用了 charint 类型,编译器会进行隐式类型转换,将 char 类型的值转换为 int 类型进行运算。最后,我们打印出 result 的值,它将是 75。
image.png

示例2:精度丢失

#include <stdio.h>
int main() {
    int largeNum = 300;
    char smallChar = largeNum;
    
    printf("Small Char: %c\n", smallChar);  // 注意:可能会发生精度丢失
    
    return 0;
}

在这个示例中,将一个超出 char 类型表示范围的整数值 300 赋给 char 类型的变量 smallChar。由于 char 类型的有效范围是 -128 到 127(或 0 到 255,取决于是否有符号),因此发生了精度丢失。当我们打印 smallChar 的值时,结果可能会是一个不正确的字符。
image.png

示例3:溢出

#include <stdio.h>

int main() {
    char charA = 100;
    char charB = 80;
    char sum = charA + charB;  // 注意:可能会发生溢出
    
    printf("Sum: %d\n", sum);
    
    return 0;
}

在这个示例中,将两个 char 类型的变量 charA 和 charB 初始化为 100 和 80。然后,将它们相加并将结果赋给另一个 char 类型的变量 sum。由于 char 类型的表示范围是 -128 到 127(或 0 到 255)
char 类型的范围为 -128127(或 0255)是因为它可以表示有符号或无符号字符。在C语言中,char 类型默认被视为带符号类型。对于一个有符号的 char 类型,它的范围是 -128 到 127,其中最高位用于表示符号位:0 表示正数,1 表示负数。这样,char 类型可以表示从 -128 到 127 共计 256 个不同的值。
然而,根据编译器和平台的不同,char 类型也可以被定义为无符号类型。对于无符号的 char 类型,它的范围是 0 到 255,它的所有位都用于表示数值,没有符号位。
由于 char 类型的范围是与编译器和平台相关的,所以具体范围可能会有所不同。在不同的编译器和平台上,char 类型的默认有无符号性质以及范围可能会有所不同,但通常情况下都能覆盖 ASCII 码表中的字符范围。
需要注意的是,在进行字符处理时,如果需要明确指定有无符号类型,建议使用 signed char 或 unsigned char 来替代简单的 char 类型,以避免产生不同编译环境下的差异。

,在进行相加运算时可能会发生溢出。当我们打印 sum 的值时,结果可能是一个不正确的数值。
image.png

不同类型数据的混合运算

1、不同类型数据之间的类型转换

在C语言中 整型 单精度型 双精度型可以混合运算 前面我们已经知道 字符型数据可以与整型数据通用 因此 整型 实型 字符型数据间可以进行混合运算
不同类型数据进行混合运算时 首先要把不同类型的数据转换成同一类型 然后进行运算 这种转换由编译系统自动完成 其转换遵守以下规则:

  1. 整型提升规则:如果参与运算的操作数有不同的整数类型,那么会将低精度的整型提升为高精度的整型。整型提升按照以下顺序进行:char -> short -> int -> unsigned int -> long -> unsigned long -> long long -> unsigned long long
  2. 浮点数类型提升规则:如果参与运算的操作数有不同的浮点数类型,那么会将低精度的浮点数类型提升为高精度的浮点数类型。浮点数类型提升按照以下顺序进行:float -> double -> long double
  3. 隐式类型转换规则:当进行混合运算时,C语言会自动进行隐式类型转换,以便使得运算能够进行。在隐式类型转换中,从低精度到高精度的类型转换是安全的,但从高精度到低精度的类型转换可能导致精度丢失或溢出。

下面是一个简单的关系图表,展示了混合运算中数据类型之间的转换关系:
image.png
这个关系图表以数据类型的精度和范围递增的方式排列,更高精度的类型在下方。随着从上到下的移动,类型提升的顺序也是逐步增加的。
以下是一些示例:

示例1:整型与浮点型的混合运算

int num1 = 5;
float num2 = 2.5;
float result = num1 + num2; // 自动将整型转换为浮点型后相加

示例2:不同精度的浮点型运算

float num1 = 3.14;
double num2 = 2.71828;
double result = num1 + num2; // 自动将低精度的浮点型转换为高精度后相加

示例3:字符与数字的混合运算

char ch = 'A';
int num = 5;
int result = ch + num; // 将字符 'A' 转换为 ASCII 码值 65 后与数字相加

2、赋值运算中的数据类型转换

在赋值运算中,数据类型转换是指将一个数据类型的值赋给另一个不同数据类型的变量。这种转换通常发生在两个数据类型之间存在不兼容的情况下,例如将一个整数赋给一个浮点数变量,或将一个字符赋给一个整数变量。
数据类型转换可以分为隐式转换和显式转换两种形式:

  1. 隐式转换:当表达式涉及到不同数据类型时,编程语言会自动进行数据类型转换,以便使表达式能够正确执行。这种转换是自动进行的,无需程序员明确指定。
int num = 10;
float total = num;  // 隐式转换:将整数类型转换为浮点数类型
  1. 显式转换:有时候需要显式地告诉编译器要进行的数据类型转换,这时候就需要使用显式转换操作符(也称为强制类型转换)。显式转换可以通过将目标数据类型放在圆括号中来完成。
float num1 = 3.14f;
int num2 = (int)num1;  // 显式转换:将浮点数类型转换为整数类型

需要注意的是,数据类型转换可能导致信息的丢失或精度的损失。例如将一个浮点数转换为整数时,小数部分将被截断。因此,在进行数据类型转换时,应该谨慎处理,并确保不会导致意外的结果。

3、强制类型转换

C语言中的强制类型转换(Type Casting)是一种将一个数据类型转换为另一个数据类型的操作。它可以在某些情况下改变数据的存储方式,以便更好地满足程序的需求。
强制类型转换的语法如下:

(type) expression

其中,type表示要转换的目标数据类型,expression表示要进行转换的表达式。

下面是一些常见的强制类型转换的示例和说明:

  1. 将浮点数转换为整数:
float num1 = 3.14;
int num2 = (int) num1;

在上述示例中,将浮点数num1强制转换为整数类型,结果存储在变量num2中。强制转换会将浮点数的小数部分截断,只保留整数部分。

  1. 将整数转换为浮点数:
int numa = 10;
float numb = (float) numa;

在上述示例中,将整数numa强制转换为浮点数类型,结果存储在变量numb中。强制类型转换会将整数转换为相应的浮点数表示。

  1. 将指针类型转换为另一种指针类型:
int* ptr1;
char* ptr2 = (char*) ptr1;

在上述示例中,将指针ptr1强制转换为char类型的指针,并将结果存储在变量ptr2中。强制转换可以改变指针的解释方式,将指针指向的数据按照不同类型进行解释。

  1. 将较大的整数类型转换为较小的整数类型:
long numx = 1000000;
int numy = (int) numx;

在上述示例中,将较大的整数numx强制转换为较小的整数类型,结果存储在变量numy中。强制类型转换可能导致数据溢出或丢失精度,需要注意。在进行强制类型转换时,需要谨慎考虑数据的范围和精度,并确保是安全合理的。

四、枚举类型

枚举类型是一种用户自定义的数据类型,用于列举一组相关的常量。它提供了一种更可读和易于理解的方式来表示固定的取值范围。

定义枚举类型

在C语言中,可以使用 enum 关键字来定义枚举类型。枚举类型的定义通常在函数外部或文件的顶部进行

enum Season{
    SPRING,
    SUMMER,
    AUTUMN,
    WINTER
};

上述代码定义了一个名为Season的枚举类型,其中包含了四个枚举常量:SPRING、SUMMER、AUTUMN和WINTER。这些枚举常量被视为整数值,在默认情况下,从0开始递增,依次分配给每个常量。

枚举常量的值

可以为枚举常量显式指定值。如果未显式指定值,则编译器将按照默认规则设置值

enum Month{
    JANUARY = 1,
    FEBRUARY,
    MARCH = 3,
    APRIL,
    MAY,
    JUNE
};

enum Color{
    RED = 10,
    GREEN = 20,
    BLUE = 30
};

在上述代码中,Month枚举类型的前两个常量被显式赋值为1和2。后续枚举常量将按照递增规则进行分配。类似的,在Color枚举类型中,RED、GREEN和BLUE常量被显式赋值为10、20和30。
给枚举常量赋值的意义在于为其指定一个具体的值,以便在代码中使用这个值时可以更加清晰地表达其含义。枚举常量通常用于表示一组相关的值,可以在代码中反复使用,而且可以为不同的值指定不同的含义和用途。在某些情况下,枚举常量也可以用于在代码中强制执行某些约束条件,例如限制某个变量的取值范围或约束某个操作的执行方式。通过为枚举常量赋值,可以确保代码中的变量或操作符合预期的约束条件,从而提高了代码的可读性和可维护性。
总之,给枚举常量赋值有助于提高代码的可读性和可维护性,并有助于确保代码的正确性和稳定性。

使用枚举类型

可以声明变量并使用枚举类型来存储枚举常量。

enum Season currentSeason;
currentSeason = SUMMER;

enum Month currentMonth = MAY;

if(currentSeason == SUMMER){
    printf("It's summer!\n");
}

switch(currentMonth){
    case JANUARY:
        printfI("It's January.\n");
        break;
    case FEBRUARY:
        printf("It's February.\n");
        break;
        //...
}

在上述代码中,我们声明了一个名为currentSeason的变量,并将其设置为SUMMER枚举常量。同样的,我们声明了一个名为currentMonth的变量,并将其设置为MAY枚举常量。我们可以使用**==运算符进行枚举常量的比较,也可以在switch**语句中使用枚举常量进行条件判断和流程控制。

枚举类型的优势

  • 增强代码的可读性:使用枚举类型可以使用具有描述性的常量名称,使代码更易于理解和维护。
  • 提供编译时检查:在使用枚举类型时,编译器可以检查是否使用了正确的枚举值,从而减少错误。

总结

枚举类型时一种用户自定义的数据类型,用于列举一组相关的常量。它提供了一种更可读和易于理解的方式来表示固定的取值范围。通过enum关键字进行定义,可以显式或隐式的为枚举常量指定值。枚举类型在增加代码可读性和提供编译时检查方面具有优势。

综合示例

#include<stdio.h>

enum Weekdays{
    MONDAY,
    TUESDAY,
    WENDESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY,
    SUNDAY
};

int main(){
    enum Weekdays today = TUESDAY;

    if(today == SATURDAY || today == SUNDAY){
        printf("It's a weekend!\n");
    }else{
        printf("It's a weekday.\n");
    }
    
    return 0;
}

image.png
在上面的示例中,我们定义了一个枚举类型Weekdays来表示一周的不同天。通过给每个取值赋予具有意义的名称,代码更加易读。然后,在**main()**函数中,我们声明了一个变量today并将其赋值为TUESDAY,最后根据这个值打印出对应的信息。

五、数组类型

程序设计语言为了处理类似的批量数据,提供了一种组织数据的机制——数组。C语言也不例外。
C语言中的数组是一种存储相同类型数据的连续内存区域。它可以包含多个元素,这些元素可以通过索引来访问和操作。数组在C语言中非常常用,用于存储和处理大量数据。

数组的声明需要指定数组的类型和大小。语法如下:

type arrayName[size];

其中,type表示数组元素的类型,arrayName是数组的名称,size表示数组的大小。数组的大小必须是一个常量表达式。

下面是一个例子,声明了一个存储5个整数的数组:

int numbers[5];

数组的索引从0开始,因此第一个元素的索引是0,第二个元素的索引是1,以此类推。可以使用索引来访问和修改数组中的元素。

numbers[0] = 10;
numbers[1] = 20;

数组元素的访问、修改和遍历可以使用循环语句来简化操作:

int len = sizeof(number)/sizeof(int); //计算数组元素个数

for (int i = 0; i < len; i++) {
    numbers[i] = i * 10;
}

int index = 0;
while (index < len)
{
    printf("index:%d value:%d\n", index,number[index]);//当前的元素
    index++;//数组元素索引值+1
}

image.png
数组也可以用于存储其他类型的数据,如字符、浮点数等。使用相应的类型来声明数组即可。

除了一维数组,C语言还支持多维数组。多维数组可以理解为数组的数组,可以用于表示更复杂的数据结构。例如,可以声明一个二维数组来表示矩阵:

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

上述代码声明了一个3x3的整数矩阵,并初始化了每个元素的值。
二维数组的四种遍历方式示例:

/*Function:二维数组的四种遍历方式:a[i][j],*(a[i]+j),*(*(a+i)+j),*(&a[0][0]+i*n+j) */
#include <stdio.h>
int main(){
        int i,j;
        int a[3][3]={
            {1,2,3},
            {4,5,6},
            {7,8,9},
        };
 
        printf("方式一:a[i][j]\n");     //方式一
        for(i=0;i<3;i++){
                for(j=0;j<3;j++){
                        printf("%d ",a[i][j]);
                }
            printf("\n");
        }
 
        printf("\n方式二:*(a[i]+j)\n"); //方式二
        for(i=0;i<3;i++){
                for(j=0;j<3;j++){
                        printf("%d ",*(a[i]+j));
                }
            printf("\n");
        }
 
        printf("\n方式三:*(*(a+i)+j)\n"); //方式三
        for(i=0;i<3;i++){
                for(j=0;j<3;j++){
                        printf("%d ",*(*(a+i)+j));
                }
            printf("\n");
        }
 
        printf("\n方式四:*(&a[0][0]+i*3+j)\n"); //方式四
        for(i=0;i<3;i++){
                for(j=0;j<3;j++){
                        printf("%d ",*(&a[0][0]+i*3+j));
                }
            printf("\n");
        }
    
    return 0;
}

image.png

总结

  1. 数组是一种存储相同类型数据的数据结构。
  2. 数组的声明需要指定数组的类型和大小。
  3. 数组的大小必须是一个常量表达式。
  4. 数组的索引从0开始,可以使用索引来访问和修改数组中的元素。
  5. 可以使用循环语句和索引来遍历数组中的元素。
  6. 数组可以用于存储不同类型的数据,如整数、字符、浮点数等。
  7. C语言还支持多维数组,用于表示更复杂的数据结构。

六、结构体类型

在编程中,结构体是一种自定义的数据类型,它允许您将多个不同类型的变量组合在一起,形成一个更复杂的数据结构。通过结构体,您可以为这些变量定义一个共同的名称,并以这种方式存储和操作它们。
结构体的定义使用关键字struct,后跟结构体的名称和包含在结构体中的变量的列表。每个变量都有一个名称和一个类型。
以下是一个示例结构体的定义:

struct Person {
    char name[50];
    int age;
    float height;
};

在上面的示例中,我们定义了一个名为Person的结构体,它有三个成员变量:name、age和height。name是一个字符数组,用于存储人的姓名;age是一个整数,用于存储人的年龄;height是一个浮点数,用于存储人的身高。
接下来,我们可以声明一个该结构体类型的变量,并对其进行初始化和使用:

struct Person person1;  // 声明一个结构体变量

strcpy(person1.name, "John Doe");  // 对成员变量赋值
person1.age = 25;
person1.height = 1.75;

printf("姓名:%s\n", person1.name);  // 访问成员变量并输出
printf("年龄:%d\n", person1.age);
printf("身高:%.2f\n", person1.height);

在上面的示例中,我们声明了一个名为person1的结构体变量,并使用点运算符.访问成员变量并对其进行赋值。最后,我们使用printf函数输出结构体变量的成员变量。
除了点运算符,还可以使用箭头运算符->来访问结构体指针的成员变量。

struct Person *personPtr = &person1;
printf("姓名:%s\n", personPtr->name);  // 使用箭头运算符访问成员变量 

七、共同体类型

八、指针类型

九、空类型

  • 16
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,针对您的需求,我们可以设计一个系统,实现医药公司定期对各药品的销售记录进行统计,并按药品编号、单价、销售量或销售额做出排序。以下是一个简单的设计分析: 1. 定义一个结构体 DataType,用于存储药品信息,包括药品编号、药品名称、单价、销售量、销售额; 2. 定义一个顺序表 sequenList,用于存储所有药品的信息记录; 3. 读取数据文件,将各药品的信息记录存储在 sequenList 中; 4. 设计四个排序函数,分别按药品编号、单价、销售量、销售额进行排序; 5. 在每次统计时,调用对应的排序函数,将药品信息按照指定方式排序,并输出统计结果。 以下是一个简单的示例代码: ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #define maxsize 100 typedef struct node{ char num[4]; /*药品编号*/ char name[10]; /*药品名称*/ float price; /*单价*/ int count; /*销售量*/ float sale; /*销售额*/ }DataType; typedef struct{ DataType r[maxsize]; int length; }sequenList; void read_data_file(sequenList* list); void sort_by_num(sequenList* list); void sort_by_price(sequenList* list); void sort_by_count(sequenList* list); void sort_by_sale(sequenList* list); int main() { sequenList list; list.length = 0; read_data_file(&list); sort_by_num(&list); sort_by_price(&list); sort_by_count(&list); sort_by_sale(&list); return 0; } void read_data_file(sequenList* list) { FILE* fp; DataType data; fp = fopen("data.txt", "r"); if (fp == NULL) { printf("Failed to read data file.\n"); exit(1); } while (fscanf(fp, "%s %s %f %d %f", data.num, data.name, &data.price, &data.count, &data.sale) != EOF) { list->r[list->length++] = data; } fclose(fp); } void sort_by_num(sequenList* list) { int i, j; DataType temp; for (i = 0; i < list->length; i++) { for (j = i + 1; j < list->length; j++) { if (strcmp(list->r[i].num, list->r[j].num) > 0) { temp = list->r[i]; list->r[i] = list->r[j]; list->r[j] = temp; } } } printf("Sort by num:\n"); for (i = 0; i < list->length; i++) { printf("%s %s %.2f %d %.2f\n", list->r[i].num, list->r[i].name, list->r[i].price, list->r[i].count, list->r[i].sale); } } void sort_by_price(sequenList* list) { int i, j; DataType temp; for (i = 0; i < list->length; i++) { for (j = i + 1; j < list->length; j++) { if (list->r[i].price > list->r[j].price) { temp = list->r[i]; list->r[i] = list->r[j]; list->r[j] = temp; } } } printf("Sort by price:\n"); for (i = 0; i < list->length; i++) { printf("%s %s %.2f %d %.2f\n", list->r[i].num, list->r[i].name, list->r[i].price, list->r[i].count, list->r[i].sale); } } void sort_by_count(sequenList* list) { int i, j; DataType temp; for (i = 0; i < list->length; i++) { for (j = i + 1; j < list->length; j++) { if (list->r[i].count > list->r[j].count) { temp = list->r[i]; list->r[i] = list->r[j]; list->r[j] = temp; } } } printf("Sort by count:\n"); for (i = 0; i < list->length; i++) { printf("%s %s %.2f %d %.2f\n", list->r[i].num, list->r[i].name, list->r[i].price, list->r[i].count, list->r[i].sale); } } void sort_by_sale(sequenList* list) { int i, j; DataType temp; for (i = 0; i < list->length; i++) { for (j = i + 1; j < list->length; j++) { if (list->r[i].sale > list->r[j].sale) { temp = list->r[i]; list->r[i] = list->r[j]; list->r[j] = temp; } } } printf("Sort by sale:\n"); for (i = 0; i < list->length; i++) { printf("%s %s %.2f %d %.2f\n", list->r[i].num, list->r[i].name, list->r[i].price, list->r[i].count, list->r[i].sale); } } ``` 需要注意的是,以上代码仅为示例代码,可能存在实际应用中需要优化的地方。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值