Вы на правильном пути. Ваш рекурсивный подход к проверке того, является ли ввод числом, выглядит примерно так: правильно? Обратите внимание, что вы можете пойти и вычесть '0'
от персонажа, не утруждая себя преобразованием в 48 себя.
int number_length(char *s, int pos) {
int d;
if (s[pos] == '\0') {
return pos;
}
d = s[pos] - '0';
if (d < 0 || d > 9) {
return -1;
}
return number_length(s, pos+1);
}
выше функция возвращает -1, если входной является недействительным, а длина номера в противном случае. Мы можем использовать длину входных чисел, когда мы начинаем процесс рекурсивного сложения.
Куда должна начинаться рекурсия? Когда мы добавляем пару чисел, удобно начинать с наименее значимых цифр.
Если мы имеем пару char *
переменных a
и b
указывающей на номера, и если мы знаем, что a
содержит a_length
цифры и b
содержит b_length
цифры, то:
Мы не знаем заранее, как долго результат будет, так что давайте строить цифры в int *
массива, начиная с позиции 0. Это означает, что мы будем иметь результат цифры в обратном порядке , так что мы будем печатать их, начиная с конца и вернуться к 0.
ядро вычислений заключается в следующем:
Учитывая позицию a_pos
в a
и b_pos
в b
, а также цифру переноса carry
, вычислите сумму цифр в a
и b
вместе с цифрой переноса.
Обновить цифру переноса.
Добавить результат в массив результатов и обновить длину массива.
В C, мы можем выразить вычисление следующим образом:
d = a[a_pos--] + b[b_pos--] - 2*'0' + carry;
carry = (d >= 10 ? 1 : 0);
result[result_pos++] = d%10;
a[a_pos--] + b[b_pos--]
Выражение становится недействительным сразу a_pos
или b_pos
стал отрицательным. Другими словами, мы должны иметь дело с ситуациями, когда у нас закончились цифры в одном или обоих числах. Мы должны позаботиться о:
случаев Рукоятки, где мы уже обработаны наиболее значительную цифру a
, но не b
или b
, но не a
.
Когда мы достигли конца как a
, так и b
, не забудьте проверить цифру переноса: если она равна 1, добавьте ее к результату и увеличьте длину результата.
Ниже приводится полная реализация в ANSI C.
#include <stdio.h>
#include <string.h>
#define BUFFER_SIZE 8192
char a[BUFFER_SIZE], b[BUFFER_SIZE];
int result[BUFFER_SIZE];
int number_length(char *s, int pos) {
int d;
if (s[pos] == '\0') {
return pos;
}
d = s[pos] - '0';
if (d < 0 || d > 9) {
return -1;
}
return number_length(s, pos+1);
}
int add(char *a, int a_pos, char *b, int b_pos,
int *result, int result_pos, int carry) {
int d;
if (a_pos < 0 && b_pos < 0) {
if (carry == 1) {
result[result_pos++] = 1;
}
return result_pos;
}
if (a_pos < 0) {
result[result_pos++] = b[b_pos--] - '0' + carry;
carry = 0;
} else if (b_pos < 0) {
result[result_pos++] = a[a_pos--] - '0' + carry;
carry = 0;
} else {
d = a[a_pos--] + b[b_pos--] - 2*'0' + carry;
carry = (d >= 10 ? 1 : 0);
result[result_pos++] = d%10;
}
return add(a, a_pos, b, b_pos, result, result_pos, carry);
}
int main() {
int a_length, b_length, i, result_length;
printf("First number > ");
scanf("%s", a);
if ((a_length = number_length(a, 0)) == -1) {
printf("%s is not a number.\n", a);
return 0;
}
printf("Second number > ");
scanf("%s", b);
if ((b_length = number_length(b, 0)) == -1) {
printf("%s is not a number.\n", b);
return 0;
}
result_length = add(a, a_length-1, b, b_length-1, result, 0, 0);
for (i = result_length-1; i >= 0; --i) {
printf("%d", result[i]);
}
printf("\n");
return 0;
}
@huehuehuebr Что следует делать, если строка только частично состоит из начальных цифр, например «12345A»? –