Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Проверка на число

335
04 октября 2005 года
enola
379 / / 25.01.2005
Добрый день!
Необходимо проверить строку, т.е. является ли она числом или нет, причем число может быть большим, порядка 13 знаков.

Поэтому вот такой вариант не проходит:
 
Код:
try
{
    int i;
    i = StrToInt(Строка);
}
catch (EConvertError&)
{
    // ошибка конвертации
    ;
}


Может есть какая-нить стандартная функция?
Страницы:
259
04 октября 2005 года
AlexandrVSmirno
1.4K / / 03.12.2004
Цитата:
Originally posted by enola
Добрый день!
Необходимо проверить строку, т.е. является ли она числом или нет, причем число может быть большим, порядка 13 знаков.

Поэтому вот такой вариант не проходит:
 
Код:
try
{
    int i;
    i = StrToInt(Строка);
}
catch (EConvertError&)
{
    // ошибка конвертации
    ;
}

Может есть какая-нить стандартная функция?


Функция isdigit.
Header File

ctype.h, mbstring.h

Category

Classification Routines

Prototype

int isdigit(int c);

int iswdigit(wint_t c);

int _ismbcdigit(unsigned int c);

Description

Tests for decimal-digit character.

isdigit is a macro that classifies ASCII-coded integer values by table lookup. The macro is affected by the current locale’s LC_CTYPE category. For the default C locale, c is a digit (0 to 9).

You can make this macro available as a function by undefining (#undef) it.

Return Value

isdigit returns nonzero if c is a digit.

_ismbcdigit returns true if and only if the argument c is a single-byte representation of an ASCII digit.

362
04 октября 2005 года
_kolyan
339 / / 03.12.2002
Цитата:
Originally posted by enola
Может есть какая-нить стандартная функция?



Можно написать свою нестандартную очень быстро, если стандартную не найдешь:

 
Код:
bool IsDigit(String S)
{
  for(int i = 0; i < S.Length(); i++)
    if(S < '0' || S > '9')
      return false;
  return true;
}


не помню только с 0 или с 1 в билдере символы в String нумеруются. Код неоптимальный, вероятно если бежать по строке не используя оператор [], а при помощи указателей то быстрее получится (а может и нет - не проверял)
259
04 октября 2005 года
AlexandrVSmirno
1.4K / / 03.12.2004
Цитата:
Originally posted by _kolyan
Можно написать свою нестандартную очень быстро, если стандартную не найдешь:

 
Код:
bool IsDigit(String S)
{
  for(int i = 0; i < S.Length(); i++)
    if(S < '0' || S > '9')
      return false;
  return true;
}


не помню только с 0 или с 1 в билдере символы в String нумеруются. Код неоптимальный, вероятно если бежать по строке не используя оператор [], а при помощи указателей то быстрее получится (а может и нет - не проверял)


Еще нужно добавить проверочку на "+","-","." или ","

362
04 октября 2005 года
_kolyan
339 / / 03.12.2002
Цитата:
Originally posted by AlexandrVSmirno
Еще нужно добавить проверочку на "+","-","." или ","



Ну надо, так надо. Это не сложно :)

335
04 октября 2005 года
enola
379 / / 25.01.2005
да я уж до этого дошел, вот по-моему самый оптимальный:
 
Код:
char *p;

for (int i = strlen(p) - 1; i >= 0; i--)
    if (!isdigit(p))
            ;


в функцию это дело запихивать не очень целесообразно, т.к. массив данных большой.
362
04 октября 2005 года
_kolyan
339 / / 03.12.2002
Цитата:
Originally posted by enola
да я уж до этого дошел, вот по-моему самый оптимальный:
 
Код:
char *p;

for (int i = strlen(p) - 1; i >= 0; i--)
    if (!isdigit(p))
            ;


в функцию это дело запихивать не очень целесообразно, т.к. массив данных большой.



Может и так, только непонятно сразу быстрее ли будет вызывать функцию isdigit для каждого символа, или просто проверять не равен ли этот символ одному из набора - ведь их не так уж и много, цифры, да несколько знаков.

А какое значение имеет длина массива для вызова функции - передается все равно только указатель независимо от длины.

335
04 октября 2005 года
enola
379 / / 25.01.2005
Цитата:
Originally posted by _kolyan

А какое значение имеет длина массива для вызова функции - передается все равно только указатель независимо от длины.



под понятием "массив" я имел ввиду не форму организации данных в языке программирования, а некоторую совокупность данных, в моем случае это файл, в котором порядка 35 тыщ. строк, каждую из которых необходимо проверить на число, а если каждый раз при проверки строки вызывать функцию, то на этот вызов буду терять время, зачем?

362
04 октября 2005 года
_kolyan
339 / / 03.12.2002
Цитата:
Originally posted by enola
под понятием "массив" я имел ввиду не форму организации данных в языке программирования, а некоторую совокупность данных, в моем случае это файл, в котором порядка 35 тыщ. строк, каждую из которых необходимо проверить на число, а если каждый раз при проверки строки вызывать функцию, то на этот вызов буду терять время, зачем?



Согласен, только тогда тем более нет смысла вызывать функцию (isdigit) для каждого символа, ведь из гораздо больше чем 35 тысяч.

335
05 октября 2005 года
enola
379 / / 25.01.2005
Цитата:
Originally posted by _kolyan
Можно написать свою нестандартную очень быстро, если стандартную не найдешь:

 
Код:
bool IsDigit(String S)
{
    for(int i = 0; i < S.Length(); i++)
        if(S < '0' || S > '9')
            return false;
    return true;
}


не помню только с 0 или с 1 в билдере символы в String нумеруются. Код неоптимальный, вероятно если бежать по строке не используя оператор [], а при помощи указателей то быстрее получится (а может и нет - не проверял)



не работает этот код, ошибку искать не стал, а сделать нужно вот так:

 
Код:
bool IsDigit(char *S)
{
    for (int i = strlen(S) - 1; i >= 0; i--)
            if(S < '0' || S > '9')
            return false;
    return true;
}
310
05 октября 2005 года
fellow
853 / / 17.03.2003
Цитата:
Originally posted by enola
Добрый день!
Необходимо проверить строку, т.е. является ли она числом или нет, причем число может быть большим, порядка 13 знаков.

Поэтому вот такой вариант не проходит:
 
Код:
try
{
    int i;
    i = StrToInt(Строка);
}
catch (EConvertError&)
{
    // ошибка конвертации
    ;
}


Может есть какая-нить стандартная функция?



А такой вариант не пойдёт?

 
Код:
try
{
    double i;
    i = StrToFloat(Строка);
}
catch (EConvertError&)
{
    // ошибка конвертации
    ;
}
299
05 октября 2005 года
3D Bob
885 / / 18.04.2005
Кстати очень не советую и спользовать исключения в качетве определения чего-то там. Их всегда надо использовать на крайний случай.
310
05 октября 2005 года
fellow
853 / / 17.03.2003
Цитата:
Originally posted by 3D Bob
Кстати очень не советую и спользовать исключения в качетве определения чего-то там. Их всегда надо использовать на крайний случай.



1) Обоснуй. И поясни, что такое "крайний случай".

2) Скажи это создателям StrToFloat - другого способа сообщить о неудаче преобразования строки в число, кроме выбрасывания исключения, у этой функции нет.

299
05 октября 2005 года
3D Bob
885 / / 18.04.2005
Всмысле их надо использовать когда без них не обойтись.
А и использовать я их не люблю потому что они не объясняют в какой строчке произошла ошибка, но и ставить на каждую команду отдельное исключение тоже на мой взгяд неверно.
Может просто я их не умею правильно использовать. Но практика показала, что лучше обходится без них.
Исключения изначально были созданы, только для обработки случаев не подчиняющихся стандартной логике.
310
05 октября 2005 года
fellow
853 / / 17.03.2003
Цитата:
Originally posted by 3D Bob
Всмысле их надо использовать когда без них не обойтись.
А и использовать я их не люблю потому что они не объясняют в какой строчке произошла ошибка, но и ставить на каждую команду отдельное исключение тоже на мой взгяд неверно.
Но практика показала, что лучше обходится без них.
Исключения изначально были созданы, только для обработки случаев не подчиняющихся стандартной логике.


Чепуху говоришь.

Цитата:
Originally posted by 3D Bob
Может просто я их не умею правильно использовать.


А вот это весьма вероятно :)

299
05 октября 2005 года
3D Bob
885 / / 18.04.2005
Цитата:
Originally posted by 3D Bob
Исключения изначально были созданы, только для обработки случаев не подчиняющихся стандартной логике.


Серьёзно тебе говорю))
Например деление на нуль или выход за пределы памяти.
Где-то читал.

310
05 октября 2005 года
fellow
853 / / 17.03.2003
Цитата:
Originally posted by 3D Bob
Серьёзно тебе говорю))
Например деление на нуль или выход за пределы памяти.
Где-то читал.



Ну-ну. Информационно агентство "ОБСДП" - Одна Баба Сказала, Другая Повторила :)

Цитирую по книге Бьерна Страуструпа "Язык программирования С++. Третье издание" ("Невский Диалект", "Издательство БИНОМ", 1999г.):

[FONT=times new roman][COLOR=purple][SIZE=3]Фундаментальная идея состоит в том, что функция, обнаружившая проблему, но не знающая как её решить, генерирует (throw) исключение в надежде, что вызвавшая её (непосредственно или косвенно) функция сможет решить возникшую проблему. Функция, которая хочет решать проблемы данного типа, может указать, что она перехватывает (catch) такие исключения.[/SIZE][/COLOR][/FONT]

И оттуда же:

[FONT=times new roman][COLOR=purple][SIZE=3]Механизм обработки исключений предоставляет альтернативу традиционным методав в тех случаях, когда они недостаточны, не элегантны и подвержены ошибкам. Он предоставляет способ явного отделения кода обработки ошибки от "обычного" кода, делая таким образом программу более читабельной и лучше подходящей для различных инструментальных средств. Механизм обработки исключений предоставляет более регулярный способ обработки ошибок, упрощая в результате взаимодействие между отдельно написанными фрагментами кода.[/SIZE][/COLOR][/FONT]

3
05 октября 2005 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by 3D Bob
А и использовать я их не люблю потому что они не объясняют в какой строчке произошла ошибка, но и ставить на каждую команду отдельное исключение тоже на мой взгяд неверно.


Ты действительно не умеешь их готовить.
Простейший вариант:

 
Код:
if(pointer == 0)
    throw "pointer == 0 in line 24";

Обычно это оборачивается в макрос:
 
Код:
#define LINE_STR2(x) #x
#define LINE_STR(x) LINE_STR2(x)
#define ASSERT(exp) if(!(exp)) throw #exp" in line " LINE_STR(__LINE__)

А кто тебе объясняет в какой строчке произошла ошибка без использования исключений?
259
05 октября 2005 года
AlexandrVSmirno
1.4K / / 03.12.2004
Цитата:
Originally posted by fellow
А такой вариант не пойдёт?

 
Код:
try
{
    double i;
    i = StrToFloat(Строка);
}
catch (EConvertError&)
{
    // ошибка конвертации
    ;
}


Если внимательно читать обсуждение то видно, что автор начал именно с этого варианта и он ему не подошел. Насколько я понял важна скорость работы. Посмотрим с этой позиции:
1. StrToFloat кроме проверки на валидность осуществляет перевод в плавающее. Быстрее ли это чем просто проверка на валидность? Далеко не уверен.
2. Генерация исключения занимает тоже достаточно много времени и работает медленне, чем if ... then.
Следовательно приобретая в минимальности написания кода мы теряем в производительности. Так что думаю код

 
Код:
bool IsDigit(String S)
{
    for(int i = 0; i < S.Length(); i++)
        if(S < '0' || S > '9')
            return false;
    return true;
}

по любому будет работать быстрее.
310
05 октября 2005 года
fellow
853 / / 17.03.2003
Цитата:
Originally posted by AlexandrVSmirno
Если внимательно читать обсуждение то видно, что автор начал именно с этого варианта и он ему не подошел. Насколько я понял важна скорость работы. Посмотрим с этой позиции:
1. StrToFloat кроме проверки на валидность осуществляет перевод в плавающее. Быстрее ли это чем просто проверка на валидность? Далеко не уверен.
2. Генерация исключения занимает тоже достаточно много времени и работает медленне, чем if ... then.
Следовательно приобретая в минимальности написания кода мы теряем в производительности. Так что думаю код
 
Код:
bool IsDigit(String S)
{
    for(int i = 0; i < S.Length(); i++)
        if(S < '0' || S > '9')
            return false;
    return true;
}

по любому будет работать быстрее.



Если внимательно читать обсуждение, то видно, что автор начал вовсе не с этого варианта, а с варианта StrToInt. Чувствуете разницу?
Почему ему не подошёл StrToInt? Да потому что строка у него длинная, содержит "порядка 13 знаков". Нетрудно убедиться, что такое большое число в границы диапазона int не уместится, и произойдёт сбой, даже если строка и содержит одни цифры.

И с чего вы взяли, что надёжность и удобочитаемость отлаженной библиотечной функции и стандартного языкового механизма стоят мифического выигрыша в производительности? Что выигрыш мифический, нетрудно убедиться, слегка пораскинув мозгами. Самый медленный элемент программы - это прокладка между стулом и клавиатурой. Юзер не заметит даже 10-миллисекундной разницы в выполнении двух операций. Ладно бы эта проверка выполнялась непрерывно в цикле 10000000 раз, а так...

259
05 октября 2005 года
AlexandrVSmirno
1.4K / / 03.12.2004
Цитата:
Originally posted by fellow
Если внимательно читать обсуждение, то видно, что автор начал вовсе не с этого варианта, а с варианта StrToInt. Чувствуете разницу?
Почему ему не подошёл StrToInt? Да потому что строка у него длинная, содержит "порядка 13 знаков". Нетрудно убедиться, что такое большое число в границы диапазона int не уместится, и произойдёт сбой, даже если строка и содержит одни цифры.

И с чего вы взяли, что надёжность и удобочитаемость отлаженной библиотечной функции и стандартного языкового механизма стоят мифического выигрыша в производительности? Что выигрыш мифический, нетрудно убедиться, слегка пораскинув мозгами. Самый медленный элемент программы - это прокладка между стулом и клавиатурой. Юзер не заметит даже 10-миллисекундной разницы в выполнении двух операций. Ладно бы эта проверка выполнялась непрерывно в цикле 10000000 раз, а так...


Взял я вот с чего:
1.

Цитата:
Originally posted by enola
в моем случае это файл, в котором порядка 35 тыщ. строк, каждую из которых необходимо проверить на число

. Т.е. эта проверка выполняется в цикле и по крайней мере 35000 раз. Так что, какой бы Олвейз не лежал между стулом и клавой это уже существенно.
2. Ваша удобочитаемая, стандартная, библиотечная функция предназначена совсем не для проверки на валидность строки, а для перевода ее в число. Т.е. вы сами, заведомо , порождаете ошибочную ситуацию и делаете массу не нужного, только из - за того, что влом подумать и написать 4 оператора. Эта функция,в смысле понятности программы, только запутывает ситуацию и следовательно не дает преимущества даже в ясности и прозрачности алгоритма.
3. Далеко не все программы и не всегда имеют интерфейс с пользователем.
4. Исскуство программирования и состоит в том, чтобы в каждый момент проектирования и написания программы искать и находить оптимальные решения. Только тогда Ваш проект будет действительно успешным.

335
05 октября 2005 года
enola
379 / / 25.01.2005
Цитата:
Originally posted by AlexandrVSmirno
Взял я вот с чего:
1. . Т.е. эта проверка выполняется в цикле и по крайней мере 35000 раз. Так что, какой бы Олвейз не лежал между стулом и клавой это уже существенно.
2. Ваша удобочитаемая, стандартная, библиотечная функция предназначена совсем не для проверки на валидность строки, а для перевода ее в число. Т.е. вы сами, заведомо , порождаете ошибочную ситуацию и делаете массу не нужного, только из - за того, что влом подумать и написать 4 оператора.
3. Далеко не все программы и не всегда имеют интерфейс с пользователем.
4. Исскуство программирования и состоит в том, чтобы в каждый момент проектирования и написания программы искать и находить оптимальные решения. Только тогда Ваш проект будет действительно успешным.



полностью согласен. :D

вот тот способ с исключением я не сам придумал, просто мне его предложили, а я уже начал искать стандартную функцию, т.к. писать код, который будет работать на исключении не совсем правильно, сугубо мое мнение.

3
05 октября 2005 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by AlexandrVSmirno

1. Т.е. эта проверка выполняется в цикле и по крайней мере 35000 раз. Так что, какой бы Олвейз не лежал между стулом и клавой это уже существенно.
2. Ваша удобочитаемая, стандартная, библиотечная функция предназначена совсем не для проверки на валидность строки, а для перевода ее в число. Т.е. вы сами, заведомо , порождаете ошибочную ситуацию и делаете массу не нужного, только из - за того, что влом подумать и написать 4 оператора.
3. Далеко не все программы и не всегда имеют интерфейс с пользователем.
4. Исскуство программирования и состоит в том, чтобы в каждый момент проектирования и написания программы искать и находить оптимальные решения. Только тогда Ваш проект будет действительно успешным.



Использовать исключения для реализации ветвления стандартного алгоритма - плохая идея.
Исключения стоит использовать там, где действительно идет отклонение от нормального выполнения.
Например, отсутствие файла при его парсинге - это исключение.
Но отсутствие файла при проверке его наличия на диске - это не исключение, а вариант нормального алгоритма, т.е. просто ветвление.

Т.о. если задачей автора топика было бы перевод строки в число - то исключение здесь уместно. Но если автор пытается проверить можно ли провести такое преобразование, то исключение уже неуместно. Поэтому с пунктом 2 я согласен.

С пунктом 4 несогласен:
1) оптимальные решения нужно искать в процессе оптимизации, а не "в каждый момент проектирования и написания программы";
2) оптимальность имеет критерии и невсегда эти критерии - это скорость.

259
05 октября 2005 года
AlexandrVSmirno
1.4K / / 03.12.2004
Цитата:
Originally posted by Green
С пунктом 4 несогласен:
1) оптимальные решения нужно искать в процессе оптимизации, а не "в каждый момент проектирования и написания программы";


Вот здесь я не согласен. Есть, на мой взгляд очень хорошее правило: "Если хочется оптимизировать, не оптимизируй". Я понимаю его именно так, что не стоит оптимизацию выделять в отдельный процесс, а продумывать все на всех этапах производства программы. А уж ежели что-то хочется менять, то есть механизм версий.

Цитата:
Originally posted by Green
2) оптимальность имеет критерии и невсегда эти критерии - это скорость.


Полностью согласен. Именно поэтому и употребил слово оптимальность, а не скорость.

335
05 октября 2005 года
enola
379 / / 25.01.2005
Цитата:
Originally posted by Green

Т.о. если задачей автора топика было бы перевод строки в число - то исключение здесь уместно. Но если автор пытается проверить можно ли провести такое преобразование, то исключение уже неуместно. Поэтому с пунктом 2 я согласен.



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

3
05 октября 2005 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by AlexandrVSmirno
Я понимаю его именно так, что не стоит оптимизацию выделять в отдельный процесс, а продумывать все на всех этапах производства программы.


Продумать все невозможно по определению, а в большинстве случаев совершенно бессмыслено.
Куда более продуктивный подход не "водопад", а итерационный.

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

Цитата:
Originally posted by AlexandrVSmirno
А уж ежели что-то хочется менять, то есть механизм версий.


Не совсем понял что имелось в виду... Итерационность? :)

259
05 октября 2005 года
AlexandrVSmirno
1.4K / / 03.12.2004
Цитата:
Originally posted by Green
Продумать все невозможно по определению, а в большинстве случаев совершенно бессмыслено.
Куда более продуктивный подход не "водопад", а итерационный.


Согласен. Еще Козьма Прутков говаривал:"Нельзя объять необъятное". Да и проектирование сверху вниз еще никто не отменял.
Выделять же оптимизацию в отдельный процесс, всетаки, по моему, на этой стадии не нужно.

Цитата:
Originally posted by Green
Во-первых, как узнать, что именно оптимизировать?
Для этого существует предшествующий процесс - профайлинг.
Во-вторых, как понять, что оптимизация действительно осуществлена?
Для этого осуществляется повторный профайлинг.
Понятно, что профилировать надо уже существующую и работающую систему.


Я имел ввиду как раз стадию проектирвания и написания первой версии системы. Всетаки продумывать нужно по максимуму возможного. Чтобы в последствии оптимизировать как можно меньше. Это сокращает затраты.

Цитата:
Originally posted by Green
Не совсем понял что имелось в виду... Итерационность? :)


Для начала оговорюсь, что все сказанное применимо не для всех и не всегда, но случается и довольно часто:
Имелось ввиду, что процесс оптимизации на стадии производства программного продукта, может приобрести лавинообразный, бесконечный, не управляемый характер, требующий все болшего и большего изменения текстов и даже концепций, заложенных в продукт. В результате не появляется даже первой версии. И вот тогда и приходит на помощь механизм версий. Зафиксировали 1-ую. Провели профайлинг, оптимизацию, дополнения и т.д. и получили 2-ую. Но надо понимать, что это уже другой программный продут. Ну и т.д. и т.п.

335
26 апреля 2006 года
enola
379 / / 25.01.2005
Добрый вечер!
Поднимаю данный вопрос только в образовательных целях! :)

Вот такое решение мне тогда предложили:
 
Код:
try
    {
        double i;
        i = StrToFloat(Строка);
    }
    catch (EConvertError&
    {
        // ошибка конвертации
      ;
    }


вот что я нашел в справке Билдера:
Цитата:

TryStrToFloat

Converts a given string to a floating-point value with Boolean success code.

extern PACKAGE bool __fastcall TryStrToFloat(const AnsiString S, Extended &Value);

extern PACKAGE bool __fastcall TryStrToFloat(const AnsiString S, double &Value);
extern PACKAGE bool __fastcall TryStrToFloat(const AnsiString S, float &Value);

Description

Use TryStrToFloat to convert an AnsiString, S, to a floating-point value. S must consist of an optional sign (+ or -), a string of digits with an optional decimal point, and an optional mantissa. The mantissa consists of 'E' or 'e' followed by an optional sign (+ or -) and a whole number. Leading and trailing blanks are ignored.

The DecimalSeparator global variable defines the character that must be used as a decimal point. Thousand separators and currency symbols are not allowed in the string. If S doesn't contain a valid value, TryStrToFloat returns Default.

TryStrToFloat places the result in Value, and returns true if the conversion was successful, false otherwise.



из этого следует, что можно сделать вот так:

 
Код:
double i;

    if (!TryStrToFloat(Строка, i))
        // Не конвертируется

И не надо обрабатывать исключение.

Хочу узнать Ваше мнение господа.
362
27 апреля 2006 года
_kolyan
339 / / 03.12.2002
Чтобы узнать подходщая это функция или нет, нужно глянуть на ее исходники. А там написано, что она всего только возвращает результат функции TextToFloat. Т.о. имеем вмсто одного вызова функции - два, и соответственно два раза передаются парметры. TextToFloat инициализирует несколько переменных и использует контрольное слово процессора.

Получается много работы...
3
27 апреля 2006 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by LM(AL/M)
и другие варианты...

Эх люди кто учил вас так писать?...

Вот:
Код:
unsigned char d;
bool isLongNum(char *s)
{
  while ( *s )  // -- пока не конец строки (т.е. не 0)
  {
    d = *s - '0';
    if (d > 9)  return false;
    s++;
  }

  return true;
}


А тебя то кто учил так писать?
Объявлять глобальные переменные, использовать неконстантный указатель в качестве аргумента?
Кроме того твой пример нерабочий при символах до '0', они у тебя тоже числа.
Кстати, а для чего вообще переменная (да ещё и глобальная) и операция вычитания?

Кроме того, в примере от _kolyan используется некоторый класс String, а не char*. Поэтому вполне возможно, что разындексирование - единственный или оптимальный путь обращения к символам.
Единственный недочет в его примере - передача объекта не по ссылке.

Вот моя модификация твоего примера:

 
Код:
bool isLongNum(const char *s)
{
  while(*s>='0' && *s<='9') s++;
  return (*s=='\0');
}

Здесь исправлена ошибка для символов меньше '0',
проведена оптимизация:
1) нет лишней переменной,
2) нет операции вычитания,
3) на типичной итерации всего две проверки, а не три.
324
27 апреля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by LM(AL/M)
и другие варианты...

Эх люди кто учил вас так писать?...

Вот:
Код:
unsigned char d;
bool isLongNum(char *s)
{
  while ( *s )  // -- пока не конец строки (т.е. не 0)
  {
    d = *s - '0';
    if (d > 9)  return false;
    s++;
  }

  return true;
}



Значение меньше 0 проверять не надо,
Но код, предложенный Green на много элегантнее

324
27 апреля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by LM(AL/M)
нефига он не элегантнее, по крайней меря не вижу в чем элегантность. может объяснишь ?



он использует возможности языка

324
27 апреля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by LM(AL/M)
не знаю поверишь ты или нет но мой код тоже использует возможности языка, но кроме того он еще решает задачу максимально эффективным способом а ваш вариант -- совсем не обязательно



:)

335
27 апреля 2006 года
enola
379 / / 25.01.2005
Что Вы тут устроили балаган, тут решаем задачи, а не дискутируем что у кого больше, лучше, etc.
324
27 апреля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by LM(AL/M)
нет мы как раз не просто решаем задачи а пытаемся найти наилучшее решение для каждой задачи



+1

3
27 апреля 2006 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by LM(AL/M)
я бы рекомендовал как следует разобраться в коде прежде чем обвинять в его неработоспособности...
а насчет глобальных переменных -- мне так нравится, если не предполагается использовать ф-цию в многопоточных прилж-х -- это эффективнее


Ах да, не заметил unsigned...
Значит, у твоего кода ещё один минус - он интуитивно не ясен. зачем надо было заменять сравнение вычитанием? Для оптимизации? Но её нет, операции сравнения и вычитания соизмеримы по времени выполнения. Т.о. ты не избавился от сравнения, а сделал его неявным, чем усложнил читабельность кода. И того мы имеем на типичной итерации три операции, хотя можно ограничиться двумя, исключив из итерации проверку на конец строки. Ну и где же тут "максимальная эффективность"?

Что же касается глобальных переменных, то само их наличие - плохой тон, а уж использование там, где это совсем не требуется - совсем плохо. Хорошим стилем считается определять переменные непосредственно перед их использованием. Что же касается эффективности исполльзования глобальных переменных - так это туфта. Попробуй доказать обратное, кстати, указав критерий эффективности.

Цитата:
Originally posted by LM(AL/M)
на остальные вопр. думаю ты сможешь ответить сам


Осталось непонятным, зачем нужна глобальная переменная и замена операции сравнения операцией вычитания. :)

Цитата:
Originally posted by LM(AL/M)
да и кстати твоя модификация моего примера сводит на нет все преимущества моего примера )))


А они были? Какие?

Цитата:
Originally posted by LM(AL/M)

да и еще встречный вопрос: почему для тебя принципиально передавать именно константный указатель ? ф-ция же не модифицирует строку...


Именно потому, что не модифицирует, надо передавать указатель на константу, иначе код не будет работать в таких случаях:

 
Код:
const char str[] = "123";
    bool b = isLongNum(str);
3
27 апреля 2006 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by LM(AL/M)
по поводу оптимизации:
1. использование вычитания ==> у меня явным образом видно выполнение двух операций, у тебя их может быть три (а уж по числу пересылок между памятью и регистрами -- даже более существенная разница)


Ты что-то не в ту степь...
Смотри у тебя на типичной итерации:
while ( *s ) - раз операция (сравнение)
d = *s - '0'; - два операция (вычитание, про присвоение молчу)
if (d > 9) - три операция (сравнение)

В моём примере:
while(*s>='0' && *s<='9') - две операции сравнения (*s>='0' и *s<='9')

Третья проверка не включена в итерацию и поэтому выполняется всего один (!) раз.

Т.о. имеем для строки длинной n+1 (1 - это для учета завершающего нуля):
твой пример - 3n+1
мой пример - 2(n+1)+1

решаем неравенство: 3n+1 < 2(n+1)+1
и получаем, что лишь для n < 2 твой пример более эффективный, т.е. если мы хотим проверить строки типа "1", "2", "3" и т.д. Но для таких случаев можно предложить и более оптимальный алгоритм :)
В остальных же случиях (n>2) мой алгоритм оптимальнее.

Цитата:
Originally posted by LM(AL/M)
2. глобальная переменная используется для экономии на стековых операциях, если не нравится можно сделать локальную статик-переменную


И как же она влияет на стековые операции :)

Цитата:
Originally posted by LM(AL/M)
3. проверка на конец строки позволяет нам избавиться от использования strlen() -- сам понимаешь сколько операций это экономит,


Ты так и не понял. Можно обойтись без проверки на конец строки в итерации. Я же тебе показал как это сделать...
И strlen тут не при чем.

Цитата:
Originally posted by LM(AL/M)
у вас там у кгого то еще был вариант с классом String и свойством.


