PRB: реализация atoi
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 28.08.02 12:46
Оценка:
Итак, в качестве затравки одна довольно тривиальная задачка (крутым гуру просьба не беспокоиться , а вот те, кому интересно — дерзайте).

Задача:

Написать функцию, которая конвертирует строку (char*) в число (int), то есть реализацию atoi. Прототип функции:


int new_atoi(const char* string);


Условия:

0. Язык программирования — С/С++.

1. Запрещается пользоваться любыми библиотечными функциями (типа strlen и пр.), а также сторонними классами и иже с ними. В двух словах, задача должна решаться встроенными средствами языка С/С++.

2. Пробельные символы в начале строки (пробел и символ табуляции — \t) опускаются.

3. Знак числа должен сохраняться.

4. Возвращаемое значение — либо 0 в случае ошибки, либо часть числа до момента встречи ошибки (например, если строка содержит значение "1024u78", то возвращаемым значением будет число 1024

5. Передаваемая строка содержит числа в десятичном формате.

Набор тестов:


new_atoi("12345")       =  12345
new_atoi("22345")       =  22345
new_atoi("-12345")      = -12345
new_atoi("--12345")     =  0
new_atoi("+12345")      =  12345
new_atoi("   12345")    =  12345
new_atoi("   12345   ") =  12345
new_atoi("\t12345")     =  12345
new_atoi(NULL)          =  0
new_atoi("-r12345")     =  0
new_atoi("123w45")      =  123
new_atoi("a12345")      =  0


Дерзайте. За лучшую реализацию — приз (более интересная задача)
Re: PRB: реализация atoi
От: Yampolski_Nikita Россия http://nikitay.pisem.net
Дата: 28.08.02 13:13
Оценка:
Здравствуйте Flamer, Вы писали:

F>Итак, в качестве затравки одна довольно тривиальная задачка (крутым гуру просьба не беспокоиться , а вот те, кому интересно — дерзайте).


F>Задача:


F>Написать функцию, которая конвертирует строку (char*) в число (int), то есть реализацию atoi. Прототип функции:



F>
F>int new_atoi(const char* string);
F>


F>Условия:


F>0. Язык программирования — С/С++.


F>1. Запрещается пользоваться любыми библиотечными функциями (типа strlen и пр.), а также сторонними классами и иже с ними. В двух словах, задача должна решаться встроенными средствами языка С/С++.


F>2. Пробельные символы в начале строки (пробел и символ табуляции — \t) опускаются.


F>3. Знак числа должен сохраняться.


F>4. Возвращаемое значение — либо 0 в случае ошибки, либо часть числа до момента встречи ошибки (например, если строка содержит значение "1024u78", то возвращаемым значением будет число 1024


F>5. Передаваемая строка содержит числа в десятичном формате.


F>Набор тестов:



F>
F>new_atoi("12345")       =  12345
F>new_atoi("22345")       =  22345
F>new_atoi("-12345")      = -12345
F>new_atoi("--12345")     =  0
F>new_atoi("+12345")      =  12345
F>new_atoi("   12345")    =  12345
F>new_atoi("   12345   ") =  12345
F>new_atoi("\t12345")     =  12345
F>new_atoi(NULL)          =  0
F>new_atoi("-r12345")     =  0
F>new_atoi("123w45")      =  123
F>new_atoi("a12345")      =  0

F>


F>Дерзайте. За лучшую реализацию — приз (более интересная задача)


ВСЕ БАЛЫ ТВОИ ! что тут ? учеба ? или кто самый крутой ?
вот баталии будут )
_____________
Yampolski Nikita
Re[2]: PRB: реализация atoi
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 28.08.02 13:18
Оценка:
Здравствуйте Yampolski_Nikita, Вы писали:

[покоцано]

YN>ВСЕ БАЛЫ ТВОИ ! что тут ? учеба ? или кто самый крутой ?

YN>вот баталии будут )

Да нет, просто задачки для тех, кому интересно. Кстати, а где ваша реализация?

