Как считать двумерный массив чисел из файла?

Тема в разделе "Общие вопросы по С и С++", создана пользователем Di_Ex, 6 сен 2007.

Статус темы:
Закрыта.
  1. Di_Ex

    Di_Ex Гость

    Добрый день! Необходимо считать двумерный массив чисел из файла (квадратную матрицу размера n*n), причём размер массива заранее неизвестен. Числа разделены пробелами, например:

    1 12 4 5
    3 6 7 9
    2 0 3 6
    13 15 27 4

    Собственно говоря, всё это мне нужно для того, что-бы решить СЛАУ методом ГАУСА ;) Так что если у кого-то есть информация по теме либо исходники - you are welcom :rolleyes:
    Буду рад вашей помощи! Заранее благодарен.
     
  2. mms

    mms Гость

    Так надо считать массив или что-то решить? :rolleyes:
     
  3. Di_Ex

    Di_Ex Гость

    Ну для начала считать!
     
  4. shisik

    shisik Well-Known Member

    Регистрация:
    26 авг 2007
    Сообщения:
    154
    Симпатии:
    0
    Что-то мне не нравиться такой подход. Но очевидно это стоит в условии задачи :( Вы хотите читать из текстового файла строки, где числа разделены пробелами. Тогда нужно написать функцию поиска этих пробелов и таким образом выделить строки, содержащие эти числа. Затем их надо будет перевести в числовой тип (скажем, int или float, в зависимости от задачи). Строки матрицы у вас в файле, я так понимаю, отделены символами новой строки ("\r\n"). Значит одна строка будет содержать n-1 пробелов. Тогда для определения n нужно посчитать количество пробелов до первого \r\n и добавить 1. Затем массив будет создан как
    Код (Text):
    int **matrica;
    matrica = new int *[n];
    for (int i =0; i < n; i++)
    matrica[i] = new int[n];
    Очищать память следует в обратном порядке:
    Код (Text):
    for (i = 0; i < n; i++)
    delete matrica[i];
    delete matrica;
    Я попробую что-то подобное сделать :) Хотя я считаю, что лучше в файл писать не строки а сразу массив типа int или float. А n вычислять не через количество пробелов, а как квадратный корень из длинны файла, делённой на sizeof(тип).
     
  5. Di_Ex

    Di_Ex Гость

    Жду с нетерпением. Только на C, а не на C++ )
     
  6. shisik

    shisik Well-Known Member

    Регистрация:
    26 авг 2007
    Сообщения:
    154
    Симпатии:
    0
    На C, так на C :( Программу проверял в VC++ 6.0
    Код (Text):
    #include "stdafx.h"
    #include "windows.h" //для фукций работы с файлами и проекциями файлов
    #include "shlwapi.h" //для StrToInt()
    #include "malloc.h" //для динамического выделения памяти

    #define FILENAME "file.txt" //имя файла

    int main(int argc, char* argv[])
    {
    HANDLE hFile = CreateFile(FILENAME, GENERIC_READ,
    FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL, NULL); //открываем файл
    if (hFile == INVALID_HANDLE_VALUE) //если файла нет
    return 1; //то выходим с кодом 1
    HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); //проецируем файл в память
    char *fmatr = (char *) MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0); //получаем указатель на начало проекции

    int **matrica;
    unsigned i, n = 1;
    for (i = 0; i < strlen(fmatr); i++) { //определяем
    if (fmatr[i] == ' ')             //число
    n++;                  //пробелов
    if (fmatr[i] == '\r')         //в первой строке
    break;
    }
    matrica = (int **) calloc(n, sizeof(int*)); //выделяем память под массив указателей
    for (i = 0; i < n; i++) //содержащий
    matrica[i] = (int *) calloc(n, sizeof(int)); //массивы чисел

    int j = 0, a = 0, n1 = 0, n2 = 0;
    char val[3] = "";
    for (i = 0; i < strlen(fmatr); i++) { //читаем проекцию файла (работаем как со строкой)
    if (fmatr[i] == '\r') { //при завершении строки
    matrica[n1++][n2] = StrToInt(val); //пишем значение и переходим на новую
    n2 = 0;
    i++;
    j++;
    a = 0;
    strcpy(val, "");
    continue;
    }
    if (fmatr[i] != ' ') //если не пробел
    val[a++] = fmatr[i];//то добавляем символ к строке, седержащей элемент матрицы
    else {//а если пробел
    matrica[n1][n2++] = StrToInt(val); //то пишем значение и переходим к новой ячейке
    a = 0;
    strcpy(val, "");
    }
    }
    matrica[n1][n2] = StrToInt(val); //пишем последний элемент

    //здесь будет код работы с матрицей

    for (i = 0; i < n; i++)
    free(matrica[i]); //удаляем сначало массивы чисел (внутренние)
    free(matrica); //а затем и массив указателей
    UnmapViewOfFile(fmatr); //закрываем
    CloseHandle(hFileMap);  //все
    CloseHandle(hFile);      //объекты ядра
    return 0;
    }
    Для работы с файлом я использовал API-фукции для работы с проекцией файла в память. Это позволило рассматривать файл как простую строку (массив типа char). Файл должен содержать правильную информацию, т.е. каждый элемент должен отделяться от другого пробелом, после последнего элемента строки должна идти последовательность \r\n, после последнего элемента последней строки символов быть не должно. Каждая строка должна содержать одинаковое число элементов, равное количеству строк. Иначе код может работать некорректно.
     

    Вложения:

    • calloc.zip
      Размер файла:
      9,1 КБ
      Просмотров:
      40
  7. shisik

    shisik Well-Known Member

    Регистрация:
    26 авг 2007
    Сообщения:
    154
    Симпатии:
    0
    Только что подумал. Ведь для решения системы метдом Гаусса нужна не квадратная матрица, а столбцов должно быть на 1 больше (для свободных членов)...
     
  8. Folderx

    Folderx Гость

    Задача сводится как символы
    1 12 4 5
    из файла превратить в числа
    1,12,4,5
    убрав пробелы и конец строки

    Как 12 (это два символа), превратить в 12 (одну цифру) ?
     
  9. Over

    Over Well-Known Member

    Регистрация:
    4 июл 2007
    Сообщения:
    116
    Симпатии:
    0
    2 Foldrex: во-первых, 12 - это ДВЕ цифры, и одно число
    во-2-х. чтобы преобразовать строку в число можно использовать функцию atoi().
     
  10. shisik

    shisik Well-Known Member

    Регистрация:
    26 авг 2007
    Сообщения:
    154
    Симпатии:
    0
    <!--QuoteBegin-Folderx+6:09:2007, 23:47 -->
    <span class="vbquote">(Folderx @ 6:09:2007, 23:47 )</span><!--QuoteEBegin-->Задача сводится как символы
    1 12 4 5
    из файла превратить в числа
    1,12,4,5
    убрав пробелы и конец строки[/quote]
    По-моему, это всё уже написано :)
     
  11. mms

    mms Гость

    <!--QuoteBegin-shisik+6:09:2007, 16:17 -->
    <span class="vbquote">(shisik @ 6:09:2007, 16:17 )</span><!--QuoteEBegin-->Код
    int **matrica;
    matrica = new int *[n];
    for (int i =0; i < n; i++)
    matrica = new int[n];
    Очищать память следует в обратном порядке:
    Код
    for (i = 0; i < n; i++)
    delete matrica;
    delete matrica;
    [snapback]77403" rel="nofollow" target="_blank[/snapback]​
    [/quote]

    Неверно! Учимся удалять массивы:

     
  12. shisik

    shisik Well-Known Member

    Регистрация:
    26 авг 2007
    Сообщения:
    154
    Симпатии:
    0
    Хоть вы и правы, но это почему-то приводит к ошибке :(
     
  13. Folderx

    Folderx Гость

    А если я не хочу использовать atoi(), как вручную 123 превратить в цифру 123 а не в цифры 1 2 3 ? :(

    shisik, написано тут StrToInt(val), а чо это за функция, чо там внутри ?
    вот всё что там написано, остальное мусор какой :)
     
  14. North

    North Гость

    2 shisik

    Мапить файл в память - круто. Но лучше все это подымать асинхронно, а затем проталкивать в кеш L1.
    И считать естественно только через MMX и SSE, желательно писать интиринсиками :( .

    Если серьезно - респект.
     
  15. shisik

    shisik Well-Known Member

    Регистрация:
    26 авг 2007
    Сообщения:
    154
    Симпатии:
    0
    <!--QuoteBegin-Folderx+7:09:2007, 22:35 -->
    <span class="vbquote">(Folderx @ 7:09:2007, 22:35 )</span><!--QuoteEBegin-->написано тут StrToInt(val), а чо это за функция, чо там внутри ?[/quote]

    Я не знаю, что там внутри - функция из shlwapi.h А если вы хотите вручную перевести из char* в int, то это будет выглядеть как-то так:
    Код (Text):
    int MyStrToInt(char *val)
    {
    int res = 0;
    for (int i = 0; i < strlen(val); i++)
    switch (val[i]) {
    case '0':
    res = res * 10;
    break;
    case '1':
    res = res * 10 + 1;
    break;
    case '2':
    res = res * 10 + 2;
    break;
    case '3':
    res = res * 10 + 3;
    break;
    case '4':
    res = res * 10 + 4;
    break;
    case '5':
    res = res * 10 + 5;
    break;
    case '6':
    res = res * 10 + 6;
    break;
    case '7':
    res = res * 10 + 7;
    break;
    case '8':
    res = res * 10 + 8;
    break;
    case '9':
    res = res * 10 + 9;
    break;
    }
    return res;
    }
    Функция примитивна, но принцип, думаю, ясен :(

    Для: North
    Ну не знаю, по-моему, проще работать с массивом char, чем читать по 1 байту из файла :)
     
  16. Folderx

    Folderx Гость

    Число 158

    res = 0 * 10;
    res = 0 * 10 + 1; // получилось 1
    res = 1 * 10 + 5; // получилось 15
    res = 15 * 10 + 8; // получилось 158

    Количество цифр в числе определяется через strlen() из <string.h>

    Терь ясно :(
     
Загрузка...
Статус темы:
Закрыта.

Поделиться этой страницей