C++读取文本文件内容到char*中:
#include <iostream>
#include <fstream>
#include <iostream>
const char* readFile(const char* fileName);
int main()
{
const char* result = readFile("README.md");
std::cout << result;
}
const char* readFile(const char* fileName) {
std::ifstream file(fileName); // 打开文件
char* content;
content = (char*)malloc(sizeof(char) * 40960); // 假设文件最大为40K,可自定义
if (content)
{
char buff[1024]; // 1Kb的缓冲区
int pt = 0;
while (file.getline(buff, 1024)) // 按行读取文件到缓冲区
{
for (int i = 0; i < 1024; i++) {
char tmp = buff[i];
if (tmp == '\0') { // 遇到\0时换行,继续读取下一行
content[pt] = '\n';
pt++;
break;
}
content[pt] = tmp;
pt++;
}
}
content[pt] = '\0'; // 读取结束,构建字符串尾
char* result = (char*)malloc(sizeof(char) * (++pt)); // 申请pt+1个字节的内存空间
if (!result)
return NULL;
for (int i = 0; i < pt; i++) {
result[i] = content[i]; // 字符串复制
}
return result;
}
return NULL;
}
几个问题:
1、getline()会往缓冲区写入数据,并约定在行尾加入\0,原始缓冲区的内存是乱七八糟的值,所以要以\0截取
2、为什么不用std::strcat和std::strcpy而要遍历字符。在C++11中,strcat和strcpy被认为是不安全的,可能会发生内存重叠或溢出,被弃用了,并且相对应的引入了strcat_s和strcpy_s数据结构,这里的数据比较简单且可控,因此采用了这种方法。
3、如果一定要使用strcat_s和strcpy_s,需要设置 __STDC_WANT_LIB_EXT1__ 宏的值为1,且在确保 __STDC_LIB_EXT1__ 宏被定义时才可使用,来自官方的例子:
#define __STDC_WANT_LIB_EXT1__ 1
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *src = "Take the test.";
// src[0] = 'M' ; // this would be undefined behavior
char dst[strlen(src) + 1]; // +1 to accomodate for the null terminator
strcpy(dst, src);
dst[0] = 'M'; // OK
printf("src = %s\ndst = %s\n", src, dst);
#ifdef __STDC_LIB_EXT1__
set_constraint_handler_s(ignore_handler_s);
int r = strcpy_s(dst, sizeof dst, src);
printf("dst = \"%s\", r = %d\n", dst, r);
r = strcpy_s(dst, sizeof dst, "Take even more tests.");
printf("dst = \"%s\", r = %d\n", dst, r);
#endif
}
得到的输出:
src = Take the test.
dst = Make the test.
dst = "Take the test.", r = 0
dst = "", r = 22
具体请参阅C11标准(ISO / IEC 9899:2011):http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1570.pdf
- 7.24.2.3 strcpy函数(p:363)
- K.3.7.1.3 strcpy_s函数(p:615-616)