2015-12-17 3 views
0

Я написал класс, который возвращает случайную строку после предоставления семени, длины последовательности и набора символов, как показано ниже.Ловушка ошибки/исключения в классе

Я хотел бы знать, как поймать любой плохой ввод, например, установить семя на 0 или на отрицательное число.

Примеры, которые я видел, только что использовали cout для отправки сообщения об ошибке, а затем выхода (1); Я думаю о том, чтобы поместить флаг bool в качестве частной переменной и установить его в false при обнаружении недействительного ввода. Затем, после попытки создать случайную строку с этим классом, вы просто проверите этот флаг через функцию доступа.

Есть ли лучший и/или стандартный способ обращения с этим, который не только выйдет из программы, как выход (1)? Также приветствуется любой общий ввод о классе. Спасибо за помощь.

RandomString.h

// This is the header file randomstring.h. This is the interface for the class RandomString. 
// Values of this type are a random string of the specified length from the specified string character set. 
// The values that are needed for input are a positive integer seed, an integer desired length, and a string character set. 
// Uses the mt19937 random number engine with a uniform_int_distribution. 
#ifndef RANDOMSTRING_H 
#define RANDOMSTRING_H 

#include <string> 
#include <random> 
using namespace std; 

namespace RandomString 
{ 
    class RandomString 
    { 
    public: 
     RandomString(double newSeed, unsigned int newLength, string newCharacterSet); // Initializes the RandomString object with the provided arguments. 
     RandomString(); // Initializes the seed to 1, the length to 0, and the character set to '0'. 
     double getSeed(); 
     unsigned int getLength(); 
     string getCharacterSet(); 
     string getSequence(); 
     void setSeed(double newSeed); // Sets the new seed but does not produce a new random sequence. 
     void setLength(unsigned int newLength); // This is the length of randomSequence. 
     void setCharacterSet(string newCharacterSet); 
     void generateNext(); // Generates the next random sequence. 

    private: 
     double seed; 
     unsigned int length; 
     string characterSet; 
     string randomSequence; 
     mt19937 engine; 
    }; 

} // RandomString namespace 

#endif 

RandomString.cpp

// This is the implementation file randomstring.cpp. This is the implementation for the class RandomString. 
// The interface for the class RandomString is in the header file randomstring.h. 
#include "stdafx.h" 
#include <string> 
#include <random> 
#include "randomstring.h" 

using std::string; 
using std::uniform_int_distribution; 

namespace RandomString 
{ 
    RandomString::RandomString(double newSeed, unsigned int newLength, string newCharacterSet) 
    { 
     setSeed(newSeed); 
     setLength(newLength); 
     setCharacterSet(newCharacterSet); 
    } 

    RandomString::RandomString() 
    { 
     seed = 1; 
     length = 0; 
     characterSet = '0'; 
    } 

    double RandomString::getSeed() 
    { 
     return seed; 
    } 

    unsigned int RandomString::getLength() 
    { 
     return length; 
    } 

    string RandomString::getCharacterSet() 
    { 
     return characterSet; 
    } 

    string RandomString::getSequence() 
    { 
     return randomSequence; 
    } 

    void RandomString::setSeed(double newSeed) 
    { 
     seed = newSeed; 
     engine.seed(seed); 
    } 

    void RandomString::setLength(unsigned int newLength) 
    { 
     length = newLength; 
    } 

    void RandomString::setCharacterSet(string newCharacterSet) 
    { 
     characterSet = newCharacterSet; 
    } 

    void RandomString::generateNext() 
    { 
     randomSequence.resize(length); 
     uniform_int_distribution<> distribution(0,characterSet.length() - 1); 

     for (int i = 0; i < length; i++) 
     { 
      randomSequence[i] = characterSet[distribution(engine)]; 
     } 

    } 
} // RandomString namespace 

Наконец, здесь есть тестовая программа, которую я использую.

// test.cpp : Defines the entry point for the console application. 
// 

#include "stdafx.h" 
#include <iostream> 
#include "randomstring.h" 

