Чтение матрицы из текстового файла, C ++ - PullRequest
1 голос
/ 17 января 2012

Друзья!Язык программирования - C ++.У меня есть байтовая матрица

unsigned char Map[Height][Width];

Я инициализирую ее нулями.Затем я читаю матрицу байтов из текстового файла.Конечно, текстовый файл может быть больше, чем моя матрица.В этом случае я должен прочитать информацию из файла следующим образом: enter image description here

Текстовый файл содержит дополнительную информацию.Мне это не нужноВ другом случае матрица может быть больше, чем информация в текстовом файле:

enter image description here

В этом случае программа должна прочитать всю информацию из файла.Часть матрицы, которая не получила информацию из файла, уже инициализирована.Это нормально.

Каков наилучший способ считывания информации из файла в матрицу в моем случае?Я пытался использовать fgets, но он считывает всю информацию из файла последовательно - байт за байтом.Но мне не нужно читать лишние байты.Конечно, я могу прочитать файл за байтом и проверить счетчик.Но я уверен, что это не лучшее решение.Существует ли лучшее решение?

Форматирование моего текстового файла здесь не имеет значения.Я читаю информацию из файла как поле байтов.

Ответы [ 3 ]

1 голос
/ 17 января 2012

Если вы можете прочитать все строки с помощью функции fgets (), вы можете скопировать символ i-й строки за символом в i-ю строку вашей таблицы.Остановитесь, когда встретите конец строки или скопируете символы ширины.Обратите внимание, что fgets () может оставить символ NL в конце строки, которую вы, возможно, захотите удалить (NL + CR в Windows).

Повторяйте вышеуказанную процедуру, пока не прочитаете строки высоты или не достигнетеконец файла.

Мое решение в основном - C (потому что вы говорите, что не знакомы с функциями C ++).Вы должны использовать стандартные библиотеки C ++ (fstream, string), если вы хотите настоящую реализацию C ++.

#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);
}
1 голос
/ 17 января 2012

Предполагается, что ваши текстовые файлы выглядят примерно так:

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);, указанная выше, будет автоматически содержать нулевые символы в строке, если ширина больше длины строки в файле. Кроме того, не забудьте проверить, был ли поток успешно открыт, прежде чем пытаться читать с него (например, fstream::is_open()). Я пропустил этот чек для краткости.

1 голос
/ 17 января 2012

Считать весь файл в буфер:

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

Я полагаю, что это будет самый быстрый способ, просто захватите весь файл в память за одно чтение, а затем запишите нужные вам сегменты в байтовый массив.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...