C++讀取文本文件到char*

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)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章