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个字符。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/120869.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

时间、空间复杂度的例题详解

文章前言 上篇文章带大家认识了数据结构和算法的含义&#xff0c;以及理解了时间、空间复杂度&#xff0c;那么接下来来深入理解一下时间、空间复杂度。 时间复杂度实例 实例1 // 计算Func2的时间复杂度&#xff1f; void Func2(int N) {int count 0;for (int k 0; k <…

图的应用4.0-----关键路径(AOE网)

目录 前言 AOE网 1.基本概念 2.应用 关键路径 1.算法理论 2.代码实现&#xff08;C/C&#xff09; 前言 前面学习了图AOV网的应用&#xff0c;即拓扑排序&#xff0c;那这一期我们学习AOE网的应用&#xff0c;这是一个图的一个很广泛问题&#xff0c;也就是关键路径。那…

k8s中kubectl陈述式资源管理

目录 1、 理论 1.1、 管理k8s核心资源的三种基本方法 &#xff1a; 1.1.1陈述式的资源管理方法&#xff1a; 1.1.1.1、优点&#xff1a; 1.1.1.2、缺点&#xff1a; 1.1.2、声明式资源管理方法 1.1.3、GUI式资源管理方法 1.2、陈述式资源管理方法 2. 对资源的增、删、…

[推荐]Linux安装与配置虚拟机之虚拟机服务器坏境配置

&#x1f3ac; 艳艳耶✌️&#xff1a;个人主页 &#x1f525; 个人专栏 &#xff1a;《Spring与Mybatis集成整合》《Vue.js使用》 ⛺️ 越努力 &#xff0c;越幸运。 一.操作系统 1. 简介 操作系统&#xff08;perating System&#xff0c;简称OS&#xff09;是一种系统软件…

决定放弃uniapp开发了,因为它实在是没有taro友好

被uniapp折腾了两天&#xff0c;实在是受不了它对vue3的支持和react的支持&#xff0c;可以这么说&#xff0c;uniapp完全没有支持vue3和react&#xff0c;这么说我觉得一点也不过分。相对于折腾了两天uniapp来讲&#xff0c;我使用taro只花了1个小时不到&#xff0c;就可以完美…

【java学习—八】单例设计模式(5)

文章目录 1. 相关概念2. 单例设计模式-饿汉式3. 单例设计模式-懒汉式4. 总结 1. 相关概念 单例&#xff1a;只有一个实例&#xff08;实例化对象&#xff09; 设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。设计模式就像是经典的…

【鸿蒙软件开发】ArkTS通用事件

文章目录 前言一、点击事件1.1 基础介绍1.2 ClickEvent对象说明1.3 示例代码 二、触摸事件2.1 基础介绍2.2 ClickEvent对象说明2.3 示例代码 二、焦点事件2.2 基础介绍3.2 示例代码 总结 前言 在我们的ArkTS中有一些通用的事件&#xff0c;他们在所有的组件中都可以用&#xf…

网工内推 | 急招网工,思科、华为认证优先,法定节假日三薪

01 江苏臻云技术 招聘岗位&#xff1a;网络工程师 职责描述&#xff1a; 1、负责落实数据中心机房日常网络监测及巡检任务&#xff1b; 2、负责数据中心网络设备日常监控、变更、维护、巡检&#xff1b; 3、负责日常巡检报告、故障维护报告、变更申请的文档的编制&#xff1b;…

玩转ChatGPT:批量下载Alphafold的蛋白pdb文件

一、写在前面 突发奇想&#xff0c;想批量下载Alphafold网站的蛋白pdb文件&#xff0c;后续再做个分子对接用。又不想手动下载&#xff0c;来求助CSDN和GPT。 二、CSDN白嫖基础代码 CSDN大神多&#xff0c;这不&#xff0c;找到一个&#xff1a;Alphafold批量下载蛋白的pdb文…

Win10+Ubuntu20.04双系统双硬盘(SSD+HDD)安装与启动

Win10Ubuntu20.04双系统双硬盘安装与启动 前言准备工作Step 1: 备份你的数据Step 2: 制作安装Ubuntu的磁盘分区若以方式2进行安装&#xff1a;若以方式3进行安装&#xff1a; Step 3: 下载ubuntuStep 4: 制作ubuntu启动U盘Step 5: 从U盘启动ubuntuStep 6: 安装ubuntuStep 7: 系…

洗衣行业在线预约小程序+前后端完整搭建教程

大家好哇&#xff0c;好久不见&#xff01;今天源码师父来给大家推荐一款洗衣行业在线预约的小程序&#xff0c;带有前后端的完整搭建教程。 目前&#xff0c;人们对生活品质的追求不断提高&#xff0c;但生活节奏却也不断加快。对品质的追求遇到了忙碌的生活节奏&#xff0c;…

将安全作为首要目标 — Venus 的现状和前景展望

DeFi 的全面爆发将上一轮牛市推向巅峰。在不断的演化中&#xff0c;DeFi 领域也产生了很多新兴的细分领域&#xff0c;比如收益聚合器、合成资产、各种 DeFi 收益工具&#xff0c;以及最近整个市场都在讨论的 RWA 等。 DeFi 在不断进化&#xff0c;不变的是&#xff0c;DEX 和借…

使用内网穿透本地MariaDB数据库,并实现在公网环境下使用navicat图形化工具

公网远程连接MariaDB数据库【cpolar内网穿透】 文章目录 公网远程连接MariaDB数据库【cpolar内网穿透】1. 配置MariaDB数据库1.1 安装MariaDB数据库1.2 测试局域网内远程连接 2. 内网穿透2.1 创建隧道映射2.2 测试随机地址公网远程访问3. 配置固定TCP端口地址3.1 保留一个固定的…

Django 注册及创建订单商品

注册功能的实现 user/views from rest_framework.generics import GenericAPIView from rest_framework.views import APIViewfrom apps.user.models import User from apps.user.serializers import UserSerializer from utils import ResponseMessage from utils.jwt_auth …

P1868 饥饿的奶牛

根据题意可以知道是一个动态规划&#xff0c;看完数据范围之后可以知道是一个线性DP。 解决方法有点类似于背包问题&#xff0c;枚举背包的每一个空间。 如果把坐标轴上每个点都看成一个块儿&#xff0c;只需要按顺序求出前 i 个块儿的最大牧草堆数&#xff0c;f[i] 就是前i的…

进一步了解视频美颜SDK:美颜SDK的技术原理

美颜技术在当今的数字世界中变得越来越流行&#xff0c;尤其是在视频直播、社交媒体和视频通话应用中。用户寻求通过美颜效果增强自己的外观&#xff0c;这种需求催生了众多美颜SDK&#xff08;软件开发工具包&#xff09;的出现。这些SDK使开发者能够轻松地将美颜功能集成到他…

注意力机制、Transformer模型、生成式模型、目标检测算法、图神经网络、强化学习、深度学习模型可解释性与可视化方法等详解

采用“理论讲解案例实战动手实操讨论互动”相结合的方式&#xff0c;抽丝剥茧、深入浅出讲解注意力机制、Transformer模型&#xff08;BERT、GPT-1/2/3/3.5/4、DETR、ViT、Swin Transformer等&#xff09;、生成式模型&#xff08;变分自编码器VAE、生成式对抗网络GAN、扩散模型…

【代码思路】2023mathorcup 大数据数学建模B题 电商零售商家需求预测及库存优化问题

各位同学们好&#xff0c;我们之前已经发布了第一问的思路视频&#xff0c;然后我们现在会详细的进行代码和结果的一个讲解&#xff0c;然后同时我们之后还会录制其他小问更详细的思路以及代码的手把手教学。 大家我们先看一下代码这一部分&#xff0c;我们采用的软件是Jupyte…

通过流量安全分析发现主机异常

主机异常分析在计算机系统中具有重要意义。以下是主机异常分析的几个关键点&#xff1a; 1、检测安全威胁&#xff1a;主机是计算机系统的核心组件&#xff0c;通过对主机异常进行分析&#xff0c;可以快速检测到潜在的安全威胁&#xff0c;如恶意软件、病毒感染、黑客入侵等。…

js中的Formdata数据结构

这里写目录标题 一、基本概念二、常用方法1.append(name, value)、set(name, value)2.get()、getAll()3.has(name)4.delete(name)5.keys(),values(),entries() 三、其他细节1.for of遍历2.转为对象3.结合 URLSearchParams 转为queryString 一、基本概念 FormData 提供了一种表…