A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 franksight 于 2015-4-13 14:20 编辑
  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. }
复制代码

13 个回复

正序浏览
// 导入java.util下的所有类
import java.io.*;
/**
* Description:
* <br>Webside: <a >GitHub Of ZallerTing</a>
* <br>Date: 2016-12-21
* @author Zaller.Ting zallerting@gmail.com
* @version 1.0
* 微信/Wechat: ZALLER-TING
* QQ: 851509660
* Location:Kunshan
* 实现输入(待截取字串,开始截取字节索引,截取字节长度)后,输出截取字节长度子串,不出现半个中文字符(?)
*/
public class CutStringByByte {
        // 表示开始截取字节索引,首字符索引,字串最大长度,字串最大字节长度,子串长度,子串字节长度,前部分截取字节长度,截取字节长度,半个中文字符数量,临时变量
        protected static int startByteIndex, firstStrIndex, maxStrLen, maxByteLen, subLen, subByteLen, beforeCutByteLen, cutByteLen, halfHanNum, tmp;
        // 表示键盘输入的一行数据,待截取字串,截取子串变量
        protected static String inputStr, beCutStr, subStr;
        // 表示键盘输入的单个字符变量
        protected static char ch;
        // 表示键盘输入的一行数据组成的数组
        protected static String[] inputStrArr;
        // 表示以GBK编码方式解析的字节数组
        protected static byte bytesByGBK[];
        // 判断截取字节索引及截取字节长度是否在有效范围
        protected static boolean isProperIndex, isProperLen;
       
        // 判断是否为数值型字符串的方法(正数)
        protected static boolean isNumbericStr(String inputStr) {
                for(int i = 0; i < inputStr.length(); i++) {
                        // 返回指定索引处的字符
                        ch = inputStr.charAt(i);
                        if(ch < 46 || ch > 57) {
                                return false;
                        }
                }               
                return true;
        }
       
        // 判断是否为数值型字符串的方法(负数)
        protected static boolean isNegativeStr(String inputStr) {
                for(int i = 0; i < 1; i++) {
                        ch = inputStr.charAt(i);
                        if(ch == '-') {
                                return true;
                        }       
                }
                return false;
        }
       
        // 统计半个中文字符的数量
        protected static int halfHanNum(int startByteIndex) {
                // 初始化halfHanNum变量
                halfHanNum = 0;
                for(int i = 0; i <= startByteIndex; i++) {
                        // 字节索引对应值小于0时halfHanNum加1
                        if(bytesByGBK < 0) {
                                ++halfHanNum;
                        }
                }
                return halfHanNum;
        }
       
        // 找出需要截取子串第1个字符索引
        protected static int find1stStrIndex(int startByteIndex, String subStr) {
                // 统计半个中文字符的数量
                halfHanNum(startByteIndex);
                // startByteIndex字节索引对应字符为非中文单字节字符, 取subStr最后1个字符
                if(bytesByGBK[startByteIndex] > 0) {
                        firstStrIndex = subStr.length() > 0 ? subStr.length() - 1 : 0;
                // startByteIndex字节索引为中文字符第1个字节, 取subStr后面1个字符
                } else if(halfHanNum % 2 == 1){
                        firstStrIndex = subStr.length();
                // startByteIndex字节索引为中文字符第2个字节, 取subStr后面1个字符
                } else if(halfHanNum % 2 == 0){
                        firstStrIndex = subStr.length();
                }
                return firstStrIndex;
        }

        // 从指定字节索引startByteIndex截取cutByteLen长度的子串方法
    public static void subStr(String beCutStr, int startByteIndex, int cutByteLen) throws IOException  {
                /**
                 * 分两部分计算:
                 * 一.截取从索引startByteIndex开始的maxStrLen长度的子串:
                 *   1.截取从索引0开始的startByteIndex+1长度的子串;
                 *   2.找出需要截取子串的第1个字符索引firstStrIndex;
                 *   3.截取从索引firstStrIndex开始的maxStrLen长度的子串;
                 *   
                 * 二.截取从索引startByteIndex开始的cutByteLen长度的子串:
                 *   1.重新计算需要截取字串最大长度maxStrLen;
                 *   2.截取从索引firstStrIndex开始的cutByteLen长度的子串;
                 *   3.返回从startByteIndex字节索引截取cutByteLen长度的子串subStr;
                 */
                         
                /**
                 * 第一部分:截取从索引startByteIndex开始的maxStrLen长度的子串
                 */
                // 字串最大长度
                maxStrLen = beCutStr.length();
                // 字串最大字节长度
                maxByteLen = beCutStr.getBytes().length;
                // 前一部分截取字节长度
                beforeCutByteLen = startByteIndex > 0 ? startByteIndex + 1 : 0;
                // 从索引[0]截取长度[beforeCutByteLen]的子串
                subStr = beCutStr.substring(0, beforeCutByteLen > maxStrLen ? maxStrLen : beforeCutByteLen);
                // 子串字节长度
                subByteLen = subStr.getBytes("GBK").length;
                // 子串字节长度赋给临时变量tmp
                tmp = subByteLen;
                // 前部分截取字节长度小于子串字节长度时
                while(beforeCutByteLen < subByteLen) {
                        // 临时变量减1
                        --tmp;
                        subStr = beCutStr.substring(0, tmp > maxStrLen ? maxStrLen : tmp);
                        subByteLen = subStr.getBytes("GBK").length;
                }
                // 找出需要截取子串第1个字符索引
                find1stStrIndex(startByteIndex, subStr);
                // 找出需要截取子串
                subStr = beCutStr.substring(firstStrIndex, maxStrLen);
                /**
                 * 第二部分:截取从索引startByteIndex开始的cutByteLen长度的子串
                 */
                // 子串字节长度
                subByteLen = subStr.getBytes("GBK").length;
                // 重新计算需要截取字串最大长度
                maxStrLen = maxStrLen - firstStrIndex;
                // 子串字节长度赋给临时变量tmp
                tmp = subByteLen;
                // 需要截取字节长度小于子串字节长度时
                while(cutByteLen < subByteLen) {
                        // 需要截取字节长度减1
                        --tmp;
                        subStr = subStr.substring(0, tmp > maxStrLen ? maxStrLen : tmp);
                        subByteLen = subStr.getBytes("GBK").length;
                }                       
                System.out.println("“" + beCutStr + "” 从第" + startByteIndex + "字节索引截取" + cutByteLen + "字节的子串为: " + subStr + "\n");               
        }       
       
