1044 火星数字 ——c实现

版权声明:本文为博主原创文章,转载请务必注明出处和作者,谢谢合作! https://blog.csdn.net/zhanshen112/article/details/83717872

1044 火星数字 (20 分)

火星人是以 13 进制计数的:

  • 地球人的 0 被火星人称为 tret。
  • 地球人数字 1 到 12 的火星文分别为:jan, feb, mar, apr, may, jun, jly, aug, sep, oct, nov, dec。
  • 火星人将进位以后的 12 个高位数字分别称为:tam, hel, maa, huh, tou, kes, hei, elo, syy, lok, mer, jou。

例如地球人的数字 29 翻译成火星文就是 hel mar;而火星文 elo nov 对应地球数字 115。为了方便交流,请你编写程序实现地球和火星数字之间的互译。

输入格式:

输入第一行给出一个正整数 N(<100),随后 N 行,每行给出一个 [0, 169) 区间内的数字 —— 或者是地球文,或者是火星文。

输出格式:

对应输入的每一行,在一行中输出翻译后的另一种语言的数字。

输入样例:

4
29
5
elo nov
tam

输出样例:

hel mar
may
115
13

思路:

这道题和多数进制转换的题目看起来很相似。存在的难点是如果输入的是火星文,可能会是一个两个字符串,因此字符串的分割是难点。所以这道题的难点一是判断输入的是地球数字还是火星文,第二步是分割火星文字符,其三才是两者之间的转化。

1 判断输入的语言

由于火星文是字符串,地球文是数字,因此看起来比较容易判断。但是注意,由于火星文的字符串之间有空格,所以有必要一次将整行全部读完。这里需要用到fgets()。

fgets

文件结构体指针stream中读取数据,每次读取一行。读取的数据保存在buf指向的字符数组中,每次最多读取bufsize-1个字符(第bufsize个字符赋'\0'),如果文件中的该行,不足bufsize-1个字符,则读完该行就结束。如若该行(包括最后一个换行符)的字符数超过bufsize-1,则fgets只返回一个不完整的行,但是,缓冲区总是以NULL字符结尾,对fgets的下一次调用会继续读该行。函数成功将返回buf,失败或读到文件结尾返回NULL。因此我们不能直接通过fgets的返回值来判断函数是否是出错而终止的,应该借助feof函数或者ferror函数来判断。fgets()在头文件<stdio.h>

fgets()的典型用法如下:

fgets(buffer,n,stdin)

功能是从标准输入设备键盘(也就是stdin:stdandard input)读入n-1个字符串。由于字符串结尾以"\0"结束,因此必须留出一个,也就是只能读入n-1个。buffer可是是提前定义好的数组的指针,也就是数组名。

用这种方法可以一次将一行输入全部读入buffer缓存。但是还没有进行赋值,因此下面还要将读入的信息用于赋值和判断。更准确地说,是进行判断和赋值,因此只有先判断清楚输入的是火星文还是地球文,才能决定下面怎么赋值。比如,这里先判断读到的是不是数字,可以用<ctype.h>中的isdigit()函数来进行判断,如果读到的是数字,就要进行赋值,然后从数字转换到火星文。如果读到的是火星文,也要转换到地球文。

注意,这里赋值不能再用scanf()函数,因为scanf会读入下一个输入,而非目前读进到buffer中的输入。这里需要用到能将已经读入缓存的数据进行赋值操作,这个函数是sscanf()。百度介绍如下:

sscanf与scanf类似,都是用于输入的,只是后者以键盘(stdin)为输入源,前者以固定字符串为输入源。sscanf()在头文件<stdio.h>

例如:

sscanf("1 2 3","%d %d %d",buf1, buf2, buf3); 成功调用返回值为3,即buf1,buf2,buf3均成功转换。

sscanf("1 2","%d %d %d",buf1, buf2, buf3); 成功调用返回值为2,即只有buf1,buf2成功转换。

(注意:此处buf均为地址)

      1、一般用法

1

2

3

char buf[512] = ;

sscanf("123456 ""%s", buf);

printf("%s\n", buf);

结果为:123456
  2. 取指定长度的字符串。如在下例中,取最大长度为4字节的字符串。

1

2

sscanf("123456 ""%4s", buf);

printf("%s\n", buf);

结果为:1234
  3. 取到指定字符为止的字符串。如在下例中,取遇到空格为止字符串。

1

2

sscanf("123456 abcdedf""%[^ ]", buf);

printf("%s\n", buf);

结果为:123456
  4. 取仅包含指定字符集的字符串。如在下例中,取仅包含1到9和小写字母的字符串。

1

2

sscanf("123456abcdedfBCDEF""%[1-9a-z]", buf);

printf("%s\n", buf);

结果为:123456abcdedf
  5. 取到指定字符集为止的字符串。如在下例中,取遇到大写字母为止的字符串。

1

2

sscanf("123456abcdedfBCDEF""%[^A-Z]", buf);

printf("%s\n", buf);

结果为:123456abcdedf
  6、给定一个字符串iios/12DDWDFF@122,获取 / 和 @ 之间的字符串,先将 "iios/"过滤掉,再将非'@'的一串内容送到buf中

1

2

sscanf("iios/12DDWDFF@122""%*[^/]/%[^@]", buf);

printf("%s\n", buf);

结果为:12DDWDFF
  7、给定一个字符串"hello, world",仅保留"world"。(注意:“,”之后有一空格)

1

2

sscanf("hello, world""%*s%s", buf);

printf("%s\n", buf);

结果为:world
  P.S. %*s表示第一个匹配到的%s被过滤掉,即hello被过滤了,
  如果没有空格则结果为NULL。 [2] 

补充知识:

%[a-z] 表示匹配a到z中任意字符,贪婪性(尽可能多的匹配)

%[aB'] 匹配a、B、'中一员,贪婪性

%[^a] 匹配非a的任意字符,并且停止读入,贪婪性

这样就可以完整的读入一行信息并准确的进行赋值操作。

2 分割火星文字符

由于地球文只是数字无需转化。火星文之间有空格,因此注意要将火星文断开。这里要用到strtok()函数。百度介绍如下:

strtok

分解字符串为一组字符串。s为要分解的字符,delim为分隔符字符(如果传入字符串,则传入的字符串中每个字符均为分割符)。首次调用时,s指向要分解的字符串,之后再次调用要把s设成NULL。strtok()在头文件<string.h>

原型    char *strtok(char s[], const char *delim);

功能

分解字符串为一组字符串。s为要分解的字符串,delim为分隔符字符串。

例如:strtok("abc,def,ghi",","),最后可以分割成为abc def ghi.尤其在点分十进制的IP中提取应用较多。

常用功能是这样的:

第一次可以将s的指针传进去,第二次就需要将指针置为NULL。所以常用写法如下:

str1=strtok(line," \n");
str2=strtok(line," \n");

实例:

#include <string.h>
#include <stdio.h>
int main(void)
{
    char input[16]="abc,d";
    char*p;
    /*strtok places a NULL terminator
    in front of the token,if found*/
    p=strtok(input,",");
    if(p)
        printf("%s\n",p);
        /*A second call to strtok using a NULL
        as the first parameter returns a pointer
        to the character following the token*/
    p=strtok(NULL,",");
    if(p)
        printf("%s\n",p);
    return 0;
}

输出为:

abc

d

利用上述实例中的方法就可以断开输入的火星文字符串。由于火星文可能只有一个字符串,比如整20——hel。因此建议写成如下格式:

strtok(line," \n");
strtok(NULL," \n");

3 火星文与地球文之间的转化

地球文转到火星文比较简单,取出对应的高低位,在数组中查找即可。由于有了前两步的基础,火星文转地球文也比较简单,只需要将截断之后的火星文在建立的火星文字符串数组中遍历即可,在乘以对应的进制。

完整代码:

//1044 火星数字 V1
#include <stdio.h>
#include <ctype.h>
#include <string.h>

char *units[]={"tret","jan","feb","mar","apr","may","jun","jly","aug","sep","oct","nov","dec"};
char *tens[]={"tam","hel","maa","huh","tou","kes","hei","elo","syy","lok","mer","jou"};

int Mars2Earth(char *s){
	if(s){
		int i;
		for(i=0;i<13;i++){
			if(strcmp(s,units[i])==0)	return i;	//个位数字 
		}
		for(i=1;i<13;i++){
			if(strcmp(s,tens[i-1])==0)		return i*13;	//高位数字 
		}
	}
	return 0;
}

int main(){
	int n,m,i;	
	char line[11];
	fgets(line,11,stdin);
	sscanf(line,"%d",&n);
	for(i=0;i<n;i++){
		fgets(line,11,stdin);
		if(isdigit(line[0])){	//input is num
			sscanf(line,"%d",&m);
			if(m/13&&m%13)	printf("%s %s\n",tens[m/13-1],units[m%13]);
			if(m/13&&m%13==0)	printf("%s\n",tens[m/13-1]);
			if(m/13==0)		printf("%s\n",units[m%13]);
		}	
		else{	//input is char
			m=Mars2Earth(strtok(line," \n"));
			m+=Mars2Earth(strtok(NULL," \n"));
			printf("%d\n",m);
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zhanshen112/article/details/83717872