Что такое cin.ignore()
Работая с входными потоками C++, вы наверняка сталкивались с неожиданным поведением входных данных.
Причиной часто являются символы, которые задерживаются в буфере ввода. Здесь и приходится кстати cin.ignore(). Разберем ее функционал и эффективное использование.
Основы cin.ignore()
cin.ignore() — это функция, которой из входного потока удаляются символы. Вот ее базовый синтаксис:
cin.ignore(count, delim);
count: максимальное количество игнорируемых символов.
delim: символ-разделитель, на котором остановаются.
Если не указать эти необязательные параметры, при использовании cin.ignore() удалится только один символ. Вот простой пример:
#include <iostream>
#include <limits>
int main() {
int number;
std::cout << "Enter a number: ";
std::cin >> number;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::string line;
std::cout << "Enter a line of text: ";
std::getline(std::cin, line);
std::cout << "Number: " << number << std::endl;
std::cout << "Text: " << line << std::endl;
return 0;
}
Здесь при помощи cin.ignore() буфер ввода очищается после считывания числа и перед считыванием строки текста. Так что никакой символ новой строки в вызов getline() не вмешается.
Зачем нужен cin.ignore()?
Рассмотрим сценарий без cin.ignore():
#include <iostream>
#include <string>
int main() {
int age;
std::string name;
std::cout << "Enter your age: ";
std::cin >> age;
std::cout << "Enter your name: ";
std::getline(std::cin, name);
std::cout << "Age: " << age << ", Name: " << name << std::endl;
return 0;
}
Запустив этот код и введя 25 в age, мы не получим имени, а программа немедленно завершится. Дело в том, что символ новой строки \n, введенный после age, остается в буфере ввода, и эта пустая строка считывается getline() как имя.
Устраняем эту проблему, добавляя cin.ignore() после считывания age:
std::cin >> age;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::getline(std::cin, name);
Типичные сценарии для cin.ignore()
Очистка буфера ввода
Типичнейший сценарий cin.ignore() — очистка всего буфера ввода:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Этой строкой игнорируется максимум символов вплоть до максимально представляемого значения для streamsize, пока не встретится символ новой строки.
Пропуск определенного количества символов
Иногда требуется пропустить известное количество символов:
#include <iostream>
int main() {
std::cout << "Enter a 6-digit code, then your name: ";
// Пропускаем 6-значный код
std::cin.ignore(6);
std::string name;
std::getline(std::cin, name);
std::cout << "Name: " << name << std::endl;
return 0;
}
Здесь пропускаются первые шесть символов кода, затем считывается имя.
Считывание до определенного символа
cin.ignore() применяется также для считывания и удаления ввода до определенного символа:
#include <iostream>
#include <limits>
int main() {
std::cout << "Enter text (end with *): ";
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '*');
std::cout << "Remaining input: ";
std::string remaining;
std::getline(std::cin, remaining);
std::cout << remaining << std::endl;
return 0;
}
Этой программой игнорируется весь ввод до символа *, затем считывается остальной ввод.
Реальный сценарий: cоздание простой системы меню
Вот пример посложнее, где важен cin.ignore(). Создадим простую систему меню для базового диспетчера задач:
#include <iostream>
#include <vector>
#include <limits>
struct Task {
std::string description;
bool completed;
};
void clearInputBuffer() {
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
void addTask(std::vector<Task>& tasks) {
Task newTask;
std::cout << "Enter task description: ";
clearInputBuffer();
std::getline(std::cin, newTask.description);
newTask.completed = false;
tasks.push_back(newTask);
}
void viewTasks(const std::vector<Task>& tasks) {
if (tasks.empty()) {
std::cout << "No tasks.\n";
return;
}
for (size_t i = 0; i < tasks.size(); ++i) {
std::cout << i + 1 << ". " << tasks[i].description
<< (tasks[i].completed ? " (Completed)" : "") << std::endl;
}
}
void markTaskCompleted(std::vector<Task>& tasks) {
viewTasks(tasks);
if (tasks.empty()) return;
int taskNumber;
std::cout << "Enter the number of the task to mark as completed: ";
std::cin >> taskNumber;
if (taskNumber > 0 && static_cast<size_t>(taskNumber) <= tasks.size()) {
tasks[taskNumber - 1].completed = true;
std::cout << "Task marked as completed.\n";
} else {
std::cout << "Invalid task number.\n";
}
clearInputBuffer();
}
int main() {
std::vector<Task> tasks;
int choice;
while (true) {
std::cout << "\n1. Add Task\n2. View Tasks\n3. Mark Task as Completed\n4. Exit\n";
std::cout << "Enter your choice: ";
std::cin >> choice;
switch (choice) {
case 1:
addTask(tasks);
break;
case 2:
viewTasks(tasks);
break;
case 3:
markTaskCompleted(tasks);
break;
case 4:
std::cout << "Goodbye!\n";
return 0;
default:
std::cout << "Invalid choice. Please try again.\n";
}
clearInputBuffer();
}
return 0;
}
Здесь cin.ignore() используется через функцию clearInputBuffer() в нескольких местах:
- После считывания пункта меню — для удаления всех остальных символов новой строки.
- До считывания описания задачи — чтобы убедиться в возможности считать строку целиком.
- После обозначения задачи как выполненной — для очистки всего остального ввода.
Этим обеспечивается плавная работа системы меню, предотвращаются ошибки ввода, обусловленные символами, которые задерживаются в буфере ввода.
Типичные ошибки и как их избежать
- Игнорирование слишком многого: будьте осторожны при использовании cin.ignore() с большими значениями. Если проигнорировать больше символов, чем доступно во входном потоке,
cinпереводится в нежелательное состояние ожидания. - Невключение <limits>: при использовании
std::numeric_limits<std::streamsize>::max()не забудьте включить заголовок<limits>. - Злоупотребление cin.ignore(): чревато тем, что код становится сложнее для восприятия и сопровождения. Используйте ее разумно, то есть после операций
cin >>и перед вызовамиgetline().
Производительность
Обычно влияние cin.ignore() на производительность незначительно. Но при работе с очень большими входными данными или там, где важна производительность, учтите:
- Использование cin.ignore() для пропуска больших объемов данных медленнее, чем считывание и удаление этих данных.
- Если выполняете много операций ввода, отвяжите
cinот cout при помощиcin.tie(nullptr), так повысится производительность ввода.
Заключение
Понимание и корректное использование cin.ignore() важно для эффективной обработки ввода на C++. С ней проще управлять буфером ввода, предотвращать неожиданное поведение и создавать надежные интерактивные программы.
Применяя эти приемы и примеры, вы подготовитесь к работе с различными сценариями ввода в проектах на C++.
Читайте также:
- Объединение множеств C++: практическое руководство с реальными примерами
- C++: подробное руководство по обработке файлов с getline()
- Путешествие строки скомпилированного кода
Читайте нас в Telegram, VK и Дзен
Перевод статьи ryan: Understanding and Using cin.ignore() in C++





