黑马程序员技术交流社区

标题: 谈一道基础题的解法 [打印本页]

作者: 血色@残阳    时间: 2015-2-14 23:23
标题: 谈一道基础题的解法
题目:编写函数,从一个字符串中按字节数截取一部分,但不能截取出半个中文(GBK码表),
                  例如:从“HM程序员”中截取2个字节是“HM”,截取4个则是“HM程”,
                截取3个字节也要是"HM"而不要出现半个中文
作者: 血色@残阳    时间: 2015-2-14 23:26
  1. package com.itheima;
  2. import java.io.IOException;
  3. /**
  4. *第十题: 编写函数,从一个字符串中按字节数截取一部分,但不能截取出半个中文(GBK码表),
  5.                   例如:从“HM程序员”中截取2个字节是“HM”,截取4个则是“HM程”,
  6.                 截取3个字节也要是"HM"而不要出现半个中文
  7. * @author Administrator
  8. */
  9. public class Test10
  10. {
  11.         public static void main(String[] args) throws IOException
  12.         {
  13.                 String s = "HM程序员";
  14.                 System.out.println("原始字符串:" + s);
  15.                 System.out.println("截取1个字节:"+subStr(s,1));
  16.                 System.out.println("截取2个字节:"+subStr(s,2));
  17.                 System.out.println("截取3个字节:"+subStr(s,3));
  18.                 System.out.println("截取4个字节:"+subStr(s,4));
  19.         }
  20.         public static String subStr(String str, int len) throws IOException  
  21.     {
  22.                 if (str == null && "".equals(str))
  23.                 {  
  24.                         System.out.println("请不要输入空串!");  
  25.                         return str;  
  26.                 }     
  27.                 else
  28.                 {
  29.                         int num = len;//截取字节数
  30.                         //定义变量src,接收截取的子串
  31.                         String src = str.substring(0, len>str.length() ? str.length() : len);
  32.                         //定义变量bys,接收截取的子串src的字节长度
  33.                         int bys = src.getBytes("GBK").length;
  34.                         //说明截取的字符串中包含有汉字  
  35.                         while (bys > num)
  36.                         {  
  37.                                 int cutLen = --len;
  38.                                 src = str.substring(0, cutLen>str.length() ? str.length() : cutLen);  
  39.                                 bys = src.getBytes("GBK").length;
  40.                         }  
  41.                         return src;
  42.                 }
  43.     }
  44. }

复制代码
之前在网上看到了关于这题的一些代码,基本上都是有很大问题的,反正我是没有找到完全正确的代码的,后来我也是参见了一些别人的原理,写了这个代码,应该是没有什么问题了
代码:
作者: franksight    时间: 2015-2-15 12:08
  1. package com.itheima;

  2. import java.io.*;

  3. /**
  4. * 第10题:编写函数,从一个字符串中按字节数截取一部分,但不能截取出半个中文(GBK码表),
  5. * 例如:从“HM程序员”中截取2个字节是“HM”,截取4个则是“HM程”,截取3个字节也要是"HM"而不要出现半个中文
  6. * @author frank
  7. */

  8. public class Test10 {
  9.         public static void main(String[] args) throws IOException
  10.         {
  11.                 String str="HM程序员";//定义一个字符串
  12.                 int count=0; //记录要截取的字节数
  13.                 System.out.print("请输入要截取的字节数:");
  14.                
  15.                 //从键盘输入所要截取的字节数
  16.                 BufferedReader buf=new BufferedReader(new InputStreamReader(System.in));
  17.                 count=Integer.parseInt(buf.readLine());//将输入的字符串转换成十进制整数,并用count记录
  18.                 System.out.println(splitString(str,count));        //调用截取字符串函数,并输出结果
  19.         }
  20.        
  21.         //截取字符串函数   str:字符串   count:要截取的字节数
  22.         public static String splitString(String str,int count) throws UnsupportedEncodingException
  23.         {
  24.                 byte[] bytes=null;//定义字节数组,初始为null
  25.                 //用gbk对str进行编码,并将结果存储到bytes数组中
  26.                 bytes=str.getBytes("gbk");
  27.                
  28.                 //判断输入要截取的字节数是否为正整数
  29.                 if(count<0)
  30.                         throw new RuntimeException("非法,截取字节数为负!");
  31.                 //判断输入要截取的字节数是否大于原字符串所对应的字节数组的长度
  32.                 else if(count>bytes.length)
  33.                         return str; //若大于,则直接返回原字符串
  34.                 //判断输入要截取的字节数是否>0且为奇数
  35.                 else if(count>0&&count%2==1)
  36.                 {
  37.                         //如果是奇数,就在判断要获取的最后一个字节是不是汉字的一半,通过负数判断,因为汉字的gbk编码值<0
  38.                         if(bytes[count-1]<0)
  39.                                 count--;  //是汉字,则减1
  40.                 }

  41.                 byte[] newBytes=new byte[count]; //定义一个大小为count的新字节数组
  42.                 for(int i=0;i<count;i++)
  43.                         newBytes[i]=bytes[i]; //将bytes数组中的值赋给新字节数组
  44.                 //将新字节数组中的值转换成字符串
  45.                 String newString=new String(newBytes);
  46.                 return newString;

  47.         }
  48. }
