从文本文件C ++中读取矩阵

时间:2012-01-17 18:55:32

标签: c++ file matrix

朋友们! 编程语言是C ++。 我有一个字节矩阵

unsigned char Map[Height][Width];

我用零初始化它。 然后我从文本文件中读取字节矩阵。 当然,文本文件可能比我的矩阵更大。在这种情况下,我必须以这种方式从文件中读取信息: enter image description here

文本文件包含额外信息。我不需要它。 在另一种情况下,Matrix可以比文本文件中的信息大:

enter image description here

在这种情况下,程序必须从文件中读取所有信息。未从文件中获取信息的矩阵部分已初始化。没关系。

在我的情况下,从文件读取信息到矩阵的最佳方法是什么? 我尝试使用fgets,但它以连续的方式从文件中读取所有信息 - 逐字节。但我不需要读取额外的字节。当然,我可以逐字节读取文件并检查计数器。但我确信这不是最佳解决方案。是否存在更好的解决方案?

我的文本文件的格式与此无关。我从文件字节字段中读取信息。

3 个答案:

答案 0 :(得分:1)

将整个文件读入缓冲区:

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);
    }
}

我相信这将是最快的方法,只需在一次读取中将整个文件存入内存,然后将所需的段存储到字节数组中。

答案 1 :(得分:1)

如果您可以使用fgets()读取所有行,则可以将第i行逐字符复制到表的第i行。遇到行尾或复制宽度字符时停止。请注意,fgets()可能会在您可能要删除的行的末尾留下NL字符(Windows上的NL + CR)。

重复上述步骤,直到您已阅读高度线或到达文件末尾。

我的解决方案基本上是C(因为你说你不熟悉C ++函数)。如果你想要一个真正的C ++实现,你应该使用标准的C ++库(fstream,string)。

#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);
}

答案 2 :(得分:1)

假设您的文本文件如下所示:

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
    }
}

当Width大于文件中行的长度时,上面的line.resize(Width);行将自动在字符串中放置空字符。此外,在尝试读取流之前,请不要忘记检查流是否已成功打开(例如fstream::is_open())。为简洁起见,我跳过了检查。