Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как правильно делается sscanf для TEdit->Text
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
west329_
Изучаю работу в окнах под C++Builder 6, до этого писаль только консольные приложеня.

Вопрос следующий, есть масив
Код
unsigned char IP[4];

потом на форме есть VCL компонент типа TEdit * EditIP, в поле которого пишется ИП адрес
в таком виде - 192.168.0.1

собственно в консольном приложении я делал так
Код
scanf("%d.%d.%d.%d", &IP_server[0], &IP_server[1], &IP_server[2], &IP_server[3]);


А как такое делается в Builder ? подскажите


так не работает
Код
sscanf(&IP[0],"%d.%d.%d.%d", Edit_IP->Text);

тоесть когда вывожу отладочную информацию то масив IP[] содержит одни нули
Код
Memo1->Lines->Add(d_str.sprintf("IP %d.%d.%d.%d", IP[0],IP[1],IP[2],IP[3]) );


для проверки
Код
Memo1->Lines->Add(Edit_Login->Text);
то ип переносится нормально

подскажите что неправильно ?
andrew_b
Цитата(west329_ @ Jul 23 2009, 16:08) *
так не работает
Код
sscanf(&IP[0],"%d.%d.%d.%d", Edit_IP->Text);

тоесть когда вывожу отладочную информацию то масив IP[] содержит одни нули
Естественно, потому что Edit_IP->Text не типа char *. Как превратить String (или что там) в char *, изучайте доку на VCL.
Xenia
Код
sscanf(Edit_IP->Text.c_str(), "%d.%d.%d.%d", &IP_server[0], &IP_server[1], &IP_server[2], &IP_server[3]);
iosifk
Цитата(west329_ @ Jul 23 2009, 16:08) *
Вопрос следующий, есть масив
Код
unsigned char IP[4];

потом на форме есть VCL компонент типа TEdit * EditIP, в поле которого пишется ИП адрес
в таком виде - 192.168.0.1

подскажите что неправильно ?


Сначала пользователь заводит в Edit текстовую строку "в таком виде - 192.168.0.1". И здесь ничего руками писать не надо...
Далее - текстовая строка представляет уже собой массив. Поэтому делаете строковую переменную String IP и ей присваиваете Edit->Text...
Далее смотрите по хелпу, как получить доступ к символам строки.
Смотрите функцию поиска символа в строке. Либо вручную перебираете символы и находите первую точку, либо пользуетесь функцией Билдера...
У меня на сайте выложен пример софта для работы с JTAG. Там есть файл работы со строками. Все откоментировано достаточно подробно...
Удачи!
ReAl
Мне другое интересно - как это по формату %d вводится не в int, а в unsigned char?
Я понимаю, что везёт - и LOW ENDIAN (ну об этом действительно практически всегда можно забыть), и после массива unsigned char IP[4] просто случайно оказалось ненужное в данный момент место (а вот это уже "чревато боком" для любого процессора) и его не страшно протереть нулями при работе (s)scanf, но... Непривычно.
Xenia
Цитата(ReAl @ Jul 24 2009, 12:07) *
Мне другое интересно - как это по формату %d вводится не в int, а в unsigned char?


Верное замечание! Формат %d для вывода в char-переменные не годится. А формат %hd далеко не все компиляторы поддерживают. Надежнее, да и ближе к стандарту, завести переменные типа int (хотя бы временные), а том из них скопировать в char.
SSerge
Нельзя недооценивать пользователя. Он запросто может ввести в это поле что угодно, вплоть до собственного имени, даты рождения или номера паспорта. Для разбора таких данных sscanf() уже мало пригодна, она больше для неинтерактивных данных, где есть уверенность что нужный формат соблюдается.
Нужно проконтролировать что числа находятся в диапазоне 0-255, что между ними действительно только одна точка, что чисел всего четыре, не больше и не меньше, и по любой ошибке выдать осмысленное сообщение.
Лучше разбирать строку по частям. Можно просто вручную считывать цифры и превращать их в число или применить функции типа atoi() или strtol(), потом проверить на '.', потом следующее число...

Ещё лучше сделать четыре отдельных поля ввода, по одному для каждого числа, проще будет и точек юзеру набирать не надо, они уже будут нарисованы на форме для ввода.
mdmitry
Цитата(SSerge @ Jul 24 2009, 15:21) *
Ещё лучше сделать четыре отдельных поля ввода, по одному для каждого числа, проще будет и точек юзеру набирать не надо, они уже будут нарисованы на форме для ввода.

И при вводе контролировать правильность ввода по диапазону чисел при уходе фокуса ввода на другой элемент. Нечто аналогичное есть в MFC (Edit).
ReAl
Цитата(SSerge @ Jul 24 2009, 14:21) *
Для разбора таких данных sscanf() уже мало пригодна, она больше для неинтерактивных данных, где есть уверенность что нужный формат соблюдается.
Если это разбор конфига - то ничем не отличается от ввода с экрана, может оказаться всё, что угодно.

Цитата(SSerge @ Jul 24 2009, 14:21) *
Нужно проконтролировать что числа находятся в диапазоне 0-255, что между ними действительно только одна точка, что чисел всего четыре, не больше и не меньше, и по любой ошибке выдать осмысленное сообщение.
Лучше разбирать строку по частям. Можно просто вручную считывать цифры и превращать их в число или применить функции типа atoi() или strtol(), потом проверить на '.', потом следующее число...
Ну если опускаться до "а вот восьмым символом строки после второго числа у Вас запятая, а там надо бы точку", то, конечно, со scanf-ом туго. А так - scanf вполне нормальная штука:
Код
#include <stdio.h>

void scan_ip(const char *str)
{
    unsigned IP[4];
    char ch;
    
    printf( "`%s' : ", str);

    int result = sscanf( str, "%u.%u.%u.%u%c", IP, IP+1, IP+2, IP+3, &ch);

    if(  result == 5 ) {
        printf( "extra character in string\n");
    } else if( result < 4) {
        printf( "not all numbers entered, may be numbers delimited with invalid character\n");
    } else if( IP[0] > 255 || IP[1] > 255 || IP[2] > 255 || IP[3] > 255) {
        printf( "numbers must be in range 0..255\n");
    } else {
        printf( "valid IP = %u.%u.%u.%u\n", IP[0], IP[1], IP[2], IP[3] );
    }
}


int main()
{
    scan_ip( "192.168.0.1" );
    scan_ip( "192.168.0" );
    scan_ip( "192168.0.1.2" );
    scan_ip( "192.168.0.1*" );
    scan_ip( "192.168,0.1" );
    scan_ip( "-192.168.0.1" );

    return 0;
}

Код
`192.168.0.1' : valid IP = 192.168.0.1
`192.168.0' : not all numbers entered, may be numbers delimited with invalid character
`192168.0.1.2' : numbers must be in range 0..255
`192.168.0.1*' : extra character in string
`192.168,0.1' : not all numbers entered, may be numbers delimited with invalid character
`-192.168.0.1' : numbers must be in range 0..255
Думаю, такой диагностики достаточно и нет смысла врукопашную atoi-чить.

Цитата(SSerge @ Jul 24 2009, 14:21) *
Ещё лучше сделать четыре отдельных поля ввода, по одному для каждого числа, проще будет и точек юзеру набирать не надо, они уже будут нарисованы на форме для ввода.
Это другое дело.
Заодно можно, как это уже реализовано то там, то сям - при выходе из поля если оно оставлено пустым - занулять.
ReAl
С пробелами хуже... "192. 168. 0.1" указанным фрагментом кода воспринимается нормально.
Можно попробовать сначала втащить в промежуточную строку, заодно ограничив длину 15 символов и сделав допустимыми только символы цифр и точку
Код
char tmpstr[16];
sscanf( str, "%15[0-9.]s", tmpstr);
и дальше разбирать уже tmpstr
Но по мере наворачивания изобретательности пользователя и необходимости объяснять ему, где он неправ, разжёвывая до выделения красным мест во введённой строке, может оказаться проще действительно вручную разбирать.
Andrew2000
счас уже самолет получится...
вопрос был про C++Builder - так почему не воспользоваться его средствами?
есть-же не только Edit, но и "MaskEdit" - не помню точно как называется - можно сразу задать допустимый для ввода шаблон.
Или что-то типа такого (давно с C++Builder слез):
Код
     TStringList* Strings = new TStringList();
     Strings->CommaText = Edit->Text; /*->CommaText ждет ',' - т.е. нужно задать разделителем точку*/
     if(Strings->Count==4) {
         /*разбор Strings, возможно, через StrToInt() или ->AsInteger*/
west329_
Цитата(Andrew2000 @ Jul 25 2009, 22:56) *
Или что-то типа такого (давно с C++Builder слез):


А чем сейчас пользуетесь если не секрет.
Я взял старенький С потомучто ему не нужна NET платформа, Builder потому что экономит львиную часть времени если работать с окнами мелкософта.

есть хорошая альтернатива ?
Andrew2000
Qt
http://www.qtsoftware.com/
defunct
Цитата(Andrew2000 @ Jul 25 2009, 22:56) *
есть-же не только Edit, но и "MaskEdit" - не помню точно как называется - можно сразу задать допустимый для ввода шаблон.

Защита от дурака это хорошо, но пользователь - всегда прав. Поэтому защиту от дурака надо делать после того как пользователь ввел все что хотел и нажал "ОК", а не до. В MaskEdit же эта защита сделана "до". В результате чего, MaskEdit - это неюзабельная вещь. Поди разбери что он (этот MaskEdit) от тебя хочет, и почему проглатывает символы. Кнопки давишь, а ничего не вводится. Фтопку.

Если программа не дает пользователю ввести символы которые он хочет ввести, то место такой программе - в корзине.


PS: Мелкософт тоже маладцы блин, при конфигурировании TCP/IP если ошибочно задатать octet IP адреса скажем не 30, а 300 - автоматически получим в поле ввода 255.
И вместо того чтобы раз нажать del - придется перевводить все число наново. Спрашивается а нафига такой ителлект вводилки нужен?
Andrew2000
Цитата(defunct @ Jul 28 2009, 04:02) *
В MaskEdit же эта защита сделана "до". В результате чего, MaskEdit - это неюзабельная вещь.

Если мне память не изменяет, то у MaskEdit можно задать обработчик события неправильного ввода - т.е. можно выводить подсказки, поправлять ввод, ...
defunct
Цитата(Andrew2000 @ Jul 30 2009, 10:16) *
Если мне память не изменяет, то у MaskEdit можно задать обработчик события неправильного ввода - т.е. можно выводить подсказки, поправлять ввод, ...

Есть такое событие, но оно не делает MaskEdit пригодным к пользованию... Представьте, что на каждую нажатую Вами кнопку будет вываливаться какое-то окно с подсказкой или что еще хуже, вместо набранного Вами 300 молча появится 255.....

Чем меньше подсказок в процессе ввода - тем лучше.

А вот развернутую подсказку - объясняющую что не так после ввода давать нужно, при этом, ни в коем случае не удалять и не менять того, что пользователь ввел.
Пользователь, он хоть и дурак, но не полный, и свою опечатку уж как-то сам догадается исправить.
XVR
Цитата(defunct @ Jul 31 2009, 02:04) *
Чем меньше подсказок в процессе ввода - тем лучше.

А вот разверную подсказку - объясняющую что не так после ввода давать нужно, при этом, ни в коем случае не удалять и не менять того, что пользователь ввел.
Пользователь, он хоть и дурак, но не полный, и свою опечатку уж как-то сам догадается исправить.
Это точно. Был опыт. Нужно было сделать ввод некой величины, причем MaskEdit такой маски не имел laughing.gif Попытка сделать дружелюбный ввод с коррекцией на лету успехом не увенчалась. Проверять что вводится прямо в процессе ввода и не пропускать символы, если получается не то, не вышло - оказалось, что есть много способов вести сразу 'не то' (например тупо скопировать через буфер обмена), и есть способы из 'не то' сделать самое то. Анализировать то, что получилось в процессе ввода в Edit'е и делать откат получилось, но результат был совершенно неюзабельный. cranky.gif

В конце концов было принято такое решение - фильтрация символов на вводе и блокировка тех, которые НИКОГДА не могут появится в правильном содержимом. А так же проверка того, что получается в Edit после каждой модификации, и если там получается 'не то', то весь Edit подсвечивается красным и блокируется кнопка 'Ok' на форме
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.