Следующие работы для меня:
sysuse auto, clear
collapse (sum) price mpg, by(make)
estpost tabstat price mpg, by(make)
matrix A = e(price)', e(mpg)'
esttab matrix(A), title("Summary statistics: mean") nomtitle
Summary statistics: mean
--------------------------------------
price mpg
--------------------------------------
1 4099 22
2 4749 17
3 3799 22
4 9690 17
5 6295 23
6 9735 25
7 4816 20
8 7827 15
9 5788 18
10 4453 26
11 5189 20
12 10372 16
13 4082 19
14 11385 14
15 14500 14
16 15906 21
17 3299 29
18 5705 16
19 4504 22
20 5104 22
21 3667 24
22 3955 19
23 6229 23
24 4589 35
25 5079 24
26 8129 21
27 3984 30
28 4010 18
29 5886 16
30 6342 17
31 4296 21
32 4389 28
33 4187 21
34 5799 25
35 4499 28
36 11497 12
37 13594 12
38 13466 14
39 3995 30
40 3829 22
41 5379 14
42 6165 15
43 4516 18
44 6303 14
45 3291 20
46 8814 21
47 5172 19
48 4733 19
49 4890 18
50 4181 19
51 4195 24
52 10371 16
53 12990 14
54 4647 28
55 4425 34
56 4482 25
57 6486 26
58 4060 18
59 5798 18
60 4934 18
61 5222 19
62 4723 19
63 4424 19
64 4172 24
65 3895 26
66 3798 35
67 5899 18
68 3748 31
69 5719 18
70 7140 23
71 5397 41
72 4697 25
73 6850 25
74 11995 17
Total 6165.257 21.2973
--------------------------------------
Вот код, который Вы могли использовать, чтобы удостовериться, что Вы также отклоняете вещи как
42crap
Где несимволы числа следуют за числом. Если Вы считаете целую строку и затем проанализируете ее и выполните действия соответственно, то она возможно потребует, чтобы Вы изменили способ, которым работает Ваша программа. Если Ваша программа считала Ваше число из различных мест до сих пор, затем необходимо поместить одно центральное место, которое анализирует одну строку входа и выбирает действие. Но возможно это - хорошая вещь также - таким образом, Вы могли увеличить удобочитаемость кода тот путь путем разделения вещей: Вход - Обрабатывающий - Вывод
Так или иначе вот то, как можно отклонить number-non-number вышеупомянутых. Считайте строку в строку, затем проанализируйте ее с a stringstream
:
std::string getline() {
std::string str;
std::getline(std::cin, str);
return str;
}
int choice;
std::istringstream iss(getline());
iss >> choice >> std::ws;
if(iss.fail() || !iss.eof()) {
// handle failure
}
Это ест весь запаздывающий пробел. Когда это поражает конец файла stringstream при чтении целого числа или запаздывании пробела, затем это устанавливает eof-разрядное, и мы проверяем это. Если этому не удалось считать какое-либо целое число во-первых, то сбой или плохой бит будут установлены.
Используются более ранние версии этого ответа std::cin
непосредственно - но std::ws
не будет работать хорошо вместе с std::cin
подключенный к терминалу (это заблокирует вместо этого ожидание пользователя для ввода чего-то), таким образом, мы будем использовать a stringstream
для чтения целого числа.
Ответ на некоторые вопросы:
Вопрос: 1. Используя попытку ловят блок. Это не работало. Я думаю, что это вызвано тем, что исключение не повышено из-за плохого входного.
Ответ: Ну, можно сказать потоку выдавать исключения при чтении чего-то. Вы используете istream::exceptions
функция, которую Вы говорите, для которого вида ошибки Вы хотите бросить исключение:
iss.exceptions(ios_base::failbit);
Я никогда не использовал его. Если Вы делаете это на std::cin
, необходимо будет не забыть восстанавливать флаги для других читателей, которые полагаются на него не бросок. Нахождение его путь, легче просто использовать сбой функций, плохо попросить состояние потока.
Вопрос: 2. Я попробовал if(!cin){ //Do Something }
который не работал также. Я еще не понял этого.
Ответ: Это могло прибыть из того, что Вы дали ему что-то как "42crap". Для потока, который является абсолютно допустимым входом при выполнении извлечения в целое число.
Вопрос: 3. В-третьих, я пытался ввести строку фиксированной длины и затем проанализировать ее. Я использовал бы atoi (). Действительно ли это стандарты совместимо и портативно? Я должен записать свою собственную функцию парсинга?
Ответ: atoi Стандартный Совместимый. Но не хорошо, когда Вы хотите проверить ошибки. Нет никакой проверки ошибок, сделанной им в противоположность другим функциям. Если Вы имеете строку и хотите проверить, содержит ли она число, то сделайте это как в первоначальном коде выше.
Существуют подобные C функции, которые могут читать непосредственно из струны до. Они существуют для разрешения взаимодействия со старым, унаследованным кодом и написанием быстрого кода выполнения. Нужно избежать их в программах, потому что они работают довольно низкий уровень и требуют сырых данных использования явные указатели. По самой своей природе они не могут быть улучшены для работы с определяемыми пользователем типами также. А именно, это говорит о функции "strtol" (строка-к-длинному), которая является в основном atoi с проверкой ошибок и возможностью работать с другими основаниями (шестнадцатеричное число, например).
Вопрос: 4. Если я пишу класс, который использует cin, но динамично этот вид обнаружения ошибок, возможно, путем определения типа входной переменной во времени выполнения, он будет иметь слишком много служебным? Это даже возможно?
Ответ: Обычно Вы не должны заботиться слишком много об издержках здесь (если Вы имеете в виду издержки во время выполнения). Но это зависит конкретно от того, где Вы используете тот класс. Тот вопрос будет очень важен, если Вы запишете высокопроизводительную систему, которая обрабатывает вход и должна иметь высоко повсюду. Но если необходимо считать вход из терминала или файла, Вы уже видите то, к чему это сводится: Ожидание пользователя для ввода чего-то действительно занимает много времени, Вы не должны наблюдать затраты во время выполнения в этой точке больше в этом масштабе.
Если Вы имеете в виду код наверху - хорошо он зависит от того, как код реализован. Необходимо было бы просканировать строку, которую Вы читаете - содержит ли она число или нет, ли некоторая произвольная строка. В зависимости от того, что Вы хотите просканировать (возможно, Вам вводили "дату" или формат ввода "времени" также. Изучить boost.date_time
для этого), Ваш код может стать произвольно сложным. Для простых вещей как классификация между числом или нет, я думаю, что можно сойти с рук небольшой объем кода.
Забудьте об использовании отформатированного входа (>> оператор) непосредственно в реальном коде. Необходимо будет всегда читать необработанный текст со станд.:: getline или подобный и затем используют Ваши собственные входные стандартные программы парсинга (который может использовать>> оператор) проанализировать вход.
То, что я сделал бы, является двукратным: Во-первых, попытайтесь проверить вход и извлечь данные, с помощью регулярного выражения, если вход несколько не тривиален. Может быть очень полезно также, даже если вход является просто серией чисел.
Затем мне нравится использовать повышение:: бросок lexical_, который может повысить bad_ lexical_ исключение броска, если вход не может быть преобразован.
В Вашем примере:
std::string in_str;
cin >> in_str;
// optionally, test if it conforms to a regular expression, in case the input is complex
// Convert to int? this will throw bad_lexical_cast if cannot be converted.
int my_int = boost::lexical_cast<int>(in_str);
Это - то, что я делаю с C, но это, вероятно, применимо для C++ также.
Введите все как строку.
Затем и только затем, проанализируйте строку в то, в чем Вы нуждаетесь. Иногда лучше кодировать Ваше собственное, чем попытка изогнуть чужой к Вашему желанию.
Как насчет комбинации различных подходов:
Поймайте вход от std::cin
использование std::getline(std::cin, strObj)
где strObj
a std::string
объект.
Использовать boost::lexical_cast
выполнить лексический перевод из strObj
или к целому числу со знаком или к целому числу без знака самой большой ширины (например, unsigned long long
или что-то подобное)
Использовать boost::numeric_cast
разрушать целое число к ожидаемому диапазону.
Вы могли просто выбрать вход с std::getline
и затем звоните boost::lexical_cast
к соответственно узкому целому типу также в зависимости от того, где Вы хотите зафиксировать ошибку. Три подхода шага обладают преимуществом принятия любых целочисленных данных, и затем зафиксируйте сужающиеся ошибки отдельно.
Я соглашаюсь с Миром, самый простой способ сделать, это должно считать все как строку, затем использовать TryParse для проверки входа. Если это находится в правильном формате, то продолжите двигаться, иначе просто уведомьте, что пользователь и использование продолжают цикл.
Одна вещь, которая не была упомянута еще, состоит в том, что обычно важно, чтобы Вы протестировали, чтобы видеть, работала ли cin>> операция перед использованием переменной, которая, предположительно, получила что-то от потока.
Этот пример подобен Вашему, но делает тот тест.
#include <iostream>
#include <limits>
using namespace std;
int main()
{
while (true)
{
cout << "Enter a number: " << flush;
int n;
if (cin >> n)
{
// do something with n
cout << "Got " << n << endl;
}
else
{
cout << "Error! Ignoring..." << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}
return 0;
}
Это будет использовать обычный оператор>> семантика; это пропустит пробел сначала, затем попытаться считать столько цифр, сколько это может и затем останавливаться. Так "42crap" даст Вам, 42 затем перескакивают через "дерьмо". Если это не то, что Вы хотите, то я соглашаюсь с предыдущими ответами, необходимо считать его в строку и затем проверить его (возможно, использование регулярного выражения - но это может быть излишеством для простой числовой последовательности).