З.Ы. И не забывайте про оверквотинг
Re[3]: PRB: реализация atoi
От: Yampolski_Nikita Россия http://nikitay.pisem.net
Дата: 28.08.02 13:22
Оценка:
Здравствуйте Flamer, Вы писали:

F>Здравствуйте Yampolski_Nikita, Вы писали:


F>[покоцано]


YN>>ВСЕ БАЛЫ ТВОИ ! что тут ? учеба ? или кто самый крутой ?

YN>>вот баталии будут )

F>Да нет, просто задачки для тех, кому интересно. Кстати, а где ваша реализация?


F>З.Ы. И не забывайте про оверквотинг




а я тут как-раз пишу другую программку, а в почту сыпятсы топики форума ) только мне денежку платят )))
_____________
Yampolski Nikita
Re: PRB: реализация atoi
От: Кодт Россия  
Дата: 28.08.02 14:01
Оценка:
Здравствуйте Flamer, Вы писали:

F>Итак, в качестве затравки одна довольно тривиальная задачка (крутым гуру просьба не беспокоиться , а вот те, кому интересно — дерзайте).


вот вы хихи-хаха, а мне пришлось портировать все wcs***() ручками!
Перекуём баги на фичи!
Re[2]: PRB: реализация atoi
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 28.08.02 14:14
Оценка:
Здравствуйте Кодт, Вы писали:

К>Здравствуйте Flamer, Вы писали:


F>>Итак, в качестве затравки одна довольно тривиальная задачка (крутым гуру просьба не беспокоиться , а вот те, кому интересно — дерзайте).


К>вот вы хихи-хаха, а мне пришлось портировать все wcs***() ручками!


Я совсем не хихи-хаха Я собственно, именно для этого и завел разговор о задачках, чтобы при случае проблем с портированием wcs***() не возникало

А если серьезно, то тренировка/проверка знаний/умений/навыков еще никому не вредила...
Re: PRB: реализация atoi
От: tks Россия  
Дата: 28.08.02 14:43
Оценка:
Держите, вроде как все тесты проходит:


#include "stdafx.h"
#include <stdio.h>
#include <string.h>


int new_atoi(const char* string)
{
    if (string == NULL) return 0;
    int s = 0, f = 1;
    for (int i = 0; string[i]; i++)
    {
        if ((string[i] >= '0') && (string[i] <= '9')) 
        { s *= 10; s += (string[i] - '0'); } 
        else if (string[i] == ' ' || string[i] == '\t')
        { if (s == 0) continue; else break; }
        else if (string[i] == '-')
        { if (s == 0 && f == 1) { f = -1; continue; } else break; }
        else if (string[i] == '+')
        { if (s == 0 && f == 1) continue; else break; }
        else break;
    }
    return f*s;
}


int main(int argc, char* argv[])
{
    if (new_atoi("12345") !=  12345) printf("\nError\n");
         else if (new_atoi("22345")       !=  22345) printf("\nError\n");
    else if (new_atoi("-12345")      != -12345) printf("\nError\n");
    else if (new_atoi("--12345")     !=  0) printf("\nError\n");
    else if (new_atoi("+12345")      !=  12345) printf("\nError\n");
    else if (new_atoi("   12345")    !=  12345) printf("\nError\n");
    else if (new_atoi("   12345   ") !=  12345) printf("\nError\n");
    else if (new_atoi("\t12345")     !=  12345) printf("\nError\n");
    else if (new_atoi(NULL)          !=  0) printf("\nError\n");
    else if (new_atoi("-r12345")     !=  0) printf("\nError\n");
    else if (new_atoi("123w45")      !=  123) printf("\nError\n");
    else if (new_atoi("a12345")      !=  0) printf("\nError\n");
    else if (new_atoi("-12345\t")      != -12345) printf("\nError\n");
    else printf("\nOk\n");

    return 0;
}
Программист — это не тот, кто пишет программы, а тот, чьи программы работают.
Re: PRB: реализация atoi
От: Proph  
Дата: 29.08.02 03:10
Оценка:
Здравствуйте Flamer, Вы писали:

Еще вариант

[code]
#define ISDIGIT(c) ((c >= '0') && (c <= '9') ? 1 : 0)
#define ISSPACE(c) ((c == ' ') || (c == '\t') ? 1 : 0)
#define SIG(c) ((c == '-') ? -1 : ((c == '+') ? 1 : 0))
int new_atoi(const char *str)
{
int ret = 0, f = 0;
for( ;(str != NULL) && (*str != '\0'); str++){
if(ISSPACE(*str))
continue;
else if(SIG(*str) != 0) {
if(f == 0)
f = SIG(*str);
else
break;
}
else if(ISDIGIT(*str)){
ret = 10 * ret + (*str — '0');
f = (f == -1 ? -1 : 1);
}
else
break;
}

return f * ret;
}
[\code]

добавлено несколько проверок
[code]
new_atoi("1-2345\t") = 1
new_atoi("0-2345\t") = 0
new_atoi("+-2345\t") = 0
[\code]
Пришел, Увидел, ... Наследил.
Proph.
Re: PRB: реализация atoi
От: Vampire Россия  
Дата: 29.08.02 06:14
Оценка:
Правда чтот дофига у меня проверок получилось

int new_atoi(char *string)
{    
    char znak=0;
    int res = 0;
    if (string == NULL) return res;
    for (int i=0; string[i]; i++)
    {
        if (res == 0)
        {
            if (string[i] == '-')
            {
                if (znak != 0) return 0;
                znak = -1;                
                continue;
            }
            if (string[i] == '+')
            {
                if (znak != 0) return 0;
                znak = 1;
                continue;
            }
        }

        if ((string[i] == ' ') || (string[i] == '\t'))
            continue;
        if ((string[i] < 48) || (string[i] > 48+9))
            break;
        res = res * 10 + string[i] - 48;
    }
    if (znak == -1) res *= znak;
    return res;
}
Если долго мучиться что нибудь получится
Re[2]: PRB: реализация atoi
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 29.08.02 06:19
Оценка:
Здравствуйте tks, Вы писали:

tks>Держите, вроде как все тесты проходит:



[код покоцан]

Если вкратце — ваш вариант не совсем удачен Можно упростить, например, непонятно, зачем использовать две временных переменных (f и s) И навскидку — много лишних проверок...
Re[2]: PRB: реализация atoi
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 29.08.02 06:23
Оценка:
Здравствуйте Proph, Вы писали:

P>Здравствуйте Flamer, Вы писали:


P>Еще вариант


[код покоцан]

Значится так: знак числа можно (и нужно) устанавливать один раз перед возвратом из функции. Далее — можно (и прозрачней) обойтись без цикла for (а вот чего использовать — думайте ). И еще — в определении макросов ошибка (если внимательно посмотрите — поймете, почему).
Re[2]: PRB: реализация atoi
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 29.08.02 06:26
Оценка:
Здравствуйте Vampire, Вы писали:

V>Правда чтот дофига у меня проверок получилось


[код покоцан]

А немножко упростить код? Хотя бы вместо 48+9 написать 57? Ведь не каждый оптимизирующий компилятор это вам соптимизирует...
Re[3]: PRB: реализация atoi
От: Proph  
Дата: 29.08.02 06:58
Оценка:
Здравствуйте Flamer, Вы писали:

F>Здравствуйте Proph, Вы писали:


P>>Здравствуйте Flamer, Вы писали:


P>>Еще вариант


F>[код покоцан]


F>Значится так: знак числа можно (и нужно) устанавливать один раз перед возвратом из функции.

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

F>Далее — можно (и прозрачней) обойтись без цикла for (а вот чего использовать — думайте ).

Чем ?

F>И еще — в определении макросов ошибка (если внимательно посмотрите — поймете, почему).

Где?
Пришел, Увидел, ... Наследил.
Proph.
Re[4]: PRB: реализация atoi
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 29.08.02 07:02
Оценка:
Здравствуйте Proph, Вы писали:

P>Здравствуйте Flamer, Вы писали:


F>>Здравствуйте Proph, Вы писали:


P>>>Здравствуйте Flamer, Вы писали:


P>>>Еще вариант


F>>[код покоцан]


F>>Значится так: знак числа можно (и нужно) устанавливать один раз перед возвратом из функции.

P>переменная f служит и как знак и как флаг что уже было число.
P>а знак результата устанавливается в returne.

F>>Далее — можно (и прозрачней) обойтись без цикла for (а вот чего использовать — думайте ).

P>Чем ?

while

F>>И еще — в определении макросов ошибка (если внимательно посмотрите — поймете, почему).

P>Где?

Ну, допустим, вместо

#define ISDIGIT(c) ((c >= '0') && (c <= '9') ? 1 : 0)


более правильным был бы вариант


#define ISDIGIT(c) (( (c) >= '0') && ( (c) <= '9') ? 1 : 0)


с теоретической точки зрения
Re[5]: PRB: реализация atoi
От: Proph  
Дата: 29.08.02 07:14
Оценка:
Здравствуйте Flamer, Вы писали:

F>>>[код покоцан]


F>>>Далее — можно (и прозрачней) обойтись без цикла for (а вот чего использовать — думайте ).

P>>Чем ?

F>while

в моем коде while не выгоден (где ставить str++ )

F>>>И еще — в определении макросов ошибка (если внимательно посмотрите — поймете, почему).

P>>Где?

F>Ну, допустим, вместо


F>
F>#define ISDIGIT(c) ((c >= '0') && (c <= '9') ? 1 : 0)
F>


F>более правильным был бы вариант



F>
F>#define ISDIGIT(c) (( (c) >= '0') && ( (c) <= '9') ? 1 : 0)
F>


F>с теоретической точки зрения

согласен
Пришел, Увидел, ... Наследил.
Proph.
Re[6]: PRB: реализация atoi
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 29.08.02 07:18
Оценка:
Здравствуйте Proph, Вы писали:

[покоцано раз]

P>в моем коде while не выгоден (где ставить str++ )


А вот посмотрите здесь
Автор: Flamer
Дата: 29.08.02


[покоцано два]
Re[3]: PRB: реализация atoi
От: Vampire Россия  
Дата: 29.08.02 07:18
Оценка:
Здравствуйте Flamer, Вы писали:

F>Здравствуйте Vampire, Вы писали:


V>>Правда чтот дофига у меня проверок получилось


F>[код покоцан]


F>А немножко упростить код? Хотя бы вместо 48+9 написать 57? Ведь не каждый оптимизирующий компилятор это вам соптимизирует...


Ну есть такой вариант. Правда ввожу флаг


int new_atoi(char *string)
{    
    int i = 0;
    int res = 0;
    bool z = true;
    int znak = 1;

    if (string == NULL) return 0;
    do 
    {
        if ((string[i] == '-') && (z))
        {
            znak = -1;
            z = false;
            continue;
        }
        if ((string[i] == '+') && (z))
        {
            z = false;
            continue;
        }
        if ((string[i] == ' ') || (string[i] == '\t'))
            continue;
        if ((string[i] < 48) || (string[i] > 57))
            break;
        res = res * 10 + string[i] - 48;
    } while (string[i++]);
    return res * znak;
}
Если долго мучиться что нибудь получится
Re[7]: PRB: реализация atoi
От: Proph  
Дата: 29.08.02 07:26
Оценка:
Здравствуйте Flamer, Вы писали:

F>Здравствуйте Proph, Вы писали:


F>[покоцано раз]


P>>в моем коде while не выгоден (где ставить str++ )


F>А вот посмотрите здесь
Автор: Flamer
Дата: 29.08.02


F>[покоцано два]

на мой взгляд, в цикле где есть одинаковое измененме на каждой ирерации (типа а++)
нагляднее исрользовать for (во сказанул )
Пришел, Увидел, ... Наследил.
Proph.
Re: PRB: реализация atoi
От: Vampire Россия  
Дата: 29.08.02 07:45
Оценка:
И последний вариант


int new_atoi(char *string)
{    
    int res = 0;
    bool z = true;
    int znak = 1;

    if (string == NULL) return 0;
    do 
    {
        if ((*string == '-') && (z))
        {
            znak = -1;
            z = false;
            continue;
        }
        if ((*string == '+') && (z))
        {
            z = false;
            continue;
        }
        if ((*string == ' ') || (*string == '\t'))
            continue;
        if ((*string < 48) || (*string > 57))
            break;
        res = res * 10 + *string - 48;
    } while (string++);
    return res * znak;
}
Если долго мучиться что нибудь получится
Re: PRB: реализация atoi
От: ~Yuriy~ www.inspira.by.ru
Дата: 30.08.02 07:12
Оценка:
Здравствуйте Flamer, Вы писали:

F>Итак, в качестве затравки одна довольно тривиальная задачка (крутым гуру просьба не беспокоиться , а вот те, кому интересно — дерзайте).


F>Задача:


F>Написать функцию, которая конвертирует строку (char*) в число (int), то есть реализацию atoi. Прототип функции:



F>
F>int new_atoi(const char* string);
F>


F>Условия:


F>0. Язык программирования — С/С++.


F>1. Запрещается пользоваться любыми библиотечными функциями (типа strlen и пр.), а также сторонними классами и иже с ними. В двух словах, задача должна решаться встроенными средствами языка С/С++.


F>2. Пробельные символы в начале строки (пробел и символ табуляции — \t) опускаются.


F>3. Знак числа должен сохраняться.


F>4. Возвращаемое значение — либо 0 в случае ошибки, либо часть числа до момента встречи ошибки (например, если строка содержит значение "1024u78", то возвращаемым значением будет число 1024


F>5. Передаваемая строка содержит числа в десятичном формате.


F>Набор тестов:



F>
F>new_atoi("12345")       =  12345
F>new_atoi("22345")       =  22345
F>new_atoi("-12345")      = -12345
F>new_atoi("--12345")     =  0
F>new_atoi("+12345")      =  12345
F>new_atoi("   12345")    =  12345
F>new_atoi("   12345   ") =  12345
F>new_atoi("\t12345")     =  12345
F>new_atoi(NULL)          =  0
F>new_atoi("-r12345")     =  0
F>new_atoi("123w45")      =  123
F>new_atoi("a12345")      =  0

F>


F>Дерзайте. За лучшую реализацию — приз (более интересная задача)



//==========================================
// LIBCTINY - Matt Pietrek 2001
// MSDN Magazine, January 2001
//==========================================
#include <stdlib.h>
#include <ctype.h>

extern "C" long __cdecl atol ( const char * pstr )
{
    // The current character.
    int  cCurr ;
    // The running total.
    long lTotal ;
    // Holds the '-' sign.
    int  iIsNeg ;

    // Slide past any whitespace.
    while ( isspace ( *pstr ) )
    {
        ++pstr ;
    }

    // Get the current character.
    cCurr = *pstr++ ;
    // Save the negative sign.
    iIsNeg = cCurr ;
    if ( ( '-' == cCurr ) || ( '+' == cCurr ) )
    {
        // We have a sign, so skip it.
        cCurr = *pstr++ ;
    }

    // Initialize the total.
    lTotal = 0 ;

    // While we have digits, addem up.
    while ( isdigit ( cCurr ) )
    {
        // Add this digit to the total.
        lTotal = 10 * lTotal + ( cCurr - '0' ) ;
        // Do the next character.
        cCurr = *pstr++ ;
    }

    // If we have a negative sign, convert the value.
    if ( '-' == iIsNeg )
    {
        return ( -lTotal ) ;
    }
    else
    {
        return ( lTotal ) ;
    }
}

extern "C" int __cdecl atoi ( const char * pstr )
{
    return ( (int)atol ( pstr ) ) ;
}
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.