华南农业大学java综合性实验报告

华南农业大学数学与信息学院
综合性实验报告

  1. 题目介绍与分析

1.1 题目介绍
编写一个Java应用程序,对单个Java源程序文件及某个目录中的所有Java源程序文件(包括子目录)进行分析,分析内容包括:
Java源程序文件个数,对目录分析进行分析时是其中所有源程序文件个数总和。
Java源程序中的字符个数,对目录分析时是其中所有源程序文件的字符个数总和。
Java源程序文件中的注释的个数,即源程序文件中共有多少个注释,包括:单行注释和多行注释。对目录分析时是其中所有源程序文件的总和Java源程序文件中的注释的字符个数,即源程序文件中所有注释的字符数之和。对目录分析时是其中所有源程序文件的总和。
Java源程序文件中关键字使用情况,即源程序文件各个关键字使用了多少次。对目录分析时是其中所有源程序文件的总和。
1.1.1程序首先显示以下菜单

1.1.2分析目录或源程序文件要求
选择菜单项目1时,首先要求输入要分析的目录名或Java源程序文件名。
如果输入的目录或文件名不存在,提示不存在;输入的文件名的扩展名不是“. java”时提示不是Java源程序文件。如果输入的是一个Java源程序文件名,对该源程序文件进行分析。
如果输入的是一个目录名,对该目录中所有的源程序文件进行分析。
分析的结果存储到一个文本文件中,在当前目录中建立一个data目录,结果文件放在data目录中。分析目录时结果文件名:D_目录名_Result.txt,例如:D_lang_Result.txt。
分析源程序文件时结果文件名:F_源程序文件名_Result.txt,例如:F_String.java_Result.txt。

1.1.3查看已有的分析结果要求
选择菜单项目2时,首先列出已经分析并存储的结果,如下图:

即列出data目录中存储的所有分析结果文件,并给出一个序号输入要查看的文件序号后,显示该文件中的内容。

1.2 实验要求分析
统计Java源程序文件个数,需要统计目录下的文件个数还要统计目录下一级的目录下的文件个数;统计Java源程序字符个数,需要将文件每一行转换成字符串再进行字符计数;统计Java源程序文件中的注释的个数以及注释字符数,需要找到注释出现的不同情况,将特定符号内的注释内容进行字符计数;统计Java源程序文件中关键字使用情况,需要将文件每一行转换成字符串再进行字符计数,然后将每一个关键字分隔开,然后计数;保存分析结果时,需要根据不同的分析对象来创建文本文件,使用不同类型的文本文件名,然后转换输出流将分析结果直接输出在文本文件上。

2.程序静态结构

程序开始运行时,主类调用Menu类的start()方法进入主菜单,当选择分析目录后源程序文件时,调用Counts类的各个方法对输入的文件或者目录进行分析,最后调用Print类的方法将分析结果输出至相应的文本文件;当选择查看已有的分析结果时,调用Menu类的menu1()方法输出已分析了的文件名或目录名,选择已分析了的文件或目录对应编号后,调用Menu类的menu2()方法输出保存了已分析了的文件或目录分析结果的文本文件的内容。

2.1 Counts类
包含对目录的java源程序文件计数、java源程序文件的字符数计数、统计Java源程序文件中的注释的个数以及注释字符数、统计Java源程序文件中关键字使用情况的方法。
Counts

  • KEYWORDS :String[]
  • JAVA_SUFFIX:String
  • list: ArrayList
    +fileCounts(File): int
    +fileBytesCount(File):long
    +bytesCount(File):long
    +fileNoteCount(File):int[]
    +notesCount(File):int[]
    +keywordCount(File):Map<String, Integer>
    +fileKeywordCount(File):Map<String, Integer>

2.2 Print类
show(File dirPath)方法用于输出分析结果到文件并保存
Print

+show(File)

2.3 Menu类
start()方法输出主菜单,menu1()方法输出已经分析的目录或文件,menu2()方法输出选中的目录或文件的分析结果。
Menu
+JAVA_SUFFIX:String
+start()
+menu1()
+menu2()

2.4Main类
Main

+main(String[])

  1. 程序主要功能
    (本部分介绍程序主要的功能,如加载文件、保存文件、统计分析等的算法,使用流程图或自然语言描述,不要直接贴代码。是实验报告的主要部分之一)

3.1 Java源程序文件个数统计——fileCounts(File dirPath)
给定一个路径,使用File.listFiles()方法,返回目录下所有文件和目录的绝对路径形成一个File[]数组,遍历该数组,若为Java源程序文件,则计数加一;若为目录,则再使用fileCounts(File dirPath)方法对其目录进行计数。

3.2 Java源程序中的字符个数统计——fileBytesCount(File filePath)和bytesCount(File filePath)
先使用bytesCount(File filePath)方法,给定一个路径,若其为Java源程序文件,则对其使用fileBytesCount (File filePath)方法进行计数,用readLine()方法读取文件的每一行并且将其转换为字符串,length()方法计算每一行的字符长度,最后统计出整个文件的字符数;若其为目录,则使用File.listFiles()方法,返回目录下所有文件和目录的绝对路径形成一个File[]数组,遍历该数组,若为java源程序文件,则对其使用fileBytesCount (File filePath) 方法进行计数;若为目录,则再使用bytesCount(File filePath) 方法对其目录字符数进行计数。

3.3 Java源程序文件中的注释的个数以及注释的字节数统计—fileNoteCount(FilefilePath)和notesCount(File filePath)
先使用notesCount(File filePath)方法,给定一个路径,若其为Java源程序文件,则使用
fileNoteCount(File filePath)进行计数,返回一个int[]数组,int[0]为注释个数,int[1]为注释的字节总和;若其为目录,则使用File.listFiles()方法,返回目录下所有文件和目录的绝对路径形成一个File[]数组,遍历该数组,若为Java源程序文件,则对其使用fileNoteCount(File filePath)方法进行计数;若为目录,则再使用notesCount(File filePath)方法对其注释个数和注释字节总数进行计数。
统计一个Java源程序文件的注释个数和注释字节总数时,首先将一个Java源程序文件的每一行转换成String字符串,再将每一行放入ArrayList中以便后来的统计。根据单行注释和多行注释出现的不同的情况,使用String.indexOf() 方法返回"/"、"//"、"/“的字符串值在字符串中首次出现的位置。当注释出现时,注释个数计数加一,若为”/……/“类多行注释,则将注释第一行”/“后面的字符串字节进行计数,然后向下一行寻找与之匹配的”/",若下一行没有找到,则将整行当做注释进行注释字节数计数,直到找到与之匹配的"/",将该行"/“前面的字符串字节数进行计数;若为”//“类单行注释,则将该行”//“后面的字符串字节进行注释字节计数;若为”/……/"类单行注释,则根据返回的位置信息对该行注释内容进行字节计数。最后统计出整个Java源程序文件的注释个数以及注释字节数总和。

3.4 统计Java源程序文件中关键字使用情况——keywordCount(File filePath)和fileKeywordCount(File filePath)
先使用keywordCount (File filePath)方法,给定一个路径,若其为Java源程序文件,则对其使用fileKeywordCount (File filePath)方法进行计数;若其为目录,则使用File.listFiles()函数,返回目录下所有文件和目录的绝对路径形成一个File[]数组,遍历该数组,若为Java源程序文件,则对其使用fileKeywordCount (File filePath)方法进行关键字使用情况计数;若为目录,则再使用keywordCount (File filePath)方法对关键字使用情况进行计数。
使用keywordCount (File filePath)方法对关键字使用情况进行计数的方法与统计一个Java源程序文件的注释个数和注释字节总数类似,首先将一个文件的每一行转换成String字符串,再将每一行放入ArrayList中以便后来的统计,然后按照上述统计一个Java源程序文件的注释个数和注释字节总数的方法找到所有的注释,使用String.substring()方法通过拼接将注释删除,其次使用String.replace()方法和正则表达式将输出语句删除和将"[*" “]” “{” “}” “(” ")“转换为” "空格以保证每个关键字都被空格分隔,最后使用String.split()方法将整个文件的单词形成一个String[]数组。使用map来储存每一个单词的使用次数,遍历数组即可统计一个Java源程序文件的关键字使用次数情况。

3.5将分析结果保存至相应的文本文件——show(File dirPath)
给定一个路径,首先是根据是否为文件还是目录进行文件创建,然后更改输出流,直接通过调用不同的方法直接在文本文件上输出分析结果,在最后输出关键字使用情况时,需要重写一个降序比较器,使得储存关键字使用次数的map集合对value值进行降序排序,最终得到我们想要的结果。

3.6查看已有的分析结果——menu2()
找到储存每个分析结果的文件夹,使用File. listFiles()方法将目录下的分析结果形成String[]数组,遍历数组并且按格式进行输出。
4. 程序测试
4.1输入目录名:D:\eclipse-workspace\final,得出分析结果并保存到文本文件。

4.2输入目录名:
D:\eclipse-workspace\15,得出分析结果并保存到文本文件。

4.3输入文件名:
D:\eclipse-workspace\14\src\shape\Client.java,得出分析结果并保存到文本文件。

4.4输入文件名:
D:\eclipse-workspace\12\src\Ana\Calculate.java,得出分析结果并保存到文本文件。

4.5查看已有的分析结果

4.6退出

  1. 实验总结
    在本次综合性实验中,我在不仅运用了在这个学期学习的知识,而且还学习了许多老师在课上没有讲授的内容。首先是在存储文件分析结果时,先创建文档,然后改变输出流使得可以直接在文档上输出文件分析结果;其次是在统计文件的关键字使用情况时,使用map集合存储每一个关键字的使用次数,将map转换为list的同时重写比较器,使得map可以按照value降序进行排序,得到我们最终的输出结果;最后,我觉得实验的难点是统计关键字使用次数和统计注释个数以及其字节总数,在统计关键字使用次数时,我先把文件每一行转换为String数组,然后将注释和输出语句从每一个String中移除,最终获得没有注释和输出语句的String数组,随后我将所有可能出现在关键字旁边的字符改为空格字符,然后用String.split()方法进行分割,获得一个含有每一个单词的数组,最后再统计;在统计注释个数以及其字节总数时,方法与上述类似,在注释出现时对注释进行计数和对注释的字节进行计数即可,这里是我花时间花的最多的地方,我要对不同的注释的情况进行分析,特别是多行注释,情况比较多,因为要统计注释的字节数,需要找与注释相匹配的字符串下标然后对字符串多次截取。
    在最后几天,我尝试了使用图形化界面,但是因为自己对这个很生疏,所以做出来效果不太合适,就放弃使用该方法。虽然我没有用图形化界面,但是我也学习了许多关于这个的知识,图形化界面可以让画面更加生动多彩,更有美感。总的来说,我在这次综合性实验中收获丰满,java语言是我们学习的重点,也是我们以后工作必不可少的工具,即使这个学期课程结束了,我还是会继续的钻研学习,不断努力前进。
    在这里插入图片描述
    在这里插入图片描述

!导出jar文件

导入jar文件
导入jar文件
导入jar文件

package Main;

import java.io.*;
import Trying.*;
import Trying.Menu;

public class Main {
	public static void main(String[] args) throws IOException {
		Menu.start();
	}
}

package Trying;

import java.io.*;
import java.util.*;

public class Counts {

	public static final String[] KEYWORDS= {"abstract","assert","boolean","break","byte","case","catch","char","class","const","continue","default","do","double",
			"else","enum","extends","final","finally","float","for","goto","if","implements","import","instanceof","int","interface","long","native","new","package",
			"private","protected","public","return","short","strictfp","super","switch","synchronized","this","throw","throws","transient","try","void","volatile","while"};
	public static final String JAVA_SUFFIX = ".java";
	private static ArrayList<String> list ;//将文件的每一行转换为字符串数组放在ArrayList<>中 
	 
	public static int fileCounts(File dirPath) {
		int count = 0;
		File[] dir = dirPath.listFiles();
		for(File f : dir) {
			if(f.isDirectory())
				count += fileCounts(f.getAbsoluteFile());
			else if(f.toString().toLowerCase().endsWith(JAVA_SUFFIX))
				count ++;
		}
		return count;
	}
	public static long fileBytesCount(File filePath) {
		long count = 0;
		try(BufferedReader buf = new BufferedReader(new FileReader(filePath.getAbsoluteFile()))){
			String len;
			while((len=buf.readLine())!=null)
				count+=len.length();	
		}catch(IOException e) {
			e.printStackTrace();
		}
		return count;
	}
	public static long bytesCount(File filePath) {
		if(!filePath.isDirectory())
			return fileBytesCount(filePath.getAbsoluteFile());
		long count = 0;
		File[] files = filePath.listFiles();
		for(File f : files) {
			if(f.isDirectory())
				count += bytesCount(f.getAbsoluteFile());
			else if (f.toString().toLowerCase().endsWith(JAVA_SUFFIX))
				count += fileBytesCount(f.getAbsoluteFile());
		}
		return count;
	}
	public static int[] fileNoteCount(File filePath) {
		list = new ArrayList<String>();
		try(BufferedReader buf = new BufferedReader(new FileReader(filePath.getAbsoluteFile()))){
			String line = "";
			boolean comment =false;
			while((line=buf.readLine())!=null) {
				list.add(line);
			}
		}catch(FileNotFoundException e) {
			e.printStackTrace();
		}catch(IOException e) {
			e.printStackTrace();
		}
		 String s = null;
	     int countNote=0;
	     int charInNote=0;
	     for(int j=0;j<list.size();j++) {
	           s=list.get(j);
	           int note1=s.indexOf("/*");
	           int note2=s.indexOf("//");
	           int note3=s.indexOf("*/");
	           String dm="\"(.*)\"";//双引号            
	          if(note1!=-1&&note3==-1) {//多行注释
	              countNote++;
	              String ttt=list.get(j);
	              list.set(j, ttt.substring(0, note1));
	              charInNote+=s.substring(note1).length()+1;//+1是包括换行符      
	              s=list.get(++j);
	              while((note3=s.indexOf("*/"))==-1) {
	                    if((note2=s.indexOf("//"))!=-1) {
	                        countNote++;
	                    }
	                    list.remove(j);    
	                  charInNote+=s.length()+1;//+1是包括换行符 
	                  if(j<list.size()-1) {
	                      s=list.get(++j);
	                  }else {
	                      break;
	                  }
	              }
	              list.remove(j);
	              charInNote+=s.length();
	              
	          }else if(note2!=-1) {// "//"类的单行注释
	              countNote++;
	              list.set(j, s.substring(0,note2));
	              charInNote+=s.substring(note2).length()+1;
	          }else if(note1!=-1&&note3!=-1) {//单行注释
	              countNote++;
	              String m1=s.substring(0, note1);
	              String m2=s.substring(note3+2);
	              String m3=m1+m2;
	              charInNote+=s.substring(note1, note3+2).length();
	              list.set(j, m3);
	          }
	       }
		return new int[] {countNote,charInNote};
	}
	public static int[] notesCount(File filePath) {
		if(!filePath.isDirectory())
			return fileNoteCount(filePath.getAbsoluteFile());
		int countNote = 0;
		int charInNote = 0;
		File[] files = filePath.listFiles();
		for(File f : files) {
			if(f.isDirectory()) {
				countNote += notesCount(f.getAbsoluteFile())[0];
				charInNote += notesCount(f.getAbsoluteFile())[1];
			}		
			else if (f.toString().toLowerCase().endsWith(JAVA_SUFFIX)) {
				countNote += fileNoteCount(f.getAbsoluteFile())[0];
				charInNote += fileNoteCount(f.getAbsoluteFile())[1];
			}
		}		
		return new int[] {countNote,charInNote};
	}
	public static Map<String, Integer> keywordCount(File filePath){
		Map<String, Integer> map = new TreeMap<String, Integer>();
		for(String s : KEYWORDS)
			map.put(s, 0);
		if(filePath.isDirectory()) {
			File[] files =filePath.listFiles();
			for(File f : files) {
				if(f.isDirectory()) {
					Map<String, Integer> map1 = keywordCount(f.getAbsoluteFile());
					for (String ss : KEYWORDS) {
						map.put(ss, map.get(ss)+map1.get(ss));
					}		
				}
				else if(f.toString().toLowerCase().endsWith(JAVA_SUFFIX)){
					Map<String, Integer> map1 = fileKeywordCount(f.getAbsoluteFile());
					for (String ss : KEYWORDS) {			
						map.put(ss, map.get(ss)+map1.get(ss));
					}			
				}	
			}
		}
		else {
			return fileKeywordCount(filePath);
		}
		return map;
	}
	public static Map<String, Integer> fileKeywordCount(File filePath) {
		Map<String, Integer> map = new TreeMap<String, Integer>();
		for(String s : KEYWORDS)
			map.put(s, 0);
		//文件每一行转换成String数组
		list = new ArrayList<String>();
		try(BufferedReader buf = new BufferedReader(new FileReader(filePath.getAbsoluteFile()))){
			String line = "";
			while((line=buf.readLine())!=null) {
				list.add(line);
			}
		}catch(FileNotFoundException e) {
			e.printStackTrace();
		}catch(IOException e) {
			e.printStackTrace();
		}
		String dm="\"(.*)\"";//双引号 
		 String s = null;
	       for(int j=0;j<list.size();j++) {
	           s=list.get(j);
	           int note1=s.indexOf("/*");
	           int note2=s.indexOf("//");
	           int note3=s.indexOf("*/");
	                      
	          if(note1!=-1&&note3==-1) {//多行注释       
	              String ttt=list.get(j);
	              list.set(j, ttt.substring(0, note1));    
	                  s=list.get(++j);
	              while((note3=s.indexOf("*/"))==-1) {
	                    list.remove(j);    
	                  if(j<list.size()-1) {
	                      s=list.get(++j);
	                  }else {
	                      break;
	                  }
	              }
	              list.remove(j);             
	          }else if(note2!=-1) {// "//"类的单行注释
	              list.set(j, s.substring(0,note2));
	          }else if(note1!=-1&&note3!=-1) {//  "/*  */"类单行注释
	              String m1=s.substring(0, note1);
	              String m2=s.substring(note3+2);
	              String m3=m1+m2;
	              list.set(j, m3);
	          }else {//删除输出语句
	              String rp=list.get(j);
	              rp=rp.replaceAll(dm, "");
	              list.set(j, rp);
	          }	     
	       } 
		 for(int j=0;j<list.size();j++) {
	           s=list.get(j);
	           s = s.replace(dm, "").replace("[", " ").replace("]", " ").replace("{", " ").replace("}", " ").replace("(", " ").replace(")", " ");    
	           for(String key:KEYWORDS) {
	        	   String[] strs = s.split("\\s+");//空格分隔单词
	        	   int count = 0;
	        	   for(String s1 : strs) {//相同关键字,计数加一
	        		    if(s1.equals(key))
	        			   count ++;   		   
	        	   }
	        	   map.put(key, map.get(key)+count);
	           }
		 }
			return map;	
	}	  
}

package Trying;
import java.io.*;
import java.util.*;
public class Menu {
	public static final String JAVA_SUFFIX = ".java";
	public static boolean f=true;
	public static void  start() throws IOException {
		System.out.println("--------------------MENU--------------------");
		System.out.println("             1.分析目录或源程序文件");
		System.out.println("             2.查看已有的分析结果");
		System.out.println("             0.退出");
		System.out.println("--------------------------------------------");
		
				while(f) {
				System.out.print("             请选择:");
				Scanner input = new Scanner(System.in);
				int judge = input.nextInt();
				System.out.println("--------------------------------------------");
				switch(judge) {
				case 1:
				{menu1();
				f=false;
					break;
					
				}
					
				case 2:
				{menu2();
				f=false;
					break;
					
				}
				case 0:
				{
				f=false;
				System.out.println("             成功退出!!");
				System.exit(0);
					break;
					
				}
					
				default:
				{
					System.out.print("-------------不合法输入");
				}
					
				}
			}
				
		
	}
	
	public static void menu1() throws IOException {
		boolean f2=true;
		while(f2) {
			System.out.println("             请输入目录或源文件名:");
			Scanner input = new Scanner(System.in);
			String path = input.next();
			
			File f = new File(path);
			Counts cc = new Counts();
			if(f.exists())f2=false;
			if(!f.exists())
			{
				System.out.print("-------------不存在,请再次输入");
				
			}
			else if(f.isDirectory()||f.toString().toLowerCase().endsWith(JAVA_SUFFIX)) 
				Print.show(f.getAbsoluteFile());
			else if(!f.toString().toLowerCase().endsWith(JAVA_SUFFIX))
				System.out.print("-------------不是JAVA源程序文件");
		}
		
	}
	public static void menu2() throws IOException {
		System.out.println("--------------------------------------------");
		File f = new File("src\\data");
		File[] files = f.listFiles();
		int i = 1;
		for(File ff : files)
			System.out.println("	"+(i++)+" -- "+ff.getName());
		System.out.println("--------------------------------------------");
		System.out.print("请输入要查看的文件的编号:");
		Scanner input = new Scanner(System.in);
		int judge = input.nextInt();
		if(judge<1||judge>files.length) {
			System.out.println("输入错误。");
		}
		else {//读取文件并在控制台输出文件分析结果
			try(BufferedReader buf = new BufferedReader(new FileReader("src\\data\\"+files[judge-1].getName()))){
				String line = "";
				while((line=buf.readLine())!=null) {
					System.out.println(line);
				}
			}catch(FileNotFoundException e) {
				e.printStackTrace();
			}catch(IOException e) {
				e.printStackTrace();
			}
			System.out.println("--------------------------------------------");
			System.out.print("====输入任意数字返回主菜单====:");
			String judg= input.next();
			
				System.out.println("--------------返回成功------------------");
			start();
		}
	}
	
}
package Trying;

import java.io.*;
import java.util.*;

public class Print {
	
	public static void show(File dirPath) throws IOException {	
	    File file;
	    //创建文件
	    if(dirPath.isDirectory()) {
	    	file = new File("src\\data\\D_"+dirPath.getName()+"_Result.txt");
	    	if(!file.exists()) {
	    		file.createNewFile();
	    	}	    		
	    }
	    else {
	    	file = new File("src\\data\\F_"+dirPath.getName()+"_Result.txt");	    	 
	    	if(!file.exists()) {
	    		file.createNewFile();
	    	}    		
		}
	    //更改输出流,直接在文件上输出分析结果
	    try {
	    	PrintStream out = new PrintStream(file);
	    	PrintStream out1 =System.out;
			System.setOut(out);
			if(dirPath.isDirectory())
			System.out.println("分析目录:"+dirPath.getAbsolutePath());
		else {
			System.out.println("分析文件:"+dirPath.getAbsolutePath());
		}
		System.out.println();
		if(dirPath.isDirectory())
		System.out.println("Java源文件个数:"+Counts.fileCounts(dirPath));
		else {
			System.out.println();
		}
	    System.out.println("源文件中字符总个数:"+Counts.bytesCount(dirPath));
	    System.out.println("注释总个数:"+Counts.notesCount(dirPath)[0]);
	    System.out.println("注释总的字符数:"+Counts.notesCount(dirPath)[1]);
	    System.out.println();
	    System.out.println("关键字使用情况如下:");
	    
	    //降序比较器
	    Comparator<Map.Entry<String, Integer>> valueComparator = new Comparator<Map.Entry<String,Integer>>() {
			@Override
			public int compare(Map.Entry<String, Integer> o1,Map.Entry<String, Integer> o2) {
			return o2.getValue()-o1.getValue();
			}
			};
		//map转换为List
		List<Map.Entry<String, Integer>> klist = new ArrayList<Map.Entry<String,Integer>>(Counts.keywordCount(dirPath).entrySet());
		// 排序
		Collections.sort(klist,valueComparator);
		for (Map.Entry<String, Integer> entry : klist) 
		System.out.printf("[%-15s:%4d]\n",entry.getKey(),entry.getValue());
		//输出流改回默认,输出到控制台
		System.setOut(out1);
		System.out.println("--------------------------------------------");
			    if(dirPath.isDirectory()) {
		    	System.out.println("目录分析结束,分析结果存放在文件[data/D_"+dirPath.getName()+"_Result.txt]!");
	    }
	    else {	    	
		    	System.out.println("文件分析结束,分析结果存放在文件[data/F_"+dirPath.getName()+"_Result.txt]!");
		}	
	    }catch(FileNotFoundException e){
            e.printStackTrace();
        }
		System.out.print("输入任意数字返回主菜单:");
		Scanner input = new Scanner(System.in);
		int judge = input.nextInt();
		for(int j=0;j<3;j++)
			System.out.println("!你好,编译器轻轻的的跟屏幕前的你说一声:老师您辛苦了!新年快乐!身体健康!生活幸福!!!!-----");
		Menu.start();
	}
}

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值