using namespace std; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    do 
    { 
     double seed = 0; 
     unsigned int length = 0; 

     cout << "Enter seed: "; 
     cin >> seed; 
     cout << "Enter length of string: "; 
     cin >> length; 
     cout << endl; 

     RandomString::RandomString randomTest(seed,length,"ABCDEFGHJKLMNPQRSTUVWXYZ1234567890"); 
     cout << "class RandomString" << endl; 
     cout << "seed: " << randomTest.getSeed() << endl; 
     cout << "length: " << randomTest.getLength() << endl; 
     randomTest.generateNext(); 
     cout << "random sequence: " << randomTest.getSequence() << endl; 
     randomTest.generateNext(); 
     cout << "next random sequence: " << randomTest.getSequence() << endl << endl; 

    }while(true); 

} 
+0

[RAII] (https://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization). Выбросьте исключение из своего c'tor при получении недопустимых параметров. – IInspectable

+0

Если после инициализации был вызван randomTest.setSeed (0), а затем он попытался создать снова, это поймает его? – NinjaLlama

ответ

0

сгенерирует исключение

void RandomString::setSeed(double newSeed) 
{ 
    if (newSeed <= 0) { 
     throw std::runtime_error("seed should be positive"); 
    } 
    seed = newSeed; 
    engine.seed(seed); 
} 

Пользователь должен использовать try catch для обработки ошибки, иначе std::terminate называется.

+0

Я пробовал ваш метод, и он работает. Является ли ваш метод предпочтительным для установки внутреннего флага и проверки его перед попыткой использовать сгенерированную последовательность в основной программе? [что-то вроде randomTest.getValidStatus()] Я читал, что исключения следует использовать только в качестве последнего средства. Спасибо за помощь. – NinjaLlama

+0

Исключение не должно использоваться для потока управления в C++, но его правильная ошибка. Внутренний флаг подвержен ошибкам, так как вы должны проверять почти все методы, которые находятся в правильном состоянии. За исключением, понятно, что объект полезен или нет. Вы можете переместить исключение в конструктор и вместо этого указать код ошибки setSeed (который должен быть проверен), если вы считаете, что этот параметр для недопустимого значения является * нормальным * использованием. – Jarod42

+0

Хорошо, я попробую. Спасибо за быструю помощь, Это было очень необходимо. – NinjaLlama

0

Как насчет того, чтобы предоставить пользователю еще один шанс дать хороший ввод?

Какая следующая вещь пользователь сделает после того, как выяснит, что у них плохой ввод? Есть большая вероятность, что они попытаются снова с хорошим вводом, поэтому просто попросите другого.

while(true) 
{ 
    cout << "Enter seed: "; 
    cin >> seed; 

    if(seed > 0) 
    { 
     cout << "ERROR: Seed must be greater than 0." << endl; 
     break; 
    } 
} 

Чтобы ответить на ваш вопрос о флаге bool ошибок, я бы не сделать это таким образом. Мне не нужны плохие данные, созданные из плохого семени. Нет данных лучше плохих данных. Обычно я пытаюсь «провалиться рано, не часто», то есть я должен остановиться и сообщить об ошибке, как только я это осознаю.

Если вы были установлены для хранения этого флага ошибки, у меня бы получилось generateNext() или setSeed вернуть false, а не ничего, если возникла проблема. Исключения также работают, но медленнее, а некоторые проекты не нравятся им на C++.

Если вы планируете использовать других пользователей RandomString, я бы изменил подпись метода от double до uint (unsigned int). Это приведет к тому, что отрицательные числа будут использоваться во время компиляции, а не во время выполнения ... снова помогая неудаче даже раньше. Похоже, что это может не работать в вашем классе, но это хороший принцип в реальном мире.

+0

Я считаю, что это сработало бы в этом случае, но в финальных программах классу не будет предоставлено семя непосредственно от пользователя. – NinjaLlama

+0

Я вижу.Не могли бы вы обновить свой вопрос, чтобы показать тестовый пример, на который вы хотели бы ответить? Благодарю. –

+0

Я еще не знаю точное использование этого класса. Меня попросили предоставить его кому-то еще. Я знаю, что для этого требуется некоторая обработка, а не просто сбой. Извините за невозможность помочь больше. – NinjaLlama

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