Форум программистов, компьютерный форум, киберфорум
Наши страницы
C для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.63/8: Рейтинг темы: голосов - 8, средняя оценка - 4.63
Working
0 / 0 / 0
Регистрация: 31.08.2013
Сообщений: 38
1

Функция перевода числа в строку

05.09.2013, 22:50. Просмотров 1440. Ответов 18
Метки нет (Все метки)

всем привет. написал такую вот функцию

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
char* itoa(int i) {
    static char buf[BUFFER];
    char *p = buf + BUFFER;
 
    int sign;
 
    if ((sign = i) < 0)  /* записываем знак */
         i = -i;          /* делаем i положительным числом */
    
    do {
        *--p = '0' + (i % 10);
    } while ((i /= 10) > 0);
 
    if (sign < 0)
        *--p = '-';
 
    return p;
}
вы одобряете такую реализацию? хочу просто сделать чтобы не надо было строку потом переворачивать. может посоветуете другую реализацию.? посмотрите, может где-то подводные камни
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
05.09.2013, 22:50
Ответы с готовыми решениями:

Функция перевода переменной типа long в символьную строку в восьмеричном представлении
Написать функцию для перевода переменной типа long в символьную строку в восьмеричном представлении...

Функция для перевода целого числа в 16-ую систему счисления
Добрый день! Кто-то встречал или имеет функцию для перевода целого числа в 16-ую систему счисления?

Функция для перевода цел.числа из dec в oct
Написал функцию для перевода, вроде бы переводит, а результат не смог вывести. Укажите на ошибки....

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

Функция, для перевода из 2-ной в 10-ную систему счисления
Нужна отдельная функция (не в main) для реализации перевода чисел (не строк) из 2 в 10 систему...

18
Somebody
3101 / 1622 / 251
Регистрация: 03.12.2007
Сообщений: 4,223
Завершенные тесты: 3
05.09.2013, 23:03 2
При такой реализации надо помнить, что строка изменится при следующем вызове функции, то есть её надо скопировать куда-то. И в многопоточной программе будет нехорошо. А так вижу, что при i = -i может быть переполнение.
0
Working
0 / 0 / 0
Регистрация: 31.08.2013
Сообщений: 38
05.09.2013, 23:12  [ТС] 3
А так вижу, что при i = -i может быть переполнение.
ой да, точно. но изначально буфер выделяется с учетом что хватит его на все. насчет того что изменится, да, я так тоже подумал. хочу уточнить, а зачем плюсовать '0' ? это приведение типа?

получается здесь *--p сначала уменьшится а потом будет присвоено значение, то есть в конце будет ноль, так? а static char buf изначально всегда будет заполняться нулями, или лучше вручную заполнить? и еще такой вопрос, чего у меня sizeof(p) выдает 4 байта? ведь я 25 резервирую.
0
fanatdebian
Z3JheSBoYXQ=
339 / 234 / 83
Регистрация: 08.07.2012
Сообщений: 577
06.09.2013, 00:00 4
Цитата Сообщение от Working Посмотреть сообщение
ой да, точно. но изначально буфер выделяется с учетом что хватит его на все. насчет того что изменится, да, я так тоже подумал. хочу уточнить, а зачем плюсовать '0' ? это приведение типа?

получается здесь *--p сначала уменьшится а потом будет присвоено значение, то есть в конце будет ноль, так? а static char buf изначально всегда будет заполняться нулями, или лучше вручную заполнить? и еще такой вопрос, чего у меня sizeof(p) выдает 4 байта? ведь я 25 резервирую.
Объявление в функциях статиков дурной тон, приводящий в больших проектах к появлению трудноуловимых ошибок.
Используй максимально следующую логику для функций в виде = обработка вводных данных, и возврат результата. Все. При таком раскладе поиск багов будет простым делом и читаемость кода повысится.

*--p разыменовываешь указатель, декремент значения по адресу на единицу, затем присвоение.

sizeof(value) показывает размер в байтах тип на конкретной архитектуре компилятора.
Для статичных массивов можно использовать такого рода получения длины массива sizeof(buf)/sizeof(char)
Для динамических такой фокус не пройдет.

По самой реализации, предлагаю не объявлять статик, а выделять память под это дело, благо места будет очень мало кушать, а возвращать указатель на сегмент полученного результата.
0
06.09.2013, 00:00
ValeryS
Модератор
7747 / 5756 / 748
Регистрация: 14.02.2011
Сообщений: 19,709
Завершенные тесты: 1
06.09.2013, 00:05 5
Цитата Сообщение от Working Посмотреть сообщение
вы одобряете такую реализацию?
нет
где у тебя завершающий 0 в строке?
Цитата Сообщение от Working Посмотреть сообщение
static char buf[BUFFER];
и зачем здесь статик?
0
Working
0 / 0 / 0
Регистрация: 31.08.2013
Сообщений: 38
07.09.2013, 16:46  [ТС] 6
ну ведь у нас сначала указатель смещается на 1 положение, а затем уже присваивается значение, так? а так как изначально заполняем нулями то и конце ноль. вот, несколько переделал

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
#define BUFFER 25
 
void* fill_mem(void *s, int c, size_t n) {
    char* p=(char*)s;
    while(n--)
        *p++ = (char)c;
    return s;
}
 
char* itoa(int i) {
    char *start = (char*)malloc(sizeof(char) * BUFFER);
 
    fill_mem(start,0,30);
 
    char *p = start + BUFFER;
 
    int sign;
 
    if ((sign = i) < 0)  /* записываем знак */
         i = -i;          /* делаем i положительным числом */
    
    do {
        *--p = '0' + (i % 10);
    } while ((i /= 10) > 0);
 
    if (sign < 0)
        *--p = '-';
 
    return p;
}
получается, что возвращается нам указатель на число, но память выглядит примерно так:

["BUFFER минус количество символов в числе" нулей]собственно_где указатель[число]0

Так вот, получается каждый раз часть памяти расходуется впустую. как можно высвободить часть. кстати, если вызвать free и передать указатель который из функции возвращается, то будет освобождена вся память выделенная ранее а только начиная с места где указатель стоит, так?
0
Nameless One
Эксперт С++
5795 / 3444 / 356
Регистрация: 08.02.2010
Сообщений: 7,448
07.09.2013, 17:07 7
Цитата Сообщение от Working Посмотреть сообщение
fill_mem
Во-первых, уже есть memset; во-вторых, если тебе нужно выделить память, заполненную нулями, используй calloc.

Добавлено через 8 минут
Цитата Сообщение от Working Посмотреть сообщение
Так вот, получается каждый раз часть памяти расходуется впустую. как можно высвободить часть.
Никак. Да и зачем? Тебе 25 байт жалко?

Цитата Сообщение от Working Посмотреть сообщение
кстати, если вызвать free и передать указатель который из функции возвращается, то будет освобождена вся память выделенная ранее а только начиная с места где указатель стоит, так?
Запомни, free можно вызывать только для того адреса, который был получен с помощью предыдущего вызова malloc, calloc, realloc. Т.е. если ты хочешь, чтобы память, которую ты выделяешь в функции, можно было бы корректно очистить, ты должен возвращать именно тот адрес, на который указывает start.

Кстати, с помощью функции логарифма можно узнать, сколько цифр в десятичной записи числа.
0
castaway
Эксперт С++
4940 / 3045 / 455
Регистрация: 10.11.2010
Сообщений: 11,139
Записей в блоге: 10
Завершенные тесты: 1
07.09.2013, 19:21 8

Не по теме:

Цитата Сообщение от Nameless One Посмотреть сообщение
Кстати, с помощью функции логарифма можно узнать, сколько цифр в десятичной записи числа.
Ну так это ж долго..



Добавлено через 25 минут
Working, единственный "подводный камень" - это нехватка размера массива.
К сожалению, из этого исходят последующие обстоятельства...
0
Nameless One
Эксперт С++
5795 / 3444 / 356
Регистрация: 08.02.2010
Сообщений: 7,448
07.09.2013, 19:25 9
Цитата Сообщение от castaway Посмотреть сообщение
Ну так это ж долго.
Взять логарифм — сильно долго? Вряд ли это станет бутылочным горлышком в приложении.
0
castaway
Эксперт С++
4940 / 3045 / 455
Регистрация: 10.11.2010
Сообщений: 11,139
Записей в блоге: 10
Завершенные тесты: 1
07.09.2013, 19:29 10
Цитата Сообщение от Nameless One Посмотреть сообщение
Взять логарифм — сильно долго?
Нет, не сильно. Просто я думаю что есть способ лучше.
0
Working
0 / 0 / 0
Регистрация: 31.08.2013
Сообщений: 38
08.09.2013, 01:17  [ТС] 11
calloc кстати я вот сам думал взять. а memset лишний инклуд просит (как и ZeroMemory). там вместо 30 BUFFER кстати должен быть

если ее вызвать

C
1
char *start = (char*)calloc(sizeof(char) * BUFFER,sizeof(char));
то после числа в выводе выдается мусор почему-то (визуал студия 2010)

взять логарифм это дольше чем 2 раза крутить это?)

C
1
2
3
do {
  
} while ((i /= 10) > 0);
кстати в классическом варианте http://ru.wikipedia.org/wiki/Itoa_%28%D0%A1%D0%B8%29 тоже за пределы массива можно уйти...

в общем можно в цикл поставить счетчик, потом этот указатель снова выставить на конец и записать по-новому значение

