powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Работа со строками
9 сообщений из 9, страница 1 из 1
Работа со строками
    #38368245
kab18
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В Си для записи строки используют массив символов, и есть один большой недостаток- необходимость выделения памяти под массив с запасом, чтобы все символы записались. Ну и вообщем-то это на мой взгляд большой недостаток. Во первых: заведомо создается слабое место в программе, которое при определенных условиях (количество вводимых символов больше чем это предусмотренно программой) может привести к тому что программа окажется бесполезной, если же количество символов меньше предусмотренного, то получается, что часть выделяемой памяти занимается впустую. Решение о том, чтобы перед вводом делать запрос о количестве вводимых символов и создавать динамический массив выглядет громоздким и не удобным для пользователя. Есть ли способы определения длины строки и создания на ее основе динамического массива необходимой размерности непосредственно во время ввода информации?
...
Рейтинг: 0 / 0
Работа со строками
    #38368275
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть: вводить в заведомо большой буфер, а для хранения уже выделять столько памяти сколько надо.
...
Рейтинг: 0 / 0
Работа со строками
    #38368858
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kab18,

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

Делается это всегда так: строка читается кусочками, например, байтами, буфер выделяется на какой-то минимальный объем. По мере необходимости, когда входной буфер переполняется, он перевыделяется с большим размером, и так пока не введется вся строка.
...
Рейтинг: 0 / 0
Работа со строками
    #38368965
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivкогда входной буфер переполняется, он перевыделяется с большим размером,
или строится цепочка буферов. По окончании ввода формирутся строка актуальной длины, цепочка буферов освобождается( но это уже детали)
...
Рейтинг: 0 / 0
Работа со строками
    #38375437
kab18
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вообщем попытался реализовать задуманное, но проблема в том, что по окончании выполнения программы(после вывода введенной строки) программа время от времени совершенно произвольным образом завершается с ошибкой, ругаясь на память. Если у кого-то будут замечания по коду буду рад выслушать.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
#include <vcl.h>
#include <math.h>
#include <conio.h>
#include <iostream.h>

char* __fastcall Rus(char* text)
{
   char* bufRus;
   bufRus=new char[strlen(text)];
   CharToOem(text,bufRus);
   strcpy(text,bufRus);
   delete [] bufRus;
   return text;
}

char* __fastcall InputParam(char* Inquiry)
{
   char Buf;
   char* String=0;
   cout<<Inquiry;
   unsigned int SizeOfStr=1,Y=wherey();
   do
   {
      Buf=getche();
      //cout<<'\n'<<(int)Buf<<' '<<Buf;
      if((Buf>=61 && Buf<=122) || (Buf<=-15 && Buf>=-32) || (Buf<=-81 && Buf>=-128) || (Buf>=33 && Buf<=57) || Buf==59 || Buf==126 || Buf==-4)
      {
         String=(char*)realloc(String,SizeOfStr*sizeof(char));
         String[SizeOfStr-1]=Buf;
         SizeOfStr++;
      }
      else if(Buf==8 && String!=0)
      {
         for(unsigned int i=wherey();i>=Y;i--)
         {
         delline();
         gotoxy(1,i);
         }
         if(SizeOfStr!=1)
         {
            SizeOfStr--;
            char* StringBuf=new char[SizeOfStr];
            String=(char*)realloc(String,SizeOfStr*sizeof(char));
            strncpy(StringBuf,String,SizeOfStr-1);
            StringBuf[SizeOfStr-1]='\0';
            cout<<Inquiry<<StringBuf;
            delete [] StringBuf;
         }
         else
         {
         cout<<Inquiry;
         String=0;
         }
      }
   }while(Buf!=13 || String==0);
   String[SizeOfStr-1]='\0';
   return String;
}

int __fastcall main()
{
   double T;
   cout<<"\n"<<InputParam(Rus("Температура среды внутри трубопровода(градусы Кельвина) T="))<<endl;
   //getch();
   system("pause");
   return 0;
}
...
Рейтинг: 0 / 0
Работа со строками
    #38375482
sherzod_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kab18,

Вы занимаетесь ерундой. В принципе не понимаете самые основы ввода вывода (и компенисируете это незнание, критикой языка, смешно). А основы состоят из следующих простых истин.

1. Ввод вывод буферизован. То есть между конечным назначением и вводом существует буфер определенного размера.
2. Ввод вывод осуществляется кусками. Порядок размера кусков - килобайты. Кусок полностью может поместиться в вышеуказанным буфер.
3. Ввод вывод потоко-ориентирован. В общем случае нет начала и конца вводимых и выводимых данных.

Все. Вот так устроен механизм ввода-вывода, все другие механизмы которые у вас в голове, или предоставляемые "этими вашими" "няшными" языками, устроены поверх этих трех простых правил.

Соответственно _! в бщем случае !_ вам нужно делать так:

1. Определить какой-нибудь буфер размером в несколько КБ.
2. Считывать каждый раз в этот буфер кусок не больше размера этого буфера.
3. Заранее выделять в конечном назначении больше памяти, чтобы поместить весь логически целостный кусок для обработки, составляемый склеиванием считываемых кусков.
4. Есть возможность оптимизации, не применяя буфер, для этого вы просто содержите указатель на то место в заранее выделенной памяти, куда будете непосредственно считывать данные.

Что вы делаете не так:

Ваша программа абсолютно соответствует вышеописанному механизму (иначе быть просто не может). Вся соль в том, что вы используете буфер размером в 1 байт. Поэтому вам приходится при каждом следующем считывании символа, выделять память на 1 байт больше, и копировать все что вы считали до этого, в новую область. Именно так работает realloc. Это происходит за квадратичное время (так как для каждого считанного символа, вы пробегаетесь по всей считанной строке копируя ее), то есть за O(n^2) в то время как ввод вывод имеет сложность всего лишь 2n (с учетом копирования из буфера).
...
Рейтинг: 0 / 0
Работа со строками
    #38375496
sherzod_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kab18,

ps: То что вы сделали можно записать так:
Код: plaintext
1.
std::string text(std::istreambuf_iterator<char>(std::cin), std::istreambuf_iterator<char>());
...
Рейтинг: 0 / 0
Работа со строками
    #38376468
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Функция Rus вообще в принципе не нужна.

CharToOem использовать также нельзя, она лет 10 как устарела.
...
Рейтинг: 0 / 0
Работа со строками
    #38376473
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
char* __fastcall Rus(char* text)
{
char* bufRus;
bufRus=new char[strlen(text)];
CharToOem(text,bufRus);
strcpy(text,bufRus);
delete [] bufRus;
return text;
}

Функция неправильная, во-первых нет места в буфере под ещё один символ, '\0'.

Во вторых, она предполагает, что в разных кодировках размер строки одинаков, а это не так.

Ну и как я сказал, она в принципе не нужна в любом приложении на с++, если оно конечно не занимается непосредственно преобразованиями кодировок.
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / Работа со строками
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]