Форум русскоязычного сообщества Ubuntu


Автор Тема: Помогите усовершенствовать код в С++  (Прочитано 1122 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн serebrus

  • Автор темы
  • Любитель
  • *
  • Сообщений: 54
    • Просмотр профиля
Написала программку:

// Определить значения целочисленного массива D
// по правилу: D=1, если сумма эл-ов i-ой массива В строки >0
//                 =0 в противном случае.


#include <iostream>
#define I 4
#define J 5


using namespace std;


// прототипы функций
void inputmas(int [J], char);
void raschet(int [J], int );
void outputmasb(int [J], char);
void outputmasd(int [J], char d);
void printrez(int [J], char, int , char);

int main()
{

   int B[J];
   int D;
   inputmas (B, 'b');   
   raschet (B, D);
   cout <<"\n\n\n___________________________________";
   cout <<"\nПодведем итоги:";
   printrez (B, 'b', D, 'd');
}

// Определение функции ввода массива
void inputmas(int B[J], char b)
{
   
   int i, j;
   cout <<"Введите данные для целочисленного массива В\n";
   for (i=0; i<I; i++)
      {for (j=0; j<J; j++)
         {cout <<"    b[" <<i<< "]" <<"[" <<j<< "]=";
          cin >>B[j];
         }
      }
}

// Определение функцию для определения нового массива D
void raschet (int B[J], int D)
{
   int i, j, sum;
   for (i=0; i<I; i++)
   {sum=0;
    cout <<"\n";
      {for (j=0; j<J; j++)
         sum =sum+B[j];   
      }   
    cout <<"\nСумма элементов "<<i<<" строки = "<<sum;
      {if (sum>0)  D=1; else D=0;
       cout<<"\nЭлемент "<<i<<" строки нового массива D = "<<D;
      }
         
   }
}

// Определение функции вывода массива B
void outputmasb(int B[J], char b)
{
   int i, j;
   cout <<"\n\nВы ввели следующий массив B";
   for (i=0; i<I; i++)
   {cout <<"\n";
      for (j=0; j<J; j++)
         {cout.width( 8 );
         cout <<B[j];
         }
    }
}

// Определение функции вывода массива D
void outputmasd(int D, char d)
{
   int i;
   cout <<"\n\n\nПолучен следующий массив D\n";
   for (i=0; i<I; i++)
   cout <<"     "<< D;
   
}

// Определение функции вывода результатов программы на экран
void printrez (int B[J], char b, int D, char d)
{
   outputmasb (B, b);
   outputmasd (D, d);
}


Все работает, если вводить правильные начальные данные.

Но захотелось мне вставить проверку для вводимых данных.

Для чего модернизировала этот блок:


// Определение функции ввода массива
void inputmas(int B[J], char b)
{
   
   int i, j;
   cout <<"Введите данные для целочисленного массива В\n";
   for (i=0; i<I; i++)
      {for (j=0; j<J; j++)
         {cout <<"    b[" <<i<< "]" <<"[" <<j<< "]=";
          cin >>B[j];
            if (!cin)
            {cout <<"Вы ввели неверные данные."<<endl;
             }
         }
      }
}

Как его дописать, чтобы он, при вводе некорректных данных, начинал ввод снова? Или просто завершал программу с комментарием.

Программировать только начинаю, так что не судите строго
  :)

Оффлайн wl

  • Старожил
  • *
  • Сообщений: 1393
    • Просмотр профиля
Re: Помогите усовершенствовать код в С++
« Ответ #1 : 15 Апреля 2010, 13:08:51 »
// Определение функции ввода массива
void inputmas(int B[J], char b)
{
   int i, j;
   cout <<"Введите данные для целочисленного массива В\n";
   for (i=0; i<I; i++)
      {for (j=0; j<J; j++)
         {cout <<"    b[" <<i<< "]" <<"[" <<j<< "]=";
          cin >>B[j];
            if (!cin)
            {cout <<"Вы ввели неверные данные."<<endl;
             }
         }
      }
}

Как его дописать, чтобы он, при вводе некорректных данных, начинал ввод снова? Или просто завершал программу с комментарием.

Программировать только начинаю, так что не судите строго
  :)

Например, вводить каждое число в цикле do-while.

bool done;
do{
  done=true;
  cin >>B[i][j];
  if (!cin) {
    cout <<"Вы ввели неверные данные."<<endl;
    done=false;
  }
}while(!done);
Это простейший вариант, чтобы проиллюстрировать принцип. Переделайте его сами под Ваши нужды.
На свете феньки есть такие, брат Горацио, которых лохи просто не секут. (Шекспир, "Гамлет", вольный перевод)

Оффлайн WereBeast

  • Любитель
  • *
  • Сообщений: 85
    • Просмотр профиля
Re: Помогите усовершенствовать код в С++
« Ответ #2 : 15 Апреля 2010, 13:13:44 »
// Определение функции ввода массива
bool inputmas(int B[J], char b)
{
   
   int i, j;
   cout <<"Введите данные для целочисленного массива В\n";
   for (i=0; i<I; i++)
      {
   for (j=0; j<J; j++)
         {
       cout <<"    b[" <<i<< "]" <<"[" <<j<< "]=";
       cin >>B[j];
            if (!cin)
            {
             return false; //здесь было неверное значение
            }
         }
      }
  return true;
}

//функция main
int main()
{

   int B[J];
   int D;
  while(!inputmas (B, 'b'))
  {
     cout<<"\nЗначение было введено неправильно. Пробуем еще раз"<<endl;
  }
     
   raschet (B, D);
   cout <<"\n\n\n___________________________________";
   cout <<"\nПодведем итоги:";
   printrez (B, 'b', D, 'd');
}

Программирую пропаганду
Windows - в гландах

Оффлайн serebrus

  • Автор темы
  • Любитель
  • *
  • Сообщений: 54
    • Просмотр профиля
Re: Помогите усовершенствовать код в С++
« Ответ #3 : 15 Апреля 2010, 13:29:09 »
Если делать, как предложил WereBeast, то программу зацикливает на фразе "Значение было введено неправильно."

Попробую разобраться в цикле do-while, как предложил WL.

Спасибо друзья.

Пользователь решил продолжить мысль 15 Апреля 2010, 14:03:36:
Честно сказать, все равно сделал по-своему, так как и do-while зацикливал меня (или уж мои мозги, не скажу что точнее)

В итоге подправила два блока:



int main()
{

   int B[J];
   int D;
   inputmas (B, 'b');   // Вызов функции ввода массива В
   if (cin)
   {raschet (B, D);      // Вызов функции расчета массива D
   cout <<"\n\n\n___________________________________";
   cout <<"\nПодведем итоги:";
   printrez (B, 'b', D, 'd');      //Вызов функции печати результатов
   }
   cout <<"\nВы ввели неверные даные. Запутите программу сначала."<<endl;
}

// Определение функции ввода массива
void inputmas(int B[J], char b)
{
   
   int i, j;
   cout <<"Введите данные для целочисленного массива В\n";
   for (i=0; i<I; i++)      // Ввод массива В
      {for (j=0; j<J; j++)
         {cout <<"    b[" <<i<< "]" <<"[" <<j<< "]=";
          cin >>B[j];
            if (!cin) // Проверка вводимых данных на соответствие типу
            break;
         }
         if(!cin) break;
      }
}


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

Почему?

Вот что выходит после запуска программы:


Не пойму почему в одном случае вторая строка выскакивает, а в другом нет?


« Последнее редактирование: 15 Апреля 2010, 14:03:37 от serebrus »

Оффлайн wl

  • Старожил
  • *
  • Сообщений: 1393
    • Просмотр профиля
Re: Помогите усовершенствовать код в С++
« Ответ #4 : 15 Апреля 2010, 14:33:07 »
Потому что программа читает из буфера ввода все до точки, записывает все введенное в переменную, потом переходит к следующей итерации цикла, читает точку и только тут осознает, что это не число.

Я бы рекомендовал сохранять ввод в текстовой строке, анализировать ее, а дальше, по результатам анализа, либо переводить в число, сохранять в массиве и переходить к следующей итерации, либо завершать работу с сообщением об ошибке (или какое там поведение требуется?)

Если программа будет работать под юниксом, рекомендую ознакомиться с функцией readline (man readline).
« Последнее редактирование: 15 Апреля 2010, 14:34:49 от wl »
На свете феньки есть такие, брат Горацио, которых лохи просто не секут. (Шекспир, "Гамлет", вольный перевод)

Оффлайн serebrus

  • Автор темы
  • Любитель
  • *
  • Сообщений: 54
    • Просмотр профиля
Re: Помогите усовершенствовать код в С++
« Ответ #5 : 15 Апреля 2010, 15:06:08 »
Не поняла, она что первое число (1.1) считывает в два этапа?

Не знаю под чем она будет работать, это просто одна из задач контрольной работы в институт на сессию :-)

