Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Неправельное определение длины строки(strlen) 
V
    Опции темы
toxx
Дата 9.12.2009, 21:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 653
Регистрация: 4.3.2009
Где: НН

Репутация: нет
Всего: 13



Помогите разобраться в чем причина того что strlen(chBuff) определяет неверно количество символов в строке?Пробовал делать chBuff static но тогда размер совсем нулевой, если просто char без static размер 22(если вводить 3 символа в строку ввода).
Код

#include <windows.h>
#include<stdio.h>
#include<string.h>
#include<conio.h>


#define ID_EDIT 1001
#define ID_BUTTON 1002
#define ID_CLEAR 1003
BOOL RegClass(WNDPROC,LPCTSTR,UINT);
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE hInst;
static char szClassName[]="EditClass";
static char szTitle[]="Program";
int factor(int n)
{
 if(n<1)
    return 1;
 return n*factor(n-1);
}


HINSTANCE hInstance;
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
                   LPSTR lpszCmdLine,int nCmdShow)
{    
    HACCEL hAccel;HWND hwnd;MSG msg;
    WNDCLASSEX wndclass;
    wndclass.cbSize = sizeof(wndclass);
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = DLGWINDOWEXTRA;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(hInstance, szClassName);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground =(HBRUSH)(COLOR_WINDOW + 6);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = szClassName;
    wndclass.hIconSm = LoadIcon(hInstance, szClassName);
    RegisterClassEx(&wndclass);
    hwnd=CreateWindow(szClassName,szTitle,
        WS_OVERLAPPEDWINDOW | WS_VISIBLE,
        100, 50,364,600,
        0,0,hInstance,NULL);
    ShowWindow(hwnd, nCmdShow);
    hAccel = LoadAccelerators(hInstance,szClassName);
    while(GetMessage(&msg,0,0,0)) 
    {
        if(!TranslateAccelerator(hwnd, hAccel, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    return msg.wParam;
}BOOL RegClass(WNDPROC Proc,LPCTSTR szName,
              UINT brBackground)
{
    WNDCLASS wc;
    wc.style=wc.cbClsExtra=wc.cbWndExtra=0;
    wc.lpfnWndProc=Proc;wc.hInstance=hInst;
    wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);
    wc.hCursor=LoadCursor(NULL,IDC_ARROW);
    wc.hbrBackground=(HBRUSH)(brBackground+1);
    wc.lpszMenuName=(LPCTSTR)NULL;
    wc.lpszClassName=szName;
    return(RegisterClass(&wc)!=0);
}
LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,
                         WPARAM wParam,LPARAM lParam)
{
    static HWND hEdit,hButton,hStatic,hStatic2,hClear;
    char chBuff[10];
    HDC hdc;
    switch(msg)
    {
    case WM_CREATE:
        {

        hEdit=CreateWindow("edit",
                NULL,WS_CHILD|WS_VISIBLE|WS_BORDER|ES_RIGHT,
                30,40,300,30,hwnd,(HMENU)ID_EDIT,hInstance,NULL);
        hButton=CreateWindow("button",
                "OK",WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
                130,85,100,30,hwnd,(HMENU)ID_BUTTON,hInstance,NULL);
        hClear=CreateWindow("button",
                "Очистить",WS_CHILD|WS_VISIBLE,
                240,85,100,30,hwnd,(HMENU)ID_CLEAR,hInstance,NULL);
        hStatic2=CreateWindow("static",
                "Введите строкy",WS_CHILD|WS_VISIBLE,
                30,120,300,30,hwnd,(HMENU)0,hInstance,NULL);
        SetFocus(hEdit);
            return 0;

        }
    case WM_COMMAND:
        {
            switch(LOWORD(wParam))
            {
            case ID_CLEAR:
                {
                    InvalidateRect(hwnd, NULL, TRUE);
                    return 0;
                }
            case ID_EDIT:
                {
                    if((HIWORD(wParam))==EN_ERRSPACE)
                    MessageBox(hwnd,"LOW",szTitle,MB_OK);
                return 0;
                }
            case ID_BUTTON:
                {
                    hdc=GetDC(hwnd);
                    SendMessage(hEdit,EM_GETLINE,
                        0,(LPARAM)chBuff);
 int posok=0;
 int posno=0;

 int length=strlen(chBuff)-1;
 int n=factor(length);
char pwordtmp[10],buff[10];
 int pos=0,g;
 for(int j=0; j<length; j++)
  pwordtmp[j]=chBuff[j];
 g=0;
 for(int i=0; i<n; i++)
 {
  if(pos==length-1)
   pos=0;
  char ctmp=pwordtmp[pos];
  pwordtmp[pos]=pwordtmp[pos+1];
  pwordtmp[pos+1]=ctmp;
  pos++;
  for(int j=0; j<length; j++)
    TextOut(hdc,8,150+15*g,buff,strlen(buff));
  int flag=0;
  for(int j=0; j<length; j++)
  {

   if(chBuff[j]==pwordtmp[j])
   {
    flag=1;
    posok++;
    break;
   }
  }
  if(flag=0)
   posno++;
  g++;
 }            
                    for(int i=0;i<length;i++)
                    {
                        chBuff[i]='\0';
                        buff[i]='\0';
                    }
                    ReleaseDC(hwnd,hdc);
                    SetWindowText(hEdit,"\0");
                    SetFocus(hEdit);
                    return 0;
                }
            }
            return 0;
        }
    case WM_DESTROY:
        {
            PostQuitMessage(0);
            return 0;
        }
    }
    return DefWindowProc(hwnd,msg,wParam,lParam);
}


PM MAIL   Вверх
Earnest
Дата 10.12.2009, 09:56 (ссылка) |    (голосов:3) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 33
Всего: 183



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


--------------------
...
PM   Вверх
Alexeis
Дата 10.12.2009, 10:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 7
Всего: 459



  Типичные проблемы.
а) Не инициализированные переменные.
б) Возврат стекового значение по ссылке.
в) Переполнение буфера (затер конечный 0, а может вылез за границы памяти).
г) Использование указателя на буфер после его уничтожения.

На первый взгляд видна только проблема "а".
char chBuff[10]; => char chBuff[10] = {0};


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
xvr
Дата 10.12.2009, 14:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 40
Всего: 223



Код

 int length=strlen(chBuff)-1;
-1 IMHO лишнее

PM MAIL   Вверх
toxx
Дата 10.12.2009, 14:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 653
Регистрация: 4.3.2009
Где: НН

Репутация: нет
Всего: 13



Цитата

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


Ну вопрос я изложил правильно и проблему думаю тоже, а вот указать место где неисправность забыл(простите что конкретно не указал).

chBuff объявлен так

Код

char chBuff[10];


Место проблемы

Код

hdc=GetDC(hwnd);
SendMessage(hEdit,EM_GETLINE,
    0,(LPARAM)chBuff);
 int posok=0;
 int posno=0;

 int length=strlen(chBuff);
 int n=factor(length)-1;


Цитата

  Типичные проблемы.
а) Не инициализированные переменные.
б) Возврат стекового значение по ссылке.
в) Переполнение буфера (затер конечный 0, а может вылез за границы памяти).
г) Использование указателя на буфер после его уничтожения.

На первый взгляд видна только проблема "а".
char chBuff[10]; => char chBuff[10] = {0};


Я так уже пробовал инициализировать, но тогда длинна строки в этом месте равна 0 EM_GETLINE ничего не возвращает.
Код

SendMessage(hEdit,EM_GETLINE,
    0,(LPARAM)chBuff);
 int posok=0;
 int posno=0;

 int length=strlen(chBuff);


Также я пробовал делать результат такойже как и если инициализировать char chBuff[10]; => char chBuff[10] = {0};
Код

static  char chBuff[10] ;

Код для программы исходный брал из Р. М. Ганеев Проектирование интерфейса в Win32 API
Проблемы мб кроется в какихто новшествах win7 ? Я делал калькулятор на ХР и при переносе на win7 возникли тоже трудности(Я их исправил).
В прогрмме моего калькулятора всё объявленно точно также и работает стабильно.Вот пример определения стабильного

Код

static char chBuff[80];

SendMessage(hEdit,EM_GETLINE,
        0,(LPARAM)chBuff);
static int k;
if(!bCheck)
{
    int g=0;
        k=strlen(chBuff);


Цитата

-1 IMHO лишнее


Алгоритм не мой, я лишь создаю графическую оболочку.

Это сообщение отредактировал(а) toxx - 10.12.2009, 14:32
PM MAIL   Вверх
xvr
Дата 10.12.2009, 14:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 40
Всего: 223



Остановись отладчиком на strlen и посмотри, что у тебя в chBuff и что возвращает strlen. Она скорее всего не виновата  smile

Добавлено через 3 минуты и 31 секунду
Еще вопрос - зачем тут
Код

  for(int j=0; j<length; j++)
    TextOut(hdc,8,150+15*g,buff,strlen(buff));
выводится несколько раз один и тот же мусор (buff на данный момент не инициализированн) в одно и то же место? И зачем несколько раз, что бы экран монитору лучше протерло?  smile

Добавлено через 6 минут и 13 секунд
И еще, вот это
Код

  if(flag=0)
не будет проверять flag на 0, а просто присвоит ему 0

PM MAIL   Вверх
toxx
Дата 10.12.2009, 14:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 653
Регистрация: 4.3.2009
Где: НН

Репутация: нет
Всего: 13



Цитата

Остановись отладчиком на strlen и посмотри, что у тебя в chBuff и что возвращает strlen. Она скорее всего не виновата  smile


Вот что в них если инициализировать как char chBuff[10]; 

user posted image
Цитата


Еще вопрос - зачем тут
  for(int j=0; j<length; j++)
    TextOut(hdc,8,150+15*g,buff,strlen(buff));
выводится несколько раз один и тот же мусор (buff на данный момент не инициализированн) в одно и то же место? И зачем несколько раз, что бы экран монитору лучше протерло?  smile

не будет проверять flag на 0, а просто присвоит ему 0


там g++ стоит в конце smile 

flag=0 
не знаю о чем думал тот кто делал алгоритм) Он потомучто не мой, я тока графику делаю.
PM MAIL   Вверх
xvr
Дата 10.12.2009, 18:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 40
Всего: 223



