LINUX.ORG.RU

В Си предложили добавить switch-case для строк

 , ,


0

3

Привет, чат!

Спустя много лет, в язык Си наконец предложено добавить возможность использовать выражение switch-case для строк. Например, можно будет писать вот такое:

const char *s = get_some_string();

switch(s) {
case "this":
  handle_this();
  break;
case "that":
  handle_that();
  break;
default:
  handle_other();
  break;
}

Таким образом, в Си будет чуть меньше способов отстрелить себе ноги.

Ссылка на предложение: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3895.pdf



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

И разве не хорошо не вызывать стрлен там, где можно еще в компайлтайме узнать длину?

Вообще-то, strlen для ASCIIZ нужен в очень редких случаях. Подавляющее большинство сишных функций работы со строками возвращают текущую длину. Если зачем-то нужно, то всё сводится к чему-то не сложнее len += snprintf( str+len, size, "<format>", a, b, c, d); и никаких костылей типа особенной обработки костыльных строк из структур/классов не требуется. При этом, текущая длина всегда известна на протяжении всей жизни строки.

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

Должны, да в юникоде нет такого. А иногда в консоли хочется людям поредактировать то, что они печатали в GUI-редакторе. И CJK, и right-to-left, и ещё всякое. Только и остаётся всякие соглашения придумывать, какой юникодный codepoint сколько знакомест занимает. Но, как видно, даже прийти к соглашению не могут пока.

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

Комитет подумол, родил стд-стринг. … Комитет ещо подумол, родил стд-стринг-вю и стд-спан. … Я недумол и наколхозил структурку

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

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

Я уже выше писал - если нужен консольный шрифт с нормальной поддержкой иероглифов то он должен быть квадратным. Латиница в нём тоже будет квадратная. Но там, где поддержка иероглифов не нужна, удобнее использовать шрифта с высотой вдвое больше ширины. Что касается right-to-left, то это сфера ответственности редактора, а никак не кодировки. Консоль это техническое средство отображения матрицы символов, и она не должна на себя брать юзер-интерфейсные функции.

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

Сам прекрати. Для длины нужен нормальный беззнаковый тип, и желательно такой же битности, как биты смещения адресов. Беззнаковый - главное (uchar, ushort, uint, ulong, ullong, size_t), разрядность - желательное (size_t).

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

Мы, всё же, не в религиозной школе, равви, и не подбираем типы по соответствию доменной области!

Зы: и не длина, а размер. Давайте назовём оффсетом первого невалидного элемента за спаном, тогда под доменную область подойдет знаковое.

struct { ptrdiff_t offset; uint8_t ptr;}

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

И зачем тебе z тогда?

Затем, что null-terminated строки могут откуда-то извне поступать, или куда-то вовне отправляться. Я не сторонник сфрического программирования в вакууме. Программа в целом должна выполнять некоторую задачу максимально эффективно. А на все эти «good programming practices», костыли, модные фреймворки, теоретические споры о том, является ли NULL адресом и новейшие стандарты мне совершенно насрать.

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

Я новый примитивный тип в компилятор добавлять не буду, я тебе обещаю, у меня нет охоты и едва ли появится.

За комитеты ничего не скажу, оправданий им придумывать не буду.

Т.о. о чем мы говорим? Ты тоже в компилятор такого не добавлял, да?

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

Должна, и спан тут — приемлемый инструмент для достижения этой цели.

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

А в чём вообще смысл делать длину знаковой? Или offset, если он не может быть отрицательным?

uint8_t ptr;

Щито это такое?

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

Щито это такое?

Я с телефена, несусь в поезде) или ты про то, что не char? Тогда ответ такой: у нас в доменной области байты, а тип байта — это uint8_t

Почему оффсет-то не может быть отрицательным? Ты про логическое значение в рамках строки? Ну мы же не в комитете, нам вот это -1, 0,1, ... зачем?

Нам с этим типом работать, а работать удобнее, если нет необходимости кастовать всюду, в т.ч. в ситуациях, когда результатом операции над объектом, который также может быть и индексом для строки, может быть число отрицательное.

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

> Щито это такое?

Я с телефена, несусь в поезде)

Нет-нет, ты объясни смысл даже в случае, если ты имел в виду uint8_t *. uint8_t, если что, может быть типом, отличным от unsigned char даже в случае CHAR_BIT == 8. И тогда на него гарантии aliasing не распространяются.

Почему оффсет-то не может быть отрицательным?

Если ты в рамках «Давайте назовём оффсетом первого невалидного элемента за спаном», то, ну, по правилам логики. strlen тоже возвращает оффсет до \0, но оно почему-то возвращает size_t.

Ты про логическое значение в рамках строки? Ну мы же не в комитете, нам вот это -1, 0,1, ... зачем?

ЯННП.

Нам с этим типом работать, а работать удобнее, если нет необходимости кастовать всюду, в т.ч. в ситуациях, когда результатом операции над объектом, который также может быть и индексом для строки, может быть число отрицательное.

Как работать? В каких ситуациях? На переполнение проверять гораздо сложнее. Что там за ситуации у вас — не понимаю.

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

И тогда на него гарантии aliasing не распространяются.

Приношу извинения! Давайте для общего случая uchar*

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

Если строка со всякими счётчиками, кодовыми страницами и пр. не является примитивным типом компилятора не требующим никаких дополнительных телодвижений в коде по сравнению с [w]char *str, то уж лучше ASCIIZ чем любые подобные костыли со структурами и классами.

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

Что за чушь? Просто у них знакоместа не прямоугольные а квадратные нужны.

Нет, это не так работает. На практике. В теории можно было бы сделать так, конечно, в какой-то другой вселенной, проектируя всё с нуля. В нашей они сделали символы, занимающие ровно два знакоместа. Латиница и прочее — по одному, а их символы — по два (ну и два байта (а дальше в юникоде больше) соответственно — по очевидным причинам, их тупо намного больше, чем 256).

И да, я прекрасно понял, что ты и это назовёшь вредительством, предложишь вернуться на очень многие десятилетия назад и, видимо, утилизировать азиатов, дабы «не вредили» твоей идеальной картине мира. О чём, собственно, и был коммент, нового ты ничего не сказал. Где здесь «чушь», я до сих пор не вижу, а дальнейшее теоретизирование довольно предсказуемо, но не интересно в контексте нашего мира.

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

Каким ещё спаном? Я такое слово знаю только как html-тег, вроде это не оно. Нет, оффсет от начала строки до первого невалидного элемента отрицательным быть не может. Что за «доменная область» - не знаю.

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

Я же написал что в идеале там size_t. А так, «тормоза» от беззнакового расширения в большинстве случаев несущественны. А вот signed-фокусы в месте, где никакого signed нет и не должно быть, могут иногда логически испортить прогу.

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

Нам с этим типом работать, а работать удобнее, если нет необходимости кастовать всюду, в т.ч. в ситуациях, когда результатом операции над объектом, который также может быть и индексом для строки, может быть число отрицательное.

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

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

В нашей они сделали символы, занимающие ровно два знакоместа

Кто «они» и где сделали? Мы всё ещё про консоль? PC-консоль (текстовый режим видеокарт) такое не поддерживает.

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

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

Справедливости ради, когда нужно от конца к началу пройтись, приходится делать

for (size_t i = n - 1; i != (size_t) -1; --i)
Если бы были знаковые, это было бы удобнее. Но это нивелируется огромным количеством проблем от знаковых.

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

Потому что Си, как ни крути, какие языки ни изучай – это база. Язык системного программирования.

P.S. Тут выше обсуждали «экосистему». Нет, экосистема – это не сообщество, а сопутствующие инструменты. Стандартная библиотека, компиляторы, средства разработки, отладчики и прочее.

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

Кто «они» и где сделали? Мы всё ещё про консоль? PC-консоль (текстовый режим видеокарт) такое не поддерживает.

Да, мы всё ещё про консоль. Текстовый режим видеокарт они по понятным причинам использовать нормально не могли, поэтому их версии ДОСа (точнее его альтернативные реализации) прозрачно задействовали графический режим так, чтобы он для юзера выглядел как текстовый. Резидентная программа перехватывала прерывания, которые должны были отрабатывать на вывод текста в текстовом режиме и выводила их в графическом псевдо-текстовом.

Разделение на символы одинарной и двойной ширины было уже в JIS X 0208. Если верить википедии, она существует с 1978 года. Появилось ли оно сразу с JIS X 0208 или всё же чуть позже (но всё равно явно сильно в прошлом веке), я не вникал.

Про это дело тоже есть статья в википедии, но она совсем не информативная и не даёт истории появления и годов, когда, что и как было реализовано: https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms

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

задействовали графический режим так, чтобы он для юзера выглядел как текстовый.

Это бессмыслица. "Текстовые" VGA режимы тоже "прозрачно задействуют графический режим так, чтобы он для юзера выглядел как текстовый" - VGA режимы выводят матрицу пикселей на экран. "Настоящий текстовый вывод" - это последовательный порт и прочий телетайп.

В этом смысле между "VGA text mode" и xterm’ом нет вообще никакой принципиальной разницы - оба два дают некий API для отображения символов по их кодам.

их версии ДОСа (точнее его альтернативные реализации) прозрачно задействовали графический режим Резидентная программа перехватывала прерывания, которые должны были отрабатывать на вывод текста в текстовом режиме и выводила их в графическом псевдо-текстовом.
Про это дело тоже есть статья в википедии, но она совсем не информативная и не даёт истории появления и годов,

На википедии всё есть. Для Азии был свой клон DOS’а - DOS/V, который на старте переводил видеоадаптер в графический режим и рисовал иероглифы уже в нём.

Но это не настоящие японские ПеКа. Настоящий японский японский клон IBM PC - NEC PC-98 был не совместим по реализации с IBM PC для американского рынка. Там стояли специальная ПЗУшка с записанными шрефтами и отдельный чип, который преобразовывал кодовые символы в изображение на экране. Всё это работало в обход CPU и системной памяти. Так же как в X68000.

r--r--r--
()
Ответ на: комментарий от yars068

Полностью согласен, просто мы смотрим на это подразными углами. Ты с точки зрения системного программирования, а я с точки зрения веб-макаки, три года назад впервые понявшей, как работают функции.

Экосистема это именно сопутствующие инстурменты, но в сишке это все не централизовано, раскидано как попало и каждый должен сам озаботиться сборкой. В этом и беда. Чуть что надо - ищи вручную.

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

Для тебя сишка - основной инструмент, а для меня - редкий скальпель, чтобы запилить ускорялку для узкого места, где невозможно сделать «нормальными» инструментами и нужно копаться вручную.

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

Ты привёл как раз хороший пример того, где знаковые числа появились из-за плохого кодинга.

Правильно так:

for(i=n; i; ) {
  i--;
  ...
}

или так, если надеешься на то что компилятор оптимизирует лишний декремент сам (или просто пофиг):

for(i=n; i--; ) {
  ...
}

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

CrX пишет про програмную эмуляцию текстового режима, а видеокарта его реализует внутри себя незаметно для центрального процессора.

В этом смысле между «VGA text mode» и xterm’ом нет вообще никакой принципиальной разницы - оба два дают некий API для отображения символов по их кодам.

Разница огромная. Для вывода символа в vga text mode достаточно записать один байт в оперативную память соответствующей ассемблерной инструкцией, в xterm же для вывода одного символа надо выполнить весьма длинную функцию, включая несколько переключений контекста.

Настоящий текстовый вывод" - это последовательный порт

Вывод символа в последовательный порт весьма похож на вывод символа в текстовый экран - и там и там железу отдаётся только его код.

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

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

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

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

Ну, знаковое тут только -1. Можно переписать как

for (size_t i = n - 1; i + 1; --i)
Твои варианты корректны, но не передают намерение; мне кажется, что такое сложнее читать.

«Правильно» (с точки зрения производительности) вообще так:

if (n) {
    size_t i = n;
    do {
        --i;
        // body
    } while (i);
}
Но компиляторы умеют делать такое преобразование.

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

Помоему упоминания некрософта есть некрофилия. То есть если речь про игры в которые я играл и помню emm, xmm, то без этих игры вообще о чем говорить

ckotctvo
()
Ответ на: комментарий от shdown

А по-моему как раз мои варианты намного нагляднее и всё передают: инициализировать счётчик требуемым количеством, а затем вычесть его n-ное количество раз и одновременно повторять с этим цикл такое же количество раз. А вот что сравнение с -1 надо подумать что имелось ввиду, а «i+1» ещё хуже. А ещё i+1 без тайпкастов, как у тебя, приведёт к багам если size_t меньше int-а.

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

Что за некрософт? Микрософт? nc - norton commander, чьи клоны до сих пор лучшие файловые менеджеры из существующих. Как бы то ни было, вывод текста через прерывания делали в основном только проги, использовавшие консоль в режиме бесконечного принтера. Все остальные обычно выводили через запись в видеопамять т.к. это в 100 раз быстрее.

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

А ещё i+1 без тайпкастов, как у тебя, приведёт к багам если size_t меньше int-а.

Вот, кстати, интересное замечание. Я просто под такие платформы не пишу. Забавно, что нам в ВУЗе говорили, что «вот есть платформы, где процессоры делить не умеют нативно, но на то, что int — четыре байта, можно полагаться везде».

shdown ★★
()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.