Strut2中单元测试实例

项目文件结构图:


椭圆框中的Jar 包是单元测试时候需要引入的。

矩形框 MainTest 每个包下一个,为 JUnit4 的 Suite 套件,其作用是执行本包下的“测试类”和子包的 MainTest。

例如:jp.co.snjp.ht.MainTest

package jp.co.snjp.ht;import org.junit.runner.RunWith;
import org.junit.runners.Suite;@RunWith( Suite.class )
@Suite.SuiteClasses({ jp.co.snjp.ht.orderCheck.MainTest.class, jp.co.snjp.ht.outPreconcert.MainTest.class,jp.co.snjp.ht.partOut.MainTest.class,jp.co.snjp.ht.productCheck.MainTest.class, 
})
public class MainTest {
}
由于 jp.co.snjp.ht 包下没有“测试类”,因而只需要引入“子包”的 MainTest 即可!

而,jp.co.snjp.ht.orderCheck.MainTest

package jp.co.snjp.ht.orderCheck;import org.junit.runner.RunWith;
import org.junit.runners.Suite;@RunWith( Suite.class )
@Suite.SuiteClasses({ CheckBarcodeTest.class, OrderConfirmTest.class
})
public class MainTest {}
由于 jp.co.snjp.ht.orderCheck 下没有“子包”,因而只需要引入“测试类”

————————————————————————————————

Strut2 提供了隔离容器对象的方法,因而在所有Action 的基类将其织入。

因为本项目很小,没有单独的Business 层和DAO 层,业务逻辑在 Action 中完成,SQL 操作在 SqlHelper 中完成。

为了实现单元测试隔离测试效果,这里提供了 setSqlHelper( SqlHelper sqlHelper ) 方法,这样就可以传入模拟的 SqlHelper 对象

package jp.co.snjp.ht.util;import java.util.Date;
import java.util.List;
import java.util.Map;import jp.co.snjp.dao.SqlHelper;import org.apache.struts2.interceptor.CookiesAware;
import org.apache.struts2.interceptor.RequestAware;
import org.apache.struts2.interceptor.SessionAware;import com.opensymphony.xwork2.ActionSupport;public class BaseAction extends ActionSupport implements RequestAware,SessionAware,CookiesAware{private static final long serialVersionUID = 1L;protected Map<String,Object> requestMap;protected Map<String,Object> sessionMap;protected Map<String,String> cookieMap;/*** 查询结果集*/protected List<Object> list;/*** SQL 执行帮助类*/protected SqlHelper sqlHelper;public void setRequest(Map<String, Object> requestMap) {this.requestMap = requestMap;}public void setSession(Map<String, Object> sessionMap) {this.sessionMap = sessionMap;}public void setCookiesMap(Map<String, String> cookieMap) {this.cookieMap = cookieMap;}public void setSqlHelper( SqlHelper sqlHelper ){this.sqlHelper = sqlHelper;}/*** 记录存储过程执行的日志信息* @param start* @param name** Date	  :2012-6-7* Author :GongQiang* @throws Exception */protected void logStroeProcedure( Date start, String name ) throws Exception{String formatDateTime = Utils.formatDateTime( start );String userId = (String) sessionMap.get( "user_id" );String sql = "insert into HT_CCGC_LOG(usercode,ccgcmc,kszxsj) "+" values ('"+ userId +"','"+ name +"','"+ formatDateTime+"' );";sqlHelper.executeSQL( sql );} 
}
虽然提供了 setSqlHelper( SqlHelper sqlHelper ) 方法,但是这方法在什么时候调用呢?

为了解决这个问题,就只能把实际的业务逻辑放到 doExecute() 方法下去执行,而在 execute()方法下调用 setSqlHelper()方法,只用测试 doExecute()方法。

doExecute()方法修饰为包可见,这样就只有测试代码可以访问。代码如下:

package jp.co.snjp.ht.productCheck;import java.math.BigDecimal;
import java.util.List;
import java.util.Map;import jp.co.snjp.dao.SqlHelper;
import jp.co.snjp.ht.util.BaseAction;
import jp.co.snjp.ht.util.SpotTicketBarcodeParser;
/*** 部品检查录入-Barcode扫描Action* @author GongQiang**/
public class ProductCheckBarcode extends BaseAction {private static final long serialVersionUID = 1L;private String barcode;private String backUrl;public String getBarcode() {return barcode;}public void setBarcode(String barcode) {this.barcode = barcode;}public String getBackUrl() {return backUrl;}public void setBackUrl(String backUrl) {this.backUrl = backUrl;}/*** error_0 条码不符合规则* error_1 订单在DB中不存在 或 订单已经执行完毕* error_2 订单区分错误*/@Overridepublic String execute() throws Exception {super.execute();setBackUrl( "productCheck/scanBarcode.jsp" );setSqlHelper( new SqlHelper() );return doExecute();}String doExecute()throws Exception {SpotTicketBarcodeParser parser = new SpotTicketBarcodeParser( barcode );if( ! parser.valid() ){return "error_0";}queryOrderInfo( parser.getOrderNo() );if( orderNotExist() || orderFinished() ){return "error_1";}if( !checkDistinguish() ){return "error_2";}sessionMap.put( "order_info", list.get(0) );return SUCCESS;}void queryOrderInfo( String orderNo ) throws Exception{String sql = "select top 1 * from iOrder_Check where " +" OrderNo='" + orderNo + "' ;";list = sqlHelper.executeQuery( sql );if( list == null || list.isEmpty() ){return;}queryNameCount(orderNo);}/*** 查询订单名称 和 订单残&实收数量* ** Date	  :2012-6-8* Author :GongQiang* @throws Exception */private void queryNameCount( String orderNo ) throws Exception{String sql = "select sum(nqty) as usedCount from iOrder_Check "+" where orderno='" + orderNo + "' group by orderno;";List usedCountResult = sqlHelper.executeQuery( sql );BigDecimal orderCount = (BigDecimal) ((Map)list.get(0)).get( "pqty" );BigDecimal usedCount = (BigDecimal) ((Map)usedCountResult.get(0)).get( "usedcount" );BigDecimal remainCount = orderCount.subtract( usedCount );sql = "select itemname from iorder_operate where " +" OrderNo='" + orderNo + "' ;";List itemNameResult = sqlHelper.executeQuery( sql );String itemName = (String) ((Map)itemNameResult.get(0)).get( "itemname" );((Map)list.get(0)).put( "remaincount", remainCount );((Map)list.get(0)).put( "usedcount", usedCount );((Map)list.get(0)).put( "itemname", itemName );}/*** DB中没有关联的订单* @return** Date	  :2012-6-7* Author :GongQiang*/boolean orderNotExist(){if( list == null || list.isEmpty() ){return true;}return false;}/*** 该订单已经执行完毕* @return** Date	  :2012-6-7* Author :GongQiang*/boolean orderFinished(){BigDecimal remainCountInOrder = (BigDecimal)((Map)list.get(0)).get( "remaincount" );if( remainCountInOrder != null ){return remainCountInOrder.compareTo( new BigDecimal("0") ) <= 0 ;}return false;}/*** 检查区分是否正确* @return** Date	  :2012-6-7* Author :GongQiang*/private boolean checkDistinguish(){String[] rights = { "保证" };String dist = (String) ((Map)list.get(0)).get( "chkdistinguish" );for( int i=0 ; i<rights.length ; i++ ){if( rights[i].equals( dist ) ){return true;}}return false;}
}

逻辑很简单,这里仅仅测试最基本的4 条执行路径

1、条码解析错误

2、订单在DB中不存在

3、订单已经执行完成

4、分区错误

5、OK

下面是完整的测试类:

package jp.co.snjp.ht.productCheck;import static org.junit.Assert.*;import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import jp.co.snjp.dao.SqlHelper;import org.easymock.classextension.EasyMock;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;public class ProductCheckBarcodeTest {@BeforeClasspublic static void setUpBeforeClass() throws Exception {}@AfterClasspublic static void tearDownAfterClass() throws Exception {}/*** 错误条码* ** Date	  :2012-6-18* Author :GongQiang* @throws Exception */@Testpublic void testDoExecute_errorBarcode() throws Exception {ProductCheckBarcode action = new ProductCheckBarcode();action.setBarcode( "xxx0001" );assertEquals("error_0", action.doExecute() );action = new ProductCheckBarcode();action.setBarcode( "0123456789012345678901234567890123456789555" );assertEquals("error_0", action.doExecute() );}/*** DB中没有关联的记录* ** Date	  :2012-6-18* Author :GongQiang* @throws Exception */@Testpublic void testDoExecute_noRecord() throws Exception {SqlHelper mockSqlHelper = EasyMock.createMock( SqlHelper.class );// 返回结果EasyMock.expect( mockSqlHelper.executeQuery( (String)EasyMock.anyObject() )).andReturn( new ArrayList<Map<String,Object>>() );// ReplayEasyMock.replay( mockSqlHelper );ProductCheckBarcode action = new ProductCheckBarcode();action.setBarcode( "xxx0001|bbb" );action.setSqlHelper( mockSqlHelper );assertEquals("error_1", action.doExecute() );//VerifyEasyMock.verify( mockSqlHelper );//-----------------------------------------mockSqlHelper = EasyMock.createMock( SqlHelper.class );// 返回结果EasyMock.expect( mockSqlHelper.executeQuery( (String)EasyMock.anyObject() )).andReturn( null );// ReplayEasyMock.replay( mockSqlHelper );action = new ProductCheckBarcode();action.setBarcode( "xxx0001|bbb" );action.setSqlHelper( mockSqlHelper );assertEquals("error_1", action.doExecute() );//VerifyEasyMock.verify( mockSqlHelper );}/*** 记录已经执行完毕* ** Date	  :2012-6-18* Author :GongQiang* @throws Exception */@Testpublic void testDoExecute_finished() throws Exception {//list -- 返回的结果集Map<String, Object> map = new HashMap<String,Object>();map.put("pqty", new BigDecimal("100")); //订单关联数量map.put("usedcount", new BigDecimal("100")); //已经使用数量 -->剩余数量就是0map.put("itemname", "TextOrderXXX");List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();list.add( map );SqlHelper mockSqlHelper = EasyMock.createMock( SqlHelper.class );EasyMock.expect( mockSqlHelper.executeQuery( (String)EasyMock.anyObject() )).andReturn( list ).times(3);// ReplayEasyMock.replay( mockSqlHelper );ProductCheckBarcode action = new ProductCheckBarcode();action.setBarcode( "xxx0001|bbb" );action.setSqlHelper( mockSqlHelper );assertEquals("error_1", action.doExecute() );//VerifyEasyMock.verify( mockSqlHelper );}/*** 错误的分区* ** Date	  :2012-6-18* Author :GongQiang* @throws Exception */@Testpublic void testDoExecute_errorDistinguish() throws Exception {//list -- 返回的结果集Map<String, Object> map = new HashMap<String,Object>();map.put("pqty", new BigDecimal("100")); //订单关联数量map.put("usedcount", new BigDecimal("50")); //已经使用数量 -->剩余数量就是50map.put("itemname", "TextOrderXXX");map.put( "chkdistinguish", "不存在" );List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();list.add( map );SqlHelper mockSqlHelper = EasyMock.createMock( SqlHelper.class );EasyMock.expect( mockSqlHelper.executeQuery( (String)EasyMock.anyObject() )).andReturn( list ).times(3);// ReplayEasyMock.replay( mockSqlHelper );ProductCheckBarcode action = new ProductCheckBarcode();action.setBarcode( "xxx0001|bbb" );action.setSqlHelper( mockSqlHelper );assertEquals("error_2", action.doExecute() );//VerifyEasyMock.verify( mockSqlHelper );}/*** 正常* ** Date	  :2012-6-18* Author :GongQiang* @throws Exception */@Testpublic void testDoExecute_ok() throws Exception {//list -- 返回的结果集Map<String, Object> map = new HashMap<String,Object>();map.put("pqty", new BigDecimal("100")); //订单关联数量map.put("usedcount", new BigDecimal("50")); //已经使用数量 -->剩余数量就是50map.put("itemname", "TextOrderXXX");map.put( "chkdistinguish", "保证" );List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();list.add( map );SqlHelper mockSqlHelper = EasyMock.createMock( SqlHelper.class );EasyMock.expect( mockSqlHelper.executeQuery( (String)EasyMock.anyObject() )).andReturn( list ).times(3);// ReplayEasyMock.replay( mockSqlHelper );ProductCheckBarcode action = new ProductCheckBarcode();action.setBarcode( "xxx0001|bbb" );action.setSqlHelper( mockSqlHelper );action.setSession( new HashMap<String,Object>() );assertEquals("success", action.doExecute() );//VerifyEasyMock.verify( mockSqlHelper );}
}
下面详细讲解测试方法的写法:

1、条码解析错误

	/*** 错误条码* ** Date	  :2012-6-18* Author :GongQiang* @throws Exception */@Testpublic void testDoExecute_errorBarcode() throws Exception {ProductCheckBarcode action = new ProductCheckBarcode();action.setBarcode( "xxx0001" );assertEquals("error_0", action.doExecute() );action = new ProductCheckBarcode();action.setBarcode( "0123456789012345678901234567890123456789555" );assertEquals("error_0", action.doExecute() );}
当条码解析错误时,查询没有机会执行也就没有必要传入 SqlHelper 对象。


2、订单在DB中不存在

	/*** DB中没有关联的记录* ** Date	  :2012-6-18* Author :GongQiang* @throws Exception */@Testpublic void testDoExecute_noRecord() throws Exception {SqlHelper mockSqlHelper = EasyMock.createMock( SqlHelper.class );// 返回结果EasyMock.expect( mockSqlHelper.executeQuery( (String)EasyMock.anyObject() )).andReturn( new ArrayList<Map<String,Object>>() );// ReplayEasyMock.replay( mockSqlHelper );ProductCheckBarcode action = new ProductCheckBarcode();action.setBarcode( "xxx0001|bbb" );action.setSqlHelper( mockSqlHelper );assertEquals("error_1", action.doExecute() );//VerifyEasyMock.verify( mockSqlHelper );//-----------------------------------------mockSqlHelper = EasyMock.createMock( SqlHelper.class );// 返回结果EasyMock.expect( mockSqlHelper.executeQuery( (String)EasyMock.anyObject() )).andReturn( null );// ReplayEasyMock.replay( mockSqlHelper );action = new ProductCheckBarcode();action.setBarcode( "xxx0001|bbb" );action.setSqlHelper( mockSqlHelper );assertEquals("error_1", action.doExecute() );//VerifyEasyMock.verify( mockSqlHelper );}
为了实现单元测试的隔离性,这里使用了模拟的 SqlHelper 对象。模拟返回一个空的List 或者 null。

注意:模拟方法执行时候是严格的参数匹配的,为简易性这里直接使用 EasyMock.anyObject(),这样任何参数都能匹配执行。


3、订单已经执行完成

/*** 记录已经执行完毕* ** Date	  :2012-6-18* Author :GongQiang* @throws Exception */@Testpublic void testDoExecute_finished() throws Exception {//list -- 返回的结果集Map<String, Object> map = new HashMap<String,Object>();map.put("pqty", new BigDecimal("100")); //订单关联数量map.put("usedcount", new BigDecimal("100")); //已经使用数量 -->剩余数量就是0map.put("itemname", "TextOrderXXX");List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();list.add( map );SqlHelper mockSqlHelper = EasyMock.createMock( SqlHelper.class );EasyMock.expect( mockSqlHelper.executeQuery( (String)EasyMock.anyObject() )).andReturn( list ).times(3);// ReplayEasyMock.replay( mockSqlHelper );ProductCheckBarcode action = new ProductCheckBarcode();action.setBarcode( "xxx0001|bbb" );action.setSqlHelper( mockSqlHelper );assertEquals("error_1", action.doExecute() );//VerifyEasyMock.verify( mockSqlHelper );}
在实际代码中,当查询到记录时就要继续两个 SQL查询操作(1、查询订单名称;2、查询订单关联数量和已经检查数量)。并依次往 list 结果集中添加对象,但是在测试中为了方便起见,直接 一次性构造出完整的结果重复执行 3次


4、分区错误

	/*** 错误的分区* ** Date	  :2012-6-18* Author :GongQiang* @throws Exception */@Testpublic void testDoExecute_errorDistinguish() throws Exception {//list -- 返回的结果集Map<String, Object> map = new HashMap<String,Object>();map.put("pqty", new BigDecimal("100")); //订单关联数量map.put("usedcount", new BigDecimal("50")); //已经使用数量 -->剩余数量就是50map.put("itemname", "TextOrderXXX");map.put( "chkdistinguish", "不存在" );List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();list.add( map );SqlHelper mockSqlHelper = EasyMock.createMock( SqlHelper.class );EasyMock.expect( mockSqlHelper.executeQuery( (String)EasyMock.anyObject() )).andReturn( list ).times(3);// ReplayEasyMock.replay( mockSqlHelper );ProductCheckBarcode action = new ProductCheckBarcode();action.setBarcode( "xxx0001|bbb" );action.setSqlHelper( mockSqlHelper );assertEquals("error_2", action.doExecute() );//VerifyEasyMock.verify( mockSqlHelper );}
这里就是注意构造参数,使得前面的判断都成功,到这里判断分区时错误。


5、OK

	/*** 正常* ** Date	  :2012-6-18* Author :GongQiang* @throws Exception */@Testpublic void testDoExecute_ok() throws Exception {//list -- 返回的结果集Map<String, Object> map = new HashMap<String,Object>();map.put("pqty", new BigDecimal("100")); //订单关联数量map.put("usedcount", new BigDecimal("50")); //已经使用数量 -->剩余数量就是50map.put("itemname", "TextOrderXXX");map.put( "chkdistinguish", "保证" );List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();list.add( map );SqlHelper mockSqlHelper = EasyMock.createMock( SqlHelper.class );EasyMock.expect( mockSqlHelper.executeQuery( (String)EasyMock.anyObject() )).andReturn( list ).times(3);// ReplayEasyMock.replay( mockSqlHelper );ProductCheckBarcode action = new ProductCheckBarcode();action.setBarcode( "xxx0001|bbb" );action.setSqlHelper( mockSqlHelper );action.setSession( new HashMap<String,Object>() );assertEquals("success", action.doExecute() );//VerifyEasyMock.verify( mockSqlHelper );}
这里要注意,因为实际代码中 调用了sessionMap 的put 方法,因而这里就要传入一个对象。


————————————————————————————————————

扩展:当有单独的 Business 层和 DAO 层时候。也许没有办法像 SqlHelper 简单的只需要一个接口方法即可,也许就要每个子 Action 设置相应的Business 对象。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/497844.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

德国图宾根大学发布可扩展「对抗黑盒攻击」,仅通过观察决策即可愚弄深度神经网络

原文来源&#xff1a;arXiv作者&#xff1a;Wieland Brendel、Jonas Rauber、Matthias Bethge「雷克世界」编译&#xff1a;嗯~阿童木呀、哆啦A亮不知道大家有没有注意到&#xff0c;许多机器学习算法很容易受到几乎不可察觉的输入干扰的影响。到目前为止&#xff0c;我们还不清…

oracle中执行自带脚本,oracle自带脚本

------------------------------------------------------------优化相关------------------------------------------------------------生成sql执行计划&#xff1a;?/rdbms/admin/awrsqrpt成成sql优化建议&#xff1a;?/rdbms/admin/sqltrptADDM报告:?/rdbms/admin/addmr…

Understanding node.js

来源&#xff1a;http://debuggable.com/posts/understanding-node-js:4bd98440-45e4-4a9a-8ef7-0f7ecbdd56cb Node.js has generally caused two reactions in people Ive introduced it to. Basically people either "got it" right away, or they ended up being …

腾讯AI Lab刷新人脸检测与识别两大测评国际记录,技术日调用超六亿

来源&#xff1a;腾讯AI实验室概要&#xff1a;人脸检测是让机器找到图像视频中所有人脸并精准定位其位置信息&#xff0c;人脸识别是基于人脸图像自动辨识其身份&#xff0c;两者密切相关&#xff0c;前者是后者的前提和基础。腾讯AI Lab在国际最大、最难的人脸检测平台WIDER …

修改数据库参数oracle,Oracle 修改数据库基本参数

Oracle 通过ALTER SYSTEM语句修改数据库参数&#xff0c;其语法&#xff1a;ALTER SYSTEM SET scope[ memory | spfile | both ] [sid]SCOPE表示应用的范围&#xff0c;分成三种memeory&#xff1a;只在当前实例中修改生效&#xff0c;重启后失效(内存中)spfile&#xff1a;只…

Jeff Dean| 面向系统的机器学习和面向机器学习的系统

来源&#xff1a;全球人工智能概要&#xff1a;我们将发布一系列内容&#xff0c;展示 Google 在 NIPS 2017 上发布的工作成果。首当其冲的便是来自 Jeff Dean 的 PPT 《面向系统的机器学习和面向机器学习的系统》。第 31 届神经信息处理系统年会&#xff08;NIPS 2017&#xf…

mysql linux附加数据库文件夹,Linux全攻略--MySQL数据库配置与管理

MySQL是一种精巧的,多用户和多线程的中小型SQL数据库系统,由一个服务器守护进程mysqld和很多不同的客户程序和库组成.现在形成了一个"LinuxApachePHPMySQL"构建电子商务网站的黄金网站的黄金组合.MySQL不是开放源代码的产品,但在某些情况下可以自由使用.由于它的强大…

互联网如何促进经济发展?腾讯、谷歌、Facebook的实践和经验

来源&#xff1a;腾讯研究院右起&#xff1a;司晓 腾讯研究院院长李刚 腾讯研究院首席研究员Nicole Sremlau 牛津大学比较媒体法与政策项目负责人Pankaj Venugopal Facebook公司副总法律顾问Olivia Hatalsky Alphabet公司高级项目经理互联网正在成为社会生态的连接器&…

Execution in the Kingdom of Nouns (名词王国中的死刑)

来源&#xff1a;http://www.cnblogs.com/bigfish--/archive/2011/12/31/2308407.html Steve Yegge的大作 Execution in the Kingdom of Nounshttp://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html THURSDAY, MARCH 30, 2006 Execution in the Kingd…

linux 串口text模式安装,使用串口安装centos操作系统

使用CSS3 Media Queries实现网页自适应原文来源:http://webdesignerwall.com 翻译:http://xinyo.org 当今银屏分辨率从 320px (iPhone)到 2560px (大屏显示器)或者更大.人们也不 ...Ajax读取txt并对txt内容进行分页显示function TransferString(content) { var string content…

汇真科技李利鹏 :人工智能的应用边界

人工智能分为几个层面&#xff0c;首先是基础层&#xff0c;要有大数据云计算&#xff0c;因为你数据量大的话&#xff0c;要放到云端去处理&#xff0c;大数据、云计算、GPU/FPGA等硬件加速、新形态神经网络芯片等计算能力提供商。在技术层就是做机器学习、深度学习、增强学习…

linux java内存清理,Linux服务器用完java内存

寻找解决方法或关于如何找出问题的一些提示。Linux服务器用完java内存使用只显示引用的VisualVM工具查看heapdumps正在举行。有更好的工具可以使用吗&#xff1f;有什么我可以从命令行运行以释放这些引用&#xff1f;使用jconsole GC不起作用&#xff0c;只能延长约5天的锁定时…

中缀到后缀的转换

中缀表达式&#xff1a;ab*c(d*ef)*g 转换成后缀表达式&#xff1a;abc*de*fg* 转换步骤&#xff1a; 当读到一个操作数&#xff08;如&#xff1a;a&#xff09;时&#xff0c;立即把它放到输出中&#xff1b; 当遇到操作符&#xff08;如&#xff1a;&#xff09;时&#…

CES 2018即将揭幕:AI平台之争烽烟骤起

来源&#xff1a;机器人创新生态概要&#xff1a;一年一度的国际消费电子展&#xff08;CES&#xff09;即将揭开序幕&#xff0c;今年有哪些值得观察的热门技术呢&#xff1f;一年一度的国际消费电子展&#xff08;CES&#xff09;即将揭开序幕&#xff0c;今年有哪些值得观察…

后缀表达式转变成表达式树

后缀表达式&#xff1a;abcde** 转换的表达式树&#xff1a; 转换步骤&#xff1a; 如果符号是操作数&#xff0c;那么就建立一个单节点树并将它推入栈中。 如果符号是操作符&#xff0c;那么就从栈中弹出两颗树 T1 和 T2 &#xff08;T1 先弹出&#xff09;并形成一棵新的树…

linux用户组登录,linux用户和用户组

1.用户组和权限管理用户分为三类&#xff1a;1.1 超级用户&#xff1a;root uid0,简单来说uid为0的用户就是超级用户。1.2 虚拟用户&#xff1a;存在linux中&#xff0c;满足文件或者程序运行的需要&#xff0c;而创建的。不能登录&#xff0c;不能使用。uid1-499,1-999(centos…

人工智能和厨房电器的结合:厨房助理机器人

来源&#xff1a;人工智能学家AItists概要&#xff1a;从智能家居到无人驾驶&#xff0c;人工智能正在落地的道路上。而其中一个让人觉得有点意外也很有趣的场景是&#xff1a;厨房。从智能家居到无人驾驶&#xff0c;人工智能正在落地的道路上。而其中一个让人觉得有点意外也很…

查找N个数中第K大的数

方法一&#xff1a;将一组数放入数组中&#xff0c;升排序。并返回第 ( length - k )个元素这里消耗的时间就是排序用的时间&#xff0c;用快速排序则为&#xff1a;O( N log N )代码&#xff1a; /*** 先排序后获取* return** Date :2012-7-4* Author :GongQiang*/public in…

美国科学院学报:如何在竞争激烈的环境下维持稳定的群体

行为决策演化示意图。最上面一行是混合群体&#xff0c;下面两行是网络群体。相比于混合群体&#xff0c;网络促使合作者聚集成团簇&#xff0c;但是惩罚的加入将破坏合作环境。来源&#xff1a;中国科学院西安光机所李学龙研究员同合作者在数据驱动的行为决策研究方面取得阶段…

linux文本处理脚本题,Linux文本处理工具sed练习题

1、使用sed命令打印出ifconfig ens33的ip地址解:(1)ifconfig ens33 | sed -n 2p | sed s/.*inet // | sed s/netmask.*//(2)ifconfig ens33 | sed -n 2p | sed -r s/.*inet (.*)netmask.*/\1/(3)ifconfig ens33 | sed -r -n 2s/.*inet (.*)netmask.*/\1/p2、使用sed命令打印出系…