Цитата(toxx @ 10.12.2009,  14:48)
Цитата

Остановись отладчиком на strlen и посмотри, что у тебя в chBuff и что возвращает strlen. Она скорее всего не виновата  smile


Вот что в них если инициализировать как char chBuff[10]; 

user posted image

Ну и что ты хочешь получить от strlen - у тебя в буфере лежит не терминированная 0 строка (с мусором).

Цитата

Цитата


Еще вопрос - зачем тут
  for(int j=0; j<length; j++)
    TextOut(hdc,8,150+15*g,buff,strlen(buff));
выводится несколько раз один и тот же мусор (buff на данный момент не инициализированн) в одно и то же место? И зачем несколько раз, что бы экран монитору лучше протерло?  smile


там g++ стоит в конце smile 
В 'конце' чего? У for'а в этом куске кода тело состоит из единственного оператора - вызова TextOut. Никакого g++ 'в конце' там нету.

Цитата

flag=0 
не знаю о чем думал тот кто делал алгоритм) Он потомучто не мой, я тока графику делаю.
В смысле 'приделываю графику к неработающей программе'? Чему тогда удивляться - она от приделывания графики чудесным образом не заработает  smile 

PM MAIL   Вверх
toxx
Дата 10.12.2009, 19:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 653
Регистрация: 4.3.2009
Где: НН

Репутация: нет
Всего: 13



Цитата

Ну и что ты хочешь получить от strlen - у тебя в буфере лежит не терминированная 0 строка (с мусором).


Если эту строку обнулить(Как предлагает Alexis char chBuff[10] = {0}; )
Строка становится пустой(ктобы мог подумать=) )
И если вызвать 


Код

SendMessage(hEdit,EM_GETLINE,
    0,(LPARAM)chBuff);


то будет в дебаггере вот это

user posted image

то он вообще ничего не сохраняет в chBuff, в нём почемуто тупо нет ничего
и вот этого я никак не пойму(((
PM MAIL   Вверх
xvr
Дата 10.12.2009, 21:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 40
Всего: 223



Цитата(toxx @ 10.12.2009,  19:26)
И если вызвать 

Код

SendMessage(hEdit,EM_GETLINE,
    0,(LPARAM)chBuff);


то будет в дебаггере вот это

user posted image

то он вообще ничего не сохраняет в chBuff, в нём почемуто тупо нет ничего

Это правильно - читаем MSDN:

Цитата

lParam
    A pointer to the buffer that receives a copy of the line. Before sending the message, set the first word of this buffer to the size, in TCHARs, of the buffer. For ANSI text, this is the number of bytes; for Unicode text, this is the number of characters. The size in the first word is overwritten by the copied line.
У тебя там 0, так что ничего и не читается

PM MAIL   Вверх
toxx
Дата 10.12.2009, 22:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 653
Регистрация: 4.3.2009
Где: НН

Репутация: нет
Всего: 13



xvr

Спасибо за ответ)
А можно еще вопрос. Не могутли эти странности зависеть от ОС? 
У меня когда я читал книгу стоял ХР(и всё работало четко), щас поставил win7 и появились вот такие вот сложности.
В предыдущей своей программе когда перешел на win7 цвета отображались некорректно, вылезли левые символы(но всё благополучно исправил),
здесь же не вышло)


Кст проверил код что мне дали, чтобы туда засунуть оказалось что он кривой=( Так что теперь ждать буду пока переделают.


PM MAIL   Вверх
xvr
Дата 10.12.2009, 22:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 40
Всего: 223



Цитата(toxx @ 10.12.2009,  22:14)
А можно еще вопрос. Не могутли эти странности зависеть от ОС? 

Могут. MS не гарантирует, что OS'ы будут bug в bug compatible  smile Ошибки могут проявляться по разному.
В принципе и в правильных конструкциях могут проявляться различия, но они все связаны с OS API и проявляются только если делается что то совсем не тривиальное  smile 

Цитата

У меня когда я читал книгу стоял ХР(и всё работало четко), щас поставил win7 и появились вот такие вот сложности.
Скорее всего вылезли баги, которые под XP просто не проявлялись

PM MAIL   Вверх
GremlinProg
Дата 12.12.2009, 12:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(xvr @  11.12.2009,  00:31 Найти цитируемый пост)
Скорее всего вылезли баги, которые под XP просто не проявлялись

скорее даже багам в win7 стали ужелять большее внимание, чем в XP,
т.е. там, где на ошибку раньше закрывали глаза, теперь глаза открывают,
причем глаза самих же программистов, которые эти ошибки делали во времена XP,

а сама ось кривее не стала )


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0704 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.