LINUX.ORG.RU

Есть ли библиотека для работы с текстами в формате ascii для С или С++

 , ,


0

3

Как известно, «из-коробки» С не поддерживает работу с ascii. Например,

printf("Some\0 string");

Покажет «Some», но не «Some string», как должно быть согласно ascii. В тоже время, «0x4» не сработает. 0x08 срабатывает не всегда (он, вообще, срабатывает?). Ну и так далее. Есть ли для С или С++ библиотеки, которые понимают сабж?

★★★★★

Ты вообще в курсе, как организованны строки в C? Потому, что ты говоришь ерунду.

Твоя строка на самом деле: «Some\0 string\0». И отображается она абсолютно правильно.

По поводу управляющих символов — это зависит не от C, а от терминала. man termcap

beastie ★★★★★
()
Ответ на: комментарий от beastie

Твоя строка на самом деле: «Some\0 string\0». И отображается она абсолютно правильно.

с т.з. ASCII/терминалов и прочих - 0 просто ничего не должен делать. Поэтому ТС и спрашивает.

dib2 ★★★★★
()
Ответ на: комментарий от beastie

RFC20: NUL (Null): The all-zeros character which may serve to accomplish time fill and media fill.

dib2 ★★★★★
()
Ответ на: комментарий от beastie

Твоя строка на самом деле: «Some\0 string\0».

что значит, «на самом деле»? на самом деле, по стандарту ascii нулевой символ должен просто пропускаться, а конец текста — это 0x4. То, что в С это не так, говорит о том, что С строки не своместимы с ascii. Да и вообще, со всеми стандартными кодировками, ведь большинство из них определены как надмножество ascii.

next_time ★★★★★
() автор топика
Ответ на: комментарий от next_time

Я написал много текста объясняющего что ты не прав, но потом удалил его. Афтор, ты упорот и не понимаешь о чем говоришь.

itn ★★★
()
Ответ на: комментарий от Deleted

Это же С, тут на каждый чих своя строка. Неужели ещё никто не осилил?

next_time ★★★★★
() автор топика
Ответ на: комментарий от next_time

Мне кажется тебя какой-то поскалист покусал. То, что кажется тебе прекрасной идеей, ей скорее всего не является. Как вариант, замени все вхождения на ␀. ;)

Ncurses няп как раз умеет то, что ты хочешь.

anonymous
()

Сделай свой my_ugly_printf, который итерируется через куски, разделённые '\0', и дёргает стандартный printf.

Deleted
()
Последнее исправление: romeo250501 (всего исправлений: 2)
Ответ на: комментарий от Deleted

Это только часть требований. Мне полную совместимость хотелось бы. По сути, ascii позволяет разделять текст на куски, и т.о., работать со списком строк. \0 позволяет резервировать пространство. Это удобно. Ну и прочие плюшки. А то, что вы предлагаете — уже костыль.

next_time ★★★★★
() автор топика
Ответ на: комментарий от userd

На строковых литералах такого не организовать в принципе, printf нужно знать, где остановиться. Т.е. если не терминатор, то по крайней мере длина.

E ★★★
()
Ответ на: комментарий от next_time

Новый абзац это разрыв строки, извращенец. Либо 2, в зависимости от нужд.

Deleted
()
Последнее исправление: Mystra_x64 (всего исправлений: 1)

man 2 write

anonymous
()
Ответ на: комментарий от next_time

найди «телетайп» - то что написано в «ASCII» это его управляющие символы. Больше нигде в современном мире c такой целью не используются.

И NUL там на самом деле не делает ничего, это тупой заполнитель для скоростей до 300 бод. И в асинхронную линию он передаётся способом отличным от прочих символов.

Прочие «символы» частично задействуются как управляющие в терминалах и отдельных протоколах (см.telnet, x28, ansi, vt100 и прочие VT).

и вообще, используй ncurses - и рисуй себе «абзацы» с параграфами как хочешь в том виде в каком позволяет твой терминал. ncurses он не только чтобы рамочки рисовать :-)

MKuznetsov ★★★★★
()

Ты путаешь тёплое с красным.

Принципа всего два:
1. C имеет null-terminated строки. Если хочешь, это единственное исключение из «стандарта ASCII» в твоем понимании. Если по каким-то соображениям это не подходит, используй работу с массивами + посимвольный вывод, либо std::string из C++.

2. Управляющие символы ASCII обрабатываются терминалом. Не языком программирования - терминалом. Например, принтером, виртуальным терминалом unix и т. п. Так что в любом языке программирования, если ты выводишь символ \n, то это в терминале POSIX будет перевод строки.

printf(«Some\0 string»);
Покажет «Some», но не «Some string», как должно быть согласно ascii

Это особенность null-terminated строк в любом языке программирования. И к ASCII не имеет никакого отношения. Если нужно поведение как в «стандарте ASCII» используй посимволый вывод или std::string; см. пример ниже.

В тоже время, «0x4» не сработает.

End of Transmission
Что ты ожидаешь от этого символа при выводе? Это Ctrl+D при вводе и соответствует EOF при работе с потоками.

0x08 срабатывает не всегда

Backspace
Как и любой управляющий символ, поведение на выходе зависит от терминала
Кстати, мы помним, что это лишь перевод курсора вправо, а не стирание, так?

P. S. Еще мы помним, что \n работает только в Unix. Если нужно переносимое решение, используем std::endl в C++.

Вот тебе демо, где всё работает как нужно.

C:

#include<stdio.h>

int main()
{
	char str[] = "Word1\x08 word2\x04 word3\x00 word4";

	// Вывод NULL-terminated строки, то есть до первого символа \0
	printf("%s", str);
	printf("\n"); // Гарантирована корректная работа только в терминалах POSIX

	// Вывод всех символов
	// Обращаем внимание, что Backspace работает как надо, несмотря на то, что выводится не строка, а отдельные символы. Обработка символа Backspace производится именно терминалом.
	int i;
	for(i = 0; i < sizeof(str); i++)
			printf("%c", str[i]);
	printf("\n"); // Гарантирована корректная работа только в терминалах POSIX

	return 0;
}


C++:
#include<string>
#include<iostream>

int main()
{
	char str_c[] = "Word1\x08 word2\x04 word3\x00 word4";

	// Строковые константы в C/C++ - NULL-terminated; если нужно передать всё, передаем массив
	std::string str(str_c, sizeof(str_c)/sizeof(str_c[0]));

	// std::string - не-NULL-terminated, так что выведется всё
	std::cout << str;
	std::cout << std::endl; // Кросс-платформенное решение

	return 0;
}



А если переходить от теории к практике, то расскажи чего конкретно ты хочешь добиться (т. е. для чего тебе это нужно), тогда тебе подскажут как это лучше сделать.

Kroz ★★★★★
()
Последнее исправление: Kroz (всего исправлений: 4)
Ответ на: комментарий от Kroz

Зря ты ему это написал. Он всё равно скажет что ты не прав.

itn ★★★
()
Ответ на: комментарий от Kroz

End of Transmission
Что ты ожидаешь от этого символа при выводе?

Интерпретировать этот символ так, как в стандартной библиотеке С интерпретируется \0, очевидно

Кстати, мы помним, что это лишь перевод курсора вправо, а не стирание, так?

Да

поведение на выходе зависит от терминала

тем не менее, мы всегда можем частично эмулировать поведение этого символа, например, выводя «С» вместо «a\bC» для тех терминалов, которые не умеют полноценно работать с этим символом

Управляющие символы ASCII обрабатываются терминалом. Не языком программирования - терминалом.

Нет, не так. Управляющие символы ASCII позволяют разбивать текст на блоки. А работа с блоками уже может происходить не на стороне терминала.

А если переходить от теории к практике, то расскажи чего конкретно ты хочешь добиться (т. е. для чего тебе это нужно), тогда тебе подскажут как это лучше сделать.

Собственно, нормальную кроссплатформенную работу с терминалом в С. Ncurses и иже с ним не предлагать, ибо не стандарт. А ascii — стандарт.

В частности, недостаток С-шного подхода в том, что нет управляющих символов, позволяющих разбивать текст на куски. Хотя, стандарт это позволяет.

next_time ★★★★★
() автор топика
Последнее исправление: next_time (всего исправлений: 1)
Ответ на: комментарий от Kroz

Это особенность null-terminated строк в любом языке программирования.

null-terminated строки - это изобретение С. их больше нет ни в одном другом языке программирования, дожившего до наших дней. даже в С++ — это legacy, оставленное для обратной совместимости.

next_time ★★★★★
() автор топика
Ответ на: комментарий от next_time

null-terminated строки - это изобретение С. их больше нет ни в одном другом языке программирования, дожившего до наших дней.

Может быть. Не исследовал данный вопрос.

Kroz ★★★★★
()
Ответ на: комментарий от next_time

Интерпретировать этот символ так, как в стандартной библиотеке С интерпретируется \0, очевидно

В стандартной библиотеке С \0 обозначает просто конец блока памяти, из которого производится вывод и никак не управляет самим потоком ввода/вывода. Управляющие символы ASCII управляют именно вводом/выводом. Почитай хотябы wiki на эту тему.

Если так уж нужно такое поведение - сделай посимвольную замену. Но к стандарту ты не приблизишься.

тем не менее, мы всегда можем частично эмулировать поведение этого символа

В достаточно редких случаях. Например, как ты будешь эмулировать в случае вывода двух строк «abc» и «\bdef». или «abc\b» и «def»? Тебе для этого нужно держать в памяти содержимого всего терминала (кстати, какого размера) и перерисовывать его полностью в случае изменений. Это дублирование функций эмулятора терминала.

Управляющие символы ASCII позволяют разбивать текст на блоки.

Что есть блок?
У терминала нет понятия «блок», есть понятие «поток»
Я языках программирования блок - еще более эфимерное понятие. Даже строка в С, как верно заметил аноним, весьма условное понятие для ограниченного круга функций.

Собственно, нормальную кроссплатформенную работу с терминалом в С.

В С - не знаю.
В С++ стандартная библиотека ЕМНИП заявляется как кроссплатформенная (хотя уверен, что там много нюансов). Это там где std::cout и std::endl, и не используй никаких управляющих последовательностей в строках.

Ncurses и иже с ним не предлагать, ибо не стандарт. А ascii — стандарт.

Ты вообще различаешь кодировку и библиотеку?
ASCII ты можешь сравнивать с utf-8, win-1251, koi8-r и т. п. А ncurses - библиотека.

В частности, недостаток С-шного подхода в том, что нет управляющих символов, позволяющих разбивать текст на куски. Хотя, стандарт это позволяет.

Стандарт чего?

Конкретней скажи что тебе нужно. Псевдо-графический интерфейс а-ля ncurses? Какие платформы интересуют?

P. S. Мне почему-то кажется, что ты просто хочешь писать программу и чтобы она была кроссплатформенной «если что». Ну то есть «выработать практику на будущее». У меня такое было. Моё решение - С++ с его потоками, так как С слишком сильно учитывает особенности каждой платформы (собственно, оно так и задумывалось). В принципе, практически любой высокоуровневый язык решает эту задачу. Но не завязывайся на управляющие символы ASCII.

Если это не так - список конкретных платформ и конкретных задач - в студию!

Kroz ★★★★★
()
Ответ на: комментарий от next_time

нормальную кроссплатформенную работу с терминалом в С

не бывает такого. работа с терминалами в разных системах - это всегда ебля вприсядку и всё зависит от кучи настроек. терминалы сами по себе разные, они имеют разные настройки, а поток может быть во всяких там юникодах, мультибайтах, и прочее. от сочетания кодировки потока и настроек терминала зависит то, что узрит юзер. даже на плюсах там куча всякого неочевидного говна выплывает при реальной работе. этому посвящены километровые обсуждения на разнообразных форумах. проще всего использовать юникод однобайтовый, кмк. собсна, в ascii сейчас мало кто работает. разве что совсем жёсткий эмбеддед с ограниченными ресурсами.

Iron_Bug ★★★★★
()

0 в строках? ты упоролся

если тебе надо работать с бинарными данными как со строками, заменяй нули на свой собственный escape сиквенс, затем перед выводом переводи его обратно в 0

