Объект RegExp
отслеживает lastIndex
, где произошло совпадение, поэтому в последующих совпадениях он будет начинаться с последнего используемого индекса, а не 0. Посмотрите:
var query = 'Foo B';
var re = new RegExp(query, 'gi');
var result = [];
result.push(re.test('Foo Bar'));
alert(re.lastIndex);
result.push(re.test('Foo Bar'));
Если вы не хотите вручную сбросить lastIndex
до 0 после каждого теста, просто удалите флаг g
.
Вот алгоритм, который специфицирует спецификация (раздел 15.10.6.2):
RegExp.prototype.exec (string)
Выполняет сопоставление регулярных выражений строки с регулярным выражением и возвращает объект Array, содержащий результаты совпадение или null, если строка не соответствует. Строка ToString (string) выполняется для поиска регулярного выражения следующим образом:
blockquote>
- Пусть S - значение ToString (string) .
- Пусть length - длина S.
- Пусть lastIndex - значение свойства lastIndex.
- Пусть i - значение ToInteger (lastIndex) .
- Если глобальное свойство ложно, пусть i = 0.
- Если I & lt; 0 или I> length, тогда установите lastIndex равным 0 и верните null.
- Вызов [[Match]], давая ему аргументы S и i. Если [[Match]] возвратил ошибку, перейдите к шагу 8; в противном случае r будет его результатом состояния и перейдите к шагу 10.
- Пусть i = i + 1.
- Перейдите к шагу 6.
- Пусть e будет r endIndex.
- Если глобальное свойство истинно, установите lastIndex в e.
- Пусть n - длина массива захватов r. (Это то же значение, что и для NCapturingParens от 15.10.2.1.)
- Возвращает новый массив со следующими свойствами: Свойство index устанавливается в позицию согласованной подстроки в полной строке S. input свойство установлено равным S. Свойство length установлено в n + 1. Свойство 0 задано подстрочной подстрокой (т. е. частью S между смещением i включительно и смещением e exclusive). Для каждого целого i такого, что I> 0 и I ≤ n, задайте свойство с именем ToString (i) i-му элементу массива захватов r.
cout << "Enter the number: ";
int number;
if (cin >> number)
{
// throw away the rest of the line
char c;
while (cin.get(c) && c != '\n')
if (!std::isspace(c))
{
std::cerr << "ERROR unexpected character '" << c << "' found\n";
exit(EXIT_FAILURE);
}
cout << "Enter names: ";
string name;
// keep getting lines until EOF (or "bad" e.g. error reading redirected file)...
while (getline(cin, name))
...use name...
}
else
{
std::cerr << "ERROR reading number\n";
exit(EXIT_FAILURE);
}
В приведенном выше коде этот бит ...
char c;
while (cin.get(c) && c != '\n')
if (!std::isspace(c))
{
std::cerr << "ERROR unexpected character '" << c << "' found\n";
exit(EXIT_FAILURE);
}
... проверяет остальную строку ввода после того, как номер содержит только пробелы.
Это довольно многословно, поэтому использование ignore
в потоке после >> x
является часто рекомендуемым альтернативным способом отбрасывания контента до следующей новой строки, но он рискует выбросить не-whitespace и при этом игнорируя поврежденные данные в файле. Вам может или не все равно, в зависимости от того, доверено ли содержимое файла, насколько важно избегать обработки поврежденных данных и т. Д.
Таким образом, std::cin.clear()
(и std::cin.igore()
) для этого не требуется, но полезно для удаления состояния ошибки. Например, если вы хотите дать пользователю много шансов ввести действительный номер.
int x;
while (std::cout << "Enter a number: " &&
!(std::cin >> x))
{
if (std::cin.eof())
{
std::cerr << "ERROR unexpected EOF\n";
exit(EXIT_FAILURE);
}
std::cin.clear(); // clear bad/fail/eof flags
// have to ignore non-numeric character that caused cin >> x to
// fail or there's no chance of it working next time; for "cin" it's
// common to remove the entire suspect line and re-prompt the user for
// input.
std::cin.ignore(std::numeric_limits<std::streamsize>::max());
}
Еще одна простая, но наполовину испеченная альтернатива ignore
для вашего исходного требования использует std::skipws
, чтобы пропустить любое количество пробелов перед чтением строк ...
if (std::cin >> number >> std::skipws)
{
while (getline(std::cin, name))
...
... но если он вводится как «1E6» (например, какой-то ученый пытается ввести 1 000 000, но C ++ поддерживает эту нотацию для чисел с плавающей запятой ) не согласятся с этим, вы получите number
, установленный на 1
, и E6
считанные как первое значение name
. Отдельно, если у вас есть действительное число, за которым следуют одна или несколько пустых строк, эти строки будут игнорироваться молча.
Я только использовал
getline(cin >> ws,lard.i_npute);
со стандартным заголовком
#include <iostream>
в случаях, когда у меня возникали проблемы с возвратом каретки и работал с манипулятором ws. Я, вероятно, начну встраивать функции цикла в классы и использовать вызовы конструктора и деструктора atleast.
cout << "Enter the number: ";
int number;
cin >> number;
cout << "Enter names: ";
string names;
getline(cin, names);//works on the \n left behind
getline(cin, names);//continues and rewrites names
его довольно самообучающийся, в потоке, который используется cin >> number
, есть\n, который присваивается именам при первом использовании. Повторное использование getline теперь записывает правильное значение.
cout << "Enter the number: ";
int number;
cin >> number;
cin.ignore(256, '\n'); // remaining input characters up to the next newline character
// are ignored
cout << "Enter names: ";
string names;
getline(cin, names);
Другой способ сделать это - поставить
cin.ignore ( std::numeric_limits<std::streamsize>::max(), '\n' );
после того, как ваш cin>>number;
полностью очистит входной буфер (отклонение всех дополнительных символов до тех пор, пока не будет найдена новая строка). Вы должны #include <limits>
получить метод max()
.
while (isspace(cin.peek())) cin.ignore()
... выглядит хорошо для меня. Re выше, я думал о том, что пользователь неправильно понимает требования к формату ввода или какой-то скрипт, генерирующий входные прерывания, но сломанный ввод, кажется, успешно обрабатывается, потому что он игнорируется - они могут в конечном итоге доверять сломанным результатам. Если вход не соответствует спецификации, лучше, чтобы ваша программа выработала ошибку.
– Tony Delroy
21 April 2011 в 07:26
вы хотите использовать cin.ignore () после своих операторов cin, потому что вы хотите игнорировать «\n» слева в буфере после принятия переменной int cin.
У меня есть аналогичная программа я использовал с аналогичной проблемой:
#include <iostream>
#include <iomanip>
#include <limits>
using namespace std;
int main() {
int i = 4;
double d = 4.0;
string s = "HackerRank ";
// Declare second integer, double, and String variables.
int n;
double d2;
string str;
// Read and save an integer, double, and String to your variables.
cin >> n;
cin >> d2;
cin.ignore();
getline(cin, str);
// Print the sum of both integer variables on a new line.
cout << i + n << endl;
// Print the sum of the double variables on a new line.
cout << d + d2 << endl;
// Concatenate and print the String variables on a new line
cout << s << str << endl;
// The 's' variable above should be printed first.
return 0;
}
Попробуйте:
int number;
cin >> number;
char firstCharacterOfNames;
cin >> firstCharacterOfNames; // This will discard all leading white space.
// including new-line if there happen to be any.
cin.unget(); // Put back the first character of the name.
std::string names;
std::getline(cin, names); // Read the names;
Альтернативно. Если вы знаете, что число и имена всегда будут на разных строках.
cin >> number;
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::getline(cin, names);
#include <iostream>
#include <string>
using namespace std;
int main()
{
cout << "Enter the number: ";
int number;
cin >> number;
cout << "Enter names: ";
string names;
// USE peek() TO SOLVE IT! ;)
if (cin.peek() == '\n') {
cin.ignore(1 /*numeric_limits<streamsize>::max()*/, '\n');
}
getline(cin, names);
return 0;
}
Просто загляните вперед, используя cin.peek()
, и посмотрите, остается ли '\n'
во внутреннем буфере cin
. Если да: проигнорируйте его (в основном пропустите его)
'\r'
? Это замечательно хрупкое решение, которое я бы отклонил в обзоре кода.
– Lightness Races in Orbit
11 September 2015 в 00:20
Концептуально, я думаю, вы хотите, чтобы каждый ответ был аккуратно одной строкой. Итак, почему бы вам не попробовать это?
cout << "Enter the number: ";
string line;
getline(cin, line);
int number = std::stoi(line);
cout << "Enter names: ";
string names;
getline(cin, names);
Код правильно использует первый символ новой строки, дает номер, если строка верна или выбрасывает исключение, если это не так. Все бесплатно!
Или вы можете очистить входной буфер, чтобы прочитать строку
fflush (stdin)
blockquote>, она определена в заголовке stdio.h .
Этот код работает ..
cout << "Enter the number: "; int number; cin >> number; cout << "Enter names: "; string names; fflush(stdin); //FLUSHING STDIN getline(cin, names);
Вы можете использовать std :: ws для извлечения любых пробельных символов во входном буфере перед использованием getline. Заголовок для std :: ws является sstream.
cout << "Enter the number: ";
int number;
cin >> number;
cout << "Enter names: ";
string names;
cin>>ws;
getline(cin, names);
Вы можете найти ответ, который вы хотите найти в cppreference .
При использовании сразу после ввода с разделителями-пробелами, например. после
blockquote>int n; std::cin >> n;
, getline потребляет символ конца, оставленный на входном потоке оператором >>, и немедленно возвращается. Общее решение состоит в том, чтобы игнорировать все оставшиеся символы в строке ввода сcin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
перед переключением на линейно-ориентированный вход.
getline
потребляет новую строку после числа и циклов до тех пор, пока не найдет непустую строку ... кажется, исправлено для меня. Вопрос ОП не спросил «почему?». проблема была, но сделал комментарий, что он не был уверен, почемуclear
может понадобиться - кто-то другой отредактировал 5-летний вопрос 2 дня назад, чтобы добавить это, существенно изменив суть. – Tony Delroy 13 September 2015 в 14:01