        // 主方法,程序的入口
        public static void main(String[] args) throws IOException {
                System.out.println("【本软件实现从指定字节索引截取指定字节长度子串的功能】\n");
                System.out.print(" 以【待截字串,开始截取字节索引,截取字节长度】格式输入 :");
                // 获取键盘输入字符串
                BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
                while((inputStr = br.readLine()) != null) {
                        // 通过英文逗号分隔键盘输入的字符串
                        inputStrArr = inputStr.split(",");
                    // 将键盘输入的第1个参数以"GBK"编码形式译码成1个字节数组
                    bytesByGBK = inputStrArr[0].getBytes("GBK");
                        // 判断是否键盘输入包含英文逗号且以逗号分隔的字符串中第1个不为null
                        if(inputStr.contains(",") && !inputStr.contains(",") && inputStrArr[0] != null) {
                                // 判断是否键盘输入第2个及第3个均为数值型字符串
                                if(isNumbericStr(inputStrArr[1]) && isNumbericStr(inputStrArr[2])) {
                                        // 转换数值型字符串为对应数值
                                        startByteIndex = Integer.parseInt(inputStrArr[1]);
                                        cutByteLen = Integer.parseInt(inputStrArr[2]);
                                        // 判断键盘输入的第2个及第3个数值是否在合理范围内
                                        isProperIndex = startByteIndex >= 0 && startByteIndex <= bytesByGBK.length ? true : false;
                                        isProperLen = cutByteLen >= 0 && cutByteLen <= bytesByGBK.length - startByteIndex ? true : false;       
                                        // 再判断截取字串字节索引及字节长度是否正确
                                        if(isProperIndex) {
                                                if(isProperLen) {
                                                        // 从指定索引位置截取指定字节长度的子串
                                                        subStr(inputStrArr[0], startByteIndex, cutByteLen);
                                                } else {
                                                        System.out.println("截取字节长度输入有误!");
                                                }
                                        } else {
                                                System.out.println("开始截取字节索引输入有误!");
                                        }
                                // 判断是否键盘输入第2个及第3个均为负数值型字符串
                                } else if(isNegativeStr(inputStrArr[1]) && isNegativeStr(inputStrArr[2])){
                                        System.out.println("开始截取字节索引及截取字节长度均输入有误!");
                                } else if(isNegativeStr(inputStrArr[1]) && !isNegativeStr(inputStrArr[2])){
                                        System.out.println("开始截取字节索引输入有误!");
                                } else if(!isNegativeStr(inputStrArr[1]) && isNegativeStr(inputStrArr[2])){
                                        System.out.println("截取字节长度输入有误!");
                                }
                        // 判断是否键盘输入包含中文逗号
                        } else if(inputStr.contains(",")) {
                                System.out.println("请以英文逗号分隔字串、字节索引、字节长度!");
                        } else {
                                System.out.println("待截取字串输入为空!");
                        }
                        System.out.print(" 以【待截字串,开始截取字节索引,截取字节长度】格式输入 :");
                }
        }
}
回复 使用道具 举报
本帖最后由 AlvinDing 于 2016-12-26 14:08 编辑

加强版正确代码看下一楼本人回复:实现输入【任何字符串,开始截取字节索引,截取字节长度】输出对应截取的字符串,不会出现半个中文字符,默认以GBK格式进行编码。
回复 使用道具 举报
不过我决定先靠自己做,
回复 使用道具 举报
考题呀,而且是原题。
回复 使用道具 举报
确实有用  你也懂得
回复 使用道具 举报
原来还有这种问题!
回复 使用道具 举报
15225159271 来自手机 中级黑马 2015-7-30 13:10:12
8#
绝对大神,我都想了好久,顶
回复 使用道具 举报
新人表示很高深,看不懂
回复 使用道具 举报
楼主写的好详细啊
回复 使用道具 举报
太有用了.你懂得
回复 使用道具 举报
奋斗的黑马 发表于 2015-4-11 21:03
String str="HM程序员";//定义一个字符串...
如果把这个字符串改成“H中H国H好”的话,这个程序好像是会出 ...

这个是有问题,后来我在别人的另一个帖子里修正了,详细见:http://bbs.itheima.com/thread-170437-1-1.html
回复 使用道具 举报
String str="HM程序员";//定义一个字符串...
如果把这个字符串改成“H中H国H好”的话,这个程序好像是会出问题的

h中h国h好
请输入要截取的字节数:2
h?
回复 使用道具 举报
String str="HM程序员";//定义一个字符串
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马