У нас тут? А у тебя это где?

3
27 апреля 2006 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by LM(AL/M)

а на счет проверки на ноль -- так это операция проверки завершения цикла -- от нее ты никак не избавишься, я имею в виду что всегда есть некая проверка -- на ноль или не на ноль -- не важно; так что и у тебя такая поверка тоже есть, не сомневайся )))


Да я в курсе, что у меня она есть. Но ты понимаешь разницу между проверкой в цикле и за пределами цикла?
Объясняю: проверка в цикле будет выполняться столько раз, сколько будет итераций, проверка за пределами цикла будет выполняться один раз!

Цитата:
Originally posted by LM(AL/M)

ты забыл про операцию && ))

Т.о. основа моего цикла -- 2 операции, основа твоего -- 3 вот и все


if(*s>='0') if(*s<='9') {} - это две операции,
а if(*s>='0' && *s<='9') {} - это уже три? :D

Так где ты увидел в моем цикле три операции?
А у тебя как раз три. Мне повторить какие?
Две проверки и одно вычитание.

Цитата:
Originally posted by LM(AL/M)

-- хоть это уже и не относится к нашей задаче, но влияет так что их (стек-х оп-й) попросту нет ))


Стек есть всегда, а разница будет лишь в смещении. Вычесть 4 или вычесть 8 - это большая разница по производительности? :D

Цитата:
Originally posted by LM(AL/M)

ну ка продемонстрируй еще раз, а то не хочется прокручивать все посты...


 
Код:
bool isLongNum(const char *s)
{
  while(*s>='0' && *s<='9') s++;  // в цикле проверки нет
  return (*s=='\0');              // всегда одна(!) проверка за пределами цикла
}
3
27 апреля 2006 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by LM(AL/M)
как можно организовать цикл если проверка его завершения -- за пределами цикла?


М-да...
Ты пример мой смотрел?
Завершение цикла не обязательно должно быть жестко связано с концом строки.

Цитата:
Originally posted by LM(AL/M)

ну а где ты у меня увидел три операции ?


Я в третий раз(!) повторяю:
while ( *s ) - раз операция (сравнение)
d = *s - '0'; - два операция (вычитание, про присвоение молчу)
if (d > 9) - три операция (сравнение)

Цитата:
Originally posted by LM(AL/M)

не вижу ничего смешного и вобще хватит переходить на личности...


На личности? Личность это 4 или 8, или может улыбка в конце? :)

Цитата:
Originally posted by LM(AL/M)

mov ax, [bp + N] -- есть вычисление адреса аргумента
mov ax, [addr] -- нету
есть разница ?


Ага, весомая разница... :)
Только так mov ax, [addr] не будет,
в обоих случаях будет mov ax, [bp + N]
Можешь проверить.

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

Цитата:
Originally posted by LM(AL/M)

while ((unsigned) (*s - '0') < 9) s++;
return *s == 0;

-- наиболее компактный код, не проигрывающий по производительности твоему,
а если строка длинная и удовлетворяет исходному условию (т.е. явл-ся числом), то и выигрывающий
[/code]


А чем этот код отличается от моего?
Тем что одну из операций сравнения заменил вычитанием?
Видимо, для запутывания верояного противника... :)

Выигрывающий у кого?

3
27 апреля 2006 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by LM(AL/M)
не будет если использ. глобальную переменную


А я говорю будет! :)
Докажи примером.

Цитата:
Originally posted by LM(AL/M)

а я и не закапывался, я сразу привел более-менее оптимальный код а вы начали мудрить с strlen(), классом String и т д


Мы? Мы это кто?
Уже "более-менее оптимальный"? Раньше было "наиболее эффективный".

Цитата:
Originally posted by LM(AL/M)

тем хотя бы что мой код сгенерирует меньше операций условного перехода


Угу... только на скорости это никак не отразится.
Кроме пограничных случаев, на них твой код проскальзывает, т.к. если *s < '0', то второя проверка не нужна, а в твоем случае все равно выполянятся обе операции. Но это мелочи.

Цитата:
Originally posted by LM(AL/M)

а ты не понял ?


Нет не понял.

3
27 апреля 2006 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by LM(AL/M)
ладно уже начинается не обсуждение кода а выяснение отношений сворачиваем тему


Ок. :)

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог