Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > вопрос о контроле границ


Автор: 555shiro 17.5.2010, 16:35
Доброе время суток!
  у меня такой вопрос,почему данная программа резко закрыается,ведь компилятор должен вывести символ "у" и "r"  ?
помогите с разрешением? заранее благодарю!

Код

#include <iostream.h>
#include <stdlib.h>
#include <conio.h>
class array {
int size;
char *p;
public:
array(){p=NULL;}
array(int num);
~array (){if(p)delete[]p;}  

char& put(int i);
char get(int i);

};

array::array (int num )
{
        p=new char[num];
        if(!p)
        {       cout<<"oshibka";
                exit(1);
        }
        size=num;
}

char & array::put(int i)
{
        if(i<0 || i>=size)
        {
                cout<<"naryshenie graniz";
                exit(1);
        }
        return p[i];
}

char array :: get(int i)
{
        if(i<0 || i>=size)
        {
                cout <<"oshibka v narushenii graniz";
                exit(1);
        }
        return p[i];
}
int main()
{       int i;
        array a(5);
        a.put(4)='y';
        a.put(2)='r';
        
cout<<a.get(4)<<a.get(2)<<"\n";   // я дмаю,он должен вывести символы указанные выше....а почему то  это не так....
 
       a.put(6)='!';
        getch();
        return 0;

}


Автор: toxx 17.5.2010, 16:45
http://codepad.org/nqoycy5t

так он и выводит, то что нужно =)

Автор: kemiisto 17.5.2010, 16:50
Как вариант - использовать (всегда) std::endl для... to flush the output buffer, короче. Что-то не могу по-русски сформулировать... smile 
Код
std::cout << ... << std::endl;


Автор: djamshud 17.5.2010, 16:53
Или сделать fflush(stdout).

Автор: kemiisto 17.5.2010, 16:57
Цитата(555shiro @  17.5.2010,  17:35 Найти цитируемый пост)
данная программа резко закрыается

Хм... Что-то я не прочитал внимательно. Пробовать всё равно не буду. Ибо от богомерзкой смеси С и С++ тошнит.

Автор: toxx 17.5.2010, 16:59
Цитата

Хм... Что-то я не прочитал внимательно. Пробовать всё равно не буду. Ибо от богомерзкой смеси С и С++ тошнит.

а я попробовал и работает! smile

Автор: kemiisto 17.5.2010, 17:05
Цитата
In file included from /usr/include/c++/4.0.0/backward/iostream.h:31,
                 from /Users/kemiisto/Documents/Learning/Temp2/main.cpp:1:
/usr/include/c++/4.0.0/backward/backward_warning.h:32:2: warning: #warning This file includes at least one deprecated or antiquated header. Please consider using one of the 32 headers found in section 17.4.1.2 of the C++ standard. Examples include substituting the <X> header for the <X.h> header for C++ includes, or <iostream> instead of the deprecated header <iostream.h>. To disable this warning use -Wno-deprecated.
/Users/kemiisto/Documents/Learning/Temp2/main.cpp:3:19: error: conio.h: No such file or directory
/Users/kemiisto/Documents/Learning/Temp2/main.cpp: In function ‘int main()’:
/Users/kemiisto/Documents/Learning/Temp2/main.cpp:50: error: ‘getch’ was not declared in this scope
/Users/kemiisto/Documents/Learning/Temp2/main.cpp:42: warning: unused variable ‘i’

 smile 

Автор: toxx 17.5.2010, 17:12
kemiisto
а я исправил эти ошибки...интересно какой компилятор еще сумел пропустить их и "программа резко закрыается"

Автор: djamshud 17.5.2010, 17:14
kemiisto, 
Код

s/iostream.h/iostream/
s/conio.h//
s/getch();//


smile

Автор: kemiisto 17.5.2010, 17:47
djamshud, да я, как бы, в курсе. В этом треде не меня нужно учить программировать.

И да, getch(); лучше заменит на std::cin.get();  smile

Добавлено @ 17:54
Код

#include <iostream>

class array 
{
public:
  array()
  {
    p = NULL;
  }

  array(int num);

  ~array()
  {
    if(p) delete[] p;
  }  

  char& put(int i);

  char get(int i);
  
private:    
  int size;
  char* p;
};

array::array (int num)
{
  p = new char[num];
  if (!p)
  {       
    std::cout << "oshibka" << std::endl;
    exit(1);
  }
  size=num;
}

char& array::put(int i)
{
  if (i < 0 || i >= size)
  {
    std::cout << "naryshenie graniz" << std::endl;
    exit(1);
  }
  return p[i];
}

char array::get(int i)
{
  if (i < 0 || i >= size)
  {
    std::cout <<"oshibka v narushenii graniz" << std::endl;
    exit(1);
  }
  return p[i];
}

int main()
{
  //int i;
  array a(5);
  a.put(4)='y';
  a.put(2)='r';
        
  std::cout << a.get(4) << a.get(2) << std::endl;
 
  a.put(6)='!';
  std::cin.get();
  return 0;
}


C минимальными правками.

Автор: toxx 17.5.2010, 18:24
Цитата

В этом треде не меня нужно учить программировать.

Мало ли, вдруг не знаете  smile   smile 

Автор: GoldFinch 17.5.2010, 18:50
Цитата(kemiisto @  17.5.2010,  17:50 Найти цитируемый пост)
Как вариант - использовать (всегда) std::endl для... to flush the output buffer, короче.

как раз рекомендуют без необходимости не использовать endl, т.к. зачастую это не нужный оверхед из за "flush the output buffer"

Автор: kemiisto 17.5.2010, 18:54
Цитата(GoldFinch @  17.5.2010,  19:50 Найти цитируемый пост)
как раз рекомендуют без необходимости не использовать endl, т.к. зачастую это не нужный оверхед из за "flush the output buffer"

Ссылку в студию. Кто там и чего не рекомендует. Оверхед? В галимой учебной поделке на 20 строк? Не нужный? Тут очень даже нужный.

Автор: GoldFinch 17.5.2010, 20:17
kemiisto, 
вы писали "использовать (всегда)" а не для этой "учебной поделке на 20 строк".
endl следует использовать только если надо явно указать что кроме завершения строки, надо еще и сбросить буферы.

>Кто там и чего не рекомендует
Герб Саттер "Новые сложные задачи на С++", задача 1, замечание 5.

Автор: 555shiro 17.5.2010, 20:28
возможно я неправильно выразился,так как начинающий только,я хотел сказать что на экране что то выходит,но затем он резко исчезает...а хотелось бы чтобы он задержался,чтобы можно было увидеть что там написано...для этого я использовал getch()...но почему то все равно экран не задерживается.......

Автор: kemiisto 17.5.2010, 20:53
Цитата(GoldFinch @  17.5.2010,  21:17 Найти цитируемый пост)
вы писали "использовать (всегда)" а не для этой "учебной поделке на 20 строк".

GoldFinch, ты - тролль. smile 

Цитата(GoldFinch @  17.5.2010,  21:17 Найти цитируемый пост)
вы писали "использовать (всегда)" а не для этой "учебной поделке на 20 строк".

Я это где писал? В книжке по С++ за моим авторством? В заметке в блоге под названием "100 правил программирования на С++"? Нет. Я это писал в этой конкретной теме. Про эту конкретную учебную поделку. Я не случайно поставил скобки. Что это значит? Я вижу, что автор - новичёк и даю самый простой и топорный совет, полезный на начальных этапах обучения. Лучше пускай всегда сбрасывает буфер и получает вывод в консоль в тот момент, когда этого ожидает. Позже, когда "повзрослеет, сам разберётся, где сбрасывать буфер, а где нет. Вырывать из контекста нельзя.

Пример из Саттера
Код

vector<int> v;

v.reserve( 2 ) ;
assert( v.capacityQ == 2 );
v[0] = 1;
v[l] = 2;
for(vector<int>: riterator i = v.beginQ; i<v.end(); i
    cout << *i << endl;
}

cout << v[0];
v.reserve( 100 );
assert( v.capacityO == 100 );
cout << v[0];

v[2] = 3;
v[3] = 4;
// ...
v[99] = 100;
for( vector<int>: :iterator i = v.beginQ; i<v.end();
    cout << *i << endl;
}


Замечание 5. 
Цитата

Предпочтительнее использовать '\n' вместо endl. Использование endl заставляет вывыполнить сброс внутренних буферов потока. Если поток буферизован, а сброс буферов  всякий раз по окончании вывода строки не требуется, лучше использовать endl один раз, в конце цикла; это также повысит производительность вашей программы.

В том примере - очевидно, что предпочтительнее '\n' в цикле и endl после выхода из цикла. Массивчик не большой. Разницы в появлении его элементов в выводе не будет. У нас совершенно иная ситуация - вывод в нескольких методах. Если не сбросить буфер в одном методе, который выполнится, а затем прога рухнет, то в консоли ничего не появится и можно сделать неправильные выводы о местоположение критического бага. Так что не фига тут троллить. И заметь, ты подставляешь Саттера, выдирая его слова из контекста. Он поясняет, что имел ввиду. Приводит пример. Фактически, цитировать нужно не
Цитата
Предпочтительнее использовать '\n' вместо endl.

а то, что написано дальше:
Цитата
Если поток буферизован, а сброс буферов  всякий раз по окончании вывода строки не требуется, лучше использовать endl один раз, в конце цикла; это также повысит производительность вашей программы.

Если, лучше... Чуствуешь разницу? Сначала декламируется правило для быдла, потом поясняется, для тех у кого есть мозг. Многие книги по С++ написано в таком стиле. Вырывать из контекста нельзя.

Автор: GoldFinch 17.5.2010, 21:24
Цитата(kemiisto @  17.5.2010,  21:53 Найти цитируемый пост)
GoldFinch, ты - тролль. smile 

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

Цитата(kemiisto @  17.5.2010,  21:53 Найти цитируемый пост)
У нас совершенно иная ситуация - вывод в нескольких методах. Если не сбросить буфер в одном методе, который выполнится, а затем прога рухнет, то в консоли ничего не появится и можно сделать неправильные выводы о местоположение критического бага.

Всегда использовать endl по причине того что "прога рухнет, а в консоли ничего не появится" - это серьезная пессимизация, это не решение проблемы с падением проги. ЭТО ПЛОХОЙ СОВЕТ. От такого совета софт не станет правильнее и надежнее, он будет только более некачественным.
У endl есть конкретное назначение - его следует использовать только если есть необходимость вызвать flush, а постоянно дергать flush - это тормоза.
Падения проги должны обрабатываться нормальными способами.
Конкретно в этом случае - убивать прогу exit'ом нельзя вообще. Даже если сделать cout << endl - это поможет тольк cout, а если где-то есть еще вывод например в файл, то для этого файла никто не сделает flush, если есть еще какие-то объекты, их никто удалит. 
Надо бросать исключение. Возможно его кто-то поймает и обработает. Если никто не обработает -то по крайней мере будут вызваны деструкторы объектов (не всех), в том числе будет вызван деструктор cout.

Добавлено через 5 минут и 22 секунды
Цитата(kemiisto @  17.5.2010,  21:53 Найти цитируемый пост)
Я вижу, что автор - новичёк и даю самый простой и топорный совет, полезный на начальных этапах обучения.

Цитата(kemiisto @  17.5.2010,  21:53 Найти цитируемый пост)
Сначала декламируется правило для быдла, ...

У меня создалось впечатление что вы провели аналогию между ТСом и любыми новичками и быдлом. Это нарушает правила форума и не нравится мне лично. Исправьте свой пост.

Автор: kemiisto 17.5.2010, 21:40
Цитата(GoldFinch @  17.5.2010,  22:24 Найти цитируемый пост)
У меня уже аллергия на обвинения в троллинге. Особенно когда их используют как аргумент в споре.

Это был не аргумент.
 
Цитата(GoldFinch @  17.5.2010,  22:24 Найти цитируемый пост)
Надо бросать исключение.

Ага. Давай, расскажи ТС'у про исключения. А я послушаю.

Цитата(GoldFinch @  17.5.2010,  22:24 Найти цитируемый пост)
У меня создалось впечатление что вы провели аналогию между ТСом и любыми новичками и быдлом. Это нарушает правила форума и не нравится мне лично. Исправьте свой пост. 

У меня создалось впечатление, что ты видишь некую потенциальную причинно-следственную связь между твоими впеяатлениями и моими действиями. Это обманчивое впечатление. К тому же, аналогии там никакой не было. Новичкам - топорные решения, быдлу - лозунги, остальным - по вкусу.

Автор: GoldFinch 17.5.2010, 22:09
Цитата(kemiisto @ 17.5.2010,  22:40)
Цитата(GoldFinch @  17.5.2010,  22:24 Найти цитируемый пост)
Надо бросать исключение.

Ага. Давай, расскажи ТС'у про исключения. А я послушаю.

Все просто: 
вместо 
Код

cout << ".....";
exit(1);

надо писать
Код

cout << ".....";
throw;


программа так же закроется, но при этом будут произведены все завершающие действия.

Автор: ИванМ 17.5.2010, 22:42
555shiro, как я понимаю, прога вырубается после a.put(6)='!';, т.к. происходит выход за границы массива. getch() надо ставить перед этой строчкой, а не после нее.

Автор: kemiisto 17.5.2010, 23:16
ИванМ, я, конечно, дико извиняюсь. Но, много_матов, неужели непонятно, что я потратил своё время на форматирование и причёсывание кода не просто так. Ещё немного и ТС, возможно, САМ нашёл бы ошибку. И тут...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)