810 / 405 / 83
Регистрация: 10.06.2014
Сообщений: 2,524
|
|
1 | |
Тип char* без ограничения на длину строки для хранения любых символов07.10.2016, 17:32. Показов 9368. Ответов 26
Метки нет Все метки)
(
Как можно определить char* таким образом, что бы длина его была равна строке из стандартного входного потока и что бы туда можно было положить любые символы хоть китайские иероглифы
Было хорошо если ещё была возможность определить кодировку Добавлено через 33 минуты Вроде есть ограничение на коды символов для типа char -127/127. Думаю могут быть символы числа которых выходят за эти рамки. Как работать с такими строками? Или это исключено?
0
|
|
07.10.2016, 17:32 | |
Ответы с готовыми решениями:
26
Тип char для хранения байтов
|
Диссидент
![]() 27504 / 17193 / 3785
Регистрация: 24.12.2010
Сообщений: 38,732
|
|
08.10.2016, 12:37 | 2 |
sys_beginner, смотри в сторону UNICODE, UTF-16, UTF-8, wchar, QString и т.п.
Добавлено через 1 час 44 минуты А по-поводу на плюсах эта проблема решена. А в чистом Си придется писать свою функцию, манипулирующую памятью с помощью malloc - realloc. На форуме эта проблема уже не раз обсуждалась.
1
|
810 / 405 / 83
Регистрация: 10.06.2014
Сообщений: 2,524
|
|
08.10.2016, 14:53 [ТС] | 3 |
Взял отсюда https://ru.wikipedia.org/wiki/... 0%BE%D0%BB
Ни одного вменяемого ресурса или объяснений я не нашел, подскажи пожалуйста если знаешь как это сделать или что прочитать. Добавлено через 31 минуту Что то мне подсказывает что нужно работать с такими данными не как с символами а как с потоком байт, но как именно это организовать что бы получить то что мне нужно пока не пойму
0
|
Диссидент
![]() 27504 / 17193 / 3785
Регистрация: 24.12.2010
Сообщений: 38,732
|
|
08.10.2016, 14:57 | 4 |
sys_beginner, с твоими "капризам" о китайских иероглифах лучше забыть.
![]() А так все легко делается через обычный char. С кодировками, правда, беда. Но это беда давняя, восходит к строительству Вавилонской башни. Интересные решения на этот счет предлагает Qt. QTextCodec и прочее. Есть еще библиотека iconv. Да и много, наверное, чего еще. Лично я в своих программах цепляюсь за char до последнего. Причем для русских текстов предпочитаю кодировку 866 (так сложилось исторически). А ко всему другому прибегаю уже тогда, когда надо выводить, то есть когда уже цепляться не за что. Проблем с совместимостью Windows - Linux как будто нет. Все транслируется и работает и на BC 2.0 (досовском) и на Borland C++ 5.02, и на Builder 6, и на mingw, и на gcc (Linux). И даже на Qt (кроссплатформенной) Так что панике поддаваться не стоит... ![]()
1
|
810 / 405 / 83
Регистрация: 10.06.2014
Сообщений: 2,524
|
|
08.10.2016, 15:34 [ТС] | 5 |
Ну это получается нужно тянуть за собой фреймворк для пары операций, чего очень не хочется делать
![]() Хочется ограничиться "голым" Си. Вот такой я нудист ![]() Вот что ещё я заметил 1. Вот такой код не компилируется http://rextester.com/RXK48707 потому что иероглиф более 1 байта и char не может его вместить. 2. А вот такой компилируется http://rextester.com/NLZYW26065 Интересно знать почему. Я представляю себе это так: когда используются литералы, память резервируется динамически и выделяется необходимое количество байт для указанных данных(то есть данные уже не рассматриваются как один символ как в случае просто char, а рассматриваются как набор произвольного количества байт что наводит на мысль, что в строковый литерал можно упаковать любые данные). Только не понятно одно, каждый символ char ведь может быть не более 1 байта(а литерал это массив char-ов) с кодом максимум до 255. Как так получается что в случае использования литерала это работает? Добавлено через 2 минуты Вторую ссылку обновил.
0
|
Диссидент
![]() 27504 / 17193 / 3785
Регистрация: 24.12.2010
Сообщений: 38,732
|
||||||
08.10.2016, 16:11 | 6 | |||||
sys_beginner, Всюду где я писал 'char', я имел в виду массив, 'char[]' или 'char *'
Не понимаю, что вас смущает. int "упаковывается" в 4 байта, double - в 8. Вы вполне можете написать такой код
Вместо int может быть любой тип, в том числе определенный вами через typede. А вот так FILE *f = fopen(...); char *s = (char *)f; for(i=0; i<sizeof(FILE); i++) { printf("%x ", s[i]); }[/CLANG] вы делаете 16-ричный дамп структуры FILE Добавлено через 2 минуты Могу сказать, хотя в моих устах это звучит несколько нескромно ![]() Добавлено через 2 минуты
0
|
810 / 405 / 83
Регистрация: 10.06.2014
Сообщений: 2,524
|
|
08.10.2016, 17:23 [ТС] | 7 |
Не понял к чему это было сказано
![]() ![]() Выходит просто 'char' ограничивает разработчика хранением байтов которые соответствуют ascii символам, а 'char*' позволяет хранить произвольные байты и никак не ограничивает в хранении байтов? Правильно понимаю?
0
|
08.10.2016, 21:20 | 8 |
Никаких других байтов, кроме ASCII не существует: (расширенная) таблица ASCII включает в себя все 256 комбинаций для восьмибитного байта.
char - это символьный тип, гарантирующий хранение ровно одного (любого) байта из набора ASCII. Массив char'ов позволяет хранить произвольное (в размер массива) количество байт. Переменная типа char* - это указатель на первый элемент массива char'ов (адрес массива). Иными словами, она ничего не хранит, а только указывает адрес, по которому (насколько ей известно) хранятся данные.
1
|
Диссидент
![]() 27504 / 17193 / 3785
Регистрация: 24.12.2010
Сообщений: 38,732
|
|
08.10.2016, 22:16 | 9 |
Наверное, я неправильно понял ваши заботы. И заменил их своими. Это вполне естественно в такой беседе, когда проблемы не очень четко определены. Если вам удастся сформулировать их почетче, буду рад помочь в меру сил своих.
0
|
810 / 405 / 83
Регистрация: 10.06.2014
Сообщений: 2,524
|
|
09.10.2016, 00:06 [ТС] | 10 |
Возможно я чего то не понимаю, но символы которые включает в себя ASCII это не весь набор существующих символов.
Кажется начал понимать gazlan, Байт, Видимо я просто запутался в кодировках и байтах. Прошу вас определить, действительны ли следующие утверждения: Любые данные - это байты. Каждый символ из конкретной кодировки представляет собой определенное количество байт. Допустим в стандартный входной поток были присланы китайские иероглифы - для программы это просто набор байт, который можно хранить в char* сколько угодно (в пределах дозволенного куска памяти для хранения данных, который либо фиксированного размера изначально, либо размер под данные был выделен динамически с помощью malloc). Допустим, китайский символ составляет 2 байта, тогда char[3] будет достаточно что бы его вместить. Но сам Си не богат возможностями работать с многобайтовыми кодировками как с набором символов. Например, мне нужно определить размер символов в строке в определенной кодировке. Я бы сделал это с помощью функции которой нужно передать байты и кодировку, в которой нужно посчитать количество символов. Я правильно себе представляю работу с данными в Си?
0
|
Диссидент
![]() 27504 / 17193 / 3785
Регистрация: 24.12.2010
Сообщений: 38,732
|
||||||
09.10.2016, 00:29 | 11 | |||||
Мы далеко ушли от начала ваших вопросов. Но, как я понимаю, их было как минимум два. Первый - как ввести строку неизвестной заранее длины. Вот на него я и попытаюсь ответить. Как только я узнал и полюбил замечательный язык Си, именно это меня в первую очередь и взволновало. Потому что без этого жить и программировать вообще не имеет смысла. И вот такой получился код. Неуклюжий. Меня уже несколько раз здесь освистывали. Однако, работает. И менять я его не собираюсь.
(if (p!=NULL) free(p); )
0
|
810 / 405 / 83
Регистрация: 10.06.2014
Сообщений: 2,524
|
|
09.10.2016, 00:43 [ТС] | 12 |
Байт,
Интересно, а зачем перед возвратом результата вы снова делаете realloc? if (j!=l) b = realloc(b,j);return(b); Как я понял на момент возврата все данные уже получены, почему вы выделяете дополнительную память которая не будет использована?
0
|
Диссидент
![]() 27504 / 17193 / 3785
Регистрация: 24.12.2010
Сообщений: 38,732
|
|
09.10.2016, 00:47 | 13 |
Имхо, ваши мозги на правильном пути. Если бы вы только знали, сколь смешны ваши ваши усилия тем, кто щупал память пальцами, кто работал на старинных уродах типа Минска и Урала! Но это не ваша вина, а вина нашей цивилизации, бихиевористичной по навязанному ей недобрыми дядьками принципу
Добавлено через 2 минуты Наоборот. я ее сокращаю. realloc умнее, чем вы думаете.
1
|
810 / 405 / 83
Регистрация: 10.06.2014
Сообщений: 2,524
|
|
09.10.2016, 00:58 [ТС] | 14 |
Просто другой логики из всего обсуждения я вынести не смог... Спасибо, думаю теперь все понял
Не сомневаюсь ![]() Точно. Теперь понял ![]()
0
|
09.10.2016, 01:03 | 15 |
![]() Решение
Еще раз, медленно.
Байт - это 8 бит (прочую экзотику не рассматриваем). 2^8 = 256 - всего возможно 256 кодовых комбинаций (символов алфавита, кодов ASCII) с номерами от 0 до 255. Таблица ASCII ставит в соответствие этим 256 номерам определенные картинки, отображаемые устройством вывода (дисплей, принтер etc) как символы ASCII (первые 128 стандартизованы, следующие 128 зависят от локали). Выбор таблицы (кодировки, кодовой страницы - EBCDIC, например, итд) определяет, какие "картинки" соответствуют данному номеру кода (0..255), но никаких "более других" кодов, разумеется, не существует. И, да: любые данные - это набор байт. Просто набор байт. Ничего, кроме набора байт. Все остальное - это вопрос интерпретации (предварительной договоренности). Например, договариваются рассматривать какие-то байты как разделители строк, другие - как символы алфавита и прочие - не использовать вовсе. Такие (неполноценные) файлы называются текстовыми, а прочие файлы, в которых встречаются все возможные символы именуют бинарными. Кодировка - это вопрос предварительного соглашения между передатчиком и приемником. Например, можно договориться, что одному символу в данной кодировке будет соответствовать фиксированное число байт (обычно, 1-2-4). Более эффективная схема кодирования может использовать переменное число байт на символ (от 1 до 4). С точки зрения канала передачи, это не имеет никакого значения: передается поток байт заданного размера, а их интерпретация (как символов алфавита, например) - проблема корреспондентов. Точно также, язык C ничего не знает о кодировках и не работает с ними (исключая несколько макросов, типа isascii). Стандартная библиотека поддерживает работу с массивами байт. Если вам нужна какая-либо обработка за пределами стандартной библиотеки - ищите готовые или пишите собственные функции. Если ваш алфавит содержит больше символов, чем может вместиться в байт (8 бит) - либо используйте следуюший по размеру интегральный тип (16, 32 или 64 бит), либо используйте неравномерное кодирование (некоторые OS предлагают встроенную поддержку того и/или другого).
3
|
Байт
|
09.10.2016, 01:25
#16
|
Не по теме: gazlan, Имхо, у ТС слепились в кучу несколько разных проблем. Это бывает. Знаю по себе. Будем надеяться, что наши с вами усилия помогут ему их разлепить. Человек думает. Это радует. Пожелаем ему удачи!
0
|
810 / 405 / 83
Регистрация: 10.06.2014
Сообщений: 2,524
|
|
09.10.2016, 01:25 [ТС] | 17 |
gazlan,
Большое спасибо за развернутый ответ! Только не ясно одно, вы говорите что всё есть байты, но говоря о них делаете акцент на ASCII. Ведь байты это набор бит, единичек и ноликов(Да, нуль и единица есть в ASCII). Но не понимаю, причем тут вся таблица ASCII?
0
|
Диссидент
![]() 27504 / 17193 / 3785
Регистрация: 24.12.2010
Сообщений: 38,732
|
|
09.10.2016, 01:39 | 18 |
Да, все есть Байты! И нет ничего, кроме Байтов! А ASCII просто ими пользуется. Он вкладывает в них свой смысл. То есть это уже штука другого уровня.
Вот целое число (int) вкладывает в свои четыре байта другой смысл. И складывает их, и умножает, т.е. преобразует так, как ему нужно. А ASCII ставит в соответствие каждому байту буковку, картинку этой буквы. И показывает нам, как легко видеть. Но самим байтам на это по большому счету плевать. Они состоят из 8 бит, и это все, что их волнует. ![]() А уж как и зачем их будут интерпретировать, объединять, переставлять - это дело того, кто этим занимается.
3
|
09.10.2016, 01:55 | 19 |
Очень просто: таблица ASCII - это стандартизованный вариант визуализации "единичек и ноликов". Каждому номеру кода (0..255) соответствует единственный символ таблицы ASCII, и наоборот.
Иными словами, очень часто коды сами по себе (как конкретная комбинация битов) совершенно неважны (вы же не обращаетесь к любимой девушке по номеру ее паспорта). Важна их семантика (карточная масть, десятичная цифра, знак препинания, буква алфавита). Пиктограмма кода ASCII - это стандартное имя для номера кода, такое как 'A' или '\n'. Таким образом, в контексте, где не требуется точная битовая конструкция кода, на него, обычно, ссылаются как на символ таблицы ASCII (имя вместо номера паспорта).
1
|
09.10.2016, 01:55 | 20 |
0
|
09.10.2016, 01:55 | |
Помогаю со студенческими работами здесь
20
Массив типа char без ограничения
СМО без ограничения на длину очереди, но с ограничением на время ожидания Написать программу, которая определяет длину строки - strlen (число символов без завершающего нуль-символа) Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |