Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Вопросы по программированию на C/С++

Модерирует : ShIvADeSt

 Версия для печати • ПодписатьсяДобавить в закладки
Страницы: 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 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322

Открыть новую тему     Написать ответ в эту тему

Crazy_Shrike



Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
Вопросы по программированию на C/С++

 
  • Справочники, книги
  • Выбор IDE (среды программирования)
     
    Постарайтесь дать как можно больше информации о возникшей проблеме - это в конце концов в ваших же интересах чтобы вам помогли.

    Решения конкретных задач собираются и обсуждаются в теме Задачи по C/С++ .

    Прежде чем просить помощи в задании...
    Если позарез надо и вы даже готовы заплатить

    Как правильно задавать вопросы, если вы хотите получить ответ.

    Полезные ссылки:
    C++(eng)

  • Всего записей: 241 | Зарегистр. 25-03-2004 | Отправлено: 13:37 06-05-2004 | Исправлено: AZJIO, 19:45 12-05-2014
    BattleMage

    Newbie
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Zyava, скомпилировалось, но вот что-то это меня не сделало радостым...
     
    теперь написано так:
    strcpy(ptr->nazvanie, Edit1->Text.c_str());
    strcpy(ptr->avtor, Edit2->Text.c_str());
    strcpy(ptr->zhanr, Edit3->Text.c_str());
    strcpy(ptr->izdatelstvo, Edit4->Text.c_str());
    ptr->god_izdaniya=StrToInt(Edit5->Text);
     
    Объявление структуры такое же:
    struct kniga
     {
      struct kniga *next;
      char nazvanie[20];
      AnsiString avtor;
      AnsiString zhanr;
      AnsiString izdatelstvo;
      int god_izdaniya;
     };
    struct kniga *ptr;
     
    однако ничего... ошибка:  
    Access violation at address 32658812 in module 'CC3260MT.DLL'. Write jf address 0000004 (ошибка при нажатии на клавишу exe-шника)
     
    Добавлено:
    кстати такой вопрос... глупым наверное покажется. вот создал я на форме Edit и Button. 2 раза кликнул по батону и написал:
    char s[20];
    s=Edit1->Text;
    почему он показывает ошибку. вроде типы похожи: массив символов char и строка Ansi?
     
    а если напишешь:
    AnsiString s;
    s=Edit1->Text;  
    то ошибок не покажет...

    Всего записей: 26 | Зарегистр. 16-11-2006 | Отправлено: 16:34 15-07-2007
    TeXpert



    Silver Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    BattleMage
    Цитата:
    struct kniga *ptr;
    Ты объявил только указатель, а надо бы выделить память под это дело.
     
    Добавлено:

    Цитата:
    ошибка при нажатии на клавишу exe-шника

    Интересно). У файла есть клавиша).

    ----------
    Майкудук, Пришахтинск не предлагать!:)
    А на Пирогова приходит снова весенний гомон...

    Всего записей: 3604 | Зарегистр. 08-02-2003 | Отправлено: 18:17 15-07-2007
    BattleMage

    Newbie
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    TeXpert, СПАСИБО! думаю: вроде все правильно, вот только мелочь: память забыл выделить Постараюсь, таких ошибок не допускать
     
    Добавлено:
    А это снова я Очередной вопрос. Вот у меня есть структура. у неё 5 полей. как мне её содержимое записать в текстовый файл?
     
    FILE *db;
    db=fopen("DataBase.xxx","a+b");
     
    Кстати какой лучше вариант открытия потока выбрать? Вообще мне не только записывать нужно, но и считывать... a+?

    Всего записей: 26 | Зарегистр. 16-11-2006 | Отправлено: 23:12 15-07-2007
    Qraizer



    Advanced Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
    Ну надо же! Молчали-молчали, но вот три дня не было доступа на форум из-за падения маршрутизации где-то по дороге от провайдера до forum.ru-board.com, и как раз в эти три дня такая активность. Извиняюсь у авторов вопросов за несвоевременные ответы, но всё же не могу промолчать. Ибо вопросы не шуточные.
    Cheery
    У тебя инициализированная локальная переменная. Стандарт не определяет точное время её инициализации. Он только гарантирует, что она уже будет инициализирована на момент своего первого использования. Это сделано для предоставления возможности компилятору выполнять агрессивную оптимизацию. Например, если у тебя будет разветвлённая функция, и в одной из веток потока исполнения переменная ни разу не используется, то оптимизатор может умудриться в этой ветке не инициализировать и эту переменную, чтоб не тратить на это время. Точка останова в отладчике показывает, что в момент её срабатывания она ещё хранит мусор, а std::cout - что инициализация-таки прошла успешно. Вот и всё. Отладчик - он вправе нарушать некоторые предположения компилятора и оптимизатора.
    Abs62
    Antananarivu
    Ты совершенно правильно не понимаешь, как это может работать. Я тоже не понимаю, как автору этого кода такое могло прийти на ум. За такой код нужно немедленно увольнять. Желательно, без выходного пособия, чтоб не повадно было.
    Цитата:
    Все равно не понимаю... какой массив? ... Что это вообще за форма записи (&x)[i-1]?
    Abs62 тебе намекнул, и даже стандарт процитировал. Однако возьму смелость чуть прояснить. Операция & возвращает указатель. Неважно, является ли указатель результатом каких-нибудь вычислений, адресом переменной или именем массива - всё равно это указатель, т.е. тип данных, для которого определена операция индексирования, и при этом определена посредством других двух операций - операции сложения и разыменования: ptr[ptrdiff] есть *(ptr+ptrdiff), где ptr есть произвольный типизированный (т.е. не void) указатель на конкретные (т.е. не элементы класса) данные (т.е. не на функцию), а ptrdiff есть некое данное типа ptrdiff_t. И кстати, из-за возможности перемены мест слагаемых без изменения смысла действа не удивляйся, если вдруг увидишь где-нибудь вот такую запись: ptrdiff[ptr]. Так что в своём примере ты видишь самую обычную (просто чуть замаскированную) адресную арифметику.
    Цитата:
    Почему это работает?
    Потому что повезло.
    Цитата:
    Расположение в памяти членов класса прописано в разделе 9.2 Стандарта C++: ...  
    Ага. Вот только если уж Вы, уважаемый ссылаетесь на стандарт, то по меньше мере не вырывайте статьи из контекста, а если ещё и цитируете, то будьте добры хотя бы читать, что цитируете. Вот, из Вашей же цитаты:
    Цитата:
    Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions (10.3) and virtual base classes (10.1).
    Собственно к чему это я. Тот же стандарт чётко определяет область применения адресной арифметики - внутри диапазона статического или динамического массива, а также получение значения указателя (но не его разыменование c целью добраться до данных по этому адресу!) строго сразу за последним элементом массива. Всё. Во всех остальных случаях результат неопределён.

    ----------
    Одни с годами умнеют, другие становятся старше.

    Всего записей: 613 | Зарегистр. 08-08-2006 | Отправлено: 13:10 16-07-2007 | Исправлено: Qraizer, 13:16 16-07-2007
    Zyava



    Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору

    Цитата:
    BattleMage

    У тебя половина членов структуры char[] половина AnsiString - странно как-то    
    Для AnsiString можно и просто присваивать строки, зачем strcpy?
     

    Код:
    strcpy(ptr->nazvanie, Edit1->Text.c_str());  
    ptr->avtor, Edit2->Text;  
    ptr->zhanr = Edit3->Text;  
    ptr->izdatelstvo = Edit4->Text;  
    ptr->god_izdaniya=StrToInt(Edit5->Text);

     
    А вообще сделай или все AnsiString или все char[] - так только путаться будешь

    Всего записей: 324 | Зарегистр. 04-05-2006 | Отправлено: 14:08 16-07-2007
    BattleMage

    Newbie
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Zyava, это я просто не оттуда скопировал. Они все char [20].
     
    Это работает уже. Спасибо ещё раз. Теперь другая проблема. Как это все дело (структуру мою где 5 полей типа char [20]) записать в файл бинарный. Точнее записал, но вот не считывается...
     
    Вот так записал:
    db=fopen("DataBase.xxx","wb");
    fwrite((char*)&ptr,sizeof(ptr),1,db);
    fclose(db);
     
    Вот так считываю. То что считал хочу записать в ячейки StringGrid-a:
     db=fopen("DataBase.xxx","rb");
     fread((char*)&ptr,sizeof(ptr),1,db);
     while (fgetc(db)!=EOF)
      {
       StringGrid1->Cells[0][StringGrid1->RowCount]=IntToStr(StringGrid1->RowCount);
       StringGrid1->Cells[1][StringGrid1->RowCount]=ptr->nazvanie;
       StringGrid1->Cells[2][StringGrid1->RowCount]=ptr->avtor;
       StringGrid1->Cells[3][StringGrid1->RowCount]=ptr->zhanr;
       StringGrid1->Cells[4][StringGrid1->RowCount]=ptr->izdatelstvo;
       StringGrid1->Cells[5][StringGrid1->RowCount]=ptr->god_izdaniya;
       StringGrid1->RowCount++;
      }
     fclose(db);
     
    И вообще у меня есть сомнения, что файл, в который я записал действительно бинарный. Когда я запускаю AkelPad - ом действительно бинарный файл (другой), то он показывает что "вы действительно решили его открыть",  а вот при открытии DataBase.xxx не показывает... Неужели он текстовый?!

    Всего записей: 26 | Зарегистр. 16-11-2006 | Отправлено: 15:14 16-07-2007
    Antananarivu

    Junior Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Qraizer
    Спасибо! Очень интересный комментарий, многое прояснил! Появляйтесь здесь почаще! ))
    Еще вопрос появился..он довольно общий, если потребуется могу уточнить.
    Есть некий класс, в классе определена функция член. Ее реализация выглядит так  
    T3DMatrix T3DMatrix::inv()
    {
    T3DMatrix res;
    res = !(*this);
    *this = res;
    return res;
    };
    Это не суть важно, но ! - это перегруженный оператор и в данном случае он возвращает обратную матрицу. Так вот не поняв, зачем это тут все так наворочено я переписал функцию следующим образом:
    T3DMatrix T3DMatrix::inv()
    {
    *this = !(*this);
    return *this;
    };
    После этого вроде как ничего не изменилось, как работает так и работает. А теперь собственно вопрос: правильно ли я понимаю, что моя переделка функции в данном случае абсолютно корректна? Видимо предыдущий программист вводил res для того, чтобы сохранить сам объект содержащийся в *this, но то ли забыл, то ли еще чего и добавив строку *this = res; лишил всякого смысла ввод дополнительной переменной res. Или есть какое-то общее правило, что *this = !(*this) или там *this = -(*this) - это плохой стиль программирования чреватый потом ошибками? Заранее спасибо!

    Всего записей: 151 | Зарегистр. 10-10-2006 | Отправлено: 17:01 16-07-2007
    Abs62



    Gold Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Qraizer

    Цитата:
    Ага. Вот только если уж Вы, уважаемый ссылаетесь на стандарт, то по меньше мере не вырывайте статьи из контекста, а если ещё и цитируете, то будьте добры хотя бы читать, что цитируете. Вот, из Вашей же цитаты:

    Ага. То бишь при отсутствии виртуальных функций, виртуальных базрвых классов и выравнивании на 8 (или менее) байт этот грязный хак будет работать. Будь расположение членов класса совсем неопределено, возникла бы масса проблем с записью/чтением в/из файл(а) тех же заголовочных структур.

    ----------
    0 программистов ругал сердитый шеф
    Потом уволил одного, и стало их FF

    Всего записей: 6080 | Зарегистр. 22-10-2005 | Отправлено: 17:09 16-07-2007
    Qraizer



    Advanced Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
    Antananarivu
    Для общего случая тут нельзя сказать, как более правильно, ибо когда речь идёт о перегруженных операторах, нельзя говорить за вообще любые случаи. Всё зависит от того, как именно и что именно перегружается. В контексте, когда при перегрузке интуитивный смысл операторов не меняется, можно сказать, что обе формы - и оригинальная, и твоя изменённая - эквивалентны.
    Однако у меня будут возражения по самой форме реализации этой функциональности. Как-то не принято реализовывать методы класса путём заюзывания в них перегруженных операторов. Поясню. Перегруженный оператор ! возвращает значение. Скорее всего его прототип выглядит как T3DMatrix operator!(const T3DMatrix&);. Или я не прав? Если нет, тогда это серьёзная ошибка проектирования. Далее, раз так, то этот оператор не обязан быть даже методом класса, ибо не меняет его внутренного состояния, а конструирует новый экземпляр. Раз так, то реализация оператора присваивания, который обязан быть методом класса и при этом полагается на неметод класса, выглядит просто странно. Обычно делают наоборот - делают методы класса, которые выполняют нужные действия, а перегруженные операторы реализуют с использованием этих методов. Но это всё не настолько критично, чтобы сказать, что это неправильно. Кривое проектирование - да. Но ошибочным оно-таки не является.
    К слову сказать, могу перечислить проблемы проектирования T3DVector-а:
    public: T x,y,z; - открытые данные; тут без комментариев.
    T3DVector(int); - на кой понадобился этот конструктор - совершенно непонятно.
    int get_dim() const - то же самое. Интересно поглядеть на более общий TxDVector , если он у автора вообще получится; я в этом сильно сомневаюсь, если судить по интерфейсу T3DVector
    template <class in> T3DVector(const T3DVector<in>&); - если автор считал, что этот шаблонный контруктор сойдёт за конструктор копии, то он неправ - не сойдёт. Как результат, компилятор попытается сгенерить тривиальный копирующий конструктор, если он ему понадобится.
    template <class in> T3DVector<T>& operator =(const T3DVector<in>&) - тоже самое. Это не тот же оператор присваивания, который будет заюзан при присваивании одного экземпляра другому. Снова компилятор будет пытаться генерировать тривиальный оператор присваивания. Более того, этот шаблонный перегруженный оператор небезопасен по отношению к пользовательским исключениям.
    Непонятно откуда взялась ::norm2(). Я её прототипа не увидел.
    T3DVector<T>& operator +=(const T3DVector<T>&) и иже с ним - также небезопасны к исключениям.
    assert(a != T()); внутри T3DVector<T>& operator /=(const T3DVector<T>&) - совершенно лишняя строка, даже вредная.
    void write(std::ostream&)const и void read(std::istream&) - а я предпочитаю использовать UNICODEовые потоки. И что мне теперь делать? Кроме того, они спроектированы с нарушениями рекомендаций по разработке подобных методов. А read() - так вообще неправильно написан.
    __STL_TEMPLATE_NULL struct __type_traits<T3DFVector> и иже с ними - врут.
    template <class T> std::istream& operator >> (std::istream&, T3DVector<T>&) - неверен. Даже новички такие ошибки редко допускают.
    template <class T> inline const T3DVector<T> operator /(const T3DVector<T> a,const T) и иже с ним - константный параметр по значению... гм... я логику не осилил. assert() внутри - аналогично уже сказанному.
    template <class T>  inline const bool operator == (const T3DVector<T>&,const T3DVector<T>&) - навязывает оператору сравнения самому разбираться с неточностью представления данных с плавающей точкой.
    В общем, я бы поостерёгся пользоваться этим классом.
    Abs62
    В общем да. Но не совсем. Если быть совсем уж точным, то там говорится, что не гарантируется отсутствие незанятого пространства между элементами. Т.е. между x1, x2 и/или x3 могут быть пустоты. Для массивов же отсутствие пустот как раз гарантируется (это утверждение именно в этой цитате отсутствует, но присутствует в соответствующем разделе стандарта).

    ----------
    Одни с годами умнеют, другие становятся старше.

    Всего записей: 613 | Зарегистр. 08-08-2006 | Отправлено: 22:15 16-07-2007 | Исправлено: Qraizer, 22:23 16-07-2007
    Abs62



    Gold Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Qraizer

    Цитата:
    Если быть совсем уж точным, то там говорится, что не гарантируется отсутствие незанятого пространства между элементами. Т.е. между x1, x2 и/или x3 могут быть пустоты.

    Там говорится и то, при каких именно условиях не гарантируется отсутствие пустот. В прочих случаях расположение полей в классе чётко определено. Иначе все апишные функции, получающие параметром указатель на структуру (а в WinAPI таких немало) просто не могли бы работать корректно. Такие вещи не могут быть unspecified.

    ----------
    0 программистов ругал сердитый шеф
    Потом уволил одного, и стало их FF

    Всего записей: 6080 | Зарегистр. 22-10-2005 | Отправлено: 23:06 16-07-2007
    BattleMage

    Newbie
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Эгегей... меня кто-нибудь слышит? сообщение от 15:14 16-07-2007

    Всего записей: 26 | Зарегистр. 16-11-2006 | Отправлено: 01:19 17-07-2007
    panik1987

    Newbie
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Помогите пожалуйста решить 3 задачи:
    1.. Ввести “m”, “n” ( n<=200) и строку из “n” символов (строка оканчивается либо '.', либо ':', либо ';'). В строке среди знаков могут встречаться открывающиеся и закрывающиеся круглые, квадратные и фигурные скобки. Проверить, предшествует ли каждая открывающаяся скобка соответствующей закрывающейся, т. е. правильность расстановки скобок во всех “m” строках.
    2.Имеется кольцо, а в нём – указатели на функции, которые при выборе данного элемента кольца могут быть выполнены. Предусмотреть возможность наращивания кольца. Двигаясь по кольцу, при нажатии любой клавиши нужно показать функции, которые могут быть выполнены.
    3.4.3.6. В узлах бинарного дерева имеется элемент, определяющий частоту обращения к нему. В записях дерева хранятся следующие данные: фамилия, имя, отчество работника, его адрес, место работы, должность, дата рождения. Создать новое бинарное дерево. В качестве ключа использовать частоту обращения к нему, путь к узлам дерева должен быть оптимальным (наикратчайшим). Записи из старого дерева в новое дерево не перемещать. Рекурсии и библиотечные функции не использовать. В дереве не более пятисот узлов. Частоты в узлах дерева не совпадают.

    Всего записей: 1 | Зарегистр. 17-07-2007 | Отправлено: 12:14 17-07-2007
    Qraizer



    Advanced Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
    Abs62
    Давай я переведу твою цитату
    Цитата:
    Нестатические элементы данных класса (не являющегося объединением), объявленные без предшествующего спецификатора доступа, размещаются так, чтобы более поздние элементы имели более старшие адреса в объекте класса. Порядок размещения нестатических элементов данных, разделённых спецификатором доступа, неопределен (11.1). Требования выравнивания, обусловленные особенностями конкретных реализаций, могут быть причиной для двух смежных элементов не быть распределенными непосредственно друг за другом; так же это относится к пространству, требуемому для управления виртуальными функциями (10.3) и виртуальными базовыми классами.
    Если перевод неверен - поправь, плз, если верен - то либо я не понял, о чём ты, либо ты не понял, о чём в этой цитате говориться.
    Т.о. для того, чтобы гарантировано обеспечить чёткое распределение пространства в образе экземпляра, достаточно не использовать спецификаторов доступа. Требования выравнивания данных для элементов структур и классов в общем случае невозможно регулировать, ибо это ограничение аппаратной платформы, и перекрыть его невозможно (за исключением, если при невыровненном обращении генериться эксепшн, например). И оно же распространяется на вообще любое распределение данных, будь то локальные или глобальные переменные. Следовательно такие платформы априори не имеют упомянутой тобой проблемы. Таких архитектур, как интеловская x86, которой по большому счёту пофиг, как размещаются данные - подавляющее меньшинство, и как раз для них эта проблема встаёт в полный рост. Но как раз для них и существуют решения на основе расширения стандарта языка, наподобие #pragma pack(). Понятное дело, что стандартизировать такие вещи нельзя - у каждой платформы свои решения.

    ----------
    Одни с годами умнеют, другие становятся старше.

    Всего записей: 613 | Зарегистр. 08-08-2006 | Отправлено: 13:26 17-07-2007
    Abs62



    Gold Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Qraizer

    Цитата:
    Требования выравнивания данных для элементов структур и классов в общем случае невозможно регулировать, ибо это ограничение аппаратной платформы, и перекрыть его невозможно (за исключением, если при невыровненном обращении генериться эксепшн, например). И оно же распространяется на вообще любое распределение данных, будь то локальные или глобальные переменные.

    Тем не менее, это распределение стандартно для каждой платформы и не является compiler-depended. Что, собственно, я и хотел сказать. То бишь ответ на вопрос "почему оно работает" должен звучать не как "потому, что повезло", а как "потому, что так реализуются требования стандарта на платформе x86".

    Цитата:
    Таких архитектур, как интеловская x86, которой по большому счёту пофиг, как размещаются данные - подавляющее меньшинство

    По количеству или по распространённости? Просто мне как-то не довелось работать с другими архитектурами.

    ----------
    0 программистов ругал сердитый шеф
    Потом уволил одного, и стало их FF

    Всего записей: 6080 | Зарегистр. 22-10-2005 | Отправлено: 17:18 17-07-2007
    Antananarivu

    Junior Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Abs62
    Я вижу, что тут уже пошел спор сишных гуру, но все же свои 5 копеек. Правильно я понимаю, даже если ты и прав про стандарт платформы, все равно такая реализация функции (которую я приводил выше) как минимум... ну рискована что ли, потому что кто-то (или даже сам программист) со временем может забытиь такие тонкости и добавить, скажем, виртуальную функцию или выравнивание и все... и потом будешь полгода искать причину, почему перестало работать как надо, разве не так?

    Всего записей: 151 | Зарегистр. 10-10-2006 | Отправлено: 17:31 17-07-2007
    Abs62



    Gold Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Antananarivu
    Правильно.  Qraizer уже сказал, как следует поступать с авторами подобного кода. И я с ним согласен.


    ----------
    0 программистов ругал сердитый шеф
    Потом уволил одного, и стало их FF

    Всего записей: 6080 | Зарегистр. 22-10-2005 | Отправлено: 18:17 17-07-2007
    Qraizer



    Advanced Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
    Abs62

    Цитата:
    Тем не менее, это распределение стандартно для каждой платформы и не является compiler-depended. Что, собственно, я и хотел сказать.
    Это-то да, но как сказано чуть ниже, для платформ, подобных x86, это перестаёт быть справедливым.
    Цитата:
    То бишь ответ на вопрос "почему оно работает" должен звучать не как "потому, что повезло", а как "потому, что так реализуются требования стандарта на платформе x86".
    В общем-то, это вопрос терминологии, так что спорить не буду. Однако, "повезло" мне больше по душе по двум причинам: во-первых, чем меньше не достаточно опытных в программировании людей увидят такие вот хаки, тем меньшее из них количество извлечёт из этого крайне отрицательные уроки, ошибочно считая их вершиной "мастерства", так что раз уж такая информация попала в их поле зрения, запрет должен быть как можно более категоричным; во-вторых, требования стандарта - это закон, поэтому если стандарт говорит, что сие есть неопределённое поведение, значит это есть неопределенённое поведение, следовательно "повезло" тут уместнее, ибо ожидаемое поведение есть частный случай неопределённого.
    Цитата:
    По количеству или по распространённости?
    Не скажу точно. Однакое я не слышал (впрочем, возможно, забыл) не x86, которые бы не требовали выравнивания в обязательном порядке. Получается, что x86 чуть ли не единственная в своём роде. Распространённость, я думаю, тут ни при чём, ибо стандарт по-любому обязан рассматривать все возможные варианты, без учёта распространённости.

    ----------
    Одни с годами умнеют, другие становятся старше.

    Всего записей: 613 | Зарегистр. 08-08-2006 | Отправлено: 14:17 18-07-2007
    BattleMage

    Newbie
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Вот у меня есть ComboBox. Я его заполянил некоторыми строчками:
    ComboBox1->Clear();
    ComboBox1->Items->Add("Строка1");
    ComboBox1->Items->Add("Строка2");
    ComboBox1->Items->Add("Строка3");
    ComboBox1->Items->Add("Строка4");
     
    Потом есть процедура по нажатию на некоторую клавишу.
    Вопрос: как определить что именно выбрал пользователь "Строка1" или "Строка3", к примеру
     
    Заранее спасибо :)

    Всего записей: 26 | Зарегистр. 16-11-2006 | Отправлено: 20:10 22-07-2007
    Antananarivu

    Junior Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    продолжаю серию ламерских вопросов... ))
    функция fscanf...
     
    FILE* Read;
    int n;
    fscanf(Read,"%d\n",&n);
    cout << n << endl;
     
    Вопрос, что дает \n ?
    У меня что fscanf(Read,"%d\n",&n);
    что fscanf(Read,"%d",&n);
    работают идентично...
    Я уже пытался разделить два числа символом новой строки и чего только не пытался... В книге написано (если я правильно понял), что по идее компилятор должен будет проигнорировать символ конца строки... но хоть убей у меня этого не получается...  
    P.S. Я даже не совсем понимаю, как он должен его проигнорировать? У меня файл, в файле 2 числа через пробел 1 и 2, в результате выполнения программы  в n запишется число 1, теперь я в файле пишу 1, жму Enter и пишу 2, по логике вещей, если бы компилятор проигнорировал символ конца строки в n должно было бы записаться число 12, разве не так? Но на самом деле ничего не меняется... Где я глобально заблуждаюсь? Заранее спасибо!

    Всего записей: 151 | Зарегистр. 10-10-2006 | Отправлено: 14:44 23-07-2007 | Исправлено: Antananarivu, 14:59 23-07-2007
    Qraizer



    Advanced Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
    Ты заблуждаешься в своём представлении того, как функции xxxscanf() обрабатывают форматную строку. Ты считаешь, что она вначале целиком разбирается по элементам, а потом уже на основе разбора выполняется чтение данных. На самом деле она обрабатывается последовательно, и все встреченные форматные спецификаторы обрабатываются сразу же, без заглядывания вперёд. Т.е. когда разбор дойдёт до %d, сразу же будет выполнена попытка ввести целое десятичное, которое и вводится как 1, т.к. ввод из потока остановится на первом разделителе, неважно, пробел ли это будет или \n. И только потом начнётся анализ дальнейшего содержимого форматной строки.
    При вводе, каждый спецификатор формата может начинать разбор содержимого потока с последовательности разделителей, каковыми являются пробелы, табуляции и "новые строки". При этом все эти последовательные разделители пропускаются. (Исключение составляет только %c, который никогда не учитывает разделители и считает из обычными символами.) Если в форматной строке встречаются не только спецификаторы формата, считается, что в соответствующих позициях потока должны располагаться именно эти символы. При этом они благополучно вычитываются и отбрасываются. Т.о. scanf("%d%d", &n1, &n2) после ввода n1 будет ожидать в потоке хотя бы один разделитель (иначе два числа просто сольются), а следом значение n2, а scanf("%dи далее%d", &n1, &n2) после ввода n1 будет ожидать последовательности "и далее" и только потом n2; при этом разделители уже не обязательны, т.к. ввод n1 будет остановлен на символе "и" (ибо этот символ явно не относится к цифрам), а после "далее" сразу же ожидается новое число. Если же в потоке между значениями n1 и n2 будет что-то другое, отличное от "и далее", то ввод прекратится на несовпавшем символе, и будет зафиксирована ошибка. Например, если в потоке будет "1и далие2", то после выборки из потока символа "л" вычитается "и", а не "е", как указано в форматной строке, и это будет расценено как ошибка данных в потоке. В результате поток не дойдёт до "2", и n2 не будет введено.
    Отсюда следует, что указывать сами разделители в форматной строке не имеет особого смысла (если только они не должны быть введены спецификатором %c). Фактически они могут рассматриваться как поясняющие. Смотри например, что произойдёт с scanf("%d\n%d", &n1, &n2).
    Когда после %d обнаружится \n, то именно он и будет ожидаться после ввода n1. Если он в потоке и правда есть, то он благополучно вычитается и отбросится; если же вместо него там будет, например, какой-нибудь пробел, то произойдёт ошибка, и он не вычитается. Однако далее следует ещё один %d, поэтому дальше начнётся ввод ещё одного целого, и начнётся он с разделителя, того самого, который не вычитался, и который теперь благополучно пропустится как лидирующий. Так что действительно - никакой разницы.


    ----------
    Одни с годами умнеют, другие становятся старше.

    Всего записей: 613 | Зарегистр. 08-08-2006 | Отправлено: 23:58 23-07-2007 | Исправлено: Qraizer, 00:11 24-07-2007
    Открыть новую тему     Написать ответ в эту тему

    Страницы: 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 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322

    Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Вопросы по программированию на C/С++


    Реклама на форуме Ru.Board.

    Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
    Modified by Ru.B0ard
    © Ru.B0ard 2000-2024

    BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

    Рейтинг.ru