Russian Qt Forum
Сентябрь 24, 2024, 06:22 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 ... 6 7 [8] 9 10 ... 12   Вниз
  Печать  
Автор Тема: Тренировка навыков быстрого программирования  (Прочитано 79997 раз)
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #105 : Март 05, 2014, 10:48 »

Old, мне очень хочется узнать Ваше мнение, куда прижимать значок '&'?
Я прижимаю к имени, и ссылку и указатель.

И ещё вопрос: в следующей функции уместны ли буквы 'i' и 'o' перед именами:  Bulls и Cows
Для меня не уместны.
Записан
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #106 : Март 05, 2014, 11:58 »

Помогите, пожалуйста. Сейчас пытаюсь решить вот эту задачу: http://acmp.ru/?main=task&id_task=13

Вот с такими тестами нормально запускается (такие же тесты, как под описанием задачи на сайте):

Код
C++ (Qt)
   QTest::addColumn<int>("first");
   QTest::addColumn<int>("second");
   QTest::addColumn<int>("nbulls_expected");
   QTest::addColumn<int>("ncows_expected");
 
   QTest::newRow("bulls_and_cows_01") << 5671 << 7251 << 1 << 2;
   QTest::newRow("bulls_and_cows_02") << 1234 << 1234 << 4 << 0;
   QTest::newRow("bulls_and_cows_03") << 2034 << 6234 << 2 << 1;
 

Вот моя функция, которая решает задачу:

Код
C++ (Qt)
/**
* Возвращает (через ссылки) количество совпадений цифр двух
* чисел на тех же позициях (быки) и на разных (коровы)
*
* @param first Первое число
* @param second Второе число
* @param nbulls Возвращаемое значение. Количество совпадений вместе с
* позицией (быки)
* @param ncows Возвращаемое значение. Количество совпадений, не
* учитывая позицию (коровы)
*/

void bulls_and_cows(int first, int second, int &nbulls, int &ncows) {
 
   div_t divresult_first;
   div_t divresult_second;
 
   int first_temp = first;
   int second_temp = second;
 
   std::vector<int> vec_first;
   std::vector<int> vec_second;
 
   const std::size_t nsize = 4;
 
   // Подсчёт быков
   for (std::size_t i = 0; i < nsize; ++i) {
       // Деление с сохранением частного и остатка
       divresult_first = div(first_temp, 10);
       divresult_second = div(second_temp, 10);
 
       // Сохраняем цифры для поиска коров
       vec_first.push_back(divresult_first.rem);
       vec_second.push_back(divresult_second.rem);
 
       // Поиск быков
       if (divresult_first.rem == divresult_second.rem) {
           ++nbulls;
       }
       first_temp = divresult_first.quot;
       second_temp = divresult_second.quot;
   }
 
   // Проверяем, что числа четырёхзначные
   if ( (vec_first.size() != nsize) && (vec_second.size() != nsize) ) {
       return;
   }
 
   // Подсчёт коров
   for (std::size_t i = 0; i < nsize; ++i) {
       std::vector<int>::const_iterator it = std::find(vec_second.begin(), vec_second.end(), vec_first[i]);
       if (it != vec_second.end()) {
           if (*it != vec_second[i]) {
               ++ncows;
           }
       }
   }
}

А это всё содержимое main.cpp:
Код
C++ (Qt)
#include <string>
#include <fstream>
#include <iostream>
#include <cstdlib>
#include <vector>
#include <algorithm>
 
//#define TESTING
 
#ifndef TESTING
int readData(const std::string &iFileName, int &first, int &second);
int writeResult(const std::string& oFileName, int nbulls, int ncows);
int showError(int err, const std::string& fileName);
void bulls_and_cows(int first, int second, int &nbulls, int &ncows);
 
int main(int argc, char** argv) {
 
   // Входные данные
   int first;
   int second;
 
   // Имя входного файла
   std::string iFileName = "input.txt";
 
   // Читаем данные из файла
   int err = readData(iFileName, first, second);
   if (err) return showError(err, iFileName);
 
   // Выполняем содержательную часть
   int nbulls, ncows;
   nbulls = ncows = 0;
   bulls_and_cows(first, second, nbulls, ncows);
 
   // Записываем выходной файл
   std::string oFileName = "output.txt";
   err = writeResult(oFileName, nbulls, ncows);
   if (err) return showError(err, oFileName);
 
   return 0;
}
 
/**
* Читаем данные из файла
*
* @param iFileName Имя входного файла
* @param vec Массив, в который будут считаны входные данные
* @return Код ошибки: 0 - если ошибок нет
*                     1 - если файл не удалось открыть
*                     2 - если в файле некорректные данные
*/

int readData(const std::string& iFileName, int &first, int &second) {
 
   // Код ошибки
   int err = 0;
 
   // Открываем файл с входными данными
   std::ifstream in;
   in.open(iFileName.c_str());
   if (!in.is_open()) {
       err = 1;
       return err;
   }
 
   // Считываем данные из файла
   if (in >> first >> second) {
       err = 0;
       return err;
   } else {
       err = 2;
       return err;
   }
 
   // Закрываем файл и возвращаем нулевой код ошибки
   in.close();
   return err;
}
 
/**
* Записываем результат выходной в файл
*
* @param iFileName Имя выходного файла
* @param vec Массив, который нужно записать в файл
* @return Код ошибки: 0 - если ошибок нет
*                     1 - если файл не удалось открыть
*                     2 - если в файле не удалось записать
*/

int writeResult(const std::string& oFileName, int nbulls, int ncows) {
 
   // Открываем файл для записи
   std::ofstream out;
   out.open(oFileName.c_str());
   if (!out.is_open()) {
       return 1;
   }
 
   // Записываем данные в файл
   out << nbulls << " " << ncows << std::endl;
 
   // Закрываем файл и возвращаем код ошибки
   out.close();
   return 0;
}
 
/**
* Выводит текст с ошибкой на экран
*
* @param err Код ошибки
* @param iFileName Имя файла, в котором произошла ошибка
*/

int showError(int err, const std::string& fileName) {
   switch (err) {
   case 1:
       std::cerr << "Error: could not open the file " << fileName.c_str() << std::endl;
       break;
   case 2:
       std::cerr << "Error: incorrect data in the file " << fileName.c_str() << std::endl;
       break;
   default:
       std::cerr << "Error code: " << err << "; file name: " << fileName.c_str() << std::endl;
       break;
   }
 
   return err;
}
#endif
 
/**
* Возвращает (через ссылки) количество совпадений цифр двух
* чисел на тех же позициях (быки) и на разных (коровы)
*
* @param first Первое число
* @param second Второе число
* @param nbulls Возвращаемое значение. Количество совпадений вместе с
* позицией (быки)
* @param ncows Возвращаемое значение. Количество совпадений, не
* учитывая позицию (коровы)
*/

void bulls_and_cows(int first, int second, int &nbulls, int &ncows) {
 
   div_t divresult_first;
   div_t divresult_second;
 
   int first_temp = first;
   int second_temp = second;
 
   std::vector<int> vec_first;
   std::vector<int> vec_second;
 
   const std::size_t nsize = 4;
 
   // Подсчёт быков
   for (std::size_t i = 0; i < nsize; ++i) {
       // Деление с сохранением частного и остатка
       divresult_first = div(first_temp, 10);
       divresult_second = div(second_temp, 10);
 
       // Сохраняем цифры для поиска коров
       vec_first.push_back(divresult_first.rem);
       vec_second.push_back(divresult_second.rem);
 
       // Поиск быков
       if (divresult_first.rem == divresult_second.rem) {
           ++nbulls;
       }
       first_temp = divresult_first.quot;
       second_temp = divresult_second.quot;
   }
 
   // Проверяем, что числа четырёхзначные
   if ( (vec_first.size() != nsize) && (vec_second.size() != nsize) ) {
       return;
   }
 
   // Подсчёт коров
   for (std::size_t i = 0; i < nsize; ++i) {
       std::vector<int>::const_iterator it = std::find(vec_second.begin(), vec_second.end(), vec_first[i]);
       if (it != vec_second.end()) {
           if (*it != vec_second[i]) {
               ++ncows;
           }
       }
   }
}
 

Не знаю, у все проходило Улыбающийся
инклудов много - один проект использовал для всех задач, и было влом убирать их после решения Улыбающийся
Код:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <vector>
#include <math.h>
#include <list>
#include <map>
#include <set>
#include <iomanip>
#include <iterator>
#include <sstream>
#include <algorithm>
 
using namespace std;
 
int main()
{
    freopen( "input.txt", "r", stdin );
    freopen( "output.txt", "w", stdout );
 
    string s1, s2;
    cin >> s1 >> s2;
    int bulls=0, cows=0;
 
//    cout << s1 << " " << s2 << "\n";
 
    for ( int i = 0; i < 4; i++ )
        if ( s1[i] == s2[i] )
            bulls++;
 
    for ( int i = 0; i < 4; i++ )
    {
        for ( int j = 0; j < 4; j++ )
            if ( s1[i] == s2[j] && i != j )
                cows++;
    }
 
    cout << bulls << " " << cows /*<< "\n"*/;
 
    return 0;
}

Но я бы на вашем месте решал бы нормальные (попробуйте сделать браузер или текстовый редактор, можно и xml с html, или плеер видео или ауди) - такие будут интереснее и познавательнее )
Олимпиадные мало чему научат, там просто нужно знать мат алгоритмы или хорошо их гуглить в википедии. Да и олимпиадные больше части уникальные, их алгоритм пригодится только для данной задачи и все.
Сам решил около сотни задач, не все своими силами - алгоритмы некоторых находились в википедии Улыбающийся
Удачи с задачками ))
« Последнее редактирование: Март 05, 2014, 12:04 от gil9red » Записан

8Observer8
Гость
« Ответ #107 : Март 05, 2014, 14:00 »

Смысл: вызывающий видит вход/выход, Если же ссылки, то можно так
Код
C++ (Qt)
void bulls_and_cows(int iFirst, int iSecond, int & oBulls, int & oCows)
 

Решил первые переменные немного дополнить:
Код
C++ (Qt)
void bulls_and_cows(int firstNumber, int secondNumber, ...)
 

Если переменные используются для выхода, то лучше отметить это, указав букву 'o':
Код
C++ (Qt)
int readData(const std::string & fileName, int & oFirstNumber, int & oSecondNumber);
 

Если название функции "прочитатьДанные" readData(const std::string & fileName, ...), то понятно, что имя входного файла нужно передать, поэтому пишу просто: fileName

Считаю, что в следующей функции уточнения излишни (так как мы записываем в файл, то что передаём) и можно просто написать число быков и число коров: int nBulls, int nCows
Код
C++ (Qt)
int writeResult(const std::string & fileName, int nBulls, int nCows);
 

Как и здесь:
Код
C++ (Qt)
int showError(int err, const std::string & fileName);
 

А вот в следующей функции, как-то не очень смотрятся переменные: nBulls и nCows если пометить, что они используются для выхода: int & onBulls, int & onCows

Код
C++ (Qt)
void bulls_and_cows(int firstNumber, int secondNumber, int & onBulls, int & onCows);
 

Можно конечно и так написать: o_nBulls, o_nCows, но это не очень хорошо смотрится. Или же так: oBulls, oCows. Но а что если я перед переменной хочу букву поставить, которая в данном случае обозначает "количество": nBulls
Записан
OKTA
Гость
« Ответ #108 : Март 05, 2014, 14:03 »

Чем мой вариант не устраивает?  Смеющийся
Записан
8Observer8
Гость
« Ответ #109 : Март 05, 2014, 14:06 »

Чем мой вариант не устраивает?  Смеющийся

Я до него ещё не добрался Улыбающийся Не могу всё сразу Улыбающийся

Куча разных дел, приходится переключаться с одного на другое.
Записан
OKTA
Гость
« Ответ #110 : Март 05, 2014, 14:07 »

Так он как раз избавит от проблемы с добавлением буковок  Смеющийся
Записан
8Observer8
Гость
« Ответ #111 : Март 05, 2014, 14:08 »

А этот способ только для Windows?
Записан
OKTA
Гость
« Ответ #112 : Март 05, 2014, 14:11 »

для всего конечно  Подмигивающий
Записан
8Observer8
Гость
« Ответ #113 : Март 05, 2014, 14:16 »

для всего конечно  Подмигивающий

Сначала со следующими вариантами хочу разобраться Улыбающийся

Решил, что лучше отказаться от буквы 'n' для обозначения количества. И для возвращаемых переменных из фукнций писать: oBulls

Правда, тогда получается, что если эти переменные - это входные данные для функции, то их нужно передавать так: bulls, cows, то есть писать с маленькой буквы.

Для входа: oBulls, oCows
Для выхода: bulls, cows

Ну либо так:
Для входа: oBulls, oCows
Для выхода: nBulls, nCows

Правда в последнем случае получается небольшая путанница. Как будто буквы 'o' и 'n' противоположенны друг другу. Поэтому лучше так:
Для входа: oBulls, oCows
Для выхода: bulls, cows
Записан
Bepec
Гость
« Ответ #114 : Март 05, 2014, 14:18 »

А есть ещё методика (непомню кого), где пишут явно inBulls, outBulls.
PS выбирать надо как тебе нравится.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #115 : Март 05, 2014, 14:20 »

Можно конечно и так написать: o_nBulls, o_nCows, но это не очень хорошо смотрится. Или же так: oBulls, oCows. Но а что если я перед переменной хочу букву поставить, которая в данном случае обозначает "количество": nBulls
oNumBulls (Cows), префикс "n" проблематичен. Если аргумент подается по НЕконстантой ссылке - и так ясно что ожидается его заполнение/изменение. Другое дело что это не поможет вызывающему, напр
Код
C++ (Qt)
bulls_and_cows(first, second, nBulls, nCows);
Где вход и выход? Пока неясно, нужно лезть в прототип ф-ции (а это время)
Код
C++ (Qt)
bulls_and_cows(first, second, &nBulls, &nCows);
A так? Да, внутри указатель может чуть менее удобен, но зато куда яснее на вызове. Библия рекомендует этот вариант

Но в конце-концов все это - дело вкуса. Опять Вы песиками увлеклись Улыбающийся А ведь "содержательная часть" провалена капитально.

Чем мой вариант не устраивает?  Смеющийся
Да тем что он невыносимо длинный  Улыбающийся Для API/экспорта - согласен, есть смысл, но в каждой рабочей ф-ции так делать вряд ли кто будет
Записан
OKTA
Гость
« Ответ #116 : Март 05, 2014, 14:27 »

А если вход и выход в одном аргументе?  Смеющийся
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #117 : Март 05, 2014, 14:31 »

Библия рекомендует этот вариант
Про какую библию вы все время говорите?
Записан
8Observer8
Гость
« Ответ #118 : Март 05, 2014, 15:56 »

Я определился с именами переменных.

1) Если в программе есть имена входного и выходного файла, то лучше это отметить:
Код
C++ (Qt)
int main(int argc, char** argv) {
   // ...
   std::string iFileName = "input.txt";
   // ...
   std::string oFileName = "output.txt";
   // ...
}

2) В принимающей функции решил отказаться от каких-либо букв, а писать названия полностью, например: numberOfBulls

3) Решил отказаться от букв 'i' и 'o', так как, если ссылка НЕ константная, то и так понятно, что переменная используется для выходных значений:
Код
C++ (Qt)
void bulls_and_cows(int firstNumber, int secondNumber, int &numberOfBulls, int &numberOfCows);
 

4) Прижимаю значок '&' к имени переменной, как написано в руководстве: http://qt-project.org/wiki/Qt_Coding_Style_Russian

Цитировать
Всегда ставьте один пробел после ‘*’ или ‘&’, если они стоят перед описанием типов. Но никогда не ставьте пробелы после ‘*’ или ‘&’ и именем переменной.
Код
C++ (Qt)
    char *x;
    const QString &myString;
    const char * const y = "hello";
 
« Последнее редактирование: Март 05, 2014, 16:30 от 8Observer8 » Записан
8Observer8
Гость
« Ответ #119 : Март 05, 2014, 16:01 »

...куда прижимать значок '&'?

По этому поводу можно почитать вот это.

Вот за это отдельное спасибо! Улыбающийся
Записан
Страниц: 1 ... 6 7 [8] 9 10 ... 12   Вверх
  Печать  
 
Перейти в:  


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