第六周 使用对象(第二题有详解)

1   单词长度(5分)

题目内容:你的程序要读入一行文本,其中以空格分隔为若干个单词,以‘.’结束。你要输出这行文本中每个单词的长度。这里的单词与语言无关,可以包括各种符号,比如“it's”算一个单词,长度为4。注意,行中可能出现连续的空格。

输入格式:输入在一行中给出一行文本,以‘.’结束,结尾的句号不能计算在最后一个单词的长度内。

输出格式:在一行中输出这行文本对应的单词的长度,每个长度之间以空格隔开,行末没有最后的空格。

输入样例:It's great to see you here.

输出样例:4 5 2 3 3 4

代码实现:

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {

		Scanner in = new Scanner ( System.in );
		String s = in.nextLine();
		
//		System.out.println(s);

		int number = 0;
		for ( int i=0 ; i<s.length() ; i++ ) {
			number++;
			if ( i>0 ) {
				if ( s.charAt(i)==' ' ) {
					if ( s.charAt(i-1)!=' ' )
						System.out.print((number-1)+" ");
					number = 0;
				}
				if ( s.charAt(i)=='.' ) {
					if ( s.charAt(i-1)!=' ' )
						System.out.print(number-1);
					else 
						System.out.print("0");
				}
			}
		}
		
		in.close();
	}

}

2   GPS数据处理(5分)

题目内容:

NMEA-0183协议是为了在不同的GPS(全球定位系统)导航设备中建立统一的BTCM(海事无线电技术委员会)标准,由美国国家海洋电子协会(NMEA-The National Marine Electronics Associa-tion)制定的一套通讯协议。GPS接收机根据NMEA-0183协议的标准规范,将位置、速度等信息通过串口传送到PC机、PDA等设备。
NMEA-0183协议是GPS接收机应当遵守的标准协议,也是目前GPS接收机上使用最广泛的协议,大多数常见的GPS接收机、GPS数据处理软件、导航软件都遵守或者至少兼容这个协议。
NMEA-0183协议定义的语句非常多,但是常用的或者说兼容性最广的语句只有$GPGGA、$GPGSA、$GPGSV、$GPRMC、$GPVTG、$GPGLL等。其中$GPRMC语句的格式如下
$GPRMC,024813.640,A,3158.4608,N,11848.3737,E,10.05,324.27,150706,,,A*50
这里整条语句是一个文本行,行中以逗号“,”隔开各个字段,每个字段的大小(长度)不一,这里的示例只是一种可能,并不能认为字段的大小就如上述例句一样。
字段0:$GPRMC,语句ID,表明该语句为Recommended Minimum Specific GPS/TRANSIT Data(RMC)推荐最小定位信息
字段1:UTC时间,hhmmss.sss格式
字段2:状态,A=定位,V=未定位

字段3:纬度ddmm.mmmm,度分格式(前导位数不足则补0)
字段4:纬度N(北纬)或S(南纬)
字段5:经度dddmm.mmmm,度分格式(前导位数不足则补0)
字段6:经度E(东经)或W(西经)
字段7:速度,节,Knots
字段8:方位角,度
字段9:UTC日期,DDMMYY格式
字段10:磁偏角,(000 - 180)度(前导位数不足则补0)
字段11:磁偏角方向,E=东W=西
字段16:校验值
这里,“*”为校验和识别符,其后面的两位数为校验和,代表了“$”和“*”之间所有字符(不包括这两个字符)的异或值的十六进制值。上面这条例句的校验和是十六进制的50,也就是十进制的80。
提示:^运算符的作用是异或将$和*之间所有的字符做^运算(第一个字符和第二个字符异或,结果再和第三个字符异或,依此类推)之后的值对65536取余后的结果,应该和*后面的两个十六进制数字的值相等否则的话说明这条语句在传输中发生了错误。注意这个十六进制值中是会出现A-F的大写字母的。另外,如果你需要的话,可以用Integer.parseInt(s)从String变量s中得到其所表达的整数数字;而Integer.parseInt(s, 16)从String变量s中得到其所表达的十六进制数字
现在,你的程序要读入一系列GPS输出,其中包含$GPRMC,也包含其他语句。在数据的最后,有一行单独的END表示数据的结束。
你的程序要从中找出$GPRMC语句计算校验和,找出其中校验正确,并且字段2表示已定位的语句,从中计算出时间,换算成北京时间。一次数据中会包含多条$GPRMC语句,以最后一条语句得到的北京时间作为结果输出
你的程序一定会读到一条有效的$GPRMC语句。

输入格式:多条GPS语句,每条均以回车换行结束。最后一行是END三个大写字母。

输出格式:6位数时间,表达为:hh:mm:ss.  其中,hh是两位数的小时,不足两位时前面补0;mm是两位数的分钟,不足两位时前面补0;ss是两位数的秒,不足两位时前面补0。

输入样例:

$GPRMC,024813.640,A,3158.4608,N,11848.3737,E,10.05,324.27,150706,,,A*50
END

输出样例:10:48:13

题目分析:

首先这题题目较长,但是题目中有效信息不多,所有有效信息,我均用蓝色字体给大家标识出来了,这题说白了就是让你判断三个事:第一,找出输入的$GPRMC语句,第二,$与*之间的字符的异或值对65586取余是否与*后面的16进制数相同;第三,第二个逗号后面的字段是不是A. 只要满足以上两点的一条数据,即为正确的数据,而这个程序可能输入多条数据,以END作为最后一条数据,但是我们只要输出之后一条合法数据中的时间对应的北京时间,即第一个逗号与第二个逗号之间的数据,只取整数部分,然后再将得到的六位整数,中的前两位加8,在做跨日计算处理,之后输出即可.

在这其中用到的新运算与字符串操作的函数列举如下:

1. 异或运算:

int m = a;
int n = b;
int c = m^n;

其中c的值为m,n两变量的异或值,也就是a,b的异或值; 

2. 得到字符串中某个位置上的存储的内容:

int i = a;
char c = s.charAt(i);

其中a为我要取的内容在数组中存放的位置;

3. 截取某一字符串中的一部分,赋值给另一个新数组:

int loc_start = a;
int loc_end = b;
String s1 = new String ("abcdef");
String S2 = s1.substring(loc_start,loc_end);

其中loc_start表示需要截取的字符串s1的起始位置,loc_end表示需要截取的字符串s1的终止位置,也就是
把字符串s1的从a到b位置的内容赋值给字符数穿s2;

4. 若字符串内存储的是整数,将字符串内的整数赋值给一个整型变量:

int number = 0;
String s = new String ("123");
number = Integer.parseInt ( s,10 );

 表示将获取字符串s内存储的十进制数,赋值给整型变量number.

代码实现:

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		
		Scanner in = new Scanner ( System.in );    //开始输入
		String s = new String("");
		//初始化字符串,准备读入语句

		int [] time = new int [3];//定义time数组,便于存储时间
		s = in.nextLine();        //读入语句
		do {
			boolean right = true;
                //定义布尔类型变量right便于后续判断语句是否合法

            //取出字段0,并判断是否是$GPRMC语句
            String title = s.substring(1,6);    //取出字段0,存入字符串title
			if ( title.compareTo("GPRMC")!=0 )    
				right = false;    
                        //比较字符串title与GPRMC是否相同,否则语句不合法,
                        //不参与后续时间计算,right赋为假

                //判断$与*之间的异或值对65536取余是否与校验值相同
			int loc_value = 0;    //定义变量,以便确定校验值的位置
			for ( int i=0 ; i<s.length() ; i++ ) {
				if ( s.charAt(i)=='*' ) {    
					loc_value = i + 1;
					break;
                        //由于*之后为校验值,故找到*即可跳出循环,得到校验值位置
				}
			}
			//将校验值对应的两个位置内存储的两位整型变量提取到新的字符串s_value中
			String s_value = s.substring(loc_value,loc_value+2);
			int value = Integer.parseInt(s_value,16);
            //由于校验值为16进制,故将字符串中存储的16进制数赋值给value
			
			int test = (int)s.charAt(1);    //定义变量,计算异或值
			for ( int i=2 ; i<loc_value-1 ; i++ )
				test = test ^ (int)s.charAt(i);
                //每一轮循环让现有的异或值同下一个变量进行异或计算,得到最终异或值
			
			if ( (test%65536)!=value )
				right = false;
                //判断异或值对65536取余是否与校验值相等,否则数据传输出错,
                //不参与后续时间计算,right赋为假
			
            //判断字段2处的内容是否为A
			int loc_A = 0;    //定义变量,以便确定字段2的位置
			for ( int j=0 ; j<2 ; j++ ) {
				for ( int i=loc_A ; i<s.length() ; i++ ) {
					if ( s.charAt(i)==',' ) {
						loc_A = i + 1;
						break;
                        //由于字段2在第二个逗号后面,故通过两轮循环找到第二个
                        //逗号后跳出循环,即得到字段2的位置
					}
				}
			}
			
			char comp = s.charAt(loc_A);    //将字段2内容存入新的char变量comp
			if ( comp!='A' )
				right = false;
                //判断comp内内容是否为A,否则数据非法,
                //不参与后续时间计算,right赋为假
			
            //若数据合法,进行如下时间操作
			if ( right ) {
				int loc = 0;    //定义变量,以便确定六位时间的位置
				for ( int i=0 ; i<s.length() ; i++ ) {
					if ( s.charAt(i)==',' ) {
						loc = i + 1;
						break;
                        //由于时间存放在第一个逗号后面,故找到第一个逗号,
                        //即可跳出循环,即得到六位时间的位置
					}
				}
				
                //将时间的前两位取出作为time数组的第一个变量,当做小时
				String time_min = s.substring(loc,loc+2);
//				System.out.println(time);
				time[0] = Integer.parseInt(time_min,10) + 8;
				
                //防止出现小时数大于24的情况,便做如下时间跨日处理
				if ( time[0]>=24 )
					time[0] = time[0] - 24;
				
                //分别取出时间的中间两位与后两位,分别作为数组time的
                //第二三个变量,当做分钟与秒
				time_min = s.substring(loc+2,loc+4);
				time[1] = Integer.parseInt(time_min,10);
				
				time_min = s.substring(loc+4,loc+6);
				time[2] = Integer.parseInt(time_min,10);
			}
			
			s = in.nextLine();
            //对当前语句全部处理结束,录入下一条一句
		} while ( s.compareTo("END")!=0 );
		//如果语句的内容为END跳出循环,即对当前语句即END不做处理
        //视作数据处理结束,准备打印时间
        
        //现在数组time内时间为最后一条合法语句的时间,打印出即可
        //不满两位,即数据小于10的前面补0
		if ( time[0]<10 )
			System.out.print("0");
		System.out.print(time[0]+":");
		
		if ( time[1]<10 )
			System.out.print("0");
		System.out.print(time[1]+":");
		
		if ( time[2]<10 )
			System.out.print("0");
		System.out.print(time[2]);
		
		in.close();
            //输入流结束
	}

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值