编写一个程序,从标准输入读取一些字符,并把他们写到标准输出上,它同时应该计算checksum值,并写在字符的后面。
checksum(检验和)用一个sunged char 类型的变量进行计算,它初始为-1.当每个字符从标准输入读取时,它的值就被加到checksum中。如果checksum变量产出了溢出,那么这些溢出就会被忽略。当所有的字符均被写入后,程序以十进制整数的形式打印出checksum的值,它有可能是负值。注意在checksum后面要添加一个换行符。在使用ASSII码的计算机中,在包含“Hello world!”这几个词并以换行符结尾的文件上运行这个程序,应该产生以下列输出:
Hello world!
102
#include<stdio.h>
int main(){
signed char checksum = -1;
signed char c;
while( ( c = getchar() ) != '\n' )
{
checksum += c;
printf("checksum: %d c: %d\n", checksum, c);
}
checksum += c;
printf("\n%d\n", checksum);
return 0;
}
解释:
计算机用的是补码运算的,而通过printf显示给我们看的是原码,通过补码运算得到。
第一位是符号位,
正数 = 原码 = 反码 = 补码
负数 = 原码 = [符号位][真值]
负数反码 = [符号位][真值取反]
负数补码 = [符号位][真值取反 + 1]
以下所有加减均用补码
DEC是十进制的意思
-1:1000 0001 反码:1111 1110 补码:1111 1111
H: 0100 1000
checksum = H + (-1)= 0100 1000 + 1111 1111 = 0100 0111
e: 0110 0101
checksum = e + checksum = 0110 0101 + 0100 0111 = 1010 1100
此时checksum为补码,获得真值就要补码-1,除符号位外其它位取反
1010 1100 - 1 = 1010 1011
1010 1011取反 = 1101 0100 = - 2^6 + 2^4 + 2^2 = -84
l: 0110 1100
checksum = l + checksum = 0110 1100 + 1010 1100 = 0001 1000
checksum = 0001 1000 = 2^4 + 2^3 = 24
l: 0110 1100
checksum = l + checksum = 0110 1100 + 0001 1000 = 1000 0100
1000 0100 - 1 = 1000 0011
1000 0011取反 = 1111 1100 = -2^6 + 2^5 + 2^4 + 2^3 + 2^2 = -124
o: 0110 1111
checksum = o + checksum = 0110 1111 + 1000 0100 = 1111 0011
1111 0011 - 1 = 1111 0010
1111 0010取反 = 1000 1101 = -2^3 + 2^2 + 2^0 = -13
空格:0010 0000
checksum = 空格 + checksum = 0010 0000 + 1111 0011 = 0001 0011
checksum = 0001 0011 = 2^4 + 2^1 + 2^0 = 19
w: 0111 0111
checksum = w + checksum = 0111 0111 + 0001 0011 = 1000 1010
1000 1010 - 1 = 1000 1001
1000 1001取反 = 1111 0110 = -2^6 + 2^5 + 2^4 + 2^2 + 2^1 = -118
o:0110 1111
checksum = o + checksum = 0110 1111 + 1000 1010 = 1111 1001
1111 1001 - 1 = 1111 1000
1111 1000取反 = 1000 0111 = -2^2 + 2^1 + 2^0 = -7
r:0111 0010
checksum = r + checksum = 0111 0010 + 1111 1001 = 0110 1011
0110 1011 = 2^6 + 2^5 + 2^3 + 2^1 + 2^0 = 107
l:0110 1100
checksum = l + checksum = 0110 1100 + 0110 1011 = 1101 0111
1101 0111 - 1 = 1101 0110
1101 0110取反:1010 1001 = -2^5 +2^3 + 2^0 = -41
d:0110 0100
checksum = d + checksum = 0110 0100 + 1101 0111 = 0011 1011
checksum = 0011 1011 = 2^5 + 2^4 + 2^3 + 2^1 + 2^0 = 59
!:0010 0001
checksum = ! + checksum = 0010 0001 + 0011 1011 = 0101 1100
checksum = 0101 1100 = 2^6 + 2^4 + 2^3 + 2^2 = 92
'\n’回车:0000 1010
checksum = ‘\n’ + checksum = 0000 1010 + 0101 1100 = 0110 0110
checksum = 0110 0110 = 2^6 + 2^5 + 2^2 + 2^1 = 102