Ну и да, если ты не понимаешь что являет собой сущность строк, то ты выбрал не тот язык. Правда.

reprimand ★★★★★
()
Ответ на: комментарий от reprimand

если тебе надо работать с бинарными данными как со строками

мне надо работать с текстом, как с текстом

next_time ★★★★★
() автор топика
Ответ на: комментарий от Iron_Bug

всякие там юникоды всё равно наследуют от ascii. т.е., в реальности, кодировка может быть и немного другой, но это неважно.

next_time ★★★★★
() автор топика
Ответ на: комментарий от next_time

мне надо работать с текстом, как с текстом

откуда в тексте нулевой байт?

что ты подразумеваешь под работой с текстом?

hint: текст - это набор строк

КЕК2016

не мучай жопу, меняй язык )

reprimand ★★★★★
()
Ответ на: комментарий от Kroz

В стандартной библиотеке С \0 обозначает просто конец блока памяти,

да, это как раз и нужно

Тебе для этого нужно держать в памяти содержимого всего терминала (кстати, какого размера)

Зачем? Достаточно поправить строку перед выводом на экран.

ASCII ты можешь сравнивать с utf-8, win-1251, koi8-r и т. п. А ncurses - библиотека.

я сравниваю гипотетическую библиотеку для работы исключительно с ascii и ncurses

Какие платформы интересуют?

все. нужна максимальная кроссплатформенность вплоть до поддержки (в идеале, конечно же) произвольной на коленке написанной ОС.

хочешь писать программу и чтобы она была кроссплатформенной «если что»

пишу программу, под GPL, максимально кроссплатформенную. точнее так: подразумевается скорее, что код программы должен максимально легко адаптироваться под любую платформу.

Но не завязывайся на управляющие символы ASCII.

А на что тогда завязывать выхлоп программы в консоль? Как мне разделять блоки текста? Перевод строки — плохая идея, потому, что это значение уже зарезервировано, собственно, под перевод строки. Грубо говоря, мне нужно разделять текст на страницы.

next_time ★★★★★
() автор топика
Ответ на: комментарий от reprimand

откуда в тексте нулевой байт?

зарезервированное место под изменения, как оно и есть по стандарту ascii

next_time ★★★★★
() автор топика
Ответ на: комментарий от reprimand

меняй язык )

на какой? скажем, что вы можете предложить для того же plan9?

next_time ★★★★★
() автор топика

Вообще-то, С «из коробки» не поддерживает ничего, кроме ASCII

RiseOfDeath ★★★★
()
Ответ на: комментарий от next_time

нтерпретировать этот символ так, как в стандартной библиотеке С интерпретируется \0, очевидно

А схренали ЯП вообще должен знать, как будет интерпретироваться escape-последовательность тем или иным устройством вывода?

Аппаратная абстракция это задача ОС.

RiseOfDeath ★★★★
()
Ответ на: комментарий от eao197

во-во, в ascii оно есть, а в т.н. «си-строках» поведение этого символа ничем не примечательно.

next_time ★★★★★
() автор топика
Ответ на: комментарий от RiseOfDeath

вывода

почему сразу устройством вывода? мне это нужно для обработки текста скорее, чем для вывода.

next_time ★★★★★
() автор топика
Ответ на: комментарий от next_time

Как мне разделять блоки текста?

Если ты будешь разделять с помощью ^D (End of Transmission), то ты гарантированно получишь несовместимость практически со всем, что есть. Ибо никто так не делает.

Еще раз: что есть блоки текста? Кто или что должны различать блоки? Приведи пример использования (use case). Если для человека - ^D (End of Transmission), как ты понимаешь, вообще не вариант, так как он даже строки не переведет; визуально два блока сольются в одну кашу. Если программа - бери любую схему разметки текста, хоть xml, хоть json, хоть самописный. Лицо морщишь? - а ведь это стандартные методы, для которых есть проверенные временем библиотеки, притом кроссплатформенные. Если и человеку, и машине - зафиксируй формат вывода, чтобы можно было легко по'grep'ать или как-то еще обработать.

Kroz ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.