#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#ifndef DEFAULT_STRING_LENGTH
#define DEFAULT_STRING_LENGTH 50 //默认长度 50
#endif
//自动扩容版的 fgets
char* autoalloc_fgets(char* _Str, size_t* const _Capacity, FILE* const _Stream) {
/*
警告:
只能用于动态分配的数组,静态数组使用后果自负。
*/
char* _Temp;
size_t _Index = 0;
//输入检查
if (!*_Capacity) {//容量为 0
_Str = (char*)malloc(DEFAULT_STRING_LENGTH * sizeof(char));//分配 DEFAULT_STRING_LENGTH 长度的空间
if (_Str) {//分配成功
*_Capacity = DEFAULT_STRING_LENGTH;
}
else {//分配失败
return NULL;
}
}
else if (!_Str) {//传入空指针
_Str = (char*)malloc(*_Capacity * sizeof(char));//分配* _Capacity 长度的空间
if (!_Str) {//分配失败
*_Capacity = 0;
return NULL;
}
}
#define _Len (_Index + 1)
for (;;) {
if (_Len < *_Capacity) {
LABEL:
switch (_Str[_Index] = fgetc(_Stream)) {//遇到以下字符,终止扫描
case '\n':
case '\r':
case EOF:
_Str[_Index] = '\0';//'\0' 的话,就不需要重置了
case '\0':
*_Capacity = _Len;
return (char*)realloc(_Str, *_Capacity * sizeof(char));
}
++_Index;
}
else {//扩容,默认扩容为原来的两倍
*_Capacity <<= 1;
if (_Temp = (char*)realloc(_Str, *_Capacity * sizeof(char))) {//为了防止 realloc 返回 NULL 造成内存泄露
_Str = _Temp;
goto LABEL;//扩容完之后不需要重新判断,goto 提高效率
}
else {//扩容失败
_Str[_Index] = '\0';//放置字符串终止符
*_Capacity >>= 1;//退回来
return _Str;
}
}
}
#undef _Len
return NULL;//装饰
}
//自动扩容版的 gets
char* autoalloc_gets(char* _Str, size_t* const _Capacity) {
return autoalloc_fgets(_Str, _Capacity, stdin);//直接调用 autoalloc_fgets
}