Рекурсивный Инкрементер - PullRequest
2 голосов
/ 21 мая 2009

Я пишу рекурсивную функцию, которая принимает массив символов, представляющий число, и указатель на цифру в этом массиве. Смысл функции в том, чтобы увеличивать число так же, как оператор ++. Тем не менее, когда я попробую его на номер «819». Он не увеличивает его до «820», а вместо этого меняет его на «810» (он увеличивает последнюю цифру, но не выполняет рекурсию, которую я хочу). Может ли кто-нибудь помочь мне с этим? Спасибо.

#include <stdio.h>

char* inc(char *num, char* p)
{   
    if( *p>='0' && *p<='8' )
    {
        *p++;
    }
    else if ( *p=='9' )
    {
        *p = '0';
        inc(num, --p);
    }

    return num;
}

main()
{
    char x[] = "819";

    printf("%s\n", inc(x, x+strlen(x)-1) ); //pass the number and a pointer to the last digit
}

Ответы [ 4 ]

11 голосов
/ 21 мая 2009

Изменение *p++ to (*p)++; Вы хотите увеличить число, содержащееся в п.

   char* inc(char *num, char* p)
    {   
        if( *p>='0' && *p<='8' )
        {
            (*p)++;       //==> change
        }
        else if ( *p=='9' )
        {
            *p = '0';
            inc(num, --p);
        }

        return num;
    }

EDIT:

++ оператор имеет более высокий приоритет над *. Следовательно,

*p++ ==> *p then p++; // p's value before the increment.

См. Таблицу приоритетов здесь .

4 голосов
/ 21 мая 2009

Это потому, что *p++ получает символ, затем увеличивает указатель . Вы хотите (*p)++, который увеличивает символ в этом указателе:

#include <stdio.h>

char *inc (char *num, char* p) {
    if (*p >= '0' && *p <= '8') {
        (*p)++;
    } else if (*p == '9') {
        *p = '0';
        inc(num, --p);
    }
    return num;
}

Вы должны быть очень осторожны при выполнении этого для строк выше 9xxx, так как вам нужно убедиться, что вы оставили место для следующей цифры вверх (предварительно заполните 0, если необходимо). В противном случае добавьте защиту, такую ​​как функция обтекания ниже:

#include <stdio.h>

char *inc (char *num, char* p) {
    if (p < num)
        return num;
    if ((*p < '0') || (*p > '9'))
        return num;
    if (*p < '9') {
        (*p)++;
        return num;
    }
    *p = '0';
    return inc(num, --p);
}

int main (int argc, char *argv[]) {
    char x[] = "819";
    char y[] = "8999";
    char z[] = "9999";
    char a[] = "aaa72";
    char b[] = "aaa279";
    char c[] = "aaa9999";
    printf("%s\n", inc(x, x+strlen(x)-1) );
    printf("%s\n", inc(y, y+strlen(y)-1) );
    printf("%s\n", inc(z, z+strlen(z)-1) );
    printf("%s\n", inc(a, a+strlen(a)-1) );
    printf("%s\n", inc(b, b+strlen(b)-1) );
    printf("%s\n", inc(c, c+strlen(c)-1) );
    return 0;
}

Этот код приводит к:

820
9000
0000
aaa73
aaa280
aaa0000

как и ожидалось.

1 голос
/ 21 мая 2009

Я всегда следую некоторым рекомендациям, которые помогают достичь правильности при кодировании на C ++:

  • Не изменяйте и получайте значение что-нибудь в той же инструкции. т.е. inc(num, --p); забанен потому что второй аргумент инк не постоянный.
  • Никогда не разыменовывать указатель и сделать что-то с этим в одна и та же строка. т.е. все формы (*p)++; забанены.
  • Всегда гарантирует постоянную корректность параметров функции .
  • Разделение команд / запросов : Обычно функции должны быть либо константными, либо недействительными.
  • Не использовать рекурсия если вы можете избежать этого, то есть всегда сначала ищите нерекурсивную альтернативу. (Этот вопрос является примером, в котором вы можете избежать его).
  • Проектирование по контракту. Добавить предварительные условия к начало и постусловия к конец ваших функций.

Применение их к вашей функции может помочь устранить ошибки в ней.

0 голосов
/ 21 мая 2009

Пример побочного эффекта исходной программы, скомпилированной в gcc, (Этот побочный эффект не возникает в программе @Pax)

int
 main()
{
char x[] = "9";
char z[] = {57,57,57,57};

int t=0;
for(t=0;t<4;++t)
    printf("z == %d\n",z[t]);

inc(x, x+strlen(x)-1);

for(t=0;t<4;++t)
    printf("z == %d\n",z[t]);

}

Выход: z == 57 z == 57 z == 57 z == 57 z == 48 z == 48 z == 48 z == 48

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...