Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.65/37: Рейтинг темы: голосов - 37, средняя оценка - 4.65
CEO SOVAZ Corp.
386 / 232 / 51
Регистрация: 17.12.2011
Сообщений: 822
Записей в блоге: 1
1

Моя реализация функции перевода string в int

21.12.2012, 18:23. Показов 7304. Ответов 57

Author24 — интернет-сервис помощи студентам
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <iostream>
#include <string>
 
using namespace std;
 
int str_to_int(string a);
 
int main() {
    string s = "-4789";
    cout << str_to_int(s);
}
 
int str_to_int(string a) {
    int num = 0;
    int tmp;
    bool anti = false;
 
    for(int i = a.size() - 1, l = 1; i >= 0; --i, l *= 10) {
        if(a[i] == '0') {tmp = 0;}
 
        else if(i == 0 && a[i] == '-') {anti = true;}
 
        else if(a[i] == '1') {tmp = 1;}
        else if(a[i] == '2') {tmp = 2;}
        else if(a[i] == '3') {tmp = 3;}
        else if(a[i] == '4') {tmp = 4;}
        else if(a[i] == '5') {tmp = 5;}
        else if(a[i] == '6') {tmp = 6;}
        else if(a[i] == '7') {tmp = 7;}
        else if(a[i] == '8') {tmp = 8;}
        else if(a[i] == '9') {tmp = 9;}
 
        else {
                return 0;
        }
 
        num += (tmp * l);
    }
 
    if(anti == true) {return -num;}
    else {return num;}
}


P.S. Пишите предложения по улучшению этой функции

Добавлено через 5 минут
Актуальна

Добавлено через 5 минут
Вверх
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
21.12.2012, 18:23
Ответы с готовыми решениями:

Моя реализация функции перевода STRING в DOUBLE
#include &lt;iostream&gt; #include &lt;string&gt; using namespace std; double str_to_double(string a); ...

Реализация функции char *padl(const char *string, int len, int c=' ')
Реализовать функцию возвращающую указатель на новую строку длины len, полученную из string либо...

Моя реализация алгоритма перевода числа в пропись (русский язык)
Добрый день.Недавно передо мной стояла задача сделать REST сервис перевода числа в пропись(на...

Too few parameters in call to 'Lechebnica::AddNewElement(int,int,string,string,int,string)
Edit1 Id Edit2 Имя Edit3 Фамилия Edit4 Номер телефона ComboBox1 Услуга ...

57
go
Эксперт С++
3646 / 1378 / 243
Регистрация: 16.04.2009
Сообщений: 4,526
22.12.2012, 16:11 41
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от sovaz1997 Посмотреть сообщение
Моя реализация функции перевода string в int
Это не серьезно. Добавте системы счисление. Я когда-то strtol реализовывал. Могу код поискать.
1
Форумчанин
Эксперт CЭксперт С++
8215 / 5045 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
22.12.2012, 16:47 42
Почему все так упорно игнорируют isdigit, isalpha?
1
Модератор
Эксперт по электронике
8908 / 6677 / 918
Регистрация: 14.02.2011
Сообщений: 23,521
22.12.2012, 21:09 43
и так поехали
Цитата Сообщение от fit Посмотреть сообщение
зачем лезть в асм. все проверяется куда проще:
"Пастернака не читал но осуждаю"
Цитата Сообщение от fit Посмотреть сообщение
как видишь, никакого \0 в памяти после двойки нет,
во первых какой компилятор? во вторых в каком режиме?
Цитата Сообщение от fit Посмотреть сообщение
думаю, на этом спор исчерпан.
нет он только начинается
еще раз
во первых какой компилятор? во вторых в каком режиме?
никто не гарантировал что вокруг памяти будут 0 но у ТС срабатывает эта строка
C++
1
int m=atoi(buf);
значит никакого мусора нет (иначе бы ноль вернула)
Цитата Сообщение от fit Посмотреть сообщение
это делается не "занулением". new резервирует необходимое кол-во байт в незанятой памяти. компилятор это число запоминает и при попытке изменить значение ячейки ОП вне выделенного числа байт выдает ошибку.
хотелось бы верить но в жизни все не так
в отладочном режиме ты выделяешь 100 байт а выделяется 200(к примеру) и сверху и снизу есть защитный буфер при обращении к которому вызывается исключение
в режиме реализации ничего такого нет, поэтому можно получить странное поведение
еще раз если ты что то утверждаешь приводи ассемблерные листинги(хотя бы для одного конкретного компилятора)

Цитата Сообщение от fit Посмотреть сообщение
это делается не "занулением". new резервирует необходимое кол-во байт в незанятой памяти. компилятор это число запоминает и при попытке изменить значение ячейки ОП вне выделенного числа байт выдает ошибку.
ссылку в листинге, а не свои размышления.
где он их запоминает? формат памяти в дампах?

Цитата Сообщение от fit Посмотреть сообщение
она работает не потому что ch терминирован '\0', а потому что:
1. atoi игнорирует символы, не являющиеся числом.
и смело возвращает 0
Цитата Сообщение от fit Посмотреть сообщение
сканирует память до первого встретившегося \0. а он рано или поздно там встретиться. только вот сколько ему придется прочитать для этого байт - черт его знает. вот чтобы не пришлось читать лишнюю память, в спецификации и требуется \0 в конце.
спасибо что ты напомнил мне как устроена строка в С
Цитата Сообщение от fit Посмотреть сообщение
статическая char строка терминуется \0 всегда. это стандарт языка. и лежит она в программном стеке, а не куче, где работает new.
еще раз спасибо
в общем давайте спорить о вкусе устриц с теми хоть однажды их ел
кстати ты не ответил на такой вопрос
Цитата Сообщение от ValeryS Посмотреть сообщение
C++
1
2
3
4
5
6
7
char *buf=new char[5];
buf[0]='5';
buf[1]='3';
buf[2]=0;
buf[3]='6';
buf[4]='7';
int m=atoi
(buf);
выделено 5 байт
посредине я вставил 0 т.е строка всего три байта
что выдаст atoi?
по твоей логике 5367( я же пять байт выделил)
по моей 53( строка кончилась)


Цитата Сообщение от fit Посмотреть сообщение
статическая char строка терминуется \0 всегда.
Цитата Сообщение от fit Посмотреть сообщение
к тому же, atoi получит ровно столько, сколько зарезервировал new.
противоречия не чествуем?
в статике нет new
1
CEO SOVAZ Corp.
386 / 232 / 51
Регистрация: 17.12.2011
Сообщений: 822
Записей в блоге: 1
22.12.2012, 21:22  [ТС] 44
Актуальна
0
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
22.12.2012, 21:31 45
Цитата Сообщение от ValeryS Посмотреть сообщение
и смело возвращает 0
Ну не совсем. Если были до буквенного символа цифры, то возвращается то самое число. Например строка "123b123" вернет число 123. Так же игнорируются первые пробельные символы. Например строка " \t 123b123" вернет все тоже число 123. Ну и само собой засчитывается символы + и -, если они перед первой цифрой стоят.
0
4043 / 2332 / 292
Регистрация: 03.02.2011
Сообщений: 5,066
Записей в блоге: 10
22.12.2012, 23:02 46
sovaz1997, это соц-исследование какое-то что ли? Зачем понукаешь?
1
go
Эксперт С++
3646 / 1378 / 243
Регистрация: 16.04.2009
Сообщений: 4,526
22.12.2012, 23:13 47
Вот писал на чистом Си(не С99)

<ctype.h> не юзал.
Только функции ввода/вывода.
<stdlib.h> для system();

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <stdio.h>
#include <stdlib.h>
 
long strtol (char *, char **, int );
double pow (double , int );
 
#define isdigit(a) ((a) >= '0' && (a) <= '9') 
#define tolower(a) ((a) >= 'A' && (a) <= 'Z' ? (a) - 'A' + 'a' : (a)  )
#define isalpha(a) ( ((a) >= 'A' && (a) <= 'Z') || ((a) >= 'a' && (a) <= 'z')  ? (a) : 0 )
 
int main (void)
{
    char s[] = "021 10x 0xff";
    char *p;
 
    printf ("%ld\n", strtol (s, &p, 8) );
    printf ("%ld\n", strtol ("101", &p, 2) );
    printf ("%ld\n", strtol ("125", &p, 10) );
    printf ("%ld\n", strtol ("0x5Ab", &p, 16) );
    printf ("%ld\n", strtol ("5Ab", &p, 16) );
    system ("pause");
    return 0;
}
 
long strtol (char *s, char **end, int base)
{
    long res = 0L;
    char *p;
    int exp;
 
    if ( s && *s )
    {
        for ( ; *s && !isdigit(*s) && !isalpha (*s) ; ++s )
            ;
        for ( *end = s ; **end && **end - '0' < base && isdigit (**end) ; ++*end ) 
            ;
    }
    else 
    {
        *end = NULL;
        return res;
    }
 
    if ( base )
        if ( base >= 2 && base <= 36 ) 
        {
            if ( base > 10 ) // dvigaen *end do konca
                for ( ; **end && tolower(**end) - 'a' + 10 < base && isalpha(**end) ; ++**end )
                    ;
            //Run
            for ( p = *end - 1, exp = 0 ; p != (s - 1) ; --p )
                res +=  (isalpha (*p) ? tolower(*p) - 'a' + 10 : *p - '0') * (long) pow ( (double) base, exp++ );// Zde
        }
        else
        {
            // ERROR ret 0L
        }
    else
    {
        //Standart 0x 1123 
        // else ret 0L 
        if ( tolower(*(s + 1)) == 'x' ) // !!!!!!!!!!!WRONG!!!!!!!!!!
            res = strtol ( s + 2, end, 16 );                
    }
    return res;
}
 
double pow( double base, int exp )
{
    size_t i;
    double res = 1;
 
    if ( exp < 0 )
        res = pow ( 1 / base , -1 * exp );
    else
    {
        for ( i = 0 ; i < (size_t) exp ; ++i )
            res *= base;
    }
    return res;
}
Согласен вариант не очень, но писалась давно нет желания допиливать.
Если будут конфликтовать идентификаторы, то либо компилить с другими ключами, либо добавить макросы.
1
Форумчанин
Эксперт CЭксперт С++
8215 / 5045 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
22.12.2012, 23:22 48
go, у меня конфликтует с strtol из stdlib.h (minGW)
Комменты точно в "грязном С".

Добавлено через 4 минуты
И если убрать комменты, stdlib.h и system, то крах после вывода значений.
0
go
Эксперт С++
3646 / 1378 / 243
Регистрация: 16.04.2009
Сообщений: 4,526
22.12.2012, 23:42 49
MrGluck, угу. В GCC Segmentation fault. Если есть возможность, запусти в Visual Studio 2010. Писал именно там, где-то видно с указателями напутал. Правда, нет ни интереса, ни времени исправлять.
0
1405 / 647 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
23.12.2012, 01:01 50
go, я попробовал реализовать перевод из одной СС в другую, можете посмотреть?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <iostream>
#include <string>
#include <cmath>
#include <cctype>
#include <algorithm>
 
 
void UpperCase (std::string::iterator a, std::string::iterator b)
{
    while (a != b)
    {
        *a = toupper (*a);
        ++a;
    }
}
 
 
std::string Process (std::string s, int start, int finish)
{
    if (start < 2 || finish < 2)
        return ("Wrong Start or Finish CC!");
 
    int ans = 0, tmp, b = -1;
    UpperCase (s.begin(), s.end());
    //To 10 CC
    for (int i=s.length()-1; i >= 0; --i)
    {
        if ( isdigit(s[i]) )
            tmp = s[i] - '0';
        else
            tmp = s[i] - 'A' + 10;
 
        ans += tmp * pow (start + .0, ++b);
    }
 
    //From 10 CC
    std::string a;
    if (!ans) 
        a = '0';
    else
        while (ans)
        {
            if (ans % finish <= 9)
                a += (char(ans % finish + '0'));
            else
                a += (char(ans % finish - 10 + 'A'));
            ans /= finish;
        }
        std::reverse (a.begin(), a.end());
    return a;
}
 
int main()
{
    std::string str;
    int s, f;
 
    std::cout << "Enter Number: ";
    std::cin >> str;
    std::cout << "Enter start and end CC: ";
    std::cin >> s >> f;
 
    std::cout << Process (str, s, f) << std::endl;
    system ("pause");
    return 0;
}
0
14 / 14 / 1
Регистрация: 20.04.2010
Сообщений: 102
23.12.2012, 06:48 51
Цитата Сообщение от ValeryS
"Пастернака не читал но осуждаю"
да я-то с ним знаком, только зачем так все усложнять ежели и так все под носом
Цитата Сообщение от ValeryS
нет он только начинается
еще раз
во первых какой компилятор? во вторых в каком режиме?
VS2010. и в runtime и в debug после двойки мусор. cout же это наглядно поясняет и без отладчика.

Цитата Сообщение от ValeryS
никто не гарантировал что вокруг памяти будут 0 но у ТС срабатывает эта строка
C++
1
int m=atoi(buf);
значит никакого мусора нет (иначе бы ноль вернула)
читаем спецификацию функции и таки прекращаем спор
еще раз, на пальцах объясню, каким чудом это работает в нашем случае:
1. atoi начинает сканировать строку. видит, первый символ - число. все нормально, сканирует дальше.
2. видит, 2ой элемент массива не число (мусор пошел). игнорирует его - завершает разбор. переводит найденную до того цифру к int и возвращает значение.
3. 0 atoi возвращает ежели в переданном массиве не встретилось вообще ни одного числа, либо перед цифрами имелся не числовой символ (за исключением \t, +, -)
в общем, мифические "зануления" здесь не причем.

Цитата Сообщение от ValeryS
ссылку в листинге, а не свои размышления.
где он их запоминает? формат памяти в дампах?
это я во всякой разной литературе читал, когда писал компилятор. так-то сейчас специально уточнил и вот что обнаружил: конкретно в с++ контроль за выходом за границы динамического массива вообще отсутствует.
подтверждаю рабочим примером:
C++
1
2
int* f = new int[5];
f[6]=7;
проверьте - ни разу не ругнется на выход за пределы памяти, никаких исключений. ни в runtime, ни в debug. еще один аргумент, что никакого "зануления" в целях отлова как оказалось мифической для плюсов ошибки не существует.

Цитата Сообщение от ValeryS
в отладочном режиме ты выделяешь 100 байт а выделяется 200(к примеру) и сверху и снизу есть защитный буфер при обращении к которому вызывается исключение
в режиме реализации ничего такого нет, поэтому можно получить странное поведение
еще раз если ты что то утверждаешь приводи ассемблерные листинги(хотя бы для одного конкретного компилятора)
1. этоn буфер принудительно зануляется? нет, я конечно сейчас не могу отрицать его существование. но у меня большие сомнения, что там именно нули. а это важно.
2. почему примеры говорят об обратном? ну не видит VS никаких исключений, а мусор видит и массивы за границей памяти спокойно инициализирует. и я не полезу в ассемблер дабы это проверять, потому как пока что верю своим глазам и таки знаю стандарты.

Цитата Сообщение от ValeryS
выделено 5 байт
посредине я вставил 0 т.е строка всего три байта
что выдаст atoi?
по твоей логике 5367( я же пять байт выделил)
по моей 53( строка кончилась)
atoi ведет разбор до первого нечислового символа. в идеале это нулевой байт \0. в реалиях что угодно не числовое.

Цитата Сообщение от ValeryS
противоречия не чествуем?
в статике нет new
с new я видимо неправильно сформулировал свою мысль. не имелось ввиду, что передается к примеру 5 байт, что new зарезервировал. конечно же передается только указатель (адрес на 1 элемент).
мной имелось ввиду, что динамический char массив не терминуется нулем при его инициализации. new инициализирует ровно столько байт, сколько нужно для размещения переданного аргумента.
про статику. видимо невнимательно читаешь, либо специально делаешь из меня дурака.
конструкция:
C++
1
char* ch = "abcd"
неявно терминует \0 строку abcd в конце. вот тут-то, в статике, есть этот \0, который не мы "не видим". при инициализации через new \0 не существует.
0
What a waste!
1608 / 1300 / 180
Регистрация: 21.04.2012
Сообщений: 2,729
23.12.2012, 07:23 52
Цитата Сообщение от fit Посмотреть сообщение
подтверждаю рабочим примером:
C++
1
2
int* f = new int[5];
f[6]=7;
проверьте - ни разу не ругнется на выход за пределы памяти, никаких исключений. ни в runtime, ни в debug. еще один аргумент, что никакого "зануления" в целях отлова как оказалось мифической для плюсов ошибки не существует.
VS 2010? Если есть delete[] f; то вроде должен ругаться в дебаге.
0
4043 / 2332 / 292
Регистрация: 03.02.2011
Сообщений: 5,066
Записей в блоге: 10
23.12.2012, 11:23 53
Цитата Сообщение от fit Посмотреть сообщение
проверьте - ни разу не ругнется на выход за пределы памяти, никаких исключений. ни в runtime, ни в debug. еще один аргумент, что никакого "зануления" в целях отлова как оказалось мифической для плюсов ошибки не существует.
Зануления нет, конечно - это было бы крайне неэффективно.
Но вот шариться за пределами выделенной памяти получится лишь до поры до времени, пока не попытаешься модифицировать чужой выделенный кусок.
0
~ Эврика! ~
1256 / 1005 / 74
Регистрация: 24.07.2012
Сообщений: 2,002
23.12.2012, 11:31 54
Цитата Сообщение от BRcr Посмотреть сообщение
Но вот шариться за пределами выделенной памяти получится лишь до поры до времени, пока не попытаешься модифицировать чужой выделенный кусок.
Да легко.

Это Си++. Один из его императивов: не мешать творить что угодно, если этого явно просят. Поэтому в стандарте обращение к невыделенной памяти описано как UB. Можно это делать, но под свою ответственность.

Поэтому никакие проверки выделенности не обязаны выполняться, если самостоятельно их не выполнять. Это может быть как использование аналога обёртки над std::vector с проверкой границ, так и запуск программы под каким-нибудь Валгриндом.

Максимум операционка по носу даст сегфолтом за обращения к невыделенным страницам, но и то, она может это не делать, и buffer overflow в пределах страницы это не детектит.
0
4043 / 2332 / 292
Регистрация: 03.02.2011
Сообщений: 5,066
Записей в блоге: 10
23.12.2012, 12:12 55
А я о чем? Можно, если осторожно. Еще DEP, если соответственно включен, будет рубить поползновения к чужой памяти.
0
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
23.12.2012, 12:21 56
Нельзя просто так получить доступ к чужой памяти. Не такими способами как Вы думаете. new ( malloc и другие аллокаторы ) часто выделяют память с запасом. Вот по этому запасу и удается беспроблемно гулять, потому что это память размечена ОС для вашей программы. Вот дальше этой памяти уже идет не размеченная область. Она никуда не указывает, эти адреса виртуального пространства просто напросто не связаны ОС с физическими адресами памяти. При доступе к ним ( чтение/запись ) программа просто падает. Так же можно без проблем гулять и по памяти, которая была выделена при запуске ( стек, глобальные/статические переменные ).
0
go
Эксперт С++
3646 / 1378 / 243
Регистрация: 16.04.2009
Сообщений: 4,526
23.12.2012, 13:48 57
Цитата Сообщение от Dani Посмотреть сообщение
go, я попробовал реализовать перевод из одной СС в другую, можете посмотреть?
В принципе все логично.
1
CEO SOVAZ Corp.
386 / 232 / 51
Регистрация: 17.12.2011
Сообщений: 822
Записей в блоге: 1
23.12.2012, 15:06  [ТС] 58
Актуальна
0
23.12.2012, 15:06
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
23.12.2012, 15:06
Помогаю со студенческими работами здесь

Метод int MmPp(string str) для перевода строковой даты в число
Написать метод int MmPp(string str) {} Параметром является дата в виде &quot;21.mai&quot; (число, точка,...

Создайте класс Animal. Добавьте поля string Name, string Kind, string Areal, int Population
Здравствуйте! По C# есть задачка, с которой я так и не разобрался :( Задача: Создайте...

Создайте класс Animal. Добавьте поля string Name, string Kind, string Areal, int Population
Создайте класс Animal. Добавьте поля string Name, string Kind, string Areal, int Population....

Функция isspace и тип string: Не существует подходящей функции преобразования из "std::string" в "int"
Добрый день! Я только начинаю изучать язык c++ по книге &quot;Язык программирования С++. Базовый курс...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
58
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru