2014-12-15 4 views
3

Следующий код отлично работает при чтении двух файлов .txt, содержащих два массива 5X5.Чтение произвольного массива любого размера

#include <iostream> 
    #include <string> 
    #include <fstream> 
    #include <sstream> 
    #include <stdio.h> 
    #include <vector> 
    #include <sstream> 

    using namespace std; 

    int main() 
    { 
     string myFile, mysecondFile, mystring; 
     string DIR; 
     string extension; 
     int total = 0; 

     int number_of_lines = 0; 
     string line; 

     extension = ".txt"; 
     DIR = "H:\\Year2\\EE273\\EE273\\Week6\\"; 

     cout << "Enter the name of the file: \t"; 
     cin >> myFile; 
     cout << "Enter the name of the second file: \t"; 
     cin >> mysecondFile; 

     myFile = DIR + myFile + extension; 
     mysecondFile = DIR + mysecondFile + extension; 

     ifstream inFile; 
     ifstream inFile2; 

    int i=5; 
    int j=5; 
    int i2=5; 
    int j2=5; 
    int i3=5; 
    int j3=5; 
    int k; 
    int l; 

int Array[5][5]; 
int Array2[5][5]; 
int Array3[5][5]; 
string attempt1,attempt2; 
int row = 0; 
int col = 0; 
int row2 = 0; 
int col2 = 0;//i = row 
        //y = column 

inFile.open(myFile.c_str()); 


if (!inFile) { 
    cout <<"Error opening file"<<myFile<<endl; 
    return -1; 
} 

while (!inFile.eof()) 
{ 
    getline(inFile, attempt1); 
    stringstream iss(attempt1); 
    string result; 
    col = 0; 
    while (getline(iss, result, ',')) 
    { 
     //cout << result << endl; 
     Array[row][col] = atoi(result.c_str()); 
     //j = j + 1; 
     col = col + 1; 

    } 
    row = row + 1; 
} 
inFile.close(); 

inFile2.open(mysecondFile.c_str()); 
if (!inFile2) { 
    cout <<"Error opening file"<<mysecondFile<<endl; 
    return -1; 
} 
while (!inFile2.eof()) 
{ 
    getline(inFile2, attempt2); 
    stringstream iss(attempt2); 
    string result2; 
    col2 = 0; 
    while (getline(iss, result2, ',')) 
    { 
     //cout << result2 << endl; 
     Array2[row2][col2] = atoi(result2.c_str()); 
     col2 = col2 + 1; 
    } 
    row2 = row2 + 1; 
} 
inFile2.close(); 

/*for (int i=0;i<5;i++){ 
    for (int j=0; j<5; j++){ 
     cout<<Array[i][j]<<endl;}} 
for (int i2=0;i2<5;i2++){ 
    for (int j2=0; j2<5; j2++){ 
     cout<<Array2[i2][j2]<<endl; 
    }} 

Здесь я выполняю умножение между двумя матрицами и записывая полученные значения в третью матрицу.

int Total=0; 
i=0; 
j2=0; 
j=0; 
j3=0; 
for (i3=0; i3<5; i3++) { 
    while(j3<5){ 
      while (j<5){ 
      for (i2=0;i2<5;i2++){ 
      Total += Array[i][j]*Array2[i2][j2]; 
      j++; 
      Array3[i3][j3]=Total; 

      }} 
      j=0; 
      j2++; 
      j3++; 
      Total=0; 
      } 
    i++; 
    j=0; 
    j2=0; 
    j3=0; 
    Total=0; 
} 

Мой вопрос: что это самый простой способ изменить код таким образом, что он может читать два .txt файлов, содержащих массив любого размера, а затем выполнить умножение успешно?

EDIT Я должен сделать это, используя только массивы, к сожалению, я не могу использовать векторы.

Я правильно понял, что задействован оператор ?

+6

Использовать ['std :: vector'] (http://en.cppreference.com/w/cpp/container/vector) вместо обнаженных массивов. –

+0

Вещь - это оценка, и нам сказали, что мы используем только массивы – pkpkpk

+2

Гы, вам не кажется, что вы должны были включить это ограничение в свой пост? –

ответ

3

«самый легкий» путь был бы сделать что-то наивное, как чтение файла один раз полностью, чтобы получить число строк/перевалы, а затем читает файл снова, чтобы фактически хранить значения в матрице:

unsigned int rows = 0; 
unsigned int cols = 0; 

std::string line; 
while (std::getline(inFile, line)) { 
    rows++; 
    std::stringstream ss(line); 

    std::string col; 
    while (std::getline(ss, col, ',')) { 
     cols++; 
    } 
} 

// Now allocate the rows*cols matrix 
int** matrix = new int*[rows]; 
for (int i = 0; i < rows; i++) { 
    matrix[i] = new int[cols]; 
} 

// and read your values into the matrix ... 
// matrix[m][n] = xxx 

Это довольно неэффективно, чтобы прочитать файл дважды; и есть другие способы получить размер заранее. Например, вы могли бы иметь соглашение в входном файле, чтобы включить матрицу ширина/высота до данных:

[infile.txt] 
3,3 
1,2,3 
4,5,6 
7,8,9 

Теперь вы можете прочитать первую строку файла, и вы будете знать, что остальная часть этого файл содержит матрицу 3x3. Выделите свою матрицу с помощью new (аналогично приведенному выше примеру), затем продолжайте читать остальную часть файла.

Запомните, чтобы очистить динамически распределенные матрицы с помощью delete[]. Для каждого звонка до new должен быть 1 звонок до delete.

for (int i = 0; i < rows; i++) { 
    delete[] matrix[i]; 
} 
delete[] matrix; 
+0

Это именно то, что я искал. Пока getline продолжает находить значения, строки и столбцы будут увеличиваться. Я попробую код позже, но я уверен, что он будет работать отлично. Почему вы говорите, что это неэффективно? Разве это не самое эффективное решение, если, скажем, мы хотим открыть файлы .txt, содержание которых неизвестно? – pkpkpk

+1

@Paolokiller. Выполнение чего-либо дважды всегда будет занимать больше времени, чем одно и то же. В частности, чтение файла с диска, как правило, является медленной операцией, поэтому вы захотите избежать избыточности.В моем ответе я включил один из таких методов: 'включить ширину/высоту матрицы перед данными' :) Вы также можете сохранить файл как двоичный и определить размер с помощью' seekg() 'и' tellg() ' , но это связано с другими сложностями (например, не читаемыми человеком). Если бы это было разрешено, 'std :: vector' тоже работал бы. Между решениями всегда существуют компромиссы. – Julian

1

Используйте std::vector вместо необработанных массивов. Например. вы можете push_back пункт на вектор. И что более важно, вы можете создать его с размером, известным только во время выполнения, например. от информации в файле.

+1

В соответствии с комментарием OP, вектор can not используется, потому что его назначение и им сказали использовать массивы. – Borgleader

+0

@Borgleader: Да, он опубликовал это после того, как я опубликовал этот ответ. я не собираюсь преследовать меняющиеся требования. –

+1

Делайте то, что хотите, с информацией, я просто предоставлял ее. В любом случае, это глупое требование. – Borgleader

1

Самый простой подход требует, чтобы файл содержал размер матрицы в качестве первых записей. При этом, вы можете Откат к использованию C (C++ не допускают матрицы динамического размера) и выполните следующие действия:

  1. Прочитайте размерность матрицы в переменные width и heigh.

  2. Выделяют матрицу с помощью

    int (*dynamicMatrix)[width] = malloc(height*sizeof(*dynamicMatrix)); 
    
  3. Повторное использование кода, чтобы заполнить матрицу.

Если вы не можете упасть обратно в C, и не может использовать std::vector<>, единственное, что осталось для вас, чтобы использовать двойной указатель:

int**dynamicMatrix = new int*[height]; 
for(size_t i = width; i--;) dynamicMatrix[i] = new int[width]; 

Опять же, это проще, если вы можете определить первые два числа в файле, чтобы они содержали ширину и высоту матрицы в файле. Если вы не можете кодировать эти два числа в файл, вы должны расти ваши динамические массивы, как вы идете:

size_t lines = 0, allocatedLines = 8; 
int** dynamicMatrix = new int*[allocatedLines]; 
while(/* can read a line */) { 
    if(lines == allocatedLines) { 
     int** temp = new int*[allocatedLines *= 2]; 
     for(size_t i = lines; i--;) temp[i] = dynamicMatrix[i]; 
     delete[] dynamicMatrix; 
     dynamicMatrix = temp; 
    } 

    //add one line 
    size_t curLineLength = 0, allocatedLineLength = 8; 
    dynamicMatrix[lines++] = new int[allocatedLineLength]; 

    //fill the line 
    ... 
} 

Аналогичный блок для переразмещают линии должны идти в петлю, где вы читаете элементы одной линии. Это утомительно; но единственный способ стать лучше - использовать материал, который вам не разрешено использовать.


Btw: даже перераспределить вещи проще в C, так как она обеспечивает realloc() функцию:

size_t lines = 0, allocatedLines = 8; 
int** dynamicMatrix = malloc(allocatedLines * sizeof(*dynamicMatrix)); 
while(/* can read a line */) { 
    if(lines == allocatedLines) { 
     //realloc takes care of copying the data to a new location (if that is necessary): 
     allocatedLines *= 2; 
     dynamicMatrix = realloc(dynamicMatrix, allocatedLines * sizeof(*dynamicMatrix)); 
    } 

    //add one line 
    size_t curLineLength = 0, allocatedLineLength = 8; 
    dynamicMatrix[lines++] = malloc(allocatedLineLength * sizeof(**dynamicMatrix)); 

    //fill the line 
    ... 
} 

Поскольку не существует никакого эквивалента realloc() работать с new/delete, вы должны либо используйте std::vector<> в C++, либо для копирования, как указано выше.

+1

Я пишу программу на C++, поэтому я не думаю, что должен использовать malloc. Моя первоначальная идея подходить к проблеме заключалась в том, чтобы использовать getline для чтения в txt-файлы и иметь одну переменную для строк и одну для столбцов, которые увеличиваются в соответствии с прочитанным файлом. Это имеет смысл? Я не уверен, как это сделать, но я думаю, что если я смогу заставить программу знать, сколько строк/столбцов есть в файлах, я могу заставить остальные работать ... – pkpkpk

+1

Я удалил упоминание 'std :: vector <> 'и заменил его базовым описанием того, что вам нужно делать на C++ без него. Надеюсь, это поможет. – cmaster

Смежные вопросы