返回C++中字符数组相减的结果

发布于 2024-12-10 07:49:21 字数 207 浏览 0 评论 0原文

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

"1000000000001" - "0100000000001" = "900000000000"

如果我的函数原型如下所示,我将如何开始实现此功能:

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

I'm trying to subtract strings where each ASCII character is treated as a decimal digit. For instance:

"1000000000001" - "0100000000001" = "900000000000"

How would I get started on an implementation of this if my function prototype looked like:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

眼眸里的那抹悲凉 2024-12-17 07:49:21

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

Just remember how you learned to do subtraction of large numbers in your Algorithms 001 class, the primary school. Subtract the least significant digits of both numbers, add 10 if smaller than 0, remember carry, go on to next digit pair.

往日情怀 2024-12-17 07:49:21

似乎不是,但这是一个相当复杂的问题(除非我太老了)。
这只适用于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;
}

It doesn't seems, but it's a quite complex problem (unless I'm getting too much old).
This works only in N. So it must be true that a >= 0, b >= 0, a >= b. I won't explain how does it works. As I've written, it's quite complex :-) (and I'm not even happy of what I've written. I'm sure there is something I haven't thought)

#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;
}
如果没结果 2024-12-17 07:49:21

取a和b的最低有效位,通过减去字符“0”的值将它们转换为整数。 (有些人会正确地指出这是不可移植的,我说当您发现现代使用中的实用系统在其上不起作用时请回复我!)。如果a位小于b位,则a位加10,设置“借位标志”,b位减去a位。该值是答案的最低有效数字。

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

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

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

Taking the least significant digit of a and b, convert them to an integer by subtracting the value of the character '0'. (Some will correctly state that this is not portable, to which I say get back to me when you have found a practical system in modern use on which this will not work!). If the a digit is less than the b digit, add 10 to the a digit, set a "borrow flag", and subtract the a digit from the b digit. This value is the least significant digit of the answer.

Move to the next least significant digit, if the borrow flag is set, subtract 1 from the a digit, and clear the borrow flag, then repeat as above.

If one string runs out of digits before the other (i.e. is shorter), then the corresponding digit should be taken as being equal to zero.

This can be performed iteratively or recursively; I would not attempt recursion unless it has been specifically taught in the class and is therefore likely to be accepted as a solution, or even the required solution.

万人眼中万个我 2024-12-17 07:49:21

这是 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++ 中,您可以对内存进行更多自动管理,并鼓励使用更通用的算法方法。

Here is a scaffold for a C++ solution, that doesn't solve the problem, but throws you some linguistic tinker-toys you'd need for a fairly straightforward implementation. It iterates backward through the digits and builds up a result which just has 1s where both numbers have nonzero digits, and 0s otherwise:

#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;
}

The output of the program is:

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

Really it makes a big difference, if you're in a class, if you're solving it in the framework they're teaching you about. If everything you're learning is char* and strlen() and such, you're learning C... not idiomatic C++. In C++ you have a lot more automatic management of memory and an encouragement to use more generic algorithmic approaches.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文