No.1——洛谷新手村数字反转(升级版)P1553

这是自己的第一篇博客。留给自己做个纪念吧。
因为是洛谷的题,肯定有很多大神写了更简单的解法,我这个不够简洁应该没人会看到…
自己刚入门确实比较菜,要学习的还有很多。打算把C++学完了再重新刷一遍新手村,也能更好地理解大佬们的题解。
这题昨天下午敲了一小时,运行时发现连输出都没有…今早索性全部推倒重来,多写了几个函数。这题确实有一些坑,需要细心地注意0在整数部分和小数部分不同位置的各种情况。第一次提交有8个数据点没有过,后面修修补补才全部AC。

//开一个字符数组,存放原数据,输入,存入。
//遍历,查找特征符号,标记状态(自动机)。
//编写一个通用函数,malloc一个新的字符数组,直接将原字符串倒着存入。
//编写两个函数,用于整数和小数。根据前面确定的状态,分别调整新字符串。
//最后输出新字符串并补上特征符号。 
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//自动机的四种状态
#define INT 1 //整数
#define DEC 2 //小数
#define FRA 3 //分数
#define PER 4 //百分数
void input(char *); //把scanf和getchar合并
char* rotate(char *str, int length); //把字符串翻转
void forFRA(char *str, int length); //处理分数的函数
void forDEC(char *str, int length); //处理小数的函数
void forPER(char *str, int length); //处理百分数的函数
void forINT(char *str, int length); //处理整数的函数
char *function2(char *str); //处理末尾的0(用于小数部分翻转前、后)
char *function1(char *str); //处理开头的0 (用于翻转后的整数部分)
int status(char *str); //检测特殊字符,确定自动机状态
int main()
{
	char original[21];
	int type, length;
	input(original);
	type = status(original);
	length = strlen(original);
	switch(type)
	{
		case INT:
			forINT(original, length);
			break;
		case DEC:
			forDEC(original, length);
			break;
		case FRA:
			forFRA(original, length);
			break;
		case PER:
			forPER(original, length);
			break;
	}
}

void input(char *str)
{
	scanf("%s", str);
	getchar();
}

int status(char *str)
{
	char *temp = str;
	int flag = 1;
//若检测到特征字符,把该字符设置为空,把字符串分为两部分
//同时用flag来确定已经检测到了特殊字符,退出遍历
	while (*temp && flag == 1)
	{
		if (*temp == '.')
		{
			flag = 2;
			*temp = 0;
		} 
		else if (*temp == '/')
		{
			flag = 3;
			*temp = 0;
		}
		else if (*temp == '%')
		{
			flag = 4;
			*temp = 0;
		}
		temp++;
	}
	return flag;
}

//重新malloc一个字符数组,倒着把源字符串存进去
//最后返回新字符串的指针
//要注意的是,malloc数量应该是length+1,不能漏了'\0'
char* rotate(char *str, int length)
{
	int i;
	char *temp = (char*)malloc(sizeof(char) * length + 1);
	for (i = 0; i < length; i++)
		temp[i] = str[length - i - 1];
	temp[length] = 0;
	return temp;
}

char *function1(char *str)//用于处理整数部分 
{
	int status = 0;
	char *temp = str;
	//从前往后遍历,在遇到非0数前状态为0。若遇到非零数,改变状态。
	//因为是通过指针偏移进行访问,最后返回已经偏移的指针即可。
	while(*temp && status == 0)
	{
		if (*temp != '0')
			status = 1;
		if (status == 0)
			temp++;
	} 
	return temp;
}

char *function2(char *str)
{
	int length = strlen(str);
	int status = 0;
	//与整数部分不同,小数部分从后往前遍历。
	for(; length - 1 >= 0 && status == 0; length--)
		if(str[length - 1] == '0')
			str[length - 1] = 0;
		else
			status = 1;
	return str;
}

void forINT(char *str, int length)
{
//这里是踩的第一个坑。
//如果原字符串整数部分就是一个0,那么直接输出0即可。
//不用旋转和进入function1,否则是空字符。
	if(*str == '0')
		printf("0");
	else
	{
		char* reverse = rotate(str, length);
		printf("%s",function1(reverse));
		//不要忘记free掉malloc的内存
		free(reverse);
	}
}

void forPER(char *str, int length)
{
	forINT(str, length);
	//这里也有个小细节,printf中百分号要打两个,否则编译器会认为是少了转换说明
	printf("%%");
}

void forDEC(char *str, int length)
{
//这里是第二个坑
//对于源字符串的小数部分,如果原本末尾就有0,那应该是舍去的。
//例如12.560,应该是以21.65进行翻转。否则,21.065是错误的结果。
//因此,应该在翻转之前进行一次末尾去0,保证有效数字位数正确。
	char* pfloat = function2(str + length + 1);
	pfloat = rotate(pfloat, strlen(pfloat));
	forINT(str, length);
	printf(".");
//这里是第三个坑
//按照function2的做法,从后往前遍历,只要是遇到非零数前的0全部更改为空字符。
//这就导致,如果是如123.0这样的数,会被直接输出321.
//因此,应该在function2、翻转、function2之后,判断一下是否是空字符。
//若为空字符,则直接输出0.
	if(*function2(pfloat) == 0)
		printf("0");
	else
		puts(function2(pfloat));
	free(pfloat);
}

void forFRA(char *str, int length)
{
	char* pfloat = function2(str + length + 1);
	pfloat = rotate(pfloat, strlen(pfloat));
	forINT(str, length);
	printf("/");
	if(*function2(pfloat) == 0)
		printf("0");
	else
		puts(function2(pfloat));
	free(pfloat);
}

第一次写博客。
如果有人会看到的话,欢迎指点和沟通。
实在是刚入门,技术太菜。
但是要相信自己,会进步的~
新的学期,请多多指教。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值