我正在尝试减去每个 ASCII 字符被视为十进制数字的字符串。例如:
"1000000000001" - "0100000000001" = "900000000000"
如果我的函数原型如下所示,我将如何开始执行此操作:
char* get_sub(char* a, char* b)
我正在尝试减去每个 ASCII 字符被视为十进制数字的字符串。例如:
"1000000000001" - "0100000000001" = "900000000000"
如果我的函数原型如下所示,我将如何开始执行此操作:
char* get_sub(char* a, char* b)
只要记住你是如何在小学的算法 001 课上学会做大数减法的。减去两个数字的最低有效数字,如果小于 0,则加 10,记住进位,继续下一个数字对。
似乎没有,但这是一个相当复杂的问题(除非我太老了)。这仅适用于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;
}
取 a 和 b 的最低有效位,通过减去字符“0”的值将它们转换为整数。(有些人会正确地说这是不可移植的,我说当你找到一个现代使用的实用系统时,这将无法工作!)。如果 a 位小于 b 位,则将 a 位加 10,设置“借位标志”,然后从 b 位中减去 a 位。该值是答案的最低有效数字。
移动到下一个最低有效位,如果设置了借位标志,则从 a 位减 1,并清除借位标志,然后重复上述操作。
如果一个字符串在另一个之前用完数字(即较短),则相应的数字应被视为等于零。
这可以迭代或递归执行;我不会尝试递归,除非它已在课堂上专门教授,因此很可能被接受为解决方案,甚至是所需的解决方案。
这是一个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++ 中,您可以自动管理内存并鼓励使用更通用的算法方法。