从文本文件读取char[]后,如何获取实际读取的缓冲区大小?
优化char*缓冲区读取长度的方案
嘿,针对你的需求(必须用char*、逐行读取、超长行拆分),我给你几个比手动循环找换行符更高效简洁的方案,同时修正你当前代码里的小问题:
先说说你当前代码的小问题
你的limpiarBuffer函数里,return int(strlen(buffer) - 1)是错误的——如果一行没有换行符(比如超长行被截断、或者文件最后一行没有换行),strlen(buffer)就是实际读取的字符数,减1会少算一个字符。另外,循环里每次调用strlen会重复遍历整个字符串,效率很低。
方案一:用标准库函数strchr快速定位换行符
strchr是C标准库提供的高效函数,能直接找到字符在字符串中的位置,代码简洁且性能优秀:
#include <cstring> // 或者 <string.h>,取决于你的编译环境 int Gestor::obtenerTamanoBuffer(char* buffer) { // 查找换行符的位置 char* newlinePos = strchr(buffer, '\n'); if (newlinePos != nullptr) { // 换行符到缓冲区开头的偏移量,就是实际读取的有效字符数(不含换行) return newlinePos - buffer; } else { // 没找到换行符,说明要么是行尾,要么是缓冲区满了,返回整个字符串长度 return strlen(buffer); } }
为什么这个方案更好?
- 代码可读性强,逻辑清晰;
strchr是编译器优化过的库函数,比手动写循环效率更高;- 准确处理所有情况:带换行的行、超长截断的行、无换行的文件尾行。
方案二:手动一次遍历(适合不想用库函数的场景)
如果课程要求不能用strchr,可以手动遍历一次字符串,避免重复调用strlen:
int Gestor::obtenerTamanoBuffer(char* buffer) { int len = 0; // 遍历到字符串结束或找到换行符就停止 while (buffer[len] != '\0' && buffer[len] != '\n') { len++; } return len; }
这个方案的优势:
- 只遍历一次字符串,比你原来的循环(每次迭代都调用
strlen)效率高很多; - 逻辑简单,不容易出错。
额外的读取逻辑优化
你当前用!feof(fichero)判断的写法不够稳妥,feof只有在尝试读取后才会设置标志位,更可靠的写法是直接用fgets的返回值判断循环:
char *buffer = new char[255]; int tamanio; // 直接用fgets的返回值判断:成功读取到内容就进入循环 while (fgets(buffer, 254, fichero) != NULL) { tamanio = obtenerTamanoBuffer(buffer); printf("Tamanio buffer: %i \n", tamanio); // printarCadena(buffer); } // 循环结束后,可以判断是文件结束还是读取错误 if (ferror(fichero)) { // 处理读取错误的逻辑,比如打印错误信息 perror("Error al leer el fichero"); }
这样既可以自动处理超长行拆分(fgets会每次读取253个字符,直到读完整个长行),也能准确判断读取状态。
内容的提问来源于stack exchange,提问作者Luis Bote
相关产品推荐
相关产品推荐

