添加两个二进制数字符串-C
我知道互联网上有很多关于这个问题的信息,特别是Stack上的信息,但我还是被困在里面 给定两个二进制数字符串-我们必须以字符串形式返回它们的二进制和 事实上,我想我和这家伙的问题是一样的: 但我做了一些补充和修改,如下所示:添加两个二进制数字符串-C,c,string,binary,point,C,String,Binary,Point,我知道互联网上有很多关于这个问题的信息,特别是Stack上的信息,但我还是被困在里面 给定两个二进制数字符串-我们必须以字符串形式返回它们的二进制和 事实上,我想我和这家伙的问题是一样的: 但我做了一些补充和修改,如下所示: // This function validates the two strings are really representing two binary number, and we keep the size of each int isNum(const ch
// This function validates the two strings are really representing two binary number, and we keep the size of each
int isNum(const char* num, int* sizeOfNum) {
*sizeOfNum = 0;
while (*num != '\0') {
if (*num != '0' || *num != '1') {
return 0;
}
*sizeOfNum += 1;
}
return 1;
}
char* sumOfBinString(const char* num1, const char* num2) {
int* sizeOfNum1 = (int*)(malloc(sizeof(int));
int* sizeOfNum2 = (int*)(malloc(sizeof(int));
if (isNum(num1, sizeOfNum1) && isNum(num2, sizeOfNum2)) {
if (*sizeOfNum1 > *sizeOfNum2) {
int size = (*sizeOfNum1);
}
else {
int size = (*sizeOfNum2);
}
}
//This 'size' is actually the size of the longer binary number string, and plus one for the null-terminator
char *num1Copy = (char *)malloc((size+1) * sizeof(char));
char *num2Copy = (char *)malloc((size+1) * sizeof(char));
int i;
for(i = size; i >= 0; i--)
{
num1Copy[i] = '0';
num2Copy[i] = '0';
}
for (i = *sizeOfNum1; i >= 0; i--)
if (i == 0 && num1Copy[i]=='1') //Two's complement
num1Copy[i] = '1';
else
num1Copy[size - i] = num1[*sizeOfNum1-i];
for (i = *sizeOfNum2; i >= 0; i--)
if (i == 0 && num2Copy[i]=='1') //Two's complement
num2Copy[i] == '1';
else
num2Copy[size - i] = num2[*sizeOfNum2-i];
}
但我不知道如何从这里继续,因为有些情况下进位可能会溢出,我需要“添加”这个数字作为MSB
有人能帮我从这里继续吗?首先:
int* sizeOfNum1 = (int*)(malloc(sizeof(int));
int* sizeOfNum2 = (int*)(malloc(sizeof(int));
if (isNum(num1, sizeOfNum1) && isNum(num2, sizeOfNum2)) {
if (*sizeOfNum1 > *sizeOfNum2) {
int size = (*sizeOfNum1);
}
else {
int size = (*sizeOfNum2);
}
}
您不需要使用大小为bsc的指针,很容易忘记在之后释放内存,或者遇到其他问题。您可以在int上执行此操作:
int sizeOfNum1=0,sizeOfNum2=0;
if (isNum(num1, &sizeOfNum1) && isNum(num2, &sizeOfNum2)) { //if u add & isNum can modify sizeofNum1 by itself (You give address of variable to function)
if (sizeOfNum1 > sizeOfNum2) {
int size = sizeOfNum1;
}
else {
int size = sizeOfNum2;
}
}
对于添加后面的数学,就像在学校一样:
111--- //carry line
1100
+ 10100
------
100000
在循环中,每个sizeOfNum有2个Iterator,当它达到0时,只向输出添加一个长度更高的Iterator(ofc请记住,您需要始终检查进位,就像在1100中的示例中,Iterator将结束进位仍然为1,因此您需要注意)此处的一些指南:
int i,j;
i=(size==sizeOfNum1)?size:sizeOfNum2;
j=((i==sizeOfNum1)&&(i==size))?sizeOfNum2:sizeOfNum1;
for(;i>=0;i--,j--){
//here you are adding
}
诊断
问题中显示的代码存在许多问题。这些措施包括:
- 它不是一个完整的程序,所以我们不能给出完整的分析
- 编译器通常会报告的一个bug位于以下部分:
当然,if (i == 0 && num2Copy[i]=='1') //Two's complement num2Copy[i] == '1'; else num2Copy[size - i] = num2[*sizeOfNum2-i];
正文中的if
应该是=
。编译器通常会抱怨语句无效=
- 分配指针
和sizeOfNum1
,但无法释放它们。您应该创建简单变量,并将这些变量的地址传递给函数sizeOfNum2
- 您为长字符串的两个副本加上一个空字节分配空间,但不允许为可能需要的进位分配空间。将两个二进制数相加可能会产生一个比较长的输入多出一位数的结果——十进制加法或任何其他基数的加法也是如此
- 您没有检查分配是否成功;你轻率地认为他们会。这是危险的
- 不清楚你为什么需要两份
- 您没有提供返回任何数据的机制。您的
函数声明为返回sumOfBinString()
,但不包含char*
语句。那是一只虫子。据推测,您应该返回其中一份副本,但您应该如何处理另一份?释放它是最低限度的——但你可能无论如何都不需要它return
- 您可以替换代码:
与: 这就产生了两个以null结尾的字符串,int i; for(i = size; i >= 0; i--) { num1Copy[i] = '0'; num2Copy[i] = '0'; }
返回的内存不能保证为零,这就是为什么还有malloc()
的原因calloc()
- 我可能会在
中使用一个局部变量作为计数器,并在返回之前为指针参数赋值一次。然而,你所写的是可以辩护的isNum()
- 您拥有以下代码片段:
这两个不同的变量if (isNum(num1, sizeOfNum1) && isNum(num2, sizeOfNum2)) { if (*sizeOfNum1 > *sizeOfNum2) { int size = (*sizeOfNum1); } else { int size = (*sizeOfNum2); } } char *num1Copy = (char *)malloc((size+1) * sizeof(char));
不在它们的代码块中使用,在调用size
时,这两个变量都不可访问。那代码无法编译。如果您提供非编译代码,请礼貌地这样说,并在问题中包含错误消息的文本malloc()
- “两个补充”的说法很神秘。在不知道值有多大的情况下,不能有两个补码二进制值。您可以使用32位或64位2的补码,但在不知道需要多少位的情况下,您无法判断前一位是符号位还是常规大小位。类似的注释适用于一个人的补码值。您可以使用
字符表示负数来管理符号和大小。然后,您必须对处理进行大量修改。您的代码只能处理无符号二进制数 我想如果你规定正数有一个前导零,负数有一个前导一,那么你可以使用二的补码,但是前导零通常被认为是无关紧要的。如果你真的那样使用2的补码,你还有很多工作要做-
- 我相当肯定还有其他问题——但进一步的诊断可能是不明智的
const char*binarySum(const char*num1,const char*num2)
,该函数获取2个二进制数,表示为字符串,并返回它们的总和,表示为字符串(二进制数)。注意:如果输入无效,函数应返回字符串“0”
我所写的代码使用了我在GitHub上的(堆栈溢出问题)存储库中可用的一些库代码,作为子目录中的文件stderr.c
、stderr.h
、debug.c
和debug.h
(间接地kludge.c
和kludge.h
)。提供的宏和函数允许我在代码中包含调试信息
为了编译代码(源代码binsum83.c
;测试程序binsum83
),我在一个目录中构建了该程序,其中包含一个子目录inc
,其中包含标题,另一个子目录lib
包含一个库libsoq.a
,其中包含库函数:
gcc -O3 -g -I./inc -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes \
-DTEST -DDEBUG binsum83.c -o binsum83 -L./lib -lsoq
-DTEST
标志构建程序-如果省略它,它将创建一个仅包含公开函数binarySum()
和隐藏(static
)函数的文件,而不包含main()
函数。-DDEBUG
标志启用跟踪机制-如果省略它,则设置调试级别的-d level
选项仍被接受,但它没有任何用处
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "debug.h"
#include "stderr.h"
/* External interface - result is not constant */
extern char *binarySum(const char *s1, const char *s2);
static bool is_binary(const char *str)
{
assert(*str != '\0');
for (const char *digit = str; *digit != '\0'; digit++)
{
if (*digit != '0' && *digit != '1')
return false;
}
return true;
}
static inline size_t max(size_t s1, size_t s2) { return (s1 > s2) ? s1 : s2; }
static void reverse_bytes(char *s1, char *s2)
{
assert(s2 >= s1);
while (s1 < s2)
{
char t = *s1;
*s1++ = *s2;
*s2-- = t;
}
}
static inline int binary_digit(const char *str, size_t len, size_t idx)
{
int result = 0;
if (idx < len)
result = str[len - 1 - idx] - '0';
DB_TRACE(3, "%s(): %16s (%2zu) [%2zu] = %d\n", __func__, str, len, idx, result);
return result;
}
static const char *skip_leading_zeros(const char *s1)
{
while (s1[0] == '0' && s1[1] != '\0')
s1++;
return s1;
}
char *binarySum(const char *s1, const char *s2)
{
DB_TRACE(1, "-->> %s(): evaluate %s + %s\n", __func__, s1, s2);
/* Return 0 if either of the inputs is not a valid binary number */
if (!is_binary(s1) || !is_binary(s2))
s1 = s2 = "0";
s1 = skip_leading_zeros(s1);
s2 = skip_leading_zeros(s2);
size_t len1 = strlen(s1);
size_t len2 = strlen(s2);
size_t maxlen = max(len1, len2);
DB_TRACE(2, "%s(): len(%s) = %zu; len(%s) = %zu; max = %zu\n", __func__, s1, len1, s2, len2, maxlen);
char *result = malloc(maxlen + 2);
if (result == 0)
{
DB_TRACKING();
err_sysrem("%s(): failed to allocate %zu bytes of memory\n", __func__, maxlen);
return 0;
}
char *rp = result;
int carry = 0;
for (size_t i = 0; i < maxlen; i++)
{
int d1 = binary_digit(s1, len1, i);
int d2 = binary_digit(s2, len2, i);
int r = d1 + d2 + carry;
DB_TRACE(2, "%s(): d1 = %d, d2 = %d, c = %d, r = %d\n", __func__, d1, d2, carry, r);
assert(r >= 0 && r <= 3);
*rp++ = (r & 1) + '0';
carry = r >> 1;
}
if (carry)
*rp++ = '1';
*rp = '\0';
DB_TRACE(2, "%s(): reverse = %s\n", __func__, result);
reverse_bytes(result, rp - 1);
DB_TRACE(2, "%s(): forward = %s\n", __func__, result);
DB_TRACE(1, "<<-- %s(): %s + %s = %s\n", __func__, s1, s2, result);
return result;
}
#ifdef TEST
#include <unistd.h>
static const char optstr[] = "hd:";
static const char usestr[] = "[-h][-d debug] binary1 binary2";
static const char hlpstr[] =
" -d debug Set debug level (0..3)\n"
" -h Print this help message and exit\n"
;
int main(int argc, char **argv)
{
err_setarg0(argv[0]);
int opt;
while ((opt = getopt(argc, argv, optstr)) != -1)
{
switch (opt)
{
case 'd':
db_setdebug(atoi(optarg));
break;
case 'h':
err_help(usestr, hlpstr);
/* NOTREACHED */
default:
err_usage(usestr);
/* NOTREACHED */
}
}
if (optind != argc - 2)
err_usage(usestr);
const char *num1 = argv[optind + 0];
const char *num2 = argv[optind + 1];
char *result = binarySum(num1, num2);
if (result == 0)
exit(EXIT_FAILURE);
printf("%s + %s = %s\n", num1, num2, result);
free(result);
return EXIT_SUCCESS;
}
#endif /* TEST */
这并不难
gcc -O3 -g -I./inc -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes \
-DTEST -DDEBUG binsum83.c -o binsum83 -L./lib -lsoq
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "debug.h"
#include "stderr.h"
/* External interface - result is not constant */
extern char *binarySum(const char *s1, const char *s2);
static bool is_binary(const char *str)
{
assert(*str != '\0');
for (const char *digit = str; *digit != '\0'; digit++)
{
if (*digit != '0' && *digit != '1')
return false;
}
return true;
}
static inline size_t max(size_t s1, size_t s2) { return (s1 > s2) ? s1 : s2; }
static void reverse_bytes(char *s1, char *s2)
{
assert(s2 >= s1);
while (s1 < s2)
{
char t = *s1;
*s1++ = *s2;
*s2-- = t;
}
}
static inline int binary_digit(const char *str, size_t len, size_t idx)
{
int result = 0;
if (idx < len)
result = str[len - 1 - idx] - '0';
DB_TRACE(3, "%s(): %16s (%2zu) [%2zu] = %d\n", __func__, str, len, idx, result);
return result;
}
static const char *skip_leading_zeros(const char *s1)
{
while (s1[0] == '0' && s1[1] != '\0')
s1++;
return s1;
}
char *binarySum(const char *s1, const char *s2)
{
DB_TRACE(1, "-->> %s(): evaluate %s + %s\n", __func__, s1, s2);
/* Return 0 if either of the inputs is not a valid binary number */
if (!is_binary(s1) || !is_binary(s2))
s1 = s2 = "0";
s1 = skip_leading_zeros(s1);
s2 = skip_leading_zeros(s2);
size_t len1 = strlen(s1);
size_t len2 = strlen(s2);
size_t maxlen = max(len1, len2);
DB_TRACE(2, "%s(): len(%s) = %zu; len(%s) = %zu; max = %zu\n", __func__, s1, len1, s2, len2, maxlen);
char *result = malloc(maxlen + 2);
if (result == 0)
{
DB_TRACKING();
err_sysrem("%s(): failed to allocate %zu bytes of memory\n", __func__, maxlen);
return 0;
}
char *rp = result;
int carry = 0;
for (size_t i = 0; i < maxlen; i++)
{
int d1 = binary_digit(s1, len1, i);
int d2 = binary_digit(s2, len2, i);
int r = d1 + d2 + carry;
DB_TRACE(2, "%s(): d1 = %d, d2 = %d, c = %d, r = %d\n", __func__, d1, d2, carry, r);
assert(r >= 0 && r <= 3);
*rp++ = (r & 1) + '0';
carry = r >> 1;
}
if (carry)
*rp++ = '1';
*rp = '\0';
DB_TRACE(2, "%s(): reverse = %s\n", __func__, result);
reverse_bytes(result, rp - 1);
DB_TRACE(2, "%s(): forward = %s\n", __func__, result);
DB_TRACE(1, "<<-- %s(): %s + %s = %s\n", __func__, s1, s2, result);
return result;
}
#ifdef TEST
#include <unistd.h>
static const char optstr[] = "hd:";
static const char usestr[] = "[-h][-d debug] binary1 binary2";
static const char hlpstr[] =
" -d debug Set debug level (0..3)\n"
" -h Print this help message and exit\n"
;
int main(int argc, char **argv)
{
err_setarg0(argv[0]);
int opt;
while ((opt = getopt(argc, argv, optstr)) != -1)
{
switch (opt)
{
case 'd':
db_setdebug(atoi(optarg));
break;
case 'h':
err_help(usestr, hlpstr);
/* NOTREACHED */
default:
err_usage(usestr);
/* NOTREACHED */
}
}
if (optind != argc - 2)
err_usage(usestr);
const char *num1 = argv[optind + 0];
const char *num2 = argv[optind + 1];
char *result = binarySum(num1, num2);
if (result == 0)
exit(EXIT_FAILURE);
printf("%s + %s = %s\n", num1, num2, result);
free(result);
return EXIT_SUCCESS;
}
#endif /* TEST */
const char *result = binarySum("101", "1");
printf("%s\n", result);
free(result);
binsum83 -d 3 001 000001
binsum83 -d 4 000 00000
binsum83 -d 4 000 000001
binsum83 -d 4 001 000001
binsum83 -d 5 00011010110101 000001
binsum83 -d 5 001 000001
binsum83 0 0
binsum83 0 1
binsum83 000 00000
binsum83 000 000001
binsum83 00011010110101 000001
binsum83 001 000001
binsum83 011011101 000001
binsum83 1 1
binsum83 101 1
binsum83 101 111
binsum83 101010101101101010101101010101110101010101010100010101111101010101010011100110101101010100100 101010111111010101011101110101011010101110001000011110101110101011011010101001010101011101010101010110111111111111110101010111111
binsum83 101111 10001
binsum83 11001 1111
binsum83 11010 000001
binsum83 111 1
$ sh -x test.binsum83.sh
+ binsum83 -d 3 001 000001
-->> binarySum(): evaluate 001 + 000001
binarySum(): len(1) = 1; len(1) = 1; max = 1
binary_digit(): 1 ( 1) [ 0] = 1
binary_digit(): 1 ( 1) [ 0] = 1
binarySum(): d1 = 1, d2 = 1, c = 0, r = 2
binarySum(): reverse = 01
binarySum(): forward = 10
<<-- binarySum(): 1 + 1 = 10
001 + 000001 = 10
+ binsum83 -d 4 000 00000
-->> binarySum(): evaluate 000 + 00000
binarySum(): len(0) = 1; len(0) = 1; max = 1
binary_digit(): 0 ( 1) [ 0] = 0
binary_digit(): 0 ( 1) [ 0] = 0
binarySum(): d1 = 0, d2 = 0, c = 0, r = 0
binarySum(): reverse = 0
binarySum(): forward = 0
<<-- binarySum(): 0 + 0 = 0
000 + 00000 = 0
+ binsum83 -d 4 000 000001
-->> binarySum(): evaluate 000 + 000001
binarySum(): len(0) = 1; len(1) = 1; max = 1
binary_digit(): 0 ( 1) [ 0] = 0
binary_digit(): 1 ( 1) [ 0] = 1
binarySum(): d1 = 0, d2 = 1, c = 0, r = 1
binarySum(): reverse = 1
binarySum(): forward = 1
<<-- binarySum(): 0 + 1 = 1
000 + 000001 = 1
+ binsum83 -d 4 001 000001
-->> binarySum(): evaluate 001 + 000001
binarySum(): len(1) = 1; len(1) = 1; max = 1
binary_digit(): 1 ( 1) [ 0] = 1
binary_digit(): 1 ( 1) [ 0] = 1
binarySum(): d1 = 1, d2 = 1, c = 0, r = 2
binarySum(): reverse = 01
binarySum(): forward = 10
<<-- binarySum(): 1 + 1 = 10
001 + 000001 = 10
+ binsum83 -d 5 00011010110101 000001
-->> binarySum(): evaluate 00011010110101 + 000001
binarySum(): len(11010110101) = 11; len(1) = 1; max = 11
binary_digit(): 11010110101 (11) [ 0] = 1
binary_digit(): 1 ( 1) [ 0] = 1
binarySum(): d1 = 1, d2 = 1, c = 0, r = 2
binary_digit(): 11010110101 (11) [ 1] = 0
binary_digit(): 1 ( 1) [ 1] = 0
binarySum(): d1 = 0, d2 = 0, c = 1, r = 1
binary_digit(): 11010110101 (11) [ 2] = 1
binary_digit(): 1 ( 1) [ 2] = 0
binarySum(): d1 = 1, d2 = 0, c = 0, r = 1
binary_digit(): 11010110101 (11) [ 3] = 0
binary_digit(): 1 ( 1) [ 3] = 0
binarySum(): d1 = 0, d2 = 0, c = 0, r = 0
binary_digit(): 11010110101 (11) [ 4] = 1
binary_digit(): 1 ( 1) [ 4] = 0
binarySum(): d1 = 1, d2 = 0, c = 0, r = 1
binary_digit(): 11010110101 (11) [ 5] = 1
binary_digit(): 1 ( 1) [ 5] = 0
binarySum(): d1 = 1, d2 = 0, c = 0, r = 1
binary_digit(): 11010110101 (11) [ 6] = 0
binary_digit(): 1 ( 1) [ 6] = 0
binarySum(): d1 = 0, d2 = 0, c = 0, r = 0
binary_digit(): 11010110101 (11) [ 7] = 1
binary_digit(): 1 ( 1) [ 7] = 0
binarySum(): d1 = 1, d2 = 0, c = 0, r = 1
binary_digit(): 11010110101 (11) [ 8] = 0
binary_digit(): 1 ( 1) [ 8] = 0
binarySum(): d1 = 0, d2 = 0, c = 0, r = 0
binary_digit(): 11010110101 (11) [ 9] = 1
binary_digit(): 1 ( 1) [ 9] = 0
binarySum(): d1 = 1, d2 = 0, c = 0, r = 1
binary_digit(): 11010110101 (11) [10] = 1
binary_digit(): 1 ( 1) [10] = 0
binarySum(): d1 = 1, d2 = 0, c = 0, r = 1
binarySum(): reverse = 01101101011
binarySum(): forward = 11010110110
<<-- binarySum(): 11010110101 + 1 = 11010110110
00011010110101 + 000001 = 11010110110
+ binsum83 -d 5 001 000001
-->> binarySum(): evaluate 001 + 000001
binarySum(): len(1) = 1; len(1) = 1; max = 1
binary_digit(): 1 ( 1) [ 0] = 1
binary_digit(): 1 ( 1) [ 0] = 1
binarySum(): d1 = 1, d2 = 1, c = 0, r = 2
binarySum(): reverse = 01
binarySum(): forward = 10
<<-- binarySum(): 1 + 1 = 10
001 + 000001 = 10
+ binsum83 0 0
0 + 0 = 0
+ binsum83 0 1
0 + 1 = 1
+ binsum83 000 00000
000 + 00000 = 0
+ binsum83 000 000001
000 + 000001 = 1
+ binsum83 00011010110101 000001
00011010110101 + 000001 = 11010110110
+ binsum83 001 000001
001 + 000001 = 10
+ binsum83 011011101 000001
011011101 + 000001 = 11011110
+ binsum83 1 1
1 + 1 = 10
+ binsum83 101 1
101 + 1 = 110
+ binsum83 101 111
101 + 111 = 1100
+ binsum83 101010101101101010101101010101110101010101010100010101111101010101010011100110101101010100100 101010111111010101011101110101011010101110001000011110101110101011011010101001010101011101010101010110111111111111110101010111111
101010101101101010101101010101110101010101010100010101111101010101010011100110101101010100100 + 101010111111010101011101110101011010101110001000011110101110101011011010101001010101011101010101010110111111111111110101010111111 = 101010111111010101011101110101011011011000110110001001011100000001001111111110101001110011010010101100010011100110100010101100011
+ binsum83 101111 10001
101111 + 10001 = 1000000
+ binsum83 11001 1111
11001 + 1111 = 101000
+ binsum83 11010 000001
11010 + 000001 = 11011
+ binsum83 111 1
111 + 1 = 1000
$
$ bc
bc 1.06
Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
obase=2
ibase=2
101010101101101010101101010101110101010101010100010101111101010101010011100110101101010100100 + 101010111111010101011101110101011010101110001000011110101110101011011010101001010101011101010101010110111111111111110101010111111
10101011111101010101110111010101101101100011011000100101110000000100\
1111111110101001110011010010101100010011100110100010101100011
quit
$