一.问题描述:
In the popular spreadsheets systems (for example, in Excel) the following numeration of columns is used. The first column has number A, the second — number B, etc. till column 26 that is marked by Z. Then there are two-letter numbers: column 27 has number AA, 28 — AB, column 52 is marked by AZ. After ZZ there follow three-letter numbers, etc.
The rows are marked by integer numbers starting with 1. The cell name is the concatenation of the column and the row numbers. For example, BC23 is the name for the cell that is in column 55, row 23.
Sometimes another numeration system is used: RXCY, where X and Y are integer numbers, showing the column and the row numbers respectfully. For instance, R23C55 is the cell from the previous example.
Your task is to write a program that reads the given sequence of cell coordinates and produce each item written according to the rules of another numeration system.
二.问题分析
以题目所给数据作为参考,对于每一输入字符串我们应首先识别要转换的模式。我们不妨将类似R23C55转化为BC23的模式转化记为模式1,将BC23转化为R23C55的模式记为模式0。我们先设计一recongnize函数来识别所给字符串为模式1或2。
int recongize(char st[max]){//识别所给字符串需要转换的种类
// 1:为R23C55转BC23
// 0: 为BC23转R23C55
int i,j;
int len=strlen(st);
j=0;
while (st[j]>57){//先找到数字,若之后还有字母则为C55
j++;
}
for (i=j;i<len+1;i++){
if (st[i]>57){
return(1);
}
}
return(0);
}
再依次对模式1或2进行处理。
模式1:
我们可以看到R后面的数字没有发生变化,故简单保留下来就可以了。而对于如何处理C后面的数字55便是关键,根据题意我们可以将55->BC的转化看为10进制转化为类26进制(并不是真正的26进制,在该种进制中没有0,而有Z代表的26,而十进制中是没有10对应的单个字符的),根据进制转化的规则我们既可以完成转化。
模式0:
同样BC后23只需保留即可,然后将类26进制BC转化为55即可。
三.实现过程中可能遇到的问题
1.在寻找字符串中字符为数字或字符时,我们会碰到如何识别一个字符到底是数字还是字母的问题,这时候我们可以利用ASCII标准交换码
因为在C语言中字符型和整型可以直接转化,对于下面比较有
compare(){
char a='5';
int i=52;
int d;
d=(int) a;//通过(int) a将d转化成a相对应的ascii码
if (a>i) {//直接比较是a(char)会转化成a(int)
printf("0");
}
else {
printf("1");
}
if (a>i) {
printf("0");
}
else {
printf("1");
}
return;
}
我们可以通过类似来实现将a的ascii编码赋予d,以便于后续的识别操作
d=(int) a;
2.我们可以利用atoi函数来实现从字符串到整形的转化,该函数在头文件<stdlib.h>中,相似函数有
● atof():将字符串转换为双精度浮点型值。
● atoi():将字符串转换为整型值。
● atol():将字符串转换为长整型值。
● strtod():将字符串转换为双精度浮点型值,并报告不能被转换的所有剩余数字。
● strtol():将字符串转换为长整值,并报告不能被转换的所有剩余数字。
● strtoul():将字符串转换为无符号长整型值,并报告不能被转换的所有剩余数字。
● itoa():将整型值转换为字符串。
● ltoa():将长整型值转换为字符串。
● ultoa():将无符号长整型值转换为字符串。
● gcvt():将浮点型数转换为字符串,取四舍五入。
● ecvt():将双精度浮点型值转换为字符串,转换结果中不包含十进制小数点。
● fcvt():指定位数为转换精度,其余同ecvt()。
3.在一个有返回值函数中,return的出现即意味着函数的结束。
4.注意字符串输出时格式说明符不同输出内容不同,这是因为程序在将一个字符常量放到一个字符变量中时,是将其ascii码放入,而并不是讲字符本身放到内存单元中。
//以下两种输出格式所输出的值不同
char a='5';
printf("%d",a);//输出a的ascii标准交换码
printf("%c",a);//输出字符a
四.代码实现
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<string.h>
#define max 200010
int recongize(char st[max]){//识别所给字符串需要转换的种类
// 1:为R23C55转BC23
// 0: 为BC23转R23C55
int i,j;
int len=strlen(st);
j=0;
while (st[j]>57){//先找到数字,若之后还有字母则为C55
j++;
}
for (i=j;i<len+1;i++){
if (st[i]>57){
return(1);
}
}
return(0);
}
model1(char st[max]){ //R后数字直接保留
int i,j,k,len,num[max],d,asc;
char str[max];
len=strlen(st);
for (i=len-1;i>-1;i--){//将C后数字字符储存入k中
d=(int)st[i];
if (d>57) {
for (j=i+1;j<len;j++){//复制C后字符到str中以便转化
str[j-i-1]=st[j];
}
k=atoi(str);
break;
}
}
i=0;
while ((k/26)!=0){//类似26进制倒序取余得类似BC
num[i]=k%26;
k=k/26;
i++;
}
num[i]=k;
for (j=i;j>-1;j--){//输出字符
k=num[j]+64;
printf("%c",k);
}
for (i=0;i<len;i++){//输出数字
d=(int) st[i];
if(d<58){
j=i;
asc=(int) st[j];
while (asc<58){
printf("%c",st[j]);
j++;
asc=(int) st[j];
}
break;
}
}
printf("\n");
}
model0(char st[max]){//字符后数字保留,类似将26进制转化为10进制
int i,j,k,len,num,d,key;
len=strlen(st);
key=-1;
for (i=0;i<len;i++){
d=(int) st[i];
if (d<58){
if (key==-1){
key=i;
}
}
}
printf("R");//输出字符串
for (j=key;j<len;j++){
printf("%c",st[j]);
}
k=0;
num=0;
for (j=key-1;j>-1;j--){
num=num+(st[j]-64)*pow(26,k);//将26进制转化为10进制
k++;
}
printf("C%d",num);
printf("\n");
}
main(){//主函数输入n与字符串
int n,i,j;
char st1[max];
scanf("%d",&n);
for (i=0;i<n;i++){
scanf("%s",&st1);
if (recongize(st1)==1){//识别类型
model1(st1);
}
else{
model0(st1);
}
}
return 0;
}