Способен ли С++ обрабатывать два условия, связанные в один оператор while или if? Уже несколько раз заметил, что двойные условия не работают, пока не развяжешь их в два одиночных. Например так: есть текст, считаный в память по адресу в lpText, строки в котором разделены символами 0xA или 0xD. Надо считать из текста двадцать строк и записать в листбокс. Поиск конца строки идёт по условию: Code (Text): while ((*((char*) ((int)lpText+j))!=0xA) || (*((char*) ((int)lpText+j))!=0xD)) Code (Text): char buffer[256]; //реально строки не длиннее 50-60 символов for (int i=0; i<20; i++) { int j = 0; // while не останавливается, buffer переполняется и далее прога вылетает while ((*((char*) ((int)lpText+j))!=0xA) || (*((char*) ((int)lpText+j))!=0xD)) { buffer[j] = *((char*) (int)lpText+j); j++; } //до сюда дело не доходит DBG_DEC(i); buffer[j] = 0; lpText += j; while (*((char*) ((int)lpText))==0xA || *((char*) ((int)lpText))==0xD) lpText++; SendMessage (hList, LB_ADDSTRING, 0, (LPARAM) buffer); }
в логике грабли. Code (Text): while ((*((char*) ((int)lpText+j))!=0xA) [b]||[/b] (*((char*) ((int)lpText+j))!=0xD)) надо Code (Text): while ((*(char*)(lpText+j)!=0xA) [b]&&[/b] (*(char*)(lpText+j)!=0xD))
Почему? Мне надо чтобы вышел из цикла по любому из двух символов, а не на оба сразу. Именно или. В тексте может быть 0D0A, 0A0D, 0A, 0D - любой из вариантов, поэтому проверяю на любой первый встретившийся символ.
если бы ты эту строчку переписал следующим образом: while (lpText[j] != 0xA || lpText[j] != 0xD) то, мне кажется, ошибку было бы проще найти... Ежели lpText объявлен как void*, то можно написать например так: static inline char char_at (int idx, void *buf) { char *str = (char*) buf; /*в случае C++ 'char *str = reinterpret_cast<char*> (buf)'*/ return str[idx]; } ... while (char_at (j, lpText) != 0xA || char_at (j, lpText) != 0xD)
cresta есть текст, считаный в память по адресу в lpText Ты отдаешь себе отчет как работает (int)lpText+j? У тебя каждый символ занимает четыре байта?
q_q Хоть я в сях и профан, но ИМХО (int)lpText+j это просто число равное адресу lpText смещенному на j байт, и уж затем это число\адрес приводится к типу char*. Может и коряво, но вроде верно
leo В Си принято делать так: Code (Text): (type *)lpText + j т.к. это позволяет делигировать подсчет числа (зависящего от тип) байт компилятору.
SI_16 static_cast<type*>(static_cast<void*>(var + i)) == static_cast<type*>(static_cast<void*>(static_cast<char*>(static_cast<v oid*>(var)) + i * sizeof(type))) )))
Пока меня не было, тут такая дискуссия... _DEN_ Я самоучка. И ни одной книги про си не читал. Скажу прямо, может несколько грубо: в гробе я видал этот си с его бесчисленными типами и необходимостью постоянно и непрерывно что-то куда-то приводить. Я б этого страуса с его трупом восемь раз расстрелял бы. q_q lpText у меня объявлен как LPVOID, т.к. VirtualAlloc возвращает такой тип, если я его объявлю как char*, то тогда в другом месте при выделении памяти придётся приводить тип к char*. В любом случае куда-то да придётся приводить. А в конечном итоге всё равно получился byte ptr, как ни крути, т.к. в конце концов это указатель (char*) (int)lpText сделал, чтобы компилятор не ругался на размер LPVOID.
YoungBastard Пытался я его почитать, "Преступление и наказание" Достоевского в сравнении с ним - как комиксы Вот тогда вопрос к гурам, блещущим знаниями Процедура считывает caption нажатой кнопки (которые состоят из букв алфавита: A,B,C,D....Z), и выводит в листбокс все строки файла (считанного в lpRus или lpEng), начинающиеся с этой буквы. Сейчас lpText объявил как char*, и убрал (int), хотя и с ним процедура работала корректно. Так как же должна выглядеть процедура с точки зрения правильного стиля? О размере кода и его быстродействии речь не идёт. Только правильность стиля. Code (Text): void Fill_List(int buttonID) { char buffer[256]; char* lpText; GetDlgItemText(hWnd, buttonID, buffer, 256); cr_strlcase(buffer); //перевод caption в нижний регистр if ( buffer[0] < 0 ) //char не unsigned, => если <0, то старший бит установлен lpText = (char*) lpRus; //значит кириллица else lpText = (char*) lpEng; SendMessage (hList, LB_RESETCONTENT, 0, 0); int i = 2; //первую строку не читаем (по тех. причинам) //поиск строки, начинающейся с caption while (1) { if ( buffer[0] == *(lpText+i) ) if ( *(lpText+i-1)==0xA || *(lpText+i-1)==0xD ) break; i++; } lpText += i; //подравнялись на начало строки while (1) { int j = 0; //запихиваем символы строки в buffer, пока не встретится 0xD или 0xA while ( *(lpText+j)!=0xA && *(lpText+j)!=0xD ) { buffer[j] = *(lpText+j); j++; } //забиваем символ переноса нулём buffer[j] = 0; lpText += j; //подстраиваем указатель на начало следующей строки while ( *(lpText)==0xA || *(lpText)==0xD ) lpText++; SendMessage (hList, LB_ADDSTRING, 0, (LPARAM) buffer); //если первый символ следующей строки отличен от первого предыдущей //значит все строки, начинающиеся этим символом, скопированы //и переданы в листбокс. Можно выходить. if ( *(lpText) != buffer[0] ) break; } }
cresta Сотри свой код, а то будем обсуждать его (есть к чему придраться), а не предлагать свои варианты. как же должна выглядеть процедура Прежде чем приступать к реализации поясни:<ol type=1><li>наличие разных файлов для разных языков - обязательное условие;<li>упорядоченность строк в файле - обязательное условие или результат борьбы за скорость;<li>какого размера может быть файл.</ol>
q_q,IceStudent Я вам про Фому, а вы мне про Ерему ) X+j == X+j*sizeof(*X) справедливо когда выражение X является указателем В рассматриваемом же случае (int)lpText это просто число типа int, а (int*)lpText это указатель на число типа int. Поэтому при lpText = NULL выражение (int)lpText+j == j, а (int*)lpText+j == j*4 Вопрос на засыпку: можно ли в си записать выражение (float)lpText+0.5 и если да, то чему оно будет равно ?
leo Точно, проморгал. Теоретически - результат будет float, а значение таким и будет: (float)lpText+0.5. Практически: Code (Text): LPSTR lpText = "hello, world!"; printf("lpText = 0x%X (%d)\n",lpText,lpText); // cannot convert from 'LPSTR' to 'float' float res = (float)lpText + 0.5; // INTERNAL COMPILER ERROR float res = static_cast<float>(reinterpret_cast<int>(lpText)) + 0.5; float res = (float)((int)lpText) + 0.5; printf("(float)lpText = %f\n",res); C1001 - это с O1, с Od в порядке (cl v13.10.3077)