在C语言中,数组是一种基础且重要的数据结构,用于存储相同类型的多个元素,当需要将用户输入的数据(如数据库记录)保存到数组中时,需要结合数组的定义、输入方法、数据存储逻辑以及动态扩容等技巧来实现,以下将详细说明如何使用C语言数组保存输入的数据库数据,涵盖静态数组、动态数组、结构体数组等场景,并提供具体代码示例和注意事项。
使用静态数组保存固定大小的数据库记录
静态数组在声明时需要指定固定大小,适用于数据量已知且不会变化的场景,假设要保存学生的学号和姓名,可以定义一个结构体数组,并通过循环接收用户输入。
#include <stdio.h> #include <string.h> #define MAX_STUDENTS 100 // 最大学生数量 struct Student { int id; // 学号 char name[50]; // 姓名 }; int main() { struct Student students[MAX_STUDENTS]; // 静态结构体数组 int count = 0; // 实际存储的学生数量 printf("请输入学生数量(最多%d人):", MAX_STUDENTS); scanf("%d", &count); getchar(); // 清除输入缓冲区中的换行符 for (int i = 0; i < count; i++) { printf("请输入第%d个学生的学号:", i + 1); scanf("%d", &students[i].id); getchar(); // 清除换行符 printf("请输入第%d个学生的姓名:", i + 1); fgets(students[i].name, sizeof(students[i].name), stdin); students[i].name[strcspn(students[i].name, "\n")] = '\0'; // 去除fgets读取的换行符 } // 输出保存的数据 printf("\n学生信息如下:\n"); printf("学号\t姓名\n"); for (int i = 0; i < count; i++) { printf("%d\t%s\n", students[i].id, students[i].name); } return 0; }
说明:
- 定义
MAX_STUDENTS
限制数组大小,避免越界访问。 - 使用
fgets
读取字符串可以防止缓冲区溢出,需手动去除末尾的换行符。 - 静态数组的缺点是大小固定,若输入数据超过
MAX_STUDENTS
,会导致数据丢失或程序错误。
使用动态数组保存可变大小的数据库记录
当数据量不确定或可能动态增加时,可以使用动态数组(通过malloc
、realloc
等函数实现内存分配),动态保存学生的学号和成绩:
#include <stdio.h> #include <stdlib.h> struct Student { int id; float score; }; int main() { struct Student *students = NULL; // 动态数组指针 int capacity = 5; // 初始容量 int count = 0; // 实际存储数量 int input_id; float input_score; students = (struct Student *)malloc(capacity * sizeof(struct Student)); if (students == NULL) { printf("内存分配失败!\n"); return 1; } printf("请输入学生信息(学号为0时结束):\n"); while (1) { printf("学号:"); scanf("%d", &input_id); if (input_id == 0) break; // 输入0终止输入 printf("成绩:"); scanf("%f", &input_score); // 检查是否需要扩容 if (count >= capacity) { capacity *= 2; // 容量翻倍 struct Student *temp = (struct Student *)realloc(students, capacity * sizeof(struct Student)); if (temp == NULL) { printf("内存扩容失败!\n"); free(students); return 1; } students = temp; } students[count].id = input_id; students[count].score = input_score; count++; } // 输出数据 printf("\n学生信息如下:\n"); printf("学号\t成绩\n"); for (int i = 0; i < count; i++) { printf("%d\t%.2f\n", students[i].id, students[i].score); } free(students); // 释放动态分配的内存 return 0; }
说明:
- 动态数组通过
malloc
初始化,realloc
扩容,避免静态数组的大小限制。 - 扩容策略通常采用容量翻倍,减少频繁内存分配的开销。
- 务必在程序结束时调用
free
释放内存,防止内存泄漏。
使用二维数组保存多字段数据库记录
如果数据库记录包含多个字段(如学号、姓名、成绩),可以使用二维字符数组或结构体数组,保存学生姓名和成绩:
#include <stdio.h> #include <string.h> #define MAX_STUDENTS 50 #define MAX_NAME_LENGTH 20 int main() { char names[MAX_STUDENTS][MAX_NAME_LENGTH]; // 二维字符数组保存姓名 float scores[MAX_STUDENTS]; // 一维数组保存成绩 int count; printf("请输入学生数量:"); scanf("%d", &count); getchar(); // 清除换行符 for (int i = 0; i < count; i++) { printf("请输入第%d个学生的姓名:", i + 1); fgets(names[i], MAX_NAME_LENGTH, stdin); names[i][strcspn(names[i], "\n")] = '\0'; // 去除换行符 printf("请输入第%d个学生的成绩:", i + 1); scanf("%f", &scores[i]); getchar(); // 清除换行符 } // 输出数据 printf("\n学生信息如下:\n"); printf("姓名\t成绩\n"); for (int i = 0; i < count; i++) { printf("%s\t%.2f\n", names[i], scores[i]); } return 0; }
说明:
- 二维字符数组
names[MAX_STUDENTS][MAX_NAME_LENGTH]
中,第一维是记录数量,第二维是字符串长度。 - 需注意
fgets
的缓冲区大小限制,避免截断输入字符串。
数组保存数据库的注意事项
- 边界检查:始终确保数组索引不越界,静态数组需提前定义最大容量,动态数组需检查
malloc
/realloc
的返回值。 - 内存管理:动态数组使用后必须释放内存,否则会导致内存泄漏。
- 数据类型匹配:数组元素类型需与输入数据一致,如整型数组保存学号,字符数组保存字符串。
- 输入处理:使用
scanf
后需用getchar
清除缓冲区中的残留字符,避免影响后续输入。
相关问答FAQs
问题1:C语言中如何将用户输入的字符串安全保存到字符数组中?
解答:使用fgets
函数读取字符串,并指定缓冲区大小,防止溢出。
char str[100]; fgets(str, sizeof(str), stdin); str[strcspn(str, "\n")] = '\0'; // 去除换行符
若使用scanf
,需限制输入长度并检查返回值,例如scanf("%99s", str);
。
问题2:动态数组扩容时,为什么推荐容量翻倍而不是固定增加?
解答:容量翻倍可以减少realloc
的调用次数,降低内存分配的开销,固定增加(如每次加10)可能导致频繁扩容,影响性能;而翻倍策略均摊了扩容成本,适合大多数场景,但需注意,翻倍可能导致内存浪费,因此需根据实际需求选择合适的扩容策略。