Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Работа со строками / 9 сообщений из 9, страница 1 из 1
15.08.2013, 22:12
    #38368245
kab18
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа со строками
В Си для записи строки используют массив символов, и есть один большой недостаток- необходимость выделения памяти под массив с запасом, чтобы все символы записались. Ну и вообщем-то это на мой взгляд большой недостаток. Во первых: заведомо создается слабое место в программе, которое при определенных условиях (количество вводимых символов больше чем это предусмотренно программой) может привести к тому что программа окажется бесполезной, если же количество символов меньше предусмотренного, то получается, что часть выделяемой памяти занимается впустую. Решение о том, чтобы перед вводом делать запрос о количестве вводимых символов и создавать динамический массив выглядет громоздким и не удобным для пользователя. Есть ли способы определения длины строки и создания на ее основе динамического массива необходимой размерности непосредственно во время ввода информации?
...
Рейтинг: 0 / 0
15.08.2013, 23:04
    #38368275
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа со строками
Есть: вводить в заведомо большой буфер, а для хранения уже выделять столько памяти сколько надо.
...
Рейтинг: 0 / 0
16.08.2013, 13:08
    #38368858
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа со строками
kab18,

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

Делается это всегда так: строка читается кусочками, например, байтами, буфер выделяется на какой-то минимальный объем. По мере необходимости, когда входной буфер переполняется, он перевыделяется с большим размером, и так пока не введется вся строка.
...
Рейтинг: 0 / 0
16.08.2013, 14:30
    #38368965
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа со строками
MasterZivкогда входной буфер переполняется, он перевыделяется с большим размером,
или строится цепочка буферов. По окончании ввода формирутся строка актуальной длины, цепочка буферов освобождается( но это уже детали)
...
Рейтинг: 0 / 0
23.08.2013, 09:22
    #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
23.08.2013, 10:03
    #38375482
sherzod_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа со строками
kab18,

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

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

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

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

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

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

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

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

CharToOem использовать также нельзя, она лет 10 как устарела.
...
Рейтинг: 0 / 0
24.08.2013, 11:31
    #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
Форумы / C++ [игнор отключен] [закрыт для гостей] / Работа со строками / 9 сообщений из 9, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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