题目来源:
鼠标悬停于此可预览题目
旧代码:
#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;
int myatoi ( char * ) ;
int main ( ) {
char str[ 100 ] ;
while ( cin >> str) {
cout << myatoi ( str) << endl;
}
return 0 ;
}
int myatoi ( char * str) {
if ( '-' == str[ 0 ] ) {
cout << "-" ;
}
for ( unsigned int i = 0 ; i < strlen ( str) ; ++ i) {
str[ i] = str[ i + 1 ] ;
}
return atoi ( str) ;
}
bug描述:
1、不符合题目要求:如果字符串真的很长了(long long int至多支持64位长度),
则无法如此转换——因为已经属于超精度范畴知识了。如此设计,至多表示int的范围,即:-2147483648至2147483647 ( 区间长度即:2^32)
2、函数设计不够上心,直接用了库函数、没有达到锻炼自身的效果。故,特此加以完善代码设计。
3、如此代码,C不像C,C++又不是,只能推倒重来。
新代码:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define N 100
using namespace std;
size_t myatoi ( char * ) ;
char * mySubstr ( char * , size_t, size_t) ;
size_t myStrlen ( char * ) ;
int
main ( ) {
char * str;
str = ( char * ) malloc ( ( N + 1 ) * sizeof ( char ) ) ;
assert ( str) ;
while ( 1 == scanf_s ( "%s" , str, N) ) {
if ( '+' != str[ 0 ] ) {
printf ( "%c" , str[ 0 ] ) ;
}
size_t len = myStrlen ( str) - 1 ;
size_t slice = 8 ;
size_t times = len / slice;
size_t remainder = len % slice;
char * s;
s = ( char * ) malloc ( ( slice + 1 ) * sizeof ( char ) ) ;
assert ( s) ;
for ( size_t i = 0 ; i < times; ++ i) {
s = mySubstr ( str, 1 + i * slice, slice) ;
printf ( "%u" , myatoi ( s) ) ;
}
if ( remainder) {
s = "\0" ;
s = mySubstr ( str, 1 + times * slice, remainder) ;
printf ( "%u" , myatoi ( s) ) ;
}
free ( s) ;
puts ( "\n" ) ;
}
free ( str) ;
return 0 ;
}
size_t myatoi ( char * str) {
size_t num = 0 ;
for ( size_t i = 0 ; str[ i] != '\0' ; ++ i) {
num = num * 10 + ( str[ i] - '0' ) ;
}
return num;
}
char * mySubstr ( char * str, size_t offset, size_t len) {
char * arr;
arr = ( char * ) malloc ( ( len + 1 ) * sizeof ( char ) ) ;
assert ( arr) ;
for ( size_t i = 0 ; i < len; ++ i) {
arr[ i] = str[ offset + i] ;
}
arr[ len] = '\0' ;
return arr;
}
size_t myStrlen ( char * str) {
size_t len = 0 ;
while ( str[ len] != '\0' ) {
++ len;
}
return len;
}
代码讲解:
1、用的C语言描述,C代码的设计和码字的过程,就是一个人思维方式和能力展示的过程。
2、全部用的自定义函数实现程序功能,不借助任何库函数。
3、设计的知识有:
(1)动态内存分配:
内存空间:有申请就得有释放,这是设计原则;
C语言版本不同于C++:C++用的new和delete(当然malloc和free也是可行),但C只能用malloc和free。
(2)字符数组和字符指针比较:
指针往往与动态内存分配结合起来使用,在声明指针的时候是不分配地址空间的,是一个虚的、不存在地址的野指针,往往需要先申请、分配了内存地址,才能够用于赋值等操作(这往往疏忽大意时的致命陷阱);
而数组则不然,因为数组是定长的数据存储结构,声明的时候内存地址和空间大小就已经定下来了。
(3)整型数的拼凑问题:
记得自己大一时候,问的C语言老师人家就是不说,就一句话——“看书去”。
其实不就是:
A. 通过 %10 实现取余即取得个位数的数字,
B. 通过 /= 10 实现当前数字所处的位数前挪即不断舍弃个位数上的数字。
但是这种思维,对初学者往往是很难去理解的,只有当自己真的读懂之后,举一反三、融会贯通。
本次涉及的代码是每8个字符长度当做一个数据块进行处理,这种思想在与密码学相关的算法设计上尤为凸出。
当然算法课的长精度运算,也是一种类似东西。
一个简单的测试:
鼠标悬停于此实现预览效果
易错点:
Top1: 没有使用判断条件,忘记了担长度刚好能够整除时的情形;
if ( remainder) {
s = "\0" ;
s = mySubstr ( str, 1 + times * slice, remainder) ;
printf ( "%u" , myatoi ( s) ) ;
}
Top2: 字符指针s在使用之前忘记分配内存空间:
s = mySubstr ( str, 1 + i * slice, slice) ;
s = mySubstr ( str, 1 + times * slice, remainder) ;
以及 忘记了判断内存分配是否成功:
assert ( str) ;
Top3: 忘记在末尾处添加'\0 \, 其实也就是内存地址越界问题:
arr[ len] = '\0' ;
Top4: malloc使用之后忘记了free
Top5: 实参列表的参数可能会出错,如果头脑不清醒些的话:
s = mySubstr ( str, 1 + i * slice, slice) ;
s = mySubstr ( str, 1 + times * slice, remainder) ;
后记
欢迎评论区留言,如能指出问题则是万分感谢!
也可发送私信、邮件:
联系方式: [email protected]
2019/11/27 21:22