复制代码



作者: Gonnaloveu    时间: 2015-2-15 14:25
楼主的判断空字符串倒是提醒我了几种异常情况, 楼上的明显把程序写死了,只适合例子给的"HM程序员"
作者: 血色@残阳    时间: 2015-2-15 17:12
franksight 发表于 2015-2-15 12:08

你这个代码我在网上看到了好些,这种涉及奇偶位的基本是错误的,因为你写的是个函数,你根本不可能确定给出的是什么样的字符串,更何谈奇偶位数了,你把测试字符串换一下就不行了
作者: aawenwei    时间: 2015-2-15 19:47
赞一个。。。。。            
作者: coolmiao13    时间: 2015-2-15 22:31
有模板了,哈哈哈,感谢楼主,等我学到这一块好好看看,测试题好好参考下。
作者: huangchunwei    时间: 2015-2-15 23:25
来学习学习。。
作者: xyf19881010    时间: 2015-2-15 23:53
楼主的才是正解,赞一个
作者: franksight    时间: 2015-2-16 00:49
本帖最后由 franksight 于 2015-2-16 00:55 编辑
血色@残阳 发表于 2015-2-15 17:12
你这个代码我在网上看到了好些,这种涉及奇偶位的基本是错误的,因为你写的是个函数,你根本不可能确定给 ...
我仔细看看。。。
作者: franksight    时间: 2015-2-16 01:07
血色@残阳 发表于 2015-2-15 17:12
你这个代码我在网上看到了好些,这种涉及奇偶位的基本是错误的,因为你写的是个函数,你根本不可能确定给 ...

我之前是考虑过奇偶问题的,我测试了好几个,用的字符串有问题啊啊。。。。。:funk:
作者: franksight    时间: 2015-2-16 10:21
本帖最后由 franksight 于 2015-2-16 10:28 编辑

我修改了原来代码的38-43行代码,总算是测试了别的特殊情况,现在总算没问题了吧!!!
作者: franksight    时间: 2015-2-16 10:26
本帖最后由 franksight 于 2015-2-16 10:31 编辑
  1. import java.io.*;

  2. /**
  3. * 第10题:编写函数,从一个字符串中按字节数截取一部分,但不能截取出半个中文(GBK码表),
  4. * 例如:从“HM程序员”中截取2个字节是“HM”,截取4个则是“HM程”,截取3个字节也要是"HM"而不要出现半个中文
  5. * @author frank
  6. */

  7. public class Test10 {
  8.         public static void main(String[] args) throws IOException
  9.         {
  10.                 System.out.print("请输入字符串:");
  11.                 BufferedReader bufStr=new BufferedReader(new InputStreamReader(System.in));
  12.                 String str=bufStr.readLine();
  13.                 int count=0; //记录要截取的字节数
  14.                 System.out.print("请输入要截取的字节数:");
  15.                
  16.                 //从键盘输入所要截取的字节数
  17.                 BufferedReader buf=new BufferedReader(new InputStreamReader(System.in));
  18.                 count=Integer.parseInt(buf.readLine());//将输入的字符串转换成十进制整数,并用count记录
  19.                 System.out.println(splitString(str,count));        //调用截取字符串函数,并输出结果
  20.         }
  21.         
  22.         //截取字符串函数   str:字符串   count:要截取的字节数
  23.         public static String splitString(String str,int count) throws UnsupportedEncodingException
  24.         {
  25.                 byte[] bytes=null;/
  26.                 //用gbk对str进行编码,并将结果存储到bytes数组中
  27.                 bytes=str.getBytes("gbk");
  28.                
  29.                 if(count<0)
  30.                         throw new RuntimeException("非法,截取字节数为负!");
  31.                 //判断输入要截取的字节数是否大于原字符串所对应的字节数组的长度
  32.                 else if(count>bytes.length)
  33.                         return str;
  34.                 //判断输入要截取的字节数是否>0且最后一个字节对应的是否为半个汉字,通过负数判断,因为汉字的gbk编码值<0
  35.                 else if(count>0&&(bytes[count-1]<0))
  36.                 {
  37.                         int n=0;//记录从数组尾部连续数起,汉字所占的字节数,一个汉字占2个字节。
  38.                         for(int x=count-1;x>=0;x--)//从尾部遍历数组
  39.                         {
  40.                                         if(bytes[x]<0)//如果该值<0,则是半个汉字
  41.                                                 n++;         //字节数n+1
  42.                                         else
  43.                                                 break
  44.                         }
  45.                         //如果n是奇数,则说明最后一个字节对应的是半个汉字
  46.                         if(n%2==1)
  47.                                 count--;  //是汉字,则减1
  48.                 }

  49.                 byte[] newBytes=new byte[count];
  50.                 for(int i=0;i<count;i++)
  51.                         newBytes[i]=bytes[i]; //将bytes数组中的值赋给新字节数组
  52.             
  53.                 String newString=new String(newBytes);
  54.                 return newString;

  55.         }
  56. }
复制代码



作者: franksight    时间: 2015-2-16 10:56
本帖最后由 franksight 于 2015-2-16 11:14 编辑
  1. import java.io.*;

  2. /**
  3. * 第10题:编写函数,从一个字符串中按字节数截取一部分,但不能截取出半个中文(GBK码表),
  4. * 例如:从“HM程序员”中截取2个字节是“HM”,截取4个则是“HM程”,截取3个字节也要是"HM"而不要出现半个中文
  5. * @author frank
  6. */

  7. public class Test10 {
  8.         public static void main(String[] args) throws IOException
  9.         {
  10.                 System.out.print("请输入字符串:");
  11.                 BufferedReader bufStr=new BufferedReader(new InputStreamReader(System.in));
  12.                 String str=bufStr.readLine();
  13.                 int count=0; //记录要截取的字节数
  14.                 //System.out.print("请输入要截取的字节数:");
  15.                 //从键盘输入所要截取的字节数
  16.                 //BufferedReader buf=new BufferedReader(new InputStreamReader(System.in));
  17.                 //count=Integer.parseInt(buf.readLine());//将输入的字符串转换成十进制整数,并用count记录
  18.                 //System.out.println(splitString(str,count));        //调用截取字符串函数,并输出结果
  19.                 //可用以下函数测试截取的所有情况,或直接用上5句自行测试。。。
  20.                 exam(str);

  21.         }
  22.                 //测试所以截取结果
  23.                 public static void exam(String str) throws UnsupportedEncodingException
  24.                 {
  25.                         for(int x=str.getBytes("gbk").length;x>0;x--)
  26.                         {
  27.                                 if(splitString(str,x).contains("?"))//若包含半个汉字,则字符串中会有'?'出现
  28.                                 {
  29.                                         System.out.println(str+" 在截取第"+x+"个字节时出错!");
  30.                                         break;//跳出循环,不在截取
  31.                                 }
  32.                                 else
  33.                                         System.out.println(str+" 截取第 "+x+"个字节!"+splitString(str,x));
  34.                         }
  35.                 }       
  36.         //截取字符串函数   str:字符串   count:要截取的字节数
  37.         public static String splitString(String str,int count) throws UnsupportedEncodingException
  38.         {
  39.                 byte[] bytes=null;//定义字节数组,初始为null
  40.                 //用gbk对str进行编码,并将结果存储到bytes数组中
  41.                 bytes=str.getBytes("gbk");
  42.                
  43.                 //判断输入要截取的字节数是否为正整数
  44.                 if(count<0)
  45.                         throw new RuntimeException("非法,截取字节数为负!");
  46.                 //判断输入要截取的字节数是否大于原字符串所对应的字节数组的长度
  47.                 else if(count>bytes.length)
  48.                         return str; //若大于,则直接返回原字符串
  49.                 //判断输入要截取的字节数是否>0且最后一个字节对应的是否为半个汉字,通过负数判断,因为汉字的gbk编码值<0
  50.                 else if(count>0&&(bytes[count-1]<0))
  51.                 {
  52.                         int n=0;//记录从数组尾部连续数起,汉字所占的字节数,一个汉字占2个字节。
  53.                         for(int x=count-1;x>=0;x--)//从尾部遍历数组
  54.                         {
  55.                                         if(bytes[x]<0)//如果该值<0,则是半个汉字
  56.                                                 n++;         //字节数n+1
  57.                                         else
  58.                                                 break;//跳出循环
  59.                         }
  60.                         //如果n是奇数,则说明最后一个字节对应的是半个汉字
  61.                         if(n%2==1)
  62.                                 count--;  //是汉字,则减1
  63.                 }

  64.                 byte[] newBytes=new byte[count]; //定义一个大小为count的新字节数组
  65.                 for(int i=0;i<count;i++)
  66.                         newBytes[i]=bytes[i]; //将bytes数组中的值赋给新字节数组
  67.                 //将新字节数组中的值转换成字符串
  68.                 String newString=new String(newBytes);
  69.                 return newString;

  70.         }
  71. }
复制代码



以上代码带有测试截取结果的函数,
只要输入任意一个字符串,它会把所以截取情况列出来。。。


作者: wtjohn    时间: 2015-2-16 11:11
这个视频里有讲的啊
作者: play1369    时间: 2015-2-17 15:57
血色@残阳 发表于 2015-2-14 23:26
之前在网上看到了关于这题的一些代码,基本上都是有很大问题的,反正我是没有找到完全正确的代码的,后来我 ...

第22行应该是||
作者: a410709560    时间: 2015-2-20 18:46
感谢分享
作者: ADS1993    时间: 2015-2-22 01:10
学习一下
作者: 挥斥方遒    时间: 2015-4-18 21:01
wtjohn 发表于 2015-2-16 11:11
这个视频里有讲的啊

这个是在哪个视频里头讲到了啊?我怎么没注意呢。。。求出处。看了半天头都大了。。
作者: wtjohn    时间: 2015-4-18 22:30
挥斥方遒 发表于 2015-4-18 21:01
这个是在哪个视频里头讲到了啊?我怎么没注意呢。。。求出处。看了半天头都大了。。 ...

30天版的视频 第27天的内容
作者: wtjohn    时间: 2015-4-18 22:31
挥斥方遒 发表于 2015-4-18 21:01
这个是在哪个视频里头讲到了啊?我怎么没注意呢。。。求出处。看了半天头都大了。。 ...

错了,打错了,第24天 = =
作者: 挥斥方遒    时间: 2015-4-19 19:42
wtjohn 发表于 2015-4-18 22:31
错了,打错了,第24天 = =

谢谢了哥们!不过我自己也写了个,我也发出来给大家看看。完全不同的思路写的。。可能有很多bug吧。

  1. public class Test10 {

  2.         /**
  3.          * 10、编写函数,从一个字符串中按字节数截取一部分,但不能截取出半个中文(GBK码表),
  4.          * 例如:从“HM程序员”中截取2个字节是“HM”,截取4个则是“HM程”,
  5.          * 截取3个字节也要是"HM"而不要出现半个中文
  6.          * @param args
  7.          * @throws UnsupportedEncodingException
  8.          */
  9.         public static void main(String[] args) throws UnsupportedEncodingException {
  10.                 // TODO Auto-generated method stub
  11.                 Scanner sc=new Scanner(System.in);
  12.                 System.out.println("输入字符串:");
  13.                 String str;
  14.                 str=sc.next();
  15.                 while(true){
  16.                         int x=0;
  17.                         System.out.println("输入截取字节数:");
  18.                         try{
  19.                                 x=sc.nextInt();
  20.                         }catch(InputMismatchException e){
  21.                                 System.out.println("输入的数字有误");
  22.                                 break;
  23.                         }
  24.                         if(x>=str.getBytes().length){
  25.                                 System.out.println(str);
  26.                         }else{
  27.                                 System.out.println(Test10.compare(str, x));
  28.                         }
  29.                 }
  30.         }
  31.        
  32.         //截取方法:返回截取结果
  33.         //此方法只对截取的最后一个字节做判断。
  34.         //如果最后一个字节是个汉子的前半部分,就去掉此半个汉子并返回。如果不是汉子的前半部分就返回当前字符串。
  35.         //如何判断最后一个字节是不是汉子的前半部分:
  36.         //如果x个字节的最后一个字节是汉子的前半部分,转成字符串它还是占一个字符空间。
  37.         //然而就跟x+1个字节的字符串长度是一样了。
  38.         //出现这种状况我们就断定最后一个字节是半个汉子的前半部分了。就去掉此字节,并返回字符串。
  39.        
  40.         //截取函数compare()
  41.         public static String compare(String str,int x) throws UnsupportedEncodingException{
  42.                 //out是函数的返回值,也就是要打印的结果了。
  43.                 String out=null;
  44.                 //strByte是str的字节数组
  45.                 byte[] strByte=str.getBytes("GBK");
  46.                 //byt1为str的前x个字节,
  47.                 byte[] byt1=new byte[x];
  48.                 for(int i=0;i<x;i++){
  49.                         byt1[i]=strByte[i];
  50.                 }
  51.                 //byt2为str的前x+1个字节,
  52.                 byte[] byt2=new byte[x+1];
  53.                 for(int i=0;i<=x;i++){
  54.                         byt2[i]=strByte[i];
  55.                 }
  56.                 //将x个字节和x+1个字节转成字符串
  57.                 String str1=new String(byt1,"GBK");
  58.                 String str2=new String(byt2,"GBK");
  59.                 //取x个字节的字符串长度。len1
  60.                 int len1=(str1.length());
  61.                 //取x+1个字节的字符串。len2
  62.                 int len2=(str2.length());
  63.                 //判断x和x+1个字节转成字符串后的长度
  64.                 //若str1和str2的字符串长度一样那第x个字节肯定是半个汉子。
  65.                 if(len1==len2){
  66.                         out=str1.substring(0,str1.length()-1);
  67.                         System.out.println("第"+x+"个字节是个汉子前半段");
  68.                 }else{
  69.                         out=str1;
  70.                         System.out.println("第"+x+"个字节是个汉子前半段");
  71.                 }
  72.                 return out;
  73.                
  74.         }

  75. }
复制代码

作者: 李海明    时间: 2015-5-2 19:06
wtjohn 发表于 2015-4-18 22:30
30天版的视频 第27天的内容

30天版的视频那里能下载啊?
作者: wtjohn    时间: 2015-5-2 21:45
李海明 发表于 2015-5-2 19:06
30天版的视频那里能下载啊?

官网提供的就是哇@@
作者: kingowe    时间: 2015-5-18 15:26
不错,很强大
作者: yijian2033    时间: 2015-7-12 00:24
好垃圾的思维,看我的



package cn.itcast;

public class Case10 {
        public static void main(String[] args) {
                String str = "HMC是XY这是一个程序";
                System.out.println(cutString(str, 9));
        }

        public static String cutString(String str, int a) {
                String s = str;
                if (a < str.length()) {
                        String s1 = new String(str.getBytes(), 0, a + 1);
                        s = s1.substring(0, s1.length() - 1);
                }
                return s;
        }
}

作者: yijian2033    时间: 2015-7-12 00:45
yijian2033 发表于 2015-7-12 00:24
好垃圾的思维,看我的

有一个小小的BUG 将 if(a<str,length())改为if(a<str.getBytes().length)
作者: 木易水寒    时间: 2015-8-12 15:47
楼上猛人 不过这能保证你自己添加的那个字节如果形成乱码在构造出的字符串中只占有一个长度?乱码有这规律?
楼主。。。我怎么觉得你就没切字节一直在切字符串长度。。。看了半天楼主的我想不出他切出半个汉字了么??
作者: rhyhhg5    时间: 2015-8-25 16:08
666666666666
作者: youyuxiaoyu    时间: 2015-9-17 06:35
感谢,可以参考下
作者: 18664300701    时间: 2015-9-23 00:31
wtjohn 发表于 2015-4-18 22:30
30天版的视频 第27天的内容

是老毕的吗
作者: pan1564335    时间: 2015-11-28 12:19
你这个方法太简便了
作者: hyl    时间: 2015-11-28 15:04
Android 最近就业越来越不好了。
作者: 凤华茂此时    时间: 2015-12-4 17:45
感谢分享,继续学习!




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2