1.realloc的使用方法
realloc
是 C 语言中用于动态内存管理的函数。它允许你调整已经分配的内存块的大小,通常用于数组的大小调整。realloc
可以增加或减少已分配内存的大小,并且可以保留旧数据的内容。
函数原型:
void* realloc(void* ptr, size_t size);
ptr
:指向之前通过malloc
、calloc
或realloc
分配的内存块的指针。如果ptr
是NULL
,realloc
的行为类似于malloc
。size
:新内存块的大小,以字节为单位。如果size
为 0,realloc
的行为类似于free
。-
返回值
- 成功时,返回指向重新分配的内存块的指针。如果新分配的内存块位置发生了变化,则返回新的地址,旧内存块的内容会被复制到新内存块中。
- 如果失败,返回
NULL
。原来的内存块保持不变。 - 示例代码:
-
#include <stdio.h>
#include <stdlib.h>int main() {
int *arr;
int initial_size = 5;
int i;// 使用 malloc 分配初始大小
arr = (int *)malloc(initial_size * sizeof(int));
if (arr == NULL) {
fprintf(stderr, "内存分配失败\n");
return 1;
}// 初始化数组
for (i = 0; i < initial_size; i++) {
arr[i] = i + 1;
}// 输出初始数组内容
printf("初始数组内容:\n");
for (i = 0; i < initial_size; i++) {
printf("%d ", arr[i]);
}
printf("\n");// 扩展数组大小
int new_size = 10;
int *new_arr = (int *)realloc(arr, new_size * sizeof(int));
if (new_arr == NULL) {
fprintf(stderr, "内存重新分配失败\n");
free(arr); // 释放原来的内存块
return 1;
}
arr = new_arr;// 初始化新分配的内存区域
for (i = initial_size; i < new_size; i++) {
arr[i] = i + 1;
}// 输出扩展后的数组内容
printf("扩展后的数组内容:\n");
for (i = 0; i < new_size; i++) {
printf("%d ", arr[i]);
}
printf("\n");// 释放分配的内存
free(arr);return 0;
} -
代码说明
-
初始分配:使用
malloc
分配一个包含 5 个int
元素的数组。 -
初始化和打印数组:将数组初始化为 1 到 5,并输出内容。
-
重新分配内存:使用
realloc
将数组扩展到可以容纳 10 个int
元素。原来的内容保留在新的内存块中。 -
扩展初始化:对新分配的内存部分进行初始化,并打印整个数组的内容。
-
释放内存:使用
free
释放动态分配的内存。 -
使用注意事项
- 检查返回值:
realloc
可能会返回NULL
,因此需要检查返回值是否为NULL
以防止内存泄漏。 - 扩展或缩小:
realloc
既可以扩展内存块,也可以缩小内存块。缩小时,超出部分的内存会被释放。 - 内存位置变化:在扩展内存块时,
realloc
可能会将数据移动到新的内存地址,因此需要将返回的指针重新赋值给原指针。 -
realloc
的典型用途 - 动态增长的数组:在运行时不确定数组的大小时,可以使用
realloc
动态调整数组的大小。 - 动态构建字符串:处理不断追加内容的字符串时,
realloc
可以有效地管理内存。
2.用fread实现fgetc函数和fgets函数
fgetc:
#include <stdio.h>
int my_fgetc(FILE *stream) {
unsigned char c;
// 使用 fread 读取一个字符
if (fread(&c, sizeof(unsigned char), 1, stream) == 1) {
return c;
} else {
// 如果读取失败,返回 EOF
return EOF;
}
}
int main() {
FILE *file = fopen("test.txt", "r");
if (file == NULL) {
perror("打开文件失败");
return 1;
}
int ch;
while ((ch = my_fgetc(file)) != EOF) {
putchar(ch); // 输出读取的字符
}
fclose(file);
return 0;
}
fgets:
#include <stdio.h>
#include <string.h>
char *my_fgets(char *str, int n, FILE *stream) {
if (n <= 0) {
return NULL; // 如果 n <= 0,直接返回 NULL
}
int i = 0;
while (i < n - 1) {
unsigned char c;
if (fread(&c, sizeof(unsigned char), 1, stream) != 1) {
if (i == 0) {
return NULL; // 如果第一个字符就读取失败,返回 NULL
}
break; // 如果不是第一个字符,结束读取
}
str[i++] = c;
if (c == '\n') {
break; // 如果遇到换行符,结束读取
}
}
str[i] = '\0'; // 确保字符串以 '\0' 结尾
return str;
}
int main() {
FILE *file = fopen("test.txt", "r");
if (file == NULL) {
perror("打开文件失败");
return 1;
}
char buffer[100];
while (my_fgets(buffer, sizeof(buffer), file)) {
printf("%s", buffer); // 输出读取的字符串
}
fclose(file);
return 0;
}
3.用fwrite实现fputc函数和fputs函数
fputc:
#include <stdio.h>
int my_fputc(int c, FILE *stream) {
unsigned char ch = (unsigned char)c;
// 使用 fwrite 将一个字符写入文件
if (fwrite(&ch, sizeof(unsigned char), 1, stream) == 1) {
return ch;
} else {
// 写入失败返回 EOF
return EOF;
}
}
int main() {
FILE *file = fopen("output.txt", "w");
if (file == NULL) {
perror("打开文件失败");
return 1;
}
char text[] = "Hello, World!";
for (int i = 0; text[i] != '\0'; i++) {
my_fputc(text[i], file);
}
fclose(file);
return 0;
}
fputs:
#include <stdio.h>
#include <string.h>
int my_fputs(const char *str, FILE *stream) {
size_t len = strlen(str);
// 使用 fwrite 将整个字符串写入文件
if (fwrite(str, sizeof(char), len, stream) == len) {
return 0;
} else {
// 写入失败返回 EOF
return EOF;
}
}
int main() {
FILE *file = fopen("output.txt", "w");
if (file == NULL) {
perror("打开文件失败");
return 1;
}
if (my_fputs("Hello, World!\n", file) == EOF) {
perror("写入文件失败");
}
fclose(file);
return 0;
}