[英]Reading of matrix from text file, C++
朋友们! 编程语言是C ++。 我有一个字节矩阵
unsigned char Map[Height][Width];
我用零初始化。 然后我从文本文件中读取字节矩阵。 当然,文本文件可以比我的矩阵大。 在这种情况下,我必须以这种方式从文件中读取信息:
文本文件包含其他信息。 我不需要 在另一种情况下,Matrix可以大于文本文件中的信息:
在这种情况下,程序必须从文件读取所有信息。 未从文件中获取信息的矩阵部分已被初始化。 没关系。
在我的情况下,从文件读取信息到矩阵的最佳方法是什么? 我尝试使用fgets
,但是它以连续的方式从文件读取所有信息-逐字节读取。 但是我不需要读取额外的字节。 当然,我可以逐字节读取文件并检查计数器。 但是我确信这不是最好的解决方案。 是否存在更好的解决方案?
我的文本文件的格式与此处无关。 我从字节字段之类的文件中读取信息。
将整个文件读入缓冲区:
FILE *fp;
long len;
char *buf;
fp=fopen("thefileyouwanttoread.txt","rb");
fseek(fp,0,SEEK_END); //go to end
len=ftell(fp); //get position at end (length)
fseek(fp,0,SEEK_SET); //go to beg.
buf=(char *)malloc(len); //malloc buffer
fread(buf,len,1,fp); //read into buffer
fclose(fp);
将文件复制到您的字节数组中,检查更大的文件以确定如何复制:
char *startByteArr;
unsigned char Map[Height][Width];
startByteArr = &Map[0][0];
if (len > Height*Width){
memcpy(startByteArr,buf,Height*Width);
else {
memcpy(startByteArr,buf,len);
}
假设第一个维度相同。 要考虑文件中宽度的变化,可以将memcpy更改为:
char *startByteArr;
char *EndLineFile;
int lineLengthFile;
EndLineFile = strstr (buf,"\r\n");
lineLenghtFile = (int)(EndLineFile-buf);
unsigned char Map[Height][Width];
startByteArr = &Map[0][0];
int i;
if (lineLengthFile > Width){
for(i = 0; i < Height;i++){
memcpy(startByteArr+i*Width,buf+i*lineLengthFile,Width);
}
else {
for(i = 0; i < Height;i++){
memcpy(startByteArr+i*Width,buf+i*lineLengthFile,lineLengthFile);
}
}
我相信这将是最快的方法,只需一次读取就将整个文件读入内存,然后将所需的段存储到字节数组即可。
如果您可以使用fgets()读取所有行,则可以将第i个字符逐个字符复制到表的第i行。 当遇到行尾或复制了宽度字符时,请停止。 请注意,fgets()可能会在您要删除的行的末尾留下NL字符(在Windows上为NL + CR)。
重复上述过程,直到您已阅读“高度”行或到达文件末尾。
我的解决方案基本上是C(因为您说您不熟悉C ++函数)。 如果要使用真正的C ++实现,则应使用标准的C ++库(fstream,字符串)。
#include <cstdio>
#include <cstring>
#define Height (...)
#define Width (...)
// I assume that each input line in the file can contain at most width * 3 characters.
// Three extra characters for NL, CR, 0.
// Change this if you expect the file to contain longer lines.
#define BUFFER_WIDTH (Width * 3 + 3)
unsigned char Map[Height][Width];
unsigned char line[BUFFER_WIDTH];
// Remove CR, NL at the end of the line.
void clean_line(char *line)
{
int len = strlen(line);
while (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r'))
{
line[len - 1] = '\0';
len--;
}
}
void read_table(const char *filename)
{
FILE *fp = fopen(filename, "r");
int row = 0;
while (!feof(fp) && row < Height)
{
fgets(line, BUFFER_WIDTH, fp);
clean_line(line);
int len = strlen(line);
int rowLen = len > Width ? Width : len;
for (int col = 0; col < rowLen; col++)
{
Map[row][col] = line[col];
}
row++;
}
fclose(fp);
}
假设您的文本文件如下所示:
3254352
6536543
8875687
4315254
5345435
1212122
标准库流的解决方案是这样的:
#include <fstream>
#include <string>
int main()
{
std::ifstream matrix_file("matrix.txt");
const size_t Width = 5;
const size_t Height = 5;
unsigned char Map[Width][Height];
size_t line_count = 0;
std::string line;
while (std::getline(matrix_file, line) && line_count < Height) {
line.resize(Width);
for (size_t i = 0; i < line.length(); ++i)
Map[i][line_count] = line[i];
++line_count;
}
if (line_count < Height) {
// the file didn't have enough lines to fill our matrix,
// so we'll need to fill the rest with zeroes here
}
}
line.resize(Width);
当Width大于文件中该行的长度时,以上一行将自动在字符串中放置空字符。 另外,在尝试读取流之前,请不要忘记检查流是否已成功打开fstream::is_open()
例如fstream::is_open()
)。 为了简洁起见,我跳过了这张支票。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.