Хоть это и небольшая проблема, но каждый раз, когда мне нужно распечатать какие-то данные в цикле, меня всегда раздражает, как расположить разделительный символ.
Например:
std::set<int> my_data { 1, 2, 3 };
bool is_first { true };
std::cout << '{';
for( auto i : my_data ) {
if ( is_first )
std::cout << i;
else
std::cout << ',' << i;
is_first = false;
}
std::cout << '}';
Или:
std::set<int> my_data { 1, 2, 3 };
size_t cnt { 0 };
cout << '{';
for( auto i : my_data )
if ( ++cnt == my_data.size() )
std::cout << i;
else
std::cout << i << ',';
std::cout << '}';
Как вы можете видеть в моих кодах, чтобы вставить разделительный символ в правильные места, я использовал 4-5 строк в цикле, в то время как настоящая работа — это просто std::cout << i;!
Итак, я часто делаю это так:
std::set<int> my_data { 1, 2, 3 };
char sep { '\0' };
cout << '{';
for( auto i : my_data ) {
std::cout << sep << i;
sep = ',';
}
std::cout << '}';
Безопасно ли выводить NULL ('\0') символ в std::cout? Я использую этот метод в основном в своих программах-демонах, поэтому таким образом они в основном печатают некоторый текст журнала в std::cout/std::cerr или другие текстовые файлы в файловой системе Linux.
Файлы результатов (файл журнала) в основном читаются некоторыми инструментами командной строки, такими как more/less/tail/head.
Столкнусь ли я таким образом с какими-либо сбоями? Другими словами, будет ли NULL-символ игнорироваться файловой системой/терминалом/stdout/...?
Совет: const char* sep = ""; и sep = ","; сделайте так, чтобы ваш вопрос исчез с минимальными дополнительными расходами...
«проигнорировано fs/terminal/stdout/» — Предполагается ли, что «fs» означает «файловую систему»?
Это не будет игнорироваться как таковое. Некоторые терминалы ничего не отображают, некоторые могут отображать «непечатаемый» символ, файл будет просто содержать его, и увидите ли вы его, зависит от того, что вы используете для просмотра.
Связано (не о выводе \0, а о выводе списков, разделенных запятыми): stackoverflow.com/questions/3496982/…
@JaMiT Да, здесь «fs» означает «файловая система». Спасибо, что поделились своим методом, я тоже думаю, что он очень хорош!!





Безопасно ли выводить NULL-символ в std::cout?
Да, можно с уверенностью предположить, что под безопасным вы имеете в виду хорошо сформированный.
Столкнусь ли я таким образом с какими-либо сбоями?
Нет, правильно составленная программа имеет четко определенное поведение.
Будет ли NULL-символ игнорироваться fs/terminal/stdout/...?
Файловая система:
Нет, нулевой символ не будет игнорироваться. Он будет сохранен в файле, как и любой другой персонаж. Испортит ли это ваши инструменты командной строки или нет, зависит от самих инструментов и, возможно, от того, как вы их используете.
Терминал:
Зависит от терминала. Те, которые я отправил нулевые символы, игнорировали этот символ, но другие могут отображать его так, как хотят. (Пробел или какой-либо вариант знака вопроса — два распространенных подхода к непечатаемым символам.)
стандартный вывод:
Нет, нулевой символ не будет игнорироваться. Нулевой символ будет передан в пункт назначения (которым часто является терминал, но его можно перенаправить в файл).
Подводя итог, std::cout << '\0';, скорее всего, не окажет видимого эффекта, но ваш результат может отличаться.
Предостережение, особенно. для будущих читателей: не путайте '\0' с "\0". При потоковой передаче первого через std::cout отправляется нулевой символ, а при потоковой передаче второго символы не отправляются, как если бы это была пустая строка. Кстати, если вы измените определение sep на const char* sep = ""; и последующее присвоение на sep = ",";, вы сможете получить желаемое форматирование и избежать потоковой передачи нулевого символа.
Я бы посоветовал вам также упомянуть (и объяснить) совет, который вы дали в комментариях под вопросом. Хотя он не отвечает на заданный вопрос, он предлагает решение проблемы, которую, по-видимому, пытается решить ФП.
кроме того, std::string, содержащий /0 посередине, все равно будет напечатан полностью int main() { std::string s{"Hello, World!"}; s[5] = '\0'; std::cout << s << std::endl; }. При нулевом символе будет остановлена только потоковая передача или назначение символьных литералов или массивов.
@Swift-FridayPie Верно. Вот почему я придерживался строковых литералов (без суффикса), избегая std::string.
Да, можно с уверенностью предположить, что под безопасным вы имеете в виду хорошо сформированный.