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
. Отдельно, если у вас есть действительное число, за которым следуют одна или несколько пустых строк, эти строки будут игнорироваться молча.
Я не собираюсь пытаться на самом деле ответить на Ваши вопросы здесь - вместо этого я перенаправлю Вас к книге который я видящий рекомендуемый для совета относительно этой темы: Параллелизм Java на практике .
Одно слово предупреждения: если там ответы здесь, ожидают, что довольно многие из них будут неправы. Одна из причин, я не собираюсь отправлять детали, - то, потому что я вполне уверен , я был бы понимать ее превратно в, по крайней мере, некоторых отношениях. Я не имею в виду непочтительности вообще к сообществу, когда я говорю, что возможности всех, кто думает, что они могут ответить на этот вопрос, на самом деле имеющий достаточно суровости для разбираний в нем, является практически нулевым. (Joe Duffy недавно нашел немного моделью памяти.NET, которая была удивлена. Если он может понять его превратно, так могут смертные как мы.)
<час>я предложу некоторое понимание всего на одном аспекте, потому что это часто неправильно понимается:
существует различие между энергозависимостью и атомарностью. Люди часто думают, что атомарная запись энергозависима (т.е. Вы не должны волноваться о модели памяти, если запись является атомарной). Это не верно.
Энергозависимость о том, будет ли один поток, выполняющий чтение (логически, в исходном коде), "видеть" изменения, внесенные другим потоком.
Атомарность о том, существует ли шанс, что, если изменение замечено, только часть изменения будет замечена.
, Например, возьмите запись в целочисленное поле. Это, как гарантируют, будет атомарным, но не энергозависимым. Это означает это, если мы имеем (запускающийся в foo.x = 0):
Thread 1: foo.x = 257;
Thread 2: int y = foo.x;
для y
возможно быть 0 или 257. Это не будет никакое другое значение, (например, 256 или 1) из-за ограничения атомарности. Однако, даже если Вы знаете, что в "стенное время" код в потоке 2 выполняемых после кода в потоке 1, могло быть нечетное кэширование, доступы памяти, "перемещающиеся" и т.д. Создание переменной x
энергозависимый зафиксирует это.
я оставлю остальных до настоящих кристально честных экспертов.
Я попытка привычки объяснить эти проблемы здесь, но вместо этого отослать Вас к Brian Goetz превосходная книга по предмету.
книга является "Параллелизмом Java на практике", может быть найден в Amazon или любое другое хорошо отсортированное хранилище для компьютерной литературы.
volatile
переменные могут кэшироваться поток локально, таким образом, различные потоки могут видеть различные значения одновременно; volatile
предотвращает это ( источник ) long
и double
, хотя JVMs на 64 бита, вероятно, реализуют их как атомарные операции Это - хорошая ссылка, которая может дать Вам немного подробно информацию:
http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html
Одно понятие могло бы быть полезным: данные (данная величина) и копии.
, Если Вы объявляете переменную, скажем, байт, это находится где-нибудь в памяти в сегменте данных (примерно говорящий). Существует 8 битов где-нибудь в памяти, посвященной для хранения той информации.
Однако может быть несколько копий тех данных, перемещающихся в Вашей машине. Для различных технических причин, например, локального устройства хранения данных потока, оптимизации компилятора. И если у нас есть несколько копий, они могли бы быть вне синхронизации.
, Таким образом, необходимо всегда иметь в виду это понятие. Это верно не только для полей класса Java, но и для cpp переменных, записи базы данных (рекордные данные состояния копируются в несколько сессий и т.д.). Переменные, их скрытые/видимые копии и тонкие проблемы синхронизации будут вокруг навсегда.
Я недавно нашел превосходная статья , которые объясняют энергозависимый как:
Первый, необходимо понять немного что-то о модели памяти Java. Я изо всех сил пытался за годы объяснить его кратко и хорошо. На сегодняшний день лучший способ, которым я могу думать для описания его, состоит в том, если Вы воображаете его этим путем:
Каждый поток в Java происходит в отдельном пространстве памяти (это явно неверно, поэтому терпите меня на этом).
необходимо использовать специальные механизмы, чтобы гарантировать, что коммуникация происходит между этими потоками, как Вы были бы в системе передачи сообщений.
записи Памяти, которые происходят в одном потоке, могут "просочиться через" и быть замечены другим потоком, но это ни в коем случае не гарантируется. Без явной коммуникации Вы не можете гарантировать, какие записи замечены другими потоками, или даже порядком, в котором они замечены.
Java энергозависимый модификатор является примером специального механизма, чтобы гарантировать, что коммуникация происходит между потоками. Когда один поток пишет в энергозависимую переменную, и другой поток видит, что запись, первый поток говорит, что второе обо всем содержании памяти вплоть до него выполнило запись к той энергозависимой переменной.
Дополнительные ссылки: http://jeremymanson.blogspot.com/2008/11/what-volatile-means-in-java.html http://www.javaperformancetuning.com/news/qotm030.shtml
Другие ответы выше абсолютно верны в том смысле, что ваш вопрос не для ловушек сердца.
Тем не менее, я понимаю вашу боль из-за того, что вы действительно хотите получить то, что находится под капотом - для этого я хотел бы указать вам на компиляторы миров и предшественников нижнего уровня для java, то есть на ассемблер, C и C ++.
Прочтите о различных видах заграждений («заборов»). Понимание того, что такое барьер памяти и где он необходим, поможет вам интуитивно понять, что делает volatile.