Оффлайн wl

  • Старожил
  • *
  • Сообщений: 1393
    • Просмотр профиля
Re: Помогите усовершенствовать код в С++
« Ответ #6 : 15 Апреля 2010, 15:23:12 »
Не поняла, она что первое число (1.1) считывает в два этапа?

Нет. Сначала читает 1 и записывает в B[  ][   ], потом читает точку и останавливается.

Замените везде if(!cin) break; на
if(!cin){
  cout << __LINE__ <<endl;
  break;
}
Этот код будет выводить номер строки, на которой сработал оператор break;
Пример: http://codepad.org/ch9kqExY

Либо прогоните программу пошагово. В среде у Вас наверняка есть опции трассировки. Если нет, то можно воспользоваться kdbg или ddd.
Для трассировки надо к ключам компилятора добавить -ggdb3
« Последнее редактирование: 15 Апреля 2010, 15:32:16 от wl »
На свете феньки есть такие, брат Горацио, которых лохи просто не секут. (Шекспир, "Гамлет", вольный перевод)

Оффлайн serebrus

  • Автор темы
  • Любитель
  • *
  • Сообщений: 54
    • Просмотр профиля
Re: Помогите усовершенствовать код в С++
« Ответ #7 : 15 Апреля 2010, 15:45:06 »


Вот что выдает в случае, если поправить как вы сказали:

// Определение функции ввода массива
void inputmas(int B[J], char b)
{
   
   int i, j;
   cout <<"Введите данные для целочисленного массива В\n";
   for (i=0; i<I; i++)      // Ввод массива В
      {for (j=0; j<J; j++)
         {cout <<"    b[" <<i<< "]" <<"[" <<j<< "]=";
          cin >>B[j];
            if (!cin) // Проверка вводимых данных на соответствие типу
            {cout<<__LINE__<<endl;
            break;
            }
         }
         if(!cin) break;
      }
}

Где прогнать пошагово не нашла, буду искать. Работаю в geany, может подскажете куда нырять :-)

Оффлайн wl

  • Старожил
  • *
  • Сообщений: 1393
    • Просмотр профиля
Re: Помогите усовершенствовать код в С++
« Ответ #8 : 15 Апреля 2010, 15:59:52 »
Вот что выдает в случае, если поправить как вы сказали:
Что, так и непонятно?
Про geany ничего не знаю, если не получится с ним, попробуйте поработать за компьютер, на бумаге, карандашом.

Входим в циклы.
Первая итерация.
i=0
j=0
пишем в cout "  b[0][0]="
ждем ввода от юзера
юзер пишет "1.1"
читаем все до первой нецифры, получилась единица, запихиваем ее в B[0]
проверяем !cin - ошибок нет, поэтому внутрь if не входим.
Следующая итерация внутреннего цикла.
i=0
j=1
пишем в cout "  b[0][1]="
ждем ввода от юзера.
В буфере уже есть что-то, написанное юзером, это точка.
пытаемся запихнуть ее в B[1] - не получается.
Проверяем !cin - условие выполнилось, входим внутрь if, пишем номер строки и завершаем цикл по j
После этого стоит еще одна проверка !cin, условие все еще выполняется, поэтому входим в if и выполняем оператор break, прерывающий внешний цикл.

Все, конец работы.
« Последнее редактирование: 15 Апреля 2010, 16:03:40 от wl »
На свете феньки есть такие, брат Горацио, которых лохи просто не секут. (Шекспир, "Гамлет", вольный перевод)

Оффлайн serebrus

  • Автор темы
  • Любитель
  • *
  • Сообщений: 54
    • Просмотр профиля
Re: Помогите усовершенствовать код в С++
« Ответ #9 : 15 Апреля 2010, 17:53:56 »
Это я поняла, в целом меня уже все устраивает, думаю полного совершенства программы и не требуется, судя по тем программам, которые предлагает сама препод.


Спасибо огромное, честно сказать просто не знала что он будет брать цифру до точки, а потом пытаться взять точку как отдельный знак :-) Думала что он считает все до пробела :-)


Оффлайн wl

  • Старожил
  • *
  • Сообщений: 1393
    • Просмотр профиля
Re: Помогите усовершенствовать код в С++
« Ответ #10 : 15 Апреля 2010, 18:07:18 »
Чтоб читал все до пробела, надо в строку читать, а не в int.
На свете феньки есть такие, брат Горацио, которых лохи просто не секут. (Шекспир, "Гамлет", вольный перевод)

 

Страница сгенерирована за 0.05 секунд. Запросов: 25.