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)