Advertisement
Kentoo

O#2

Sep 19th, 2018
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.98 KB | None | 0 0
  1. #include "stdafx.h"
  2. #include <iostream>
  3. #include <stdlib.h>
  4. #include <Windows.h>
  5. #include <string>
  6. #include <fstream>
  7. #include <iomanip>
  8. #include <sstream>
  9.  
  10. using namespace std;
  11.  
  12. bool    onlyNum(const string s)
  13. {
  14.     bool decimal = false; //Переменная, отвечающая за наличие символа - разделителя разрядов в числе
  15.     bool sign = false; //Переменная, отвечающая за наличие знака у числа
  16.     bool pow = false;//Переменная, отвечающая за наличие сокращения экспоненциальной степени у числа
  17.     for (unsigned int i = 0; i < s.length(); i++) //Перебирая все символы строки
  18.     {
  19.         if (s.at(i) == 'e' || s.at(i) == 'E')//Если находим символ степени
  20.             if (!pow && i != 0 && i != s.length() - 1)//Если у него хотя бы теоретически есть валидные значения основания и степени и мы его еще не находили
  21.                 pow = true;//Отмечаем, что нашли
  22.             else//Иначе
  23.                 return false;//Неверный ввод
  24.         else if (s.at(i) == '+' || s.at(i) == '-')//Если находим знак
  25.             if (!sign && i == 0 && s.length() > 1)//Если он еще не был найден и мы находимся на 1 символе
  26.                 sign = true;//Отмечаем, что нашли его
  27.             else//Иначе
  28.                 return false;//Неверный ввод
  29.         else if (s.at(i) == '.' || s.at(i) == ',') //Если находим символ-разделитель разрядов
  30.             if (!decimal) //Если он еще не был найден
  31.                 decimal = true; //Отмечаем, что нашли его
  32.             else             //Если мы его уже находили и нашли еще раз
  33.                 return false; //Неверный ввод
  34.         else if ((s.at(i) < '0' || s.at(i) > '9') && s.at(i) != ' ' && s.at(i) != '\t') //Если встречаем не число и при этом не символ-разделитель
  35.             return false; //Неверный ввод
  36.     }
  37.     return true; //Верный ввод
  38. }
  39.  
  40. void    deleteMatr(double **matr, const unsigned int    size) {
  41.     for (unsigned int i = size; i > -1; i--)//Проходя по всем строкам, для которых уже выделена память
  42.         delete(matr[i]);//Очищаем ее
  43.     delete(matr);//очищаем сам указатель
  44. }
  45.  
  46. double  **loadFile(istream &in, ostream &out, unsigned int  &rows, unsigned int &cols) {
  47.     string          fileName;
  48.     string          t;
  49.     stringstream    res, buf;
  50.     ifstream        fin;
  51.     int             tcols;
  52.     bool            failed = false;
  53.     while (!fin.is_open()) { //Пока не открыли файл
  54.         if (failed)
  55.             cout << "Неудачная попытка открытия\n";
  56.         cout << "Введите имя файла: ";
  57.         getline(cin, fileName); //Считываем имя
  58.         fin.open(fileName); //Пытаемся открыть
  59.         failed = true; //Если файл открылся, цикл не запустится ещё раз, в другом случае скажем об этом в начала следующей итерации
  60.     }
  61.     while (getline(fin, t))
  62.     {
  63.         if (t.find('0') != string::npos //Проверяем наличие цифр(теоретических элементов в строке)
  64.             || t.find('1') != string::npos
  65.             || t.find('2') != string::npos
  66.             || t.find('3') != string::npos
  67.             || t.find('4') != string::npos
  68.             || t.find('5') != string::npos
  69.             || t.find('6') != string::npos
  70.             || t.find('7') != string::npos
  71.             || t.find('8') != string::npos
  72.             || t.find('9') != string::npos)
  73.         {
  74.             tcols = 0;
  75.             buf.str(string());
  76.             buf.clear();
  77.             buf << t;//Сохраняем в sstream для подсчета столбцов
  78.             res << t;//Сохраняем для записи в матрицу
  79.             res << ' ';//Отделяем строки
  80.             while (buf >> t)
  81.                 tcols++;//Подсчитываем столбцы
  82.             if (cols == 0)//Если ещё не было известно количество столбцов
  83.                 cols = tcols;//Сохраняем
  84.             else if (tcols != cols) {//Иначе, если количество столбцов в очередной стркое не совпадает с предыдущими
  85.                 cout << "Матрица не является прямоугольной в строке " << rows + 1 << '\n';
  86.                 return nullptr;
  87.             }
  88.             rows++;
  89.         }
  90.     }
  91.     double** matr = new(std::nothrow) double*[rows]; //Выделяем память под массив
  92.     if (matr == nullptr) { //Обработка проблем с выделением памяти
  93.         deleteMatr(matr, 0);//Очищаем матрицу
  94.         cout << "Неудачная попытка выделения памяти под массив\n";
  95.         fin.close();//Закрываем поток
  96.         return nullptr;
  97.     }
  98.     for (unsigned int i = 0; i < rows; i++) {
  99.         matr[i] = new(std::nothrow) double[cols];//Выделяем память под очередную строку
  100.         if (matr[i] == nullptr) { //Обработка проблем с выделением памяти
  101.             deleteMatr(matr, i);//Очищаем матрицу
  102.             cout << "Неудачная попытка выделения памяти под массив\n";
  103.             fin.close();//Закрываем поток
  104.             return nullptr;
  105.         }
  106.         else {
  107.             for (unsigned int j = 0; j < cols; j++) {//Для каждого элемента
  108.                 res >> t; //Считываем его
  109.                 if (onlyNum(t)) { //Если он валидный
  110.                     try {
  111.                         while (t.find(",") != t.npos)
  112.                             t.replace(t.find(","), 1, ".");
  113.                         matr[i][j] = stod(t.c_str()); //Пытаемся перевести в double
  114.                     }
  115.                     catch (out_of_range err) { //Обрабатываем переполнение
  116.                         cout << "Обнаружено переполнение типа в значении \"" << t << "\" при чтении элемента " << i + 1 << " строки " << j + 1 << " столбца\n";
  117.                         deleteMatr(matr, i);//Очищаем матрицу
  118.                         fin.close();//Закрываем поток
  119.                         return nullptr;
  120.                     }
  121.                 }
  122.                 else { //Иначе
  123.                     cout << "Неверный ввод значения \"" << t << "\" при чтении элемента " << i + 1 << " строки " << j + 1 << " столбца\n";
  124.                     deleteMatr(matr, i);//Очищаем матрицу
  125.                     fin.close();//Закрываем поток
  126.                     return nullptr;
  127.                 }
  128.             }
  129.         }
  130.     }
  131.     fin.close(); //Закрываем поток
  132.     return matr;
  133. }
  134.  
  135. string  getMatr(double **matr, const unsigned int rows, const unsigned int cols) {
  136.     stringstream s;
  137.     //Записываем матрицу в sstream с последующим преобразованием в string
  138.     for (unsigned int i = 0; i < rows; i++) {
  139.         for (unsigned int j = 0; j < cols; j++)
  140.             s << setw(12) << matr[i][j] << ' ';
  141.         s << '\n';
  142.     }
  143.     return s.str();
  144. }
  145.  
  146. void    showData(ostream &out, double **matr, const unsigned int rows, const unsigned int cols) {
  147.     out << getMatr(matr, rows, cols);//Выводим созданную строку в нужный поток
  148. }
  149.  
  150. void    workWithData(double **matr, const unsigned int rows, const unsigned int cols) {
  151.     double pr;
  152.     int k = 0;
  153.  
  154.     cout << "Считанная матрица\n";
  155.     showData(cout, matr, rows, cols); //Выводим изначальну юматрицу
  156.     for (unsigned int i = 0; i < rows; i += 2) { //Проходя по всем нечетным строкам
  157.         pr = 1; //Изначально произведение равно 1
  158.         for (unsigned int j = 0; j < cols; j++) { //Проходя по всем столбцам
  159.             if (matr[i][j] < 0) { //Если элемент отрицательный
  160.                 pr *= matr[i][j]; //Изменяем произведение
  161.                 k++;//И количество отрицательных элементов
  162.             }
  163.         }
  164.         if (pr < 0) //Если произведение отрицательно
  165.             for (unsigned int j = 0; j < cols; j++) { //Заменяем всю строку нулями
  166.                 matr[i][j] = 0;
  167.             }
  168.     }
  169.     cout << "Количество отрицательных элементов в нечетных строках: " << k << '\n';
  170.     cout << "Измененная матрица\n";
  171.     showData(cout, matr, rows, cols);//Выводим измененную матрицу
  172. }
  173.  
  174. int     main() {
  175.     SetConsoleCP(1251);
  176.     SetConsoleOutputCP(1251);//Русский язык))
  177.     double          **matr = nullptr;
  178.     unsigned int    rows = 0, cols = 0;
  179.  
  180.     matr = loadFile(cin, cout, rows, cols);//Загружаем файл
  181.     if (matr != nullptr) { //Если матрица загрузилась без проблем
  182.         workWithData(matr, rows, cols);//Работаем с ней
  183.         deleteMatr(matr, rows - 1);//Очищаем выделенную память
  184.     }
  185.     cout << "Нажмите любую кнопку чтобы продолжить...\n";
  186.     getchar();
  187.     return 0;
  188. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement