• 重写:求比指定数大且最小的“不重复数”问题


     问题:给定任意一个正整数,求比这个数大且最小的“不重复数”,“不重复数”的含义是相邻两位不相同,例如1101是重复数,而1201是不重复数.

    我之前写过一个(传送门:求比指定数大且最小的“不重复数”问题),里面总结了些不足的地方,就没有想去重写。

    直到被 garbageMan 给教育了一番 (传送门:评playerc网友的"求比指定数大且最小的“不重复数”问题"),我才发现,写的太差劲了。

    在此感谢 garbageMan 的教导。不多说,下面附上代码,有什么错误还希望大家多指点.

    #include <stdio.h>
    #include <ctype.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define BCD_UINT_MAX_LENGTH (12)
    /* 这里 garbageMan 指出 存在潜在的错误,两边要加上括号;(其实回家检查的时候我也发现了)
    #define min(a,b)  (a) < (b) ? (a) : (b)
    改成如下代码
    */
    #define min(a,b) ((a) < (b) ? (a) : (b))
    
    /* bcd unsigned integer
       little endian
    */
    struct bcd_uint{
    	unsigned char value[BCD_UINT_MAX_LENGTH];
    	unsigned int length;
    };
    
    /*  从标准输入获得 bcd_uint */
    struct bcd_uint * bcd_uint_get(struct bcd_uint * v);
    
    /* 在指定的位置加 1. 返回进位影响的最高位的下标 */
    unsigned int bcd_uint_inc(struct bcd_uint *v, unsigned int where);
    
    /* 输出 bcd_uint */
    void bcd_uint_print(struct bcd_uint v);
    
    /*** utils ****/
    /*** 获得最小不重复数 ***/
    struct bcd_uint * find(struct bcd_uint v);
    
    /* 反转字符串 */
    void str_reverse(unsigned char *str, unsigned int length);
    
    /* 交换字符*/
    void exchange(unsigned char * a, unsigned char *b);
    
    /* 得到最右边开始第一次出现重复字的最小下标的地址 */
    unsigned char * get_repeat_item(unsigned char * v, unsigned int length);
    
    int main(void)
    {
    	struct bcd_uint num = {{0u},0u};
    	struct bcd_uint *res = NULL;
    
    	printf("Please input Unsigned Integer : ");
    	
    	if (bcd_uint_get(&num) == NULL) return 1;
    	
    	res = find(num);
    	bcd_uint_print(*res);
    	
    	free(res);
    	return 0;	
    }
    
    void str_reverse(unsigned char *str, unsigned int length)
    {
    	unsigned char *last;
    	if (length < 2) {
    		return;
    	}
    
    	for (last = str + length -1; last > str; ++str, --last){		
    		exchange(str,last);
    	}
    }
    
    void exchange(unsigned char * a, unsigned char *b)
    {
    /* cpoint 同学指出 这个地方存在潜在的错误,比如 a=b 的时候
    		*a ^= *b;
    		*b ^= *a;
    		*a ^= *b;
      于是,改成下面通用的代码 
    */
         unsigned char c;
         c = *a;
        *a = *b;
        *b = c;
    }
    
    struct bcd_uint * find(struct bcd_uint v)
    {
    	unsigned int search_length ;
    	unsigned char * finded;
    	unsigned char * last_finded;
    	struct bcd_uint *res = (struct bcd_uint *)malloc(sizeof (struct bcd_uint));
    
    	res->length = v.length;
    	memcpy(res->value, v.value, sizeof (unsigned char) * v.length);
    
    	bcd_uint_inc(res, 0); /* v + 1 */
    
    	search_length = res->length;
    	last_finded = res->value;
    
            /* 在最后一次找到重复的位置开始,查找指定的长度。 */
    	while ((finded = get_repeat_item(last_finded, search_length)) != NULL){
    
    		/* 在找到重复的位置+1,并依据进位影响的位置 设置搜索长度 */
    		search_length  = bcd_uint_inc(res, finded - res->value) + 1;	
    		search_length = min(search_length, res->length);
    		search_length = search_length - (finded - res->value);
    
    		last_finded = finded;
    	}
    
    	
    	/* set rests as 010101010 */
    	/* *last_finded will never be 0 */
    	while (last_finded > res->value){		
    		*(last_finded-1) = !*last_finded;
    		-- last_finded;
    	}
    
    	return res;
    }
    
    unsigned char * get_repeat_item(unsigned char * v, unsigned int length)
    {
    	unsigned char * cur;
    
    	if (length < 2){
    		return NULL;
    	}
    
    	cur = v + length -1;
    	
    	while (cur > v){
    		if ( *cur == *(cur - 1)){
    			return cur-1;
    		}
    		-- cur;
    	}
    
    	return NULL;
    }
    
    struct bcd_uint * bcd_uint_get(struct bcd_uint * v)
    {
    	unsigned char c;
    	for (v->length = 0; !feof(stdin); ++ v->length){
    
    		/* 因为最高位可能进 1 所以 -1*/
    		if (v->length > (BCD_UINT_MAX_LENGTH - 1)){
    			fprintf(stderr, "The input is too long!
    ");
    			return NULL;
    		}
    
    		c = getc(stdin);
    		if (c == '
    ' || c == ''){
    			break;
    		}
    		if (!isdigit(c)){
    			fprintf(stderr, "Please input Unsigned Integer!
    ");
    			return NULL;
    		}
    		v->value[v->length] = c - '0';		       		
    	}
    	str_reverse(v->value, v->length);
    
    	return v;
    }
    
    void bcd_uint_print(struct bcd_uint v)
    {
    	unsigned char * last ;
    
    	last = v.value + v.length; 
    	while(last > v.value){
    		-- last;
    		putchar( *last + '0');
    	}
    	putchar('
    ');
    }
    
    unsigned int bcd_uint_inc(struct bcd_uint *v, unsigned int where)
    {
    	unsigned int carry ;
    
    	for (carry = 1; carry != 0 && where < v->length; ++ where){
    		v->value[where] += carry;
    		carry = v->value[where] / 10;
    		v->value[where] %= 10;		
    	} 
    
    	if (carry != 0){
    		v->value[where] = carry;
    		++ v->length;
    	}
    	else {
    		/* 执行这里的时候 where 指向进位影响的下一个,所以减掉*/
    		--where;
    	}
    	return where;
    }
    

     总结:

    1. 无论写的函数在代码中是否出错,只要存在可能的错误,这个函数就是需要重写。(本质上是进行全面的测试)
    2. 定义宏是如果是完整的一体的运算就要括起来。
  • 相关阅读:
    环形链表II 找环入口
    最短无序连续子数组 复制数组排序后与原数组相比
    和为K的子数组 暴力 或 hash+前缀
    在排序数组中查找元素的第一个和最后一个位置 二分法+递归
    NodeJs 批量重命名文件,并保存到指定目录
    NodeJs 批量图片瘦身,重设尺寸和图片质量并保存到指定目录
    NodeJs 获取照片拍摄日期和视频拍摄日期,并按日期目录存档
    Oracle迁移记录
    Oracle数据库迁移前的准备工作(创建用户并且分配权限及表空间)
    Oracle 11g R2性能优化 10046 event【转载】
  • 原文地址:https://www.cnblogs.com/playerc/p/3372832.html
Copyright © 2020-2023  润新知