C语言之结构体和共用体详解
目录
结构体
结构体的定义和使用
结构体数组的使用
结构体指针的使用
结构体大小的计算
共用体
共用体的定义和使用
typedef用法详解
enum枚举类型
结构体
结构体的定义和使用
C语言的结构体(Struct)是一种自定义的数据类型,它允许我们将不同类型的数据组合在一起,形成一个新的复合数据类型。结构体可以包含多个成员变量,每个成员变量可以有不同的数据类型,这使得结构体能够表示更复杂的数据结构。
以下是关于C语言结构体的详细说明:
1、结构体的定义
结构体的定义使用关键字 struct,后面跟着结构体的名称和一对大括号 {}。在大括号内部,我们可以定义多个成员变量,每个成员变量由类型和名称组成,用分号 ; 分隔。
定义一般形式如下:
struct 结构类型名
{ 数据类型 成员名 1; 数据类型 成员名 2; ...... 数据类型 成员名 n;
};
例如,struct Person { char name[20]; int age; float height; }; 定义了一个名为 Person 的结构体,它包含了一个字符数组 name、一个整型变量 age 和一个浮点型变量 height。
2、结构体的声明和初始化
在定义结构体之后,我们可以通过声明结构体变量来使用它。结构体变量的声明方式与普通变量类似,需要指定结构体的类型和变量名。例如,struct Person person1; 声明了一个名为 person1 的结构体变量。我们也可以在声明结构体变量的同时进行初始化,使用一对大括号 {} 将初始化的值括起来,按照成员变量的顺序进行赋值。
结构初始化的一般形式如下:
struct 结构类型名 结构变量 = { 初始化数据 1, ...... 初始化数据 n };
例如,struct Person person2 = { "Alice", 25, 1.65 }; 将结构体变量 person2 的成员变量分别初始化为 "Alice"、25 和 1.65。
3、结构体成员的访问
结构体的成员变量可以使用点运算符 . 来访问。
例如,person1.age = 30; 将结构体变量 person1 的 age 成员变量赋值为 30。我们也可以通过结构体指针来访问结构体的成员变量,使用箭头运算符 ->。
例如,struct Person *ptr = &person1; ptr->age = 30; 使用结构体指针 ptr 访问 person1 的 age 成员变量并赋值为 30。
4、结构体作为函数参数和返回值
我们可以将结构体作为函数的参数传递,以便在函数内部操作结构体的成员变量。可以通过值传递或指针传递结构体参数。如果结构体较大,建议使用指针传递,以避免复制整个结构体。同样,函数也可以返回结构体类型的值或指针。
下面是一个简单的示例代码,演示了结构体的使用:
#include <stdio.h>
#include <string.h>
struct Person {char name[20];int age;float height;
};void printPerson(struct Person p) {printf("Name: %s\n", p.name);printf("Age: %d\n", p.age);printf("Height: %.2f\n", p.height);
}int main() {struct Person person1 = { "Alice", 25, 1.65 };printPerson(person1);struct Person person2;strcpy(person2.name, "Bob");person2.age = 30;person2.height = 1.75;printPerson(person2);return 0;
}
在上述示例中,我们定义了一个名为 Person 的结构体,它包含了三个成员变量 name、age 和 height。然后,我们定义了一个名为 printPerson 的函数,它接受一个结构体类型的参数 p,并在函数内部打印结构体的成员变量。
在 main 函数中,我们声明了两个结构体变量 person1 和 person2,并分别对它们的成员变量进行赋值。然后,我们调用 printPerson 函数来打印结构体的内容。
输出结果:
Name: Alice
Age: 25
Height: 1.65
Name: Bob
Age: 30
Height: 1.75
这个示例展示了结构体的基本用法。结构体允许我们将不同类型的数据组合在一起,形成一个新的复合数据类型,从而更好地表示和操作复杂的数据结构。
结构体数组的使用
C语言的结构体数组(Struct Array)是一种将多个结构体对象组合在一起的数据类型。它允许我们定义一个包含多个结构体对象的数组,每个结构体对象都可以包含多个成员变量,这使得结构体数组能够表示更复杂的数据结构。
以下是关于C语言结构体数组的详细说明:
1、结构体数组的定义
结构体数组的定义与普通数组类似,需要指定数组的类型、名称和长度。
例如,struct Person people[3]; 定义了一个名为 people 的结构体数组,它包含了三个元素,每个元素都是一个 Person 结构体对象。
2、结构体数组的初始化
结构体数组的初始化方式与普通数组类似,可以使用一对大括号 {} 将初始化的值括起来,按照数组元素的顺序进行赋值。每个元素的初始化值也可以使用一对大括号 {},按照结构体成员变量的顺序进行赋值。
例如,struct Person people[3] = { {"Alice", 25, 1.65}, {"Bob", 30, 1.75}, {"Charlie", 35, 1.80} }; 初始化了一个包含三个 Person 结构体对象的结构体数组 people。
3、结构体数组的访问
结构体数组的元素可以使用下标运算符 [] 来访问。例如,people[0].age = 26; 将结构体数组 people 的第一个元素的 age 成员变量赋值为 26。我们也可以通过结构体指针来访问结构体数组的元素,使用箭头运算符 ->。
例如,struct Person *ptr = &people[1]; ptr->age = 31; 使用结构体指针 ptr 访问 people 的第二个元素的 age 成员变量并赋值为 31。
4、结构体数组作为函数参数和返回值
我们可以将结构体数组作为函数的参数传递,以便在函数内部操作结构体数组的元素。可以通过值传递或指针传递结构体数组参数。如果结构体数组较大,建议使用指针传递,以避免复制整个结构体数组。同样,函数也可以返回结构体数组类型的值或指针。
下面是一个简单的示例代码,演示了结构体数组的使用:
#include <stdio.h>struct Person {char name[20];int age;float height;
};void printPeople(struct Person people[], int n) {for (int i = 0; i < n; i++) {printf("Name: %s\n", people[i].name);printf("Age: %d\n", people[i].age);printf("Height: %.2f\n", people[i].height);}
}int main() {struct Person people[3] = { {"Alice", 25, 1.65}, {"Bob", 30, 1.75}, {"Charlie", 35, 1.80} };printPeople(people, 3);return 0;
}
在上述示例中,我们定义了一个名为 Person 的结构体,它包含了三个成员变量 name、age 和 height。然后,我们定义了一个名为 printPeople 的函数,它接受一个结构体数组类型的参数 people 和一个整型变量 n,并在函数内部打印结构体数组的内容。
在 main 函数中,我们声明了一个包含三个 Person 结构体对象的结构体数组 people,并对它们的成员变量进行赋值。然后,我们调用 printPeople 函数来打印结构体数组的内容。
输出结果:
Name: Alice
Age: 25
Height: 1.65
Name: Bob
Age: 30
Height: 1.75
Name: Charlie
Age: 35
Height: 1.80
这个示例展示了结构体数组的基本用法。结构体数组允许我们将多个结构体对象组合在一起,形成一个新的复合数据类型,从而更好地表示和操作复杂的数据结构。
结构体指针的使用
C语言的结构体指针(Struct Pointer)是一种指向结构体对象的指针变量。使用结构体指针可以方便地操作和访问结构体的成员变量,同时也可以减少内存开销和提高程序的效率。以下是关于C语言结构体指针的详细说明:
1、结构体指针的定义
结构体指针的定义与普通指针类似,需要指定指针的类型和名称。
例如,struct Person *ptr; 定义了一个名为 ptr 的结构体指针,它可以指向 Person 结构体类型的对象。
2、结构体指针的赋值
结构体指针可以通过赋值操作指向一个具体的结构体对象。
例如,ptr = &person1; 将结构体指针 ptr 指向 person1 结构体对象的地址。
3、结构体指针的成员访问
通过结构体指针可以方便地访问结构体的成员变量。使用箭头运算符 -> 可以从结构体指针中访问结构体的成员变量。
例如,ptr->age = 25; 将结构体指针 ptr 所指向的结构体对象的 age 成员变量赋值为 25。
4、动态分配结构体指针的内存空间
可以使用 malloc 函数动态分配结构体指针的内存空间。
例如,struct Person *ptr = (struct Person *)malloc(sizeof(struct Person)); 动态分配了一个 Person 结构体对象的内存空间,并将其地址赋值给结构体指针 ptr。
5、结构体指针作为函数参数和返回值
结构体指针可以作为函数的参数传递,以便在函数内部操作结构体对象。通过指针传递结构体参数可以避免复制整个结构体对象,提高程序的效率。同样,函数也可以返回结构体指针类型的值或指针。
下面是一个简单的示例代码,演示了结构体指针的使用:
#include <stdio.h>
#include <stdlib.h>struct Person {char name[20];int age;float height;
};void printPerson(struct Person *ptr) {printf("Name: %s\n", ptr->name);printf("Age: %d\n", ptr->age);printf("Height: %.2f\n", ptr->height);
}int main() {struct Person person1 = {"Alice", 25, 1.65};struct Person *ptr = &person1;printPerson(ptr);struct Person *dynamicPtr = (struct Person *)malloc(sizeof(struct Person));dynamicPtr->age = 30;printf("Dynamic Person's Age: %d\n", dynamicPtr->age);free(dynamicPtr);return 0;
}
在上述示例中,我们定义了一个名为 Person 的结构体,它包含了三个成员变量 name、age 和 height。然后,我们定义了一个名为 printPerson 的函数,它接受一个结构体指针类型的参数 ptr,并在函数内部打印结构体指针所指向的结构体对象的内容。
在 main 函数中,我们声明了一个 Person 结构体对象 person1,并使用 & 运算符获取其地址,并将其赋值给结构体指针 ptr。然后,我们调用 printPerson 函数来打印结构体指针所指向的结构体对象的内容。
接下来,我们使用 malloc 函数动态分配了一个 Person 结构体对象的内存空间,并将其地址赋值给结构体指针 dynamicPtr。我们可以通过结构体指针 dynamicPtr 访问和修改动态分配的结构体对象的成员变量。最后,我们使用 free 函数释放了动态分配的内存空间,以防止内存泄漏。
输出结果:
Name: Alice
Age: 25
Height: 1.65
Dynamic Person's Age: 30
这个示例展示了结构体指针的基本用法。结构体指针可以方便地操作和访问结构体的成员变量,并且可以通过动态分配内存空间来创建和释放结构体对象,从而灵活地管理内存。
结构体大小的计算
在C语言中,结构体的大小是由其成员变量的大小和对齐方式决定的。计算结构体大小的过程如下(详细可见这篇文章):
1、计算成员变量的大小:
首先,需要计算每个成员变量的大小。对于基本数据类型,可以使用 sizeof 运算符获取其大小。例如,sizeof(int) 返回整型的大小。对于数组类型的成员变量,需要将数组元素的大小乘以数组的长度。
2、对齐成员变量:
结构体的成员变量通常需要按照某种对齐方式排列,以提高内存访问的效率。对齐方式是根据编译器和平台的不同而有所差异的,一般遵循下列规则:
- 成员变量的对齐值为其自身大小和编译器默认对齐值中较小的一个。
- 结构体的对齐值为结构体中最大的成员变量的对齐值。
3、计算结构体的大小:
结构体的大小是成员变量大小之和,再根据对齐方式进行调整。通常,结构体的大小是成员变量大小之和的倍数,且不小于结构体中最大的成员变量的大小。
以下是一个示例来说明结构体大小的计算过程:
#include <stdio.h>struct Example {char c;int i;double d;
};int main() {struct Example ex;printf("Size of char: %zu\n", sizeof(char));printf("Size of int: %zu\n", sizeof(int));printf("Size of double: %zu\n", sizeof(double));printf("Size of struct Example: %zu\n", sizeof(struct Example));return 0;
}
在上述示例中,我们定义了一个名为 Example 的结构体,它包含了一个字符型变量 c、一个整型变量 i 和一个双精度浮点型变量 d。在 main 函数中,我们使用 sizeof 运算符分别打印了各个数据类型的大小以及结构体 Example 的大小。
输出结果:
Size of char: 1
Size of int: 4
Size of double: 8
Size of struct Example: 16
需要注意的是,编译器和平台可能会有不同的对齐方式和默认对齐值,因此不同的环境下计算出的结构体大小可能会有所差异。可以使用 #pragma pack 指令或编译器的特定选项来改变对齐方式和对齐值。
共用体
共用体的定义和使用
共用体(Union)是C语言中的一种特殊数据类型,它允许在相同的内存空间中存储不同类型的数据。共用体的定义和使用如下所示:
1、定义共用体:
共用体的定义与结构体类似,使用 union 关键字,后跟共用体的名称和成员变量列表。共用体的成员变量可以是不同的数据类型,但它们共享同一块内存空间。
union MyUnion {int i;float f;char c;
};
在上述示例中,我们定义了一个名为 MyUnion 的共用体,它包含了一个整型变量 i、一个浮点型变量 f 和一个字符型变量 c。
2、使用共用体:
可以通过共用体的名称和成员变量名来访问共用体的成员变量。由于共用体的成员变量共享同一块内存空间,只能同时存储其中一个成员变量的值。
union MyUnion u;
u.i = 10;
printf("Value of i: %d\n", u.i);
u.f = 3.14;
printf("Value of f: %.2f\n", u.f);
在上述示例中,我们声明了一个 MyUnion 类型的变量 u,并分别给 u.i 和 u.f 赋值。由于它们共享同一块内存空间,改变其中一个成员变量的值会影响到其他成员变量。
3、共用体的大小:
共用体的大小是其最大成员变量的大小。因为共用体的成员变量共享同一块内存空间,所以共用体的大小足够容纳最大的成员变量即可。
使用 sizeof 运算符可以获取共用体的大小。
需要注意的是,共用体虽然灵活,但也存在潜在的问题。由于共用体的成员变量共享同一块内存空间,因此在使用共用体时需要小心,确保对成员变量的访问和修改是合法的。此外,共用体的使用也可能导致类型转换和内存对齐等问题,因此在使用共用体时需要谨慎考虑。
下面是一个完整的示例代码,演示了共用体的定义和使用:
#include <stdio.h>union MyUnion {int i;float f;char c;
};int main() {union MyUnion u;u.i = 10;printf("Value of i: %d\n", u.i);u.f = 3.14;printf("Value of f: %.2f\n", u.f);printf("Size of union MyUnion: %zu\n", sizeof(union MyUnion));return 0;
}
输出结果:
Value of i: 10
Value of f: 3.14
Size of union MyUnion: 4
根据输出结果可知,共用体 MyUnion 的大小是4字节,因为 int 类型的大小为4字节,是共用体中最大的成员变量。
总结一下,共用体是C语言中一种特殊的数据类型,允许在相同的内存空间中存储不同类型的数据。它的定义和使用方式与结构体类似,但共用体的成员变量共享同一块内存空间。需要注意共用体的大小、成员变量的访问和修改,以及潜在的类型转换和内存对齐问题。
typedef用法详解
在C语言中,typedef 是一个关键字,用于为已有的数据类型创建一个新的名称。它可以简化代码,提高可读性,并使代码更具可维护性。typedef 的用法如下:
1、为基本数据类型创建别名:
typedef 可以为基本数据类型(如 int、float、char 等)创建别名,使其在代码中使用起来更加直观。
typedef int myInt;
typedef float myFloat;
typedef char myChar;
在上述示例中,我们为 int 类型创建了别名 myInt,为 float 类型创建了别名 myFloat,为 char 类型创建了别名 myChar。
2、为结构体创建别名:
typedef 还可以为结构体创建别名,使结构体类型更易于使用。
typedef struct {int x;int y;
} Point;
在上述示例中,我们为一个匿名的结构体创建了别名 Point,该结构体包含了两个整型成员变量 x 和 y。
3、为指针类型创建别名:
typedef 还可以为指针类型创建别名,使指针类型的声明更加简洁明了。
typedef int* IntPtr;
typedef float* FloatPtr;
在上述示例中,我们为 int* 类型创建了别名 IntPtr,为 float* 类型创建了别名 FloatPtr。
4、为函数指针创建别名:
typedef 还可以为函数指针类型创建别名,使函数指针类型的声明更加简洁明了。
typedef int (*MathFunc)(int, int);
在上述示例中,我们为接受两个 int 类型参数并返回 int 类型结果的函数指针创建了别名 MathFunc。
使用 typedef 创建别名后,我们可以直接使用别名来声明变量,而无需再写出完整的数据类型。
下面是一个完整的示例代码,演示了 typedef 的用法:
#include <stdio.h>// 为基本数据类型创建别名
typedef int myInt;
typedef float myFloat;
typedef char myChar;// 为结构体创建别名
typedef struct {int x;int y;
} Point;// 为指针类型创建别名
typedef int* IntPtr;
typedef float* FloatPtr;// 为函数指针创建别名
typedef int (*MathFunc)(int, int);// 定义一个函数,接受两个 int 类型参数并返回它们的和
int sum(int a, int b) {return a + b;
}int main() {// 使用别名声明变量myInt num = 10;myFloat pi = 3.14;myChar letter = 'A';Point p;p.x = 5;p.y = 3;IntPtr pInt;FloatPtr pFloat;MathFunc add = sum;int result = add(2, 3);// 输出变量的值printf("num = %d\n", num);printf("pi = %.2f\n", pi);printf("letter = %c\n", letter);printf("p.x = %d, p.y = %d\n", p.x, p.y);printf("result = %d\n", result);return 0;
}
输出结果:
num = 10
pi = 3.14
letter = A
p.x = 5, p.y = 3
result = 5
根据输出结果可知,我们使用 typedef 创建的别名来声明变量,使代码更加简洁易读。
enum枚举类型
在 C 语言中,enum 是一种枚举类型,用于定义一个新的数据类型,该类型的取值只能是预先定义好的一些枚举常量。枚举类型可以使代码更加易读易懂,同时也可以提高代码的可维护性。
枚举类型的定义格式如下:
enum 枚举名 {枚举常量1,枚举常量2,...
};
其中,枚举名是新定义的枚举类型的名称,枚举常量是该枚举类型中定义的可取值的常量。枚举常量默认从 0 开始递增,也可以手动指定初始值。例如:
enum Color {RED, // 枚举常量 RED 的值为 0GREEN, // 枚举常量 GREEN 的值为 1BLUE // 枚举常量 BLUE 的值为 2
};enum Status {OK = 200, // 枚举常量 OK 的值为 200BAD_REQUEST, // 枚举常量 BAD_REQUEST 的值为 201NOT_FOUND // 枚举常量 NOT_FOUND 的值为 202
};
在上述示例中,我们分别定义了两个枚举类型 Color 和 Status,并为它们定义了一些枚举常量。在第一个枚举类型中,我们未手动指定枚举常量的值,因此它们默认从 0 开始递增。在第二个枚举类型中,我们手动指定了枚举常量的初始值。
定义完枚举类型后,我们可以使用该枚举类型来声明变量。例如:
enum Color c = RED;
enum Status s = OK;
在上述示例中,我们使用 enum 定义的枚举类型 Color 和 Status 来声明了变量 c 和 s,并分别将它们的值初始化为 RED 和 OK。
枚举类型还可以与 switch 语句一起使用,使代码更加清晰易懂。例如:
enum Color c = GREEN;switch (c) {case RED:printf("The color is red.\n");break;case GREEN:printf("The color is green.\n");break;case BLUE:printf("The color is blue.\n");break;default:printf("Unknown color.\n");break;
}
在上述示例中,我们使用 enum 定义的枚举类型 Color 来声明了变量 c,并将其值初始化为 GREEN。然后,我们使用 switch 语句根据变量 c 的值输出不同的结果。
总结一下,enum 是 C 语言中的一种枚举类型,用于定义一个新的数据类型,该类型的取值只能是预先定义好的一些枚举常量。枚举类型可以使代码更加易读易懂,同时也可以提高代码的可维护性。我们可以使用 enum 定义枚举类型,并为枚举常量手动指定初始值。定义完枚举类型后,我们可以使用该枚举类型来声明变量,并与 switch 语句一起使用。
下面是一个使用 enum 的代码示例,该示例定义了一个枚举类型 Weekday,并在 main 函数中使用该枚举类型输出当前是星期几:
#include <stdio.h>// 定义枚举类型 Weekday
enum Weekday {MON,TUE,WED,THU,FRI,SAT,SUN
};int main() {// 获取当前是星期几int weekday = 1; // 假设今天是星期二// 使用 switch 语句根据 weekday 输出不同的结果switch (weekday) {case MON:printf("Today is Monday.\n");break;case TUE:printf("Today is Tuesday.\n");break;case WED:printf("Today is Wednesday.\n");break;case THU:printf("Today is Thursday.\n");break;case FRI:printf("Today is Friday.\n");break;case SAT:printf("Today is Saturday.\n");break;case SUN:printf("Today is Sunday.\n");break;default:printf("Invalid weekday.\n");break;}return 0;
}
在上述示例中,我们首先定义了一个枚举类型 Weekday,并为其定义了七个枚举常量,分别代表星期一到星期日。然后,在 main 函数中,我们假设今天是星期二,将其赋值给变量 weekday。最后,我们使用 switch 语句根据变量 weekday 输出不同的结果。由于 weekday 的值为 1,因此输出的结果是 "Today is Tuesday."。
练习题
练习一
参考答案
#include <stdio.h>
#include <string.h>void copySubstring(char* dest, const char* src, int m) {int length = strlen(src);if (m > length) {// 如果起始位置超过字符串长度,则无法复制子串dest[0] = '\0';return;}strcpy(dest, src + m - 1);
}int main() {int n, m;char str[100], substr[100];scanf("%d", &n);scanf("%s", str);scanf("%d", &m);copySubstring(substr, str, m);printf("%s\n", substr);return 0;
}
这个程序首先定义了一个名为copySubstring的函数,它接受三个参数:目标字符串的指针dest、源字符串的指针src和起始位置m。该函数使用strcpy函数将从第m个字符开始的全部字符复制到目标字符串中。
- 在main函数中,首先声明了变量n和m,分别表示字符串的长度和起始位置。然后,声明了两个字符数组str和substr,用于存储输入的字符串和复制后的子串。
- 接下来,通过scanf函数分别读取n、str和m的值。
- 然后,调用copySubstring函数将从第m个字符开始的子串复制到substr数组中。
- 最后,使用printf函数输出复制后的子串。
注意:这个程序假设输入的字符串长度不超过100个字符,并且起始位置m是合法的(即大于0且不超过字符串长度)。如果输入的字符串长度超过了数组的大小,可能会导致缓冲区溢出的问题。
练习二
参考答案
#include <stdio.h>typedef struct Grade {char subject[100]; // 学科名称char name[100]; // 学生姓名int ach[10]; // 学生成绩
} grade;int compare(int n, int count[]); // 比较函数声明int main() {int n, i;int count[100] = {0}; // 统计每个学生的总成绩int average1 = 0, average2 = 0, average3 = 0; // 各门课程的总成绩scanf("%d", &n);grade person[n]; // 存储学生信息的结构体数组for (i = 0; i < n; i++) {scanf("%s", person[i].subject);scanf("%s", person[i].name);scanf("%d %d %d", &(person[i].ach[0]), &(person[i].ach[1]), &(person[i].ach[2])); // 注意取址average1 += person[i].ach[0];average2 += person[i].ach[1];average3 += person[i].ach[2];count[i] = person[i].ach[0] + person[i].ach[1] + person[i].ach[2]; // 计算每个学生的总成绩}printf("%d %d %d\n", average1 / n, average2 / n, average3 / n); // 输出各门课程的平均成绩int high = compare(n, count); // 调用比较函数,获取最高分for (i = 0; i < n; i++) {if (count[i] == high) { // 匹配最高分的学生printf("%s %s ", person[i].subject, person[i].name);printf("%d %d %d", person[i].ach[0], person[i].ach[1], person[i].ach[2]);break; // 输出后跳出循环}}return 0;
}int compare(int n, int count[]) {int i, high = count[0];for (i = 0; i < n; i++) {if (count[i] < count[i + 1])high = count[i + 1]; // 找到最大的总成绩}return high;
}
该程序首先定义了一个名为grade的结构体类型,用于存储学科名称、学生姓名和学生成绩。然后,定义了一个名为compare的函数,用于比较每个学生的总成绩,找到最高分。
- 在main函数中,首先声明了变量n,表示学生数量,并通过scanf函数读取该值。接着,使用person数组存储每个学生的信息,包括学科名称、学生姓名和三门课的成绩。在输入过程中,需要注意使用&符号取得各个成绩的地址。同时,使用count数组统计每个学生的总成绩,并累加到各门课的总成绩中。
- 接下来,使用一个循环输出各门课程的平均成绩。首先,定义三个变量average1、average2和average3,分别表示三门课程的总成绩。然后,使用循环遍历每个学生的成绩,将其累加到对应的变量中。最后,输出各门课程的平均成绩。
- 接着,调用compare函数,比较每个学生的总成绩,找到最高分。然后,使用一个循环匹配最高分的学生,并输出其信息。注意,在输出最高分学生的成绩时,需要在最后一个成绩后面添加换行符\n。
- 最后,返回0,表示程序正常结束。
需要注意的是,该程序假设输入的学生数量不超过100,并且每个学生的姓名和学科名称不超过100个字符。
相关文章:

C语言之结构体和共用体详解
目录 结构体 结构体的定义和使用 结构体数组的使用 结构体指针的使用 结构体大小的计算 共用体 共用体的定义和使用 typedef用法详解 enum枚举类型 结构体 结构体的定义和使用 C语言的结构体(Struct)是一种自定义的数据类型,它允许…...

iOS插件
把平时看到或项目用到的一些插件进行整理,文章后面分享一些不错的实例,若你有其它的插件欢迎分享,不断的进行更新; 一:第三方插件 1:基于响应式编程思想的oc 地址:https://github.com/ReactiveCocoa/Rea…...

Maven第四章:配置文件详解
Maven第四章:配置文件详解 前言 本章重点知识:掌握setting.xml配置文件以及pom.xml配置文件 setting.xml配置文件 setting.xml文件用于配置Maven的运行环境,包括本地仓库的位置、镜像仓库的配置、认证信息等。以下是setting.xml文件的详细说明: 文件位置: 全局配置文件:…...

计算机网络基础一
任务背景 由于某些原因,某公司搬迁至新地方,现需要对公司网络环境重新调整规划,申请了一个 B 类 IP 地址 : 172.25.0.0 ,子 网掩码为 255.255.224.0 。需要根据公司部门和电脑数进行子网划分并分配 IP 。公司目前有 6 个部门&am…...

搜维尔科技:Touch触觉式力反馈设备与Touch X力反馈设备对比分析
此2款力反馈为最常用的力反馈设备...

SAP保持系统长时间在线
保持系统长时间在线 保持SAP系统长长时间在线不掉线,通过代码,保持一个页面一直在线,ABAP代码如下: *&---------------------------------------------------------------------* *& Report ZGUI *&----------------------------…...

威联通NAS进阶玩法之使用Docker搭建个人博客教程
Hello大家好,本篇教程主要教大家在威联通的NAS上搭建属于自己的个人博客网站,首先介绍一下我使用的机器,四盘位威联通TS-464C2,搭载四核四线程的N5095处理器,支持4K60帧的输出以及PCIE3.0,可玩性还是非常高的。废话不多…...

模型对象CSS2DObject始终在画布的左上角(问题解决)
写了个简单案例模拟一下这个问题,看下图片 下面看下c2渲染器相关代码部分 this.css2DRenderer new CSS2DRenderer(); this.css2DRenderer.render(this.scene, this.camera); this.css2DRenderer.setSize(width, height); this.css2DRenderer.domElement.style.pos…...

LabVIEW开发基于图像处理的车牌检测系统
LabVIEW开发基于图像处理的车牌检测系统 自动车牌识别的一般步骤是图像采集、去除噪声的预处理、车牌定位、字符分割和字符识别。结果主要取决于所采集图像的质量。在不同照明条件下获得的图像具有不同的结果。在要使用的预处理技术中,必须将彩色图像转换为灰度&am…...

Data Analysis With Python
文章目录 Data Analysis With PythonAnalyzing Numerical Data with NumPyCreating NumPy ArrayNumPy Array SlicingNumPy Array BroadcastingAnalyzing Data Using Pandas In this article, we will discuss how to do data analysis with Python. We will discuss all sorts …...

【Selenium】提高测试爬虫效率:Selenium与多线程的完美结合
前言 使用Selenium 创建多个浏览器,这在自动化操作中非常常见。 而在Python中,使用 Selenium threading 或 Selenium ThreadPoolExecutor 都是很好的实现方法。 应用场景: 创建多个浏览器用于测试或者数据采集;使用Selenium 控…...

ElCLib类解析
OpenCascade 中的 ElCLib 类提供了对基本曲线(例如 2D 和 3D 空间中的二次曲线和直线)进行基本几何计算的函数。它提供与参数化、点评估和曲线参数范围内的定位相关的各种操作和计算。以下是一些需要注意的要点: 点和矢量计算:ElC…...

栈、队列、矩阵的总结
栈的应用 括号匹配 表达式求值(中缀,后缀) 中缀转后缀(机算) 中缀机算 后缀机算 总结 特殊矩阵 对称矩阵的压缩存储 三角矩阵 三对角矩阵 稀疏矩阵的压缩存储...

PCL 半径滤波剔除噪点
目录 一、算法原理二、注意事项三、代码实现一、算法原理 PCL半径滤波是删除在输入的点云一定范围内没有达到足够多领域的所有数据点。通俗的讲:就是以一个点p给定一个范围r,领域点要求的个数为m,r若在这个点的r范围内部的个数大于m则保留,小于m则删除。因此,使用该算法时…...

Android SurfaceFlinger做Layer合成时,如何与HAL层进行交互
目录 零、本文讨论问题的范围一、问题:SurfaceFlinger图层合成选择实现方式的两难1.1 从OpenGL ES、HWC本身来讲1.2 以HWC为主导的判断逻辑 二、SurfaceFlinger与HAL层进行交互的具体实现框架2.1 SurfaceFlinger 调用 OpenGL ES 流程2.2 FrameBuffer2.3 SurfaceFlin…...

华为eNSP配置专题-策略路由的配置
文章目录 华为eNSP配置专题-策略路由的配置0、概要介绍1、前置环境1.1、宿主机1.2、eNSP模拟器 2、基本环境搭建2.1、终端构成和连接2.2、终端的基本配置 3、配置接入交换机上的VLAN4、配置核心交换机为网关和DHCP服务器5、配置核心交换机和出口路由器互通6、配置PC和出口路由器…...

JAVA实现智能停车场管理系统 开源
目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容A. 车主端功能B. 停车工作人员功能C. 系统管理员功能1. 停车位模块2. 车辆模块3. 停车记录模块4. IC卡模块5. IC卡挂失模块 三、界面展示3.1 登录注册3.2 车辆模块3.3 停车位模块3.4 停车数据模块3.5 IC卡档案模块3.6 IC卡挂…...

深入理解Docker之:存储卷相关概念详解和分析
深入理解Docker之:存储卷相关概念详解和分析 1. 为什么要使用存储卷 Docker镜像由多个只读层叠加而成,启动容器时,Docker会加载只读镜像层,并在镜像栈顶部添加一个读写层如果运行中的容器修改了现有的一个已经存在的文件&#x…...

Node.js的基本概念node -v 和npm -v 这两个命令的作用
Node.js 是一个开源且跨平台的 JavaScript 运行时环境,它可以让你在服务器端运行 JavaScript 代码。Node.js 使用了 Chrome 的 V8 JavaScript 引擎来执行代码,非常高效。 在 Node.js 出现之前,JavaScript 通常只在浏览器中运行,用…...

mysql bin_log日志恢复数据
1、开启bin_log日志 开启方式1 my.ini 下配置开启或者vi /etc/my.cnf log_binmysql-bin server_id1 2、参考文章 https://blog.csdn.net/DreamEhome/article/details/130010601 (重点) 【mysql】binlog日志_mysql binlog日志-CSDN博客 MySQL 开启binlog日志和windows服务…...

C++系列之list的模拟实现
💗 💗 博客:小怡同学 💗 💗 个人简介:编程小萌新 💗 💗 如果博客对大家有用的话,请点赞关注再收藏 🌞 list的节点类 template struct list_Node { public: list_Node* _prev; list_…...

什么情况下你会使用AI工具(chatgpt、bard)?
在当今数字化和智能化的时代,AI工具已成为许多领域的常见工具。在本文中,我将探讨什么情况下会使用AI工具。前言 – 人工智能教程 ChatGPT是一款由OpenAI开发的大型语言模型,可以生成文本、翻译语言、编写不同类型的创意内容,并以…...

【go】两数求和
文章目录 题目代码解法2 代码仓库 题目 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案…...

软考高项-成本管理
工具和技术 三点估算 通过考虑估算中的不确定性与风险,使用3种估算值来界定活动成本的近似区间,可以提高活动成本估算的准确性; 储备分析 为应对成本的不确定性,成本估算中可以包括应急储备。应急储备的管理方法: 将…...

24年FRM备考知识点以及一级公式表
FRM一级公示表以及备考知识点 链接:https://pan.baidu.com/s/17RpFF9OyfRk7FGtEQrxf3A?pwd1234 提取码:1234 FRM二级公示表以及备考知识点 链接:https://pan.baidu.com/s/175D05wV1p94dIfBZThutCQ?pwd1234 提取码:1234...

Spring Cloud学习:二【详细】
目录 Nacos的配置 Nacos的单机启动 服务注册 Nacos服务分级存储模型 优先访问同集群的服务 根据权重负载均衡 环境隔离Namespace Nacos调用流程 Nacos与Eureka注册对比 Nacos与Eureka的共同点 Nacos与Eureka的区别 Nacos配置管理 统一配置 配置自动刷新 多环境配…...

Unity的live2dgalgame多语言可配置剧情框架
这段代码用于读取表格 using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using OfficeOpenXml; using System.IO; using UnityEngine.Networking; using UnityEngine.UI; using Random UnityEngine.Random;public class Plots…...

再畅通工程(最小生成树)
题目描述:还是畅通工程 某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离。省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)&…...

前后端分离不可忽视的陷阱,深入剖析挑战,分享解决方案,助你顺利实施分离开发。
不管你设计的系统架构是怎么样,最后都是你的组织内的沟通结构胜出。这个观点一直在组织内不断地被证明,但也不断地被忽略。 前后端分离的利与弊 近几年,随着微服务架构风格的引入、前后端生态的快速发展、多端产品化的出现,前后…...

(四)库存超卖案例实战——优化redis分布式锁
前言 在上一节内容中,我们已经实现了使用redis分布式锁解决商品“超卖”的问题,本节内容是对redis分布式锁的优化。在上一节的redis分布式锁中,我们的锁有俩个可以优化的问题。第一,锁需要实现可重入,同一个线程不用重…...