1

我正在尝试减去每个 ASCII 字符被视为十进制数字的字符串。例如:

"1000000000001" - "0100000000001" = "900000000000"

如果我的函数原型如下所示,我将如何开始执行此操作:

char* get_sub(char* a, char* b)

4

4 回答 4

6

只要记住你是如何在小学的算法 001 课上学会做大数减法的。减去两个数字的最低有效数字,如果小于 0,则加 10,记住进位,继续下一个数字对。

于 2011-10-16T09:55:35.040 回答
1

似乎没有,但这是一个相当复杂的问题(除非我太老了)。这仅适用于N. 所以它一定是真的a >= 0, b >= 0, a >= b。我不会解释它是如何工作的。正如我所写的那样,它非常复杂:-)(而且我什至对我所写的内容都不满意。我敢肯定有一些我没有想到的东西)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* get_sub(const char* a, const char* b);

#define MAX(a, b) (((a) > (b)) ? (a) : (b))

int main(int argc, char* argv[])
{
    char *res = get_sub("10000","9999");
    printf("%s\n", res);
    free(res);
    return 0;
}

char* get_sub(const char* a, const char* b)
{
    size_t a1len = strlen(a);
    size_t a2len = strlen(b);

    size_t max = MAX(a1len, a2len);

    /* I'm using calloc to make it easier to debug. You could use malloc, but you'll have to uncomment a line below */
    char *res = (char*)calloc(max + 1, sizeof(char));

    int carry = 0;

    char *pres = res;
    for (const char *pa = a + a1len - 1, *pb = b + a2len - 1; pa >= a || pb >= b; pa--, pb--, pres++)
    {
        int val1 = pa >= a ? (*pa - '0') : 0;
        int val2 = pb >= b ? (*pb - '0') : 0;

        int diff = val1 - carry - val2;

        if (diff >= 0)
        {
            *pres = (char)(diff + '0');
            carry = 0;
        }
        else
        {
            *pres = (char)(10 + diff + '0');
            carry = 1;
        }
    }

    if (carry != 0)
    {
        free(res);
        return (char*)calloc(1, 1);
    }

    /* *pres = '\0'; */ /* Uncomment this line to use malloc */

    pres--;

    while (pres > res && *pres == '0')
    {
        *pres = '\0';
        pres--;
    }

    strrev(res);

    return res;
}
于 2011-10-16T10:28:55.837 回答
0

取 a 和 b 的最低有效位,通过减去字符“0”的值将它们转换为整数。(有些人会正确地说这是不可移植的,我说当你找到一个现代使用的实用系统时,这将无法工作!)。如果 a 位小于 b 位,则将 a 位加 10,设置“借位标志”,然后从 b 位中减去 a 位。该值是答案的最低有效数字。

移动到下一个最低有效位,如果设置了借位标志,则从 a 位减 1,并清除借位标志,然后重复上述操作。

如果一个字符串在另一个之前用完数字(即较短),则相应的数字应被视为等于零。

这可以迭代或递归执行;我不会尝试递归,除非它已在课堂上专门教授,因此很可能被接受为解决方案,甚至是所需的解决方案。

于 2011-10-16T10:28:10.737 回答
0

这是一个C++ 解决方案的脚手架不能解决问题,但会给您一些语言上的修补程序,您需要一个相当简单的实现。它通过数字向后迭代并建立一个只有 1 的结果,其中两个数字都有非零数字,否则为 0:

#include <string>
#include <iostream>

using namespace std;

// For a more circumspect treatment of the digit/char conversion, read up:
// http://stackoverflow.com/questions/439573/how-to-convert-a-single-char-into-an-int

char charFromDigit(int d) {
    return d + '0';
}

int digitFromChar(char c) {
    return c - '0';
}

// all this routine does is iterate backward through the digits of both
// numbers and build up a result which has a 1 digit if both numbers are
// non-zero for that place value, and a 0 digit if they're both 0

string get_something(const string& a, const string& b) {

    // get reverse ("r"begin) iterators so we can index backwards
    // across the two strings.  This way we look at the last digits
    // first

    string::const_reverse_iterator a_iterator = a.rbegin();
    string::const_reverse_iterator b_iterator = b.rbegin();

    // this variable holds the result that we build

    string result;

    // simple loop that just prints digits as long as the iterators
    // haven't indicated we're out of characters by reaching their
    // respective "r"ends...

    while (a_iterator != a.rend() || b_iterator != b.rend()) {

       int a_digit = 0;
       if (a_iterator != a.rend()) {
           a_digit = digitFromChar(*a_iterator);
           a_iterator++;
       }

       int b_digit = 0;
       if (b_iterator != b.rend()) {
           b_digit = digitFromChar(*b_iterator);
           b_iterator++;
       }

       cout << "A digit " << a_digit << ", B digit " << b_digit << endl;

       int out_digit = 0;
       if ((a_digit != 0) && (b_digit !=0))
           out_digit = 1;

       result.insert(result.begin(), charFromDigit(out_digit));
    }

    return result;
}

int main(int argc, char* argv[]) {
    string a ("1000000000001");
    string b ("0100000000001");

    cout << "A is " << a << endl;
    cout << "B is " << b << endl;

    cout << "Return Value = " << get_something(a, b) << endl;

    return 0;
}

程序的输出是:

A is 1000000000001
B is 0100000000001
A digit 1, B digit 1
A digit 0, B digit 0
A digit 0, B digit 0
A digit 0, B digit 0
A digit 0, B digit 0
A digit 0, B digit 0
A digit 0, B digit 0
A digit 0, B digit 0
A digit 0, B digit 0
A digit 0, B digit 0
A digit 0, B digit 0
A digit 0, B digit 1
A digit 1, B digit 0
Return Value = 0000000000001

如果你在课堂上,如果你在他们教你的框架中解决它,真的会有很大的不同。如果您正在学习的所有内容都是char*等等strlen(),那么您正在学习 C ......而不是惯用的 C++。在 C++ 中,您可以自动管理内存并鼓励使用更通用的算法方法。

于 2011-10-16T10:52:30.687 回答