int main(int argc, char *argv[])
{
print(argv[0]);
print({});
print("a const char * array");
print("an std::string_view literal"sv);
print("an std::string instance"s);
7. Мы не протестировали функцию удаления пробелов. Передадим ей строку, которая содержит множество пробелов в начале и в конце:
print(" \t\n foobar \n \t ");
8. Еще одна приятная особенность класса string_view
"abc"
, которая не будет заканчиваться нулем, то функция print
сможет безопасно ее обработать, поскольку объект класса string_view
также содержит размер строки, на которую указывает: char cstr[] {'a', 'b', 'c'};
print(string_view(cstr, sizeof(cstr)));
}
9. Компиляция и запуск программы дадут следующий результат. Все строки обработаны корректно. Строка, которую мы заполнили большим количеством пробелов в начале и конце, также была корректно отфильтрована, а строка abc
$ ./string_view
length: 17 [./string_view]
length: 0 []
length: 20 [a const char * array]
length: 27 [an std::string_view literal]
length: 23 [an std::string instance]
length: 6 [foobar]
length: 3 [abc]
Как это работает
Мы только что увидели следующее: можно вызвать функцию, принимающую аргумент типа string_view
Интересно отметить, что в вызове print(argv[0])
string_view
путем подсчета символов до тех пор, пока не встретится нулевой символ. Поэтому нужно всегда соблюдать осторожность при работе с указателями на данные строкового представления с помощью string_view::data()
. Обычные строковые функции предполагают, что строка будет завершаться нулевым символом, и поэтому использование необработанных указателей способно привести к переполнению буфера. Всегда лучше применять интерфейсы, которые ожидают передачи строкового представления.За исключением этой особенности, у нас имеется роскошный интерфейс, с которым мы уже знакомы благодаря классу std::string
std::string_view
std::string_view
не предполагает, что строки завершаются нулевым символом.Считываем значения из пользовательского ввода
Во многих примерах нашей книги значения поступают из входного источника, которым является стандартный поток ввода или файл, а затем с ними выполняются некие действия. В этот раз мы сконцентрируемся лишь на чтении и обработке ошибок, что становится важным, если чтение каких-то данных из потока завершилось
В следующем примере мы лишь считаем данные от пользователя, но тщательно разобрав этот процесс, вы научитесь читать данные из любого другого потока. Пользовательские данные можно считать с помощью std::cin
ifstream
и istringstream
.Как это делается
В этом примере мы считаем пользовательские данные в разные переменные и увидим, как обрабатывать ошибки, а также научимся выполнять более сложную токенизацию входных данных, чтобы разбить их на полезные фрагменты.
1. На сей раз нам понадобится только iostream
std
по умолчанию:#include
using namespace std;
2. Пригласим пользователя ввести два числа. Поместим их в переменные типов int
double
. Пользователь может разделить их пробелами. Например, 1 2.3
— это корректные входные данные.int main()
{
cout << "Please Enter two numbers:\n> ";
int x;
double y;