скажите, чего у меня такой код не работает? (

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
char* itoa(int i) {
    char* start = (char*)malloc(sizeof(char) * BUFFER);
 
    fill_mem(start,0,BUFFER);
 
    char* p = start + BUFFER;
 
    int sign,counter=1; // сразу для NULL 1 резервируем
 
    if ((sign = i) < 0)
        i = -i;
            
    do {
        *--p = '0' + (i % 10);
        counter++;
    } while ((i /= 10) > 0);
 
    if (sign < 0) {
        *--p = '-';
        counter++;
    }
 
    char* new_start = (char*)malloc(sizeof(char) * counter);
    fill_mem(new_start,0,counter);
 
    char* nst = new_start;
 
    while(p) {
        
        *nst = *p;
 
        nst++;
        p++;
    }
 
    free(start);
 
    return new_start;
}
переписал вот так

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
char* itoa(int i) {
    char* start = (char*)malloc(sizeof(char) * BUFFER);
 
    memset(start,0,BUFFER);
 
    char* p = start + BUFFER;
 
    int sign,counter=0;
 
    if ((sign = i) < 0)
        i = -i;
            
    do {
        *--p = '0' + (i % 10);
        counter++;
    } while ((i /= 10) > 0);
 
    if (sign < 0) {
        *--p = '-';
        counter++;
    }
 
    char* new_start = (char*)malloc(sizeof(char) * counter+1); // 1 для NULL 
    memset(new_start,0,counter+1);
 
    memcpy(new_start,p,counter);
 
    free(start);
 
    return new_start;
}
теперь можно BUFFER без особых зазрений совести выставлять гораздо больше

Добавлено через 3 часа 23 минуты
странно, чего у меня

C
1
2
3
4
5
6
7
8
9
char* str = itoa(i);
 
    int w = 0;
 
    while(str[w]) {
        printf("%c ",str[w]);
 
        w++;
    }
в конце выводит еще какой-то символ "мусорный"?
0
OhMyGodSoLong
~ Эврика! ~
1248 / 997 / 74
Регистрация: 24.07.2012
Сообщений: 2,002
08.09.2013, 02:03 12
Чем бы дитя не тешилось, лишь бы sprintf() использовало... Зачем маллочить временный буфер — загадка. log10 2n = n log10 2, так что для какого-то там int будет точно достаточно (size_t)(CHAR_BIT * sizeof(int) * 0.30103 + 2) символов.
0
Working
0 / 0 / 0
Регистрация: 31.08.2013
Сообщений: 38
08.09.2013, 14:10  [ТС] 13
с символом в конце разобрался, уже все норм.
что для вас загадка? просто не хочу лишний раз расходовать память. где вы предлагаете sprintf влепить сюда?
0
Nameless One
Эксперт С++
5795 / 3444 / 356
Регистрация: 08.02.2010
Сообщений: 7,448
08.09.2013, 14:12 14
Цитата Сообщение от Working Посмотреть сообщение
что для вас загадка?
Зачем выделять память для буфера start вручную, если его можно разместить на стеке?
0
Working
0 / 0 / 0
Регистрация: 31.08.2013
Сообщений: 38
08.09.2013, 14:28  [ТС] 15
а насчет первого варианта, я вчера очень уставший был, напортачил там не то...

Цитата Сообщение от Nameless One Посмотреть сообщение
Зачем выделять память для буфера start вручную, если его можно разместить на стеке?
а можно практический пример?
0
Nameless One
Эксперт С++
5795 / 3444 / 356
Регистрация: 08.02.2010
Сообщений: 7,448
08.09.2013, 15:36 16
Вместо
C
1
char* start = (char*)malloc(sizeof(char) * BUFFER);
сделай
C
1
char start[BUFFER];
0
Working
0 / 0 / 0
Регистрация: 31.08.2013
Сообщений: 38
08.09.2013, 20:33  [ТС] 17
так...

когда пишу

C
1
2
char start[BUFFER];
char* p = &start[BUFFER-1];
вылетает ошибка во время выполнения. и чем предыдущий вариант плох?

так как int может быть не менее −2 147 483 648
должно нам хватить 11 символов плюс NULL

int 64 бита тоже может быть, так?
0
Nameless One
Эксперт С++
5795 / 3444 / 356
Регистрация: 08.02.2010
Сообщений: 7,448
09.09.2013, 05:23 18
Цитата Сообщение от Working Посмотреть сообщение
вылетает ошибка во время выполнения
Где именно?

Цитата Сообщение от Working Посмотреть сообщение
и чем предыдущий вариант плох?
Цитата Сообщение от Nameless One Посмотреть сообщение
Зачем выделять память для буфера start вручную, если его можно разместить на стеке?

Цитата Сообщение от Working Посмотреть сообщение
int 64 бита тоже может быть, так?
Может.
0
Working
0 / 0 / 0
Регистрация: 31.08.2013
Сообщений: 38
13.12.2013, 18:56  [ТС] 19
хочу через рекурсию сделать, скажите почему не работает такой вариант?

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
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
 
#define BUFFER 21
 
void itoa_working(int n,char* p) {
    
    if(n < 0) {
        *++p = '-';
        n = -n;
    }
 
    if(n / 10) 
        itoa_working(n / 10, p);
 
    *++p = n % 10 + '0';
}
 
void itoa(int n,char* p) {
    itoa_working(n,p);
    *++p = '\0';
}
 
int main ()
{
    int i;
 
    scanf("%d",&i); 
 
    char str[BUFFER];
    char* p = &str[0];
 
    itoa(i,p);
 
    int w = 0;
 
    while(str[w]) {
        printf("%c ",str[w]);
 
        w++;
    }
 
    getch();
 
    return 0;
}
и еще, как сделать чтобы сначала присваивалось значение по указателю, а только потом был инкремент указателя, так вот *p++ ?

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

0
13.12.2013, 18:56
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
13.12.2013, 18:56

Написать функцию для перевода double в строку
хочу написать функцию для перевода double в строку, нашел вот такую штуку в тему: union dull {...

Функция - Pos(s,s1). Назначение - поиск первого вхождения подстроки s1 в строку s (аналогичная функция C - strstr)
Функция - Pos(s,s1). Назначение - поиск первого вхождения подстроки s1 в строку s (аналогичная...

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


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

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru