Форум программистов, компьютерный форум, киберфорум
Наши страницы
C для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 5.00/6: Рейтинг темы: голосов - 6, средняя оценка - 5.00
Undisputed
206 / 135 / 37
Регистрация: 10.06.2014
Сообщений: 1,651
Завершенные тесты: 3
1

Тип char* без ограничения на длину строки для хранения любых символов

07.10.2016, 17:32. Просмотров 1222. Ответов 26
Метки нет (Все метки)

Как можно определить char* таким образом, что бы длина его была равна строке из стандартного входного потока и что бы туда можно было положить любые символы хоть китайские иероглифы
Было хорошо если ещё была возможность определить кодировку

Добавлено через 33 минуты
Вроде есть ограничение на коды символов для типа char -127/127. Думаю могут быть символы числа которых выходят за эти рамки. Как работать с такими строками? Или это исключено?
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
07.10.2016, 17:32
Ответы с готовыми решениями:

Написать программу, которая определяет длину строки - strlen (число символов без завершающего нуль-символа)
Написать программу с помощью символьных строк и функции обработки строк. ...

Свой пул памяти для хранения любых данных
Я создал свой пул памяти для строк. Действует он очень просто: выделяем большой...

Ввод символов (тип char) в динамический массив
Коллеги! Прошу помочь! Создаю символьный динамический массив (выделяю под него...

Создать тип данных для хранения строки символов. С перегрузкой оператора
Полностью задание: "Создать тип данных для хранения строки символов....

Создать класс Mystring, предназначенный для хранения строки из символов типа char. Класс имеет метод для определения дли
Создать класс Mystring, предназначенный для хранения строки из символов типа...

26
Байт
Эксперт C
18318 / 12029 / 2506
Регистрация: 24.12.2010
Сообщений: 24,293
08.10.2016, 12:37 2
sys_beginner, смотри в сторону UNICODE, UTF-16, UTF-8, wchar, QString и т.п.

Добавлено через 1 час 44 минуты
А по-поводу
Цитата Сообщение от sys_beginner Посмотреть сообщение
таким образом, что бы длина его была равна строке из входного потока
на плюсах эта проблема решена. А в чистом Си придется писать свою функцию, манипулирующую памятью с помощью malloc - realloc. На форуме эта проблема уже не раз обсуждалась.
1
Undisputed
206 / 135 / 37
Регистрация: 10.06.2014
Сообщений: 1,651
Завершенные тесты: 3
08.10.2016, 14:53  [ТС] 3
Цитата Сообщение от Байт Посмотреть сообщение
wchar
Взял отсюда https://ru.wikipedia.org/wiki/%D0%A8...B2%D0%BE%D0%BB

«размер типа wchar_t определяется компилятором, вплоть до минимальных 8 бит. Соответственно, приложения, которым требуется сохранять переносимость на различных C и C++ компиляторах, не должны использовать wchar_t для хранения Unicode-текста. Тип wchar_t предназначен для хранения широких символов в том виде, в котором их понимают конкретные компиляторы, и это может не соответствовать Юникоду».
В целом мне нужно вот что: Получить данные из входного потока, при необходимости корректно их обработать с помощью стандартных функций Си. Что бы к этим данным можно было применть все стандартные функции для работы со строками Си. Так же важна переносимость решения что бы работало и на винде и под никсами. Так же надо что бы размер идентичных данных независимо от компилятора был всегда одинаковым в байтах. Возможна ситуация когда эти данные нужно будет корректно передать другой программе(без потери данных с возможностью определить их точный размер) .

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

Добавлено через 31 минуту
Что то мне подсказывает что нужно работать с такими данными не как с символами а как с потоком байт, но как именно это организовать что бы получить то что мне нужно пока не пойму
0
Байт
Эксперт C
18318 / 12029 / 2506
Регистрация: 24.12.2010
Сообщений: 24,293
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
Undisputed
206 / 135 / 37
Регистрация: 10.06.2014
Сообщений: 1,651
Завершенные тесты: 3
08.10.2016, 15:34  [ТС] 5
Цитата Сообщение от Байт Посмотреть сообщение
Интересные решения на этот счет предлагает Qt. QTextCodec и прочее.
Ну это получается нужно тянуть за собой фреймворк для пары операций, чего очень не хочется делать
Хочется ограничиться "голым" Си. Вот такой я нудист

Вот что ещё я заметил
1. Вот такой код не компилируется http://rextester.com/RXK48707 потому что иероглиф более 1 байта и char не может его вместить.
2. А вот такой компилируется http://rextester.com/NLZYW26065
Интересно знать почему. Я представляю себе это так: когда используются литералы, память резервируется динамически и выделяется необходимое количество байт для указанных данных(то есть данные уже не рассматриваются как один символ как в случае просто char, а рассматриваются как набор произвольного количества байт что наводит на мысль, что в строковый литерал можно упаковать любые данные). Только не понятно одно, каждый символ char ведь может быть не более 1 байта(а литерал это массив char-ов) с кодом максимум до 255. Как так получается что в случае использования литерала это работает?

Добавлено через 2 минуты
Вторую ссылку обновил.
0
Байт
Эксперт C
18318 / 12029 / 2506
Регистрация: 24.12.2010
Сообщений: 24,293
08.10.2016, 16:11 6
sys_beginner, Всюду где я писал 'char', я имел в виду массив, 'char[]' или 'char *'
Цитата Сообщение от sys_beginner Посмотреть сообщение
рассматриваются как набор произвольного количества байт что наводит на мысль, что в строковый литерал можно упаковать любые данные). Только не понятно одно, каждый символ char ведь может быть не более 1 байта(а литерал это массив char-ов) с кодом максимум до 255. Как так получается что в случае использования литерала это работает?
Не понимаю, что вас смущает. int "упаковывается" в 4 байта, double - в 8.
Вы вполне можете написать такой код
C
1
2
3
4
5
6
int n;
char *s;
s = (char *)(&n);
for(i=0; i<sizeof(int); i++) {
  // перебор по байтам
}
И это будет работать всюду.
Вместо 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 минуты

Не по теме:

Цитата Сообщение от sys_beginner Посмотреть сообщение
Вот такой я нудист
Ваш минимализм мне симпатичен:)

0
Undisputed
206 / 135 / 37
Регистрация: 10.06.2014
Сообщений: 1,651
Завершенные тесты: 3
08.10.2016, 17:23  [ТС] 7
Цитата Сообщение от Байт Посмотреть сообщение
Не понимаю, что вас смущает. int "упаковывается" в 4 байта, double - в 8.
Не понял к чему это было сказано Мы вроде про char* говорим? Эх, наверное я просто тупой

Выходит просто 'char' ограничивает разработчика хранением байтов которые соответствуют ascii символам, а 'char*' позволяет хранить произвольные байты и никак не ограничивает в хранении байтов? Правильно понимаю?
0
gazlan
3141 / 1917 / 311
Регистрация: 27.08.2010
Сообщений: 5,132
Записей в блоге: 1
08.10.2016, 21:20 8
Никаких других байтов, кроме ASCII не существует: (расширенная) таблица ASCII включает в себя все 256 комбинаций для восьмибитного байта.

char - это символьный тип, гарантирующий хранение ровно одного (любого) байта из набора ASCII.

Массив char'ов позволяет хранить произвольное (в размер массива) количество байт.

Переменная типа char* - это указатель на первый элемент массива char'ов (адрес массива). Иными словами, она ничего не хранит, а только указывает адрес, по которому (насколько ей известно) хранятся данные.
1
Байт
Эксперт C
18318 / 12029 / 2506
Регистрация: 24.12.2010
Сообщений: 24,293
08.10.2016, 22:16 9
Цитата Сообщение от sys_beginner Посмотреть сообщение
Не понял к чему это было сказано
Наверное, я неправильно понял ваши заботы. И заменил их своими. Это вполне естественно в такой беседе, когда проблемы не очень четко определены. Если вам удастся сформулировать их почетче, буду рад помочь в меру сил своих.
0
Undisputed
206 / 135 / 37
Регистрация: 10.06.2014
Сообщений: 1,651
Завершенные тесты: 3
09.10.2016, 00:06  [ТС] 10
Цитата Сообщение от gazlan Посмотреть сообщение
Никаких других байтов, кроме ASCII не существует
Возможно я чего то не понимаю, но символы которые включает в себя ASCII это не весь набор существующих символов.
Цитата Сообщение от gazlan Посмотреть сообщение
Массив char'ов позволяет хранить произвольное (в размер массива) количество байт.
Кажется начал понимать

gazlan, Байт,
Видимо я просто запутался в кодировках и байтах.
Прошу вас определить, действительны ли следующие утверждения:

Любые данные - это байты. Каждый символ из конкретной кодировки представляет собой определенное количество байт. Допустим в стандартный входной поток были присланы китайские иероглифы - для программы это просто набор байт, который можно хранить в char* сколько угодно (в пределах дозволенного куска памяти для хранения данных, который либо фиксированного размера изначально, либо размер под данные был выделен динамически с помощью malloc). Допустим, китайский символ составляет 2 байта, тогда char[3] будет достаточно что бы его вместить. Но сам Си не богат возможностями работать с многобайтовыми кодировками как с набором символов. Например, мне нужно определить размер символов в строке в определенной кодировке. Я бы сделал это с помощью функции которой нужно передать байты и кодировку, в которой нужно посчитать количество символов.
Я правильно себе представляю работу с данными в Си?
0
Байт
Эксперт C
18318 / 12029 / 2506
Регистрация: 24.12.2010
Сообщений: 24,293
09.10.2016, 00:29 11
Цитата Сообщение от sys_beginner Посмотреть сообщение
что бы длина его была равна строке из стандартного входного потока
Мы далеко ушли от начала ваших вопросов. Но, как я понимаю, их было как минимум два. Первый - как ввести строку неизвестной заранее длины. Вот на него я и попытаюсь ответить. Как только я узнал и полюбил замечательный язык Си, именно это меня в первую очередь и взволновало. Потому что без этого жить и программировать вообще не имеет смысла. И вот такой получился код. Неуклюжий. Меня уже несколько раз здесь освистывали. Однако, работает. И менять я его не собираюсь.
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
char *fgm(FILE *f)  // * Чтение строки с выделением памяти 1991
{ char *b;  int c, j=0, l=81;
   if (f==NULL || feof(f)) return(NULL);
   b = malloc(l);
a: c = getc(f);
   if (c=='\n' || c==EOF) {
       b[j++] = '\0';
       if (j!=l) b = realloc(b,j);
       return(b);
   }
   if (j >= l-1) { l += 80; b = realc(b,l); }
   b[j++] = c;
   goto a;
}
Конечно, после использования полученного указателя (char *p = fgm(f); ) память надо освободить
(if (p!=NULL) free(p); )
0
Undisputed
206 / 135 / 37
Регистрация: 10.06.2014
Сообщений: 1,651
Завершенные тесты: 3
09.10.2016, 00:43  [ТС] 12
Байт,
Интересно, а зачем перед возвратом результата вы снова делаете realloc? if (j!=l) b = realloc(b,j);return(b);
Как я понял на момент возврата все данные уже получены, почему вы выделяете дополнительную память которая не будет использована?
0
Байт
Эксперт C
18318 / 12029 / 2506
Регистрация: 24.12.2010
Сообщений: 24,293
09.10.2016, 00:47 13
Цитата Сообщение от sys_beginner Посмотреть сообщение
действительны ли следующие утверждения:
Имхо, ваши мозги на правильном пути. Если бы вы только знали, сколь смешны ваши ваши усилия тем, кто щупал память пальцами, кто работал на старинных уродах типа Минска и Урала! Но это не ваша вина, а вина нашей цивилизации, бихиевористичной по навязанному ей недобрыми дядьками принципу

Добавлено через 2 минуты
Цитата Сообщение от sys_beginner Посмотреть сообщение
Как я понял на момент возврата все данные уже получены, почему вы выделяете дополнительную память которая не будет использована?
Наоборот. я ее сокращаю. realloc умнее, чем вы думаете.
1
Undisputed
206 / 135 / 37
Регистрация: 10.06.2014
Сообщений: 1,651
Завершенные тесты: 3
09.10.2016, 00:58  [ТС] 14
Цитата Сообщение от Байт Посмотреть сообщение
Имхо, ваши мозги на правильном пути.
Просто другой логики из всего обсуждения я вынести не смог... Спасибо, думаю теперь все понял

Цитата Сообщение от Байт Посмотреть сообщение
Если бы вы только знали, сколь смешны ваши ваши усилия тем, кто щупал память пальцами
Не сомневаюсь Прежде не сталкивался с такими операциями, для меня это новый шаг, вот и сложновато сразу уловить суть...

Цитата Сообщение от Байт Посмотреть сообщение
Наоборот. я ее сокращаю. realloc умнее, чем вы думаете.
Точно. Теперь понял Проглядел, там передается j, а не l вторым параметром.
0
gazlan
3141 / 1917 / 311
Регистрация: 27.08.2010
Сообщений: 5,132
Записей в блоге: 1
09.10.2016, 01:03 15
Лучший ответ Сообщение было отмечено Undisputed как решение

Решение

Еще раз, медленно.

Байт - это 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
Undisputed
206 / 135 / 37
Регистрация: 10.06.2014
Сообщений: 1,651
Завершенные тесты: 3
09.10.2016, 01:25  [ТС] 17
gazlan,
Большое спасибо за развернутый ответ!
Только не ясно одно, вы говорите что всё есть байты, но говоря о них делаете акцент на ASCII. Ведь байты это набор бит, единичек и ноликов(Да, нуль и единица есть в ASCII). Но не понимаю, причем тут вся таблица ASCII?
0
Байт
Эксперт C
18318 / 12029 / 2506
Регистрация: 24.12.2010
Сообщений: 24,293
09.10.2016, 01:39 18
Цитата Сообщение от sys_beginner Посмотреть сообщение
всё есть байты, но говоря о них делаете акцент на ASCII.
Да, все есть Байты! И нет ничего, кроме Байтов! А ASCII просто ими пользуется. Он вкладывает в них свой смысл. То есть это уже штука другого уровня.
Вот целое число (int) вкладывает в свои четыре байта другой смысл. И складывает их, и умножает, т.е. преобразует так, как ему нужно. А ASCII ставит в соответствие каждому байту буковку, картинку этой буквы. И показывает нам, как легко видеть. Но самим байтам на это по большому счету плевать. Они состоят из 8 бит, и это все, что их волнует.
А уж как и зачем их будут интерпретировать, объединять, переставлять - это дело того, кто этим занимается.
3
gazlan
3141 / 1917 / 311
Регистрация: 27.08.2010
Сообщений: 5,132
Записей в блоге: 1
09.10.2016, 01:55 19
Цитата Сообщение от sys_beginner Посмотреть сообщение
не понимаю, причем тут вся таблица ASCII?
Очень просто: таблица ASCII - это стандартизованный вариант визуализации "единичек и ноликов". Каждому номеру кода (0..255) соответствует единственный символ таблицы ASCII, и наоборот.

Иными словами, очень часто коды сами по себе (как конкретная комбинация битов) совершенно неважны (вы же не обращаетесь к любимой девушке по номеру ее паспорта). Важна их семантика (карточная масть, десятичная цифра, знак препинания, буква алфавита). Пиктограмма кода ASCII - это стандартное имя для номера кода, такое как 'A' или '\n'. Таким образом, в контексте, где не требуется точная битовая конструкция кода, на него, обычно, ссылаются как на символ таблицы ASCII (имя вместо номера паспорта).
1
Миниатюры
Тип char* без ограничения на длину строки для хранения любых символов  
gazlan
3141 / 1917 / 311
Регистрация: 27.08.2010
Сообщений: 5,132
Записей в блоге: 1
09.10.2016, 01:55 20
Цитата Сообщение от Байт Посмотреть сообщение
Человек думает. Это радует. Пожелаем ему удачи!
+ 1
0
09.10.2016, 01:55
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
09.10.2016, 01:55

Тип char для хранения байтов
Записываю в переменную типа char &quot;78 DA F3 CD 4C 2E 02 00 03 AB 01 8C&quot;, в итоге...

Массив типа char без ограничения
Помогите создать массив именно типа char без четкого ограничения. Мне говорили,...

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


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru