为了账号安全,请及时绑定邮箱和手机立即绑定
4.4 Selenium Web 应用程序测试

Selenium 是一个用于 Web 应用程序测试的工具,它使用 JavaScript 模拟真实用户对浏览器进行操作。Selenium 支持的浏览器包括IE(7, 8, 9, 10, 11),Mozilla Firefox,Safari,Google Chrome,Opera等。Selenium 支持使用 Python 语言编写动作测试脚本,测试脚本执行时,浏览器自动按照脚本代码做出点击、输入、打开、验证等操作,就像真实用户所做的一样,从终端用户的角度测试应用程序。用户使用 Python 编写测试脚本:测试应用程序的浏览器兼容性,验证应用程序是否能够工作在不同浏览器和操作系统之上创建回归测试检验软件功能和用户需求Selenium 主要用于测试 Web 应用程序,学习 web 自动化测试前,需要补充 Web 相关的知识,包括:HTTP 协议HTML 的基础知识,如何使用 Javascript 操纵 DOMFirebug 或者 Chrome 开发者工具的使用,用于抓取元素

1.3 web 开发需要越来越多的编程

在互联网早期,网站中的主要内容由静态页面构成,开发一个网站并不需要太多的编程工作,网站开发人员会编写 HTML 文件即可,很多网站甚至于不需要程序员的参与。随着互联网的发展,网站的功能越来越复杂,网站提供的功能日趋丰富,网站更像是一个本地应用程序,而不是单纯展示内容的网页。在这个时期,开发 Web 需要编写大量的程序,一个复杂的 Web 开发项目包含有数万行、甚至于数十万行的源代码,也就是说,写一个网站开始变得越来越 “麻烦”。不仅是麻烦,而且网站开发需要进行大量的重复性工作,比如说网站 A 需要开发一个后台管理系统,网站 B 也需要后台管理系统。后台管理系统功能的实现逻辑又非常相似,我们开发两个网站就要写两套后台管理系统的代码,极大地增加了程序员的工作量。既然是这样,我们为什么不能把网站开发中这些相似甚至一样的功能抽离出来,封装在一起,等到需要的时候再调用呢?那个时候的程序员非常有效率,说干就干,他们把大量的相似性功能封装起来,等到需要使用的时候进行调用,于是就慢慢地形成的 “框架” 的概念。

1. 编译程序

大家可能有个疑问,为什么需要编译程序呢?计算机不能直接执行我们编写的源代码吗?这是由于计算机只能识别由0和1组成的二进制代码。需要通过编译将源代码转换为计算机认识的二进制代码。

1.2 出现了专门的 Web 开发工程师

在互联网早期,网站中的主要内容由静态页面构成,开发一个网站并不需要太多的编程工作,网站开发人员会编写 HTML 文件即可,很多网站甚至于不需要程序员的参与。随着互联网的发展,网站的功能越来越复杂,网站提供的功能日趋丰富,网站更像是一个本地应用程序,而不是单纯展示内容的网页。在这个时期,开发 Web 需要编写大量的程序,一个复杂的 Web 开发项目包含有数万行、甚至于数十万行的源代码。随着网站开发的需求的增加,出现了专门的 Web 开发工程师,在计算机行业的招聘网站上搜索 "Web 开发”,可以获得大量的职位招聘信息:

3. 编写 Hibernate 程序

本文程序开发环境说明:操作系统: windows 7 以上;开发工具: Eclipse 。此方案可作为学习者的可选择方案之一,有兴趣可了解其它系统或开发工具!

3.2 快速编写 Hello World 程序

打开 IDE,会提示我们选择工作目录,工作目录用于存放开发者的配置和开发工件。选择好自己的工作目录后直接点击 Launch按钮即可打开 IDE。打开后会显示一个ecplise的欢迎页面。点击 Create a Hello World application。按照向导步骤即可创建并运行我们的 Hello World 程序。右侧区域为创建一个Hello World程序的整体步骤。下面我们一起动手开始吧。第一步:新建一个 Java 工程点击 New -> Java Project下图中Project name为项目名称。将项目命名为 hello(项目名的命名规范:全小写英文),并选择 JRE 为 JavaSE-14,点击 Finish 按钮。这时会出现一个是否创建模块信息的弹窗,点击 Don't Create 按钮。第二步:在工程下新建一个类在刚刚创建好的工程下的src目录上,点击右键 -> New -> Class将类名命名为 HelloWorld,并且选择创建main方法的复选框。点击 Finish 按钮第三步:编写打印语句现在,ecplise 已经为我们在 HelloWorld.java 文件中自动创建了 main 方法,在 main 方法下增加如下打印语句:System.out.println("Hello World");第四步:运行 Java 应用在源代码文件 HelloWorld.java 上点击右键(或直接在源代码中点击右键),选择 Run As -> Java Application我们可以看到控制台已成功打印 Hello World

3. 基于 Future 编写客户端程序

编写客户端程序,首先是创建 AsynchronousSocketChannel 实例,通过它的 open 方法完成。然后调用 AsynchronousSocketChannel 的 connect 方法连接服务器,同样是异步调用,不会阻塞调用线程。调用 Future 的 get 方法获取连接结果。剩下客户端数据收发逻辑和服务器的数据收发逻辑一致。客户端完整代码:import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.AsynchronousSocketChannel;import java.util.concurrent.Future;public class AsyncClient { private static final int PORT =56002; public static void main(String[] args) { try (AsynchronousSocketChannel client = AsynchronousSocketChannel.open()) { Future<Void> result = client.connect(new InetSocketAddress("127.0.0.1", PORT)); System.out.println("Async connect the server"); result.get(); String reqMessage = "Hello server!"; ByteBuffer reqBuffer = ByteBuffer.wrap(reqMessage.getBytes()); Future<Integer> writeResult = client.write(reqBuffer); System.out.println("Async send to server:" + reqMessage); writeResult.get(); ByteBuffer inBuffer = ByteBuffer.allocate(128); Future<Integer> readResult = client.read(inBuffer); readResult.get(); System.out.println("Async recv from server:" + new String(inBuffer.array()).trim()); } catch (Exception e) { e.printStackTrace(); } }}

1. 什么是元编程

元编程是计算机程序的编写,这些计算机程序将其他程序(或它们本身)作为数据写入或操作,或者在编译时完成部分工作,而这些工作原本可以在运行时完成。在许多情况下,这使程序员可以在与手动编写所有代码相同的时间内完成更多工作,或者为程序提供更大的灵活性,以有效地处理新情况而无需重新编译。或者,更简单地说:元编程是编写在运行时编写代码的代码,以使您的编程更轻松。这听上去是不是很疯狂?简而言之,您可以使用元编程来重新打开和修改类,捕获不存在的方法并即时创建它们,通过避免重复创建DRY(Don’t repeat yourself)代码等等。Ruby常见的开源框架比如Rails、Sinatra都使用了元编程这门技术。

3.2 快速编写 Hello World 程序

38打开IntelliJ IDEA,完成一些初始配置。(建议初次使用的开发者,一直点击下一步采用默认配置即可)。完成初始配置后会出现如下的欢迎窗口。第一步:新建一个 Java 工程点击 Create New Project。选择项目的 SDK。这里会自动识别我们之前所安装的 JDK14。点击 Next 按钮。选中 Create project from template -> Command Line App,表示会新建一个包含 main() 方法的简单 Java 应用。点击 Next 按钮继续。设置项目名称(Project name)为 hello,Project location 为项目的存放目录,Base package是包名,自定义即可。点击 Finish 按钮。第二步:编写输出语句新建项目成功后,IDE 会自动打开项目。点击左侧的 Project 按钮,即可查看项目的目录结构,Main.java 为 IDE 为我们自动创建的模板代码。在 Main.java 的main() 方法中,编写如下输出语句:System.out.println("Hello World!");第三步:运行 Java 应用点击 main() 方法左侧的绿色小箭头,会弹出一些选项,点击 Run 'Main.main()'。IDE 会自动编译并执行 Java 应用,稍等片刻后,在下方的控制台中会输出 Hello World!。想要执行源码,除了上述点击绿色小箭头,也可以在源代码文件中点击鼠标右键,选择Run Main来执行源代码:

4.2 编码流程

实例://封装编码方法public ByteBuf encode(Object obj) { // 1. 创建 ByteBuf 对象 ByteBuf byteBuf = ByteBufAllocator.DEFAULT.ioBuffer(); // 2. 序列化 Java 对象 byte[] bytes = SerializeUtils.serialize(obj); // 3. 实际编码过程 byteBuf.writeBytes(bytes); return byteBuf;}//序列化工具类public class SerializeUtils{ //序列化方法 public static byte[] serialize(Object obj){ //省略序列化过程 return null; }}代码说明:创建一个 ByteBuf(前面章节详细讲解过);把内容序列化成字节数组;把字节数组写入到 ByteBuf。

5.3 编写应用

本部分会学习如何高效的使用 Android Studio 来编写代码。如何高效的编排界面布局。如何合理的管理项目资源。开发 Android 应用就是编排界面、编写代码的过程。

C 语言程序结构

上一个小节 C 语言的简介中我们对 C 语言已经有了一个简单的了解。这一节我们就来看一下 C 语言的程序结构,了解了 C 语言的程序结构之后我们才能正式的开始编写 C 语言程序。下面我们来看一个最简单的 C 语言可执行程序:

3.2 使用 lambda 表达式重写程序

在前面的小节中,将函数作为参数,编写程序实现打印正数和负数。下面使用 lambda 表达式重写这个程序:list = [1, -1, 2, -2, 3, -3]def select(list, select_function): for item in list: if select_function(item): print(item)select(list, lambda item: item > 0)select(list, lambda item: item < 0)在第 3 行,定义了函数 select,它与前面的小节定义的函数完全相同在第 4 行,遍历列表 list 在第 5 行,参数 selct_function 是一个函数,用于选择是否选中当前正在遍历的数值在第 8 行,定义了 lambda 表达式lambda 表达式判断输入参数是否为正数将 lambad 表达式作为参数传递给函数 select,函数打印列表中的正数在第 9 行,定义了 lambda 表达式lambda 表达式判断输入参数是否为负数将 lambad 表达式作为参数传递给函数 select,函数打印列表中的负数程序输出结果如下:123-1-2-3

2.4 应用程序

开发者的绝大部分工作都是在这一层完成,通过 Java 编写的应用程序我们可以使用 Android 系统提供的服务来实现我们预期的功能。每一个应用程序都对应一个 Dalvik 虚拟机,利用跨平台性质,基于 Android 框架开发的应用程序可以运行于任何一台安装有 Android 系统的平台。本教程的大多数内容也是针对这一层,我们将带领你建立属于自己的第一个 Android 应用程序,并一步步由浅入深的学习 Android 各个细枝末节,让你可以更好的掌握 Android 应用程层序开发。

第一个 Java 程序

本节我们将以Windows操作系统为例,编写并执行第一个Java程序。在这之前,请确保你的操作系统上已经安装了JDK

2. 什么是网络编程

我们今天所讨论的网络编程是指编写特定的应用程序,使得接入到计算机网络中的设备能够相互通信。网络设备之间的通信,需要程序员设计好特定的协议,然后通过编程语言实现这些协议,最终由计算机设备来执行。在计算机网络的发展过程中,通用的、基础的网络协议已经被实现在计算机操作系统中,通常叫做网络协议栈。而操作系统为程序员提供了网络相关的 API ,通常把它叫做 Socket。为此,网络编程也叫 Socket 编程、套接字编程。任何事物的发展都有它的起源和历史,现在我们了解一下 Socket 的发展史。

5. 为什么学习并发编程?

可以这样来说,在目前开发市场对于程序员的硬性要求中,并发编程占据了重要的位置,不懂并发编程的从业者不是一名合格的软件工程师。尤其是大数据时代的来临,高并发更成为了家常便饭,工作中,你总是绕不开并发编程的任务,比如说,你想写个程序,一边从文件中读取数据,一边还要做实时计算… 所以,想成为一名资深的 Java 后端工程师,并发编程必须要牢牢把握。

1.2 编写应用

在此阶段你可以开始编写代码了。Android Studio 包含多种工具和智能功能,可帮助你更快速地编写应用、编写高质量的代码、设计界面以及为不同的设备类型创建资源。

3.5 编写 MainActivity

前面已经实现了布局、数据、适配器等模块的编写,整个 ExpandableListView 的框架就已经搭建完毕了。虽然本节的示例比较简单,代码量也比较少,但是也希望大家在学习过程中能够注重模块的编写顺序,循序渐进的培养自己搭建一个更完整的更大型架构的能力。框架搭建完毕就可以进入业务代码的编写了,在MainActivity中我们主要做以下4件事:设置布局文件并从布局文件中拿到 ExpandableListView 实例;获取数据集(实际使用中可能是从网络获取或者本地读取);创建适配器,并为 ExpandableListView 实例设置适配器;为 ExpandableListView 添加相应的事件监听器,并实现监听器接口中的回调方法。按照以上 4 步来做即可,代码如下:package com.emercy.myapplication;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.widget.ExpandableListAdapter;import android.widget.ExpandableListView;import android.widget.Toast;import java.util.ArrayList;import java.util.HashMap;import java.util.List;public class MainActivity extends Activity { HashMap<String, List<String>> expandableListDetail; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 1.设置布局文件并从布局文件中拿到 ExpandableListView 实例; setContentView(R.layout.activity_main); ExpandableListView listView = findViewById(R.id.expandableListView); // 2. 获取数据集(实际使用中可能是从网络获取或者本地读取) expandableListDetail = DataCollection.getData(); final List<String> heroCategory = new ArrayList<>(expandableListDetail.keySet()); // 3. 创建适配器,并为 ExpandableListView 实例设置适配器 ExpandableListAdapter adapter = new MyExpandableListAdapter(this, heroCategory, expandableListDetail); listView.setAdapter(adapter); // 4. 为 ExpandableListView 添加相应的事件监听器,并实现监听器接口中的回调方法 listView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() { @Override public void onGroupExpand(int groupPosition) { Toast.makeText(getApplicationContext(), heroCategory.get(groupPosition) + " 列表展开", Toast.LENGTH_SHORT).show(); } }); listView.setOnGroupCollapseListener(new ExpandableListView.OnGroupCollapseListener() { @Override public void onGroupCollapse(int groupPosition) { Toast.makeText(getApplicationContext(), heroCategory.get(groupPosition) + " 列表折叠", Toast.LENGTH_SHORT).show(); } }); listView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() { @Override public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) { Toast.makeText(getApplicationContext(), heroCategory.get(groupPosition) + " -> " + expandableListDetail.get(heroCategory.get(groupPosition)) .get(childPosition), Toast.LENGTH_SHORT ).show(); return false; } }); }}编译运行之后,界面上会展示一个 5 大英雄类别的 ListView,点击每个类别系统会回调onGroupExpand方法,我们在当中打印出当前被展开的类别名;然后会弹出该类下的英雄名称,点击英雄名称系统会回调onChildClick方法,我们在方法中打印出被点击的英雄名称;最后我们可以点击已经展开的英雄类别,系统会将点击的类别恢复折叠状态同时回调onGroupCollapse方法,在其中我们打印出被折叠的类别名称,最终效果如下:

Python 编程范式的科普

编程范式是计算机编程的基本风格或典范模式。如果说每个编程者都在创造虚拟世界,那么编程范式就是程序员置身其中采用的世界观和方法论。常见的编程范式包括:面向过程编程面向对象编程编程范型提供了程序员对程序执行的看法:在面向过程编程中,程序员认为程序是一系列相互调用的过程或者函数;在面向对象编程中,程序员认为程序是一系列相互作用的对象;而在函数式编程中一个程序会被看作是一个无状态的函数计算的序列。不同的编程语言也会提倡不同的编程范式,一些语言是专门为某个特定的编程范式设计的。例如,C 支持面向过程编程,Java 支持面向对象编程。Python 编程语言支持多种编程范式,应该在不同的应用场景下,选择合适的编程范式。

1. 编程示例

接下来我们来分别展示用函数式编程和普通编程方式来实现一个累加器,即输出 1+2+3+…+100 的值。普通方式实现:func main() { a := 0 for i := 1; i <= 100; i++ { a = a + i } fmt.Println(a)}函数式编程实现:package mainimport ( "fmt")type iAdder func(int) intfunc adder() iAdder { sum := 0 return func(v int) int { sum += v return sum }}func main() { a := adder() var s int for i := 1; i <= 100; i++ { s = a(i) } fmt.Println(s)}第 7 行:定义函数类型自定义数据类型;第 9~15 行:定义累加器函数;第 18 行:定义变量 a,并将累加器函数作为值赋给变量 a;第 20~22 行:累加 100 次。执行结果:两者比较,就是后者将整个累加过程作为变量放置在了循环以外,使得整个累加可以脱离循环之外。看起来就像是不断的对一个传入的常数进行加工,就像是流水线的一个工具。所以函数式编程在开发过程中经常会用在对数据的长流程处理。例如,录入身份证号时,要从身份证号中获取年龄,籍贯、性别等信息,就可以使用三个函数对身份证号进行顺序处理。这样写的好处就在于可以随时增删其流程。

3.4 服务端处理流程

假设浏览器访问 URL http://www.bbs.com/topics/12373,处理的逻辑如下图所示:服务端收到 /topics/12373 的页面请求;查询合适的函数处理路径为 /topics/12373 的页面;showTopic 处理形式为 /topics/xxx 的页面请求;showUser 处理形式为 /users/xxx 的页面请求;因此选择 showTopic 来处理此次页面请求。将页面路径拆分为 /topics 和 12373,把 12373 作为 topicID;将 topicID 传递给 showTopic,执行该函数。对每一个页面处理请求都需要进行如上的 4 步处理,在这 4 个步骤中,只有第 4 步才是应用关心的业务逻辑。如果基于 Web 框架开发 Web 应用,Web 框架完成第 1 步、第 2 步、第 3 步的工作,应用程序完成第 4 步的工作。即应用程序只需要编写具体处理页面的函数,其余繁琐的、与业务无关的工作交给 Web 框架,因此使用 Web 框架可以大大地减轻开发的工作量。

2. 书写程序

我们先来看一下代码的架构:接下来,让我们看看所有代码。import requestsfrom bs4 import BeautifulSoup from pprint import pprintimport osimport lxmlimport pymongoheaders = {'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36'} # 请求头部def get_course_info(): """ get all course basic unit """ url = "https://www.imooc.com/course/list" #慕课网免费课地址 r = requests.get(url, headers= headers) # 发送请求 bs = BeautifulSoup(r.text, "lxml") # 解析网页 course_data = bs.find_all("div", class_="course-card-container") # 定位课程信息 return course_datadef save_pics(course_data): """ save pics from imooc free course """ for each_item in course_data: img = each_item.find("img") image_link = img.attrs["data-original"].split("/") image_address = "http:" + img.attrs["data-original"] with open(image_link[-1],'wb+') as f: res = requests.get(image_address, headers= headers) # 发送请求 f.write(res.content)def save_courses_to_mongodb(mongod_con, course_data): """ save info to mongodb """ for each_item in course_data: imgs = each_item.find("img") desc = each_item.find("p", class_="course-card-desc") # 定位课程信息 class_name = each_item.find("h3", class_="course-card-name") # 定位课程信息 imooc_dict = { "class_name": class_name.getText(), "class_pics": imgs.attrs["data-original"], "people":desc.getText()} x = mongod_con.insert_one(imooc_dict)def create_local_pic_dir(): """ if don't have local dir, create one for holding the pics which download from the imooc. """ directory = os.path.dirname(os.path.realpath(__file__)) + '/imooc_pics/' if not os.path.exists(directory): os.makedirs(directory) os.chdir(directory)def db_connectin(): """ Connection to local mongo db service.""" try: myclient = pymongo.MongoClient("mongodb://localhost:27017/") mydb = myclient["practice"] mongod_con = mydb["imooc_courses"] except Exception as e: print("ERROR(MongoPipeline):", e) return mongod_condef main(): """ This is the main entry for running code.""" create_local_pic_dir() mycol = db_connectin() data = get_course_info() if data: save_pics(data) save_courses_to_mongodb(mycol, data)if __name__ == "__main__": main()代码主要有 6 个函数:create_local_pic_dir: 用来创建本地文件夹,来存储爬取的图片;db_connectin: 用来连接 mongodb;get_course_info :用来获取课程基本信息;save_pics :函数将图片存储在本地;save_courses_to_mongodb :将数据存储到 MongoDB;main :负责运行程序。

4. 编写代码测试

准备好工程后,编写我们的代码。

5. 编写视图

在 Restful Web API 中,视图扮演的角色是数据处理器。例如,客户端需要获取一个学生一次期末考试后各科成绩的平均值,而数据库中仅存了各科的成绩,这时,就需要视图对数据处理,根据各科成绩求出平均值后返回给客户端。由于本案例无需对数据进行处理,视图实现较为简单。在 booktest 应用的 views.py 中创建视图 BookInfoViewSet,这是一个视图集合。# views.pyfrom rest_framework import viewsetsfrom AppDemo.models import StudentsModelfrom AppDemo.serializers import StudentsSerializerclass StudentsViewSet(viewsets.ModelViewSet): queryset = StudentsModel.objects.all() # 使用上一步创建的StudentsSerializer对模型进行序列化 serializer_class = StudentsSerializerqueryset 指明该视图集在查询数据时使用的查询集;serializer_class 指明该视图在进行序列化或反序列化时使用的序列化器。

3. 示例程序

#include <stdio.h>#include <string.h>#define StudentNumbers 50#define NameLength 50typedef struct{ int id; char name[NameLength]; int age; int score; int flag;} Student;int add(Student student, Student Students[]);int del(int id, Student students[]);int display(Student students[]);int update(int id, Student students[]);int search(char name[], Student students[]);int main(){ int id = -1; char name[NameLength]; int choice = 0; int stop = 0; Student students[StudentNumbers]; Student student; for (int i = 0; i < StudentNumbers; i++) { students[i].id = i; students[i].flag = 0; } while (stop == 0) { printf("-------------------------\n"); printf("* 学生管理系统 *\n"); printf("-------------------------\n"); printf("1 添加\n"); printf("2 修改成绩\n"); printf("3 查询\n"); printf("4 删除\n"); printf("5 显示学生列表\n"); printf("0 退出程序\n"); printf("请直接输入数字选项:"); scanf("%d", &choice); switch (choice) { case 1: printf("请输入学生姓名:"); scanf("%s", student.name); printf("请输入学生的年龄:"); scanf("%d", &student.age); printf("请输入学生成绩:"); scanf("%d", &student.score); add(student, students); break; case 2: printf("请输入要修改成绩的学生编号:"); scanf("%d", &id); update(id, students); break; case 3: printf("请输入要查找的学生姓名:"); scanf("%s", name); search(name, students); break; case 4: printf("请输入要删除的学生编号:"); scanf("%d", &id); del(id, students); break; case 5: display(students); break; case 0: stop = 1; break; default: printf("输入选项有误\n"); break; } } return 0;}int add(Student student, Student students[]){ for (int i = 0; i < StudentNumbers; i++) { if (students[i].flag == 0) { strcpy(students[i].name, student.name); students[i].age = student.age; students[i].score = student.score; students[i].flag = 1; return 0; } } return 1;}int del(int id, Student students[]){ for (int i = 0; i < StudentNumbers; i++) { if (students[i].id == id) { students[i].flag = 0; return 0; } } return 1;}int display(Student students[]){ printf("******************\n"); printf("学生列表\n"); printf("******************\n"); for (int i = 0; i < StudentNumbers; i++) { if (students[i].flag == 1) { printf("学生编号:%d,学生姓名:%s,年龄:%d,成绩:%d\n", students[i].id, students[i].name, students[i].age, students[i].score); } } printf("******************\n"); return 0;}int update(int id, Student students[]){ int score = -1; printf("请输入新的成绩:"); scanf("%d", &score); for (int i = 0; i < StudentNumbers; i++) { if (students[i].id == id) { students[i].score = score; return 0; } } return 1;}int search(char name[], Student students[]){ for (int i = 0; i < StudentNumbers; i++) { if (strcmp(name, students[i].name) == 0) { printf("学生编号: %d,学生姓名: %s,年龄: %d,成绩: %d\n", students[i].id, students[i].name, students[i].age, students[i].score); return 0; } } printf("没有查找到相关学生信息。\n"); return 1;}很多人可能会第一次接触这么长的程序,会产生畏惧的心理。其实不用担心。要相信自己可以看懂的。我们分开来讲解一下。在程序的最开始我们需要引入程序中可能需要使用的函数的头文件。这里我们因为要使用 printf 、 scanf 等,所以需要 stdio 函数库。因为要使用 strcpy 、 strcmp 函数,所以需要 string 函数库。#include <stdio.h>#include <string.h>为了便于程序中的维护,不用在很多出修改共用的数值。所以这里定义了一个常量#define StudentNumbers 50#define NameLength 50为了存储学生的信息。我们用了 struct 来定义学生的信息。里面包含学生的编号 id ,姓名 name 这是一个字符串,年龄 age ,成绩 score ,标志位 flag 这个变量是用来表示是否有学生信息存储在该位置的。不过这里我们使用了之前没有介绍的一个 typedef 。这个关键字使用的好处是使得后面使用这个 struct 的时候不用每次都用关键字 struct 来定义,只要用这个结构的名称直接定义就可以了,如同我们定义整数等内置类型一样方便。typedef struct{ int id; char name[NameLength]; int age; int score; int flag;} Student;为了便于维护,我们没有按照函数出现的顺序来写。不过 C 语言一直秉承着先定义再使用的原则。所以。如果你使用的函数没有在使用前出现,而是在后面的话,那么你就需要先让编译器知道这个函数的基本情况。这个时候我们会先把函数的定义写在前面。我们可以看到下面我们定义了这个系统的功能。每个功能我们都会写一个函数。其实不写这些函数,把所有的功能写在 main 函数内部也是可以的。但是这样会在维护上存在问题。进行测试也会变得困难。int add(Student student, Student Students[]);int del(int id, Student students[]);int display(Student students[]);int update(int id, Student students[]);int search(char name[], Student students[]);这里定义了一些需要使用的变量。stop 变量是用来控制程序循环的,也就是控制程序在什么时候可以结束循环的。我们定义了一个 Student 的数组,用来存储学生的信息。用一个单独的变量来存储单条的学生信息。int id = -1;char name[NameLength];int choice = 0;int stop = 0;Student students[StudentNumbers];Student student;这里我们通过循环来初始化我们的数组。for (int i = 0; i < StudentNumbers; i++){ students[i].id = i; students[i].flag = 0;}循环语句如果在不改变条件的情况下会一直循环。确保我们的系统可以一直运行。while (stop == 0)在接收到输入后。我们就会通过 switch 来进行相应的匹配。完成对应的操作。这比使用大量的 if 语句简约了很多。switch (choice)在子程序中,也就是实现增、删、改、查这些功能程序中。我们用了循环语句来访问数组中的元素。同时,利用了判断语句与特定的变量,来判断该位置是否存有学生信息。运行结果:utopia@DESKTOP:~$ ./test-------------------------* 学生管理系统 *-------------------------1 添加2 修改成绩3 查询4 删除5 显示学生列表0 退出程序请直接输入数字选项:1请输入学生姓名:张三请输入学生的年龄:22请输入学生成绩:100-------------------------* 学生管理系统 *-------------------------1 添加2 修改成绩3 查询4 删除5 显示学生列表0 退出程序请直接输入数字选项:1请输入学生姓名:李四请输入学生的年龄:21请输入学生成绩:90-------------------------* 学生管理系统 *-------------------------1 添加2 修改成绩3 查询4 删除5 显示学生列表0 退出程序请直接输入数字选项:1请输入学生姓名:王二请输入学生的年龄:23请输入学生成绩:99-------------------------* 学生管理系统 *-------------------------1 添加2 修改成绩3 查询4 删除5 显示学生列表0 退出程序请直接输入数字选项:5******************学生列表******************学生编号:0,学生姓名:张三,年龄:22,成绩:100学生编号:1,学生姓名:李四,年龄:21,成绩:90学生编号:2,学生姓名:王二,年龄:23,成绩:99******************-------------------------* 学生管理系统 *-------------------------1 添加2 修改成绩3 查询4 删除5 显示学生列表0 退出程序请直接输入数字选项:2请输入要修改成绩的学生编号:1请输入新的成绩:80-------------------------* 学生管理系统 *-------------------------1 添加2 修改成绩3 查询4 删除5 显示学生列表0 退出程序请直接输入数字选项:5******************学生列表******************学生编号:0,学生姓名:张三,年龄:22,成绩:100学生编号:1,学生姓名:李四,年龄:21,成绩:80学生编号:2,学生姓名:王二,年龄:23,成绩:99******************-------------------------* 学生管理系统 *-------------------------1 添加2 修改成绩3 查询4 删除5 显示学生列表0 退出程序请直接输入数字选项:4请输入要删除的学生编号:1-------------------------* 学生管理系统 *-------------------------1 添加2 修改成绩3 查询4 删除5 显示学生列表0 退出程序请直接输入数字选项:5******************学生列表******************学生编号:0,学生姓名:张三,年龄:22,成绩:100学生编号:2,学生姓名:王二,年龄:23,成绩:99******************-------------------------* 学生管理系统 *-------------------------1 添加2 修改成绩3 查询4 删除5 显示学生列表0 退出程序请直接输入数字选项:1请输入学生姓名:张五请输入学生的年龄:20请输入学生成绩:70-------------------------* 学生管理系统 *-------------------------1 添加2 修改成绩3 查询4 删除5 显示学生列表0 退出程序请直接输入数字选项:5******************学生列表******************学生编号:0,学生姓名:张三,年龄:22,成绩:100学生编号:1,学生姓名:张五,年龄:20,成绩:70学生编号:2,学生姓名:王二,年龄:23,成绩:99******************-------------------------* 学生管理系统 *-------------------------1 添加2 修改成绩3 查询4 删除5 显示学生列表0 退出程序请直接输入数字选项:3请输入要查找的学生姓名:张五学生编号: 1,学生姓名: 张五,年龄: 20,成绩: 70-------------------------* 学生管理系统 *-------------------------1 添加2 修改成绩3 查询4 删除5 显示学生列表0 退出程序请直接输入数字选项:在程序中,我们首先添加了 3 条学生的记录。然后我们进行了列表显示。接着,我们尝试修改了其中一个学生成绩,并再次查看列表,发现成绩修改生效了。然后,我们删除了一个学生,列表显示结果其已经被删除了。然后我们又尝试添加了一个学生。列表显示结果添加成功。最后我们按照姓名查找了一个学生。

2. 什么是 Web 开发框架

其实框架这个词并不是 Web 开发领域所首创,他最早出现在软件开发行业中,一开始 “框架” 是这样被定义的:框架是一种提供了可重用的公共结构的技术,为构建新的应用程序提供了极大的便利。例如:在桌面应用程序开发的领域,微软公司的 Visual Studio C++ 为应用程序生成框架,基于 VC++ 应用程序框架可以大大地提升桌面程序的开发效率。而随着 Web 开发项目的复杂度的日益提升,软件开发中的框架技术被引入到 Web 开发领域。Web 开发框架是用于进行 Web 开发的一套软件架构,Web 框架为 Web 应用程序提供了基础的功能。开发人员在 Web 框架的基础上实现自己的业务逻辑,基于 Web 框架开发应用,开发人员只需要专注应用的业务逻辑,非业务逻辑的基础功能则由框架提供,从而提升开发效率。

4.2 程序结构

awk 在引号内有一定的程序结构,主要为以下:开始块(BEGIN BLOCK):语法:BEGIN{awk-commands}开始块就是awk程序启动时执行的代码部分(在处理输入流之前执行),并且在整个过程中只执行一次;一般情况下,我们在开始块中初始化一些变量。BEGIN是awk的关键字,因此必须要大写。【注:开始块部分是可选,即你的awk程序可以没有开始块部分】主体块(Body Block):语法:/pattern/{awk-commands}针对每一个输入的行都会执行一次主体部分的命令,默认情况下,对于输入的每一行,awk都会执行主体部分的命令,但是我们可以使用/pattern/限制其在指定模式下。结束块(END BLOCK):语法:END{awk-commands}结束块是awk程序结束时执行的代码(在处理完输入流之后执行),END也是awk的关键字,必须大写,与开始块类似,结束块也是可选的。

小程序

小程序是近两年发展非常迅速的一个生态。小程序赖于应用主体,基于这个主体提供的开放能力创建应用,如微信小程序,利用微信提供的能力,向上构建应用,最后将开发好的小程序应用进行上传发布,即可在微信内打开。本篇幅不会介绍如何开发小程序,小程序有非常完善的一套体系,其可以作为相对独立的技能进行学习,主要目的是提示读者可以向小程序方向进阶。

2.1 编写插件的主要步骤

创建 maven-plugin 项目: 其实也是创建一个 Maven 项目,只不过 pom.xml 文件中的 packaging 必须为 maven-plugin;编写插件目标: 通常情况下,一个插件会有一个或者多个目标,即一个或者多个 Mojo 。而这个 Mojo 类必须要继承 AbstractMojo 类;为目标提供配置点: 通常情况下 Maven 插件的目标都是可配置的,所以我们在编写插件的时候,也尽量需要提供可配置的参数;实现目标行为: 一个继承了 AbstractMojo 的 Mojo 类,需要实现其中的 excute 方法,这个方法即是插件目标要做的事情;记录日志并处理异常: 如同编写其他的程序一样,编写插件的时候,也需要通过记录日志的方式来记录插件的运行状态;测试并运行插件: 插件编写完成后,我们要对插件进行简单的测试,并通过实际运行插件的方式来验证插件是否能够满足我们的要求。从上面的步骤来看,其实编写插件也就相当于编写一个小型的项目,从创建项目到开发,测试再到上线发布,每一个步骤都需要经过。

首页上一页1234567下一页尾页
直播
查看课程详情
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号