循环语句(for)是计算机编程中的一种基本控制结构,它允许程序按照指定的次数或范围重复执行一段代码块。for循环在处理需要进行迭代操作的情况下非常有用,它使得程序可以更加方便地控制循环的次数。一般来说,for循环由三个部分组成:初始化部分、条件表达式和更新部分,以及一个需要重复执行的代码块。在每次循环迭代开始时,程序首先执行初始化部分,然后检查条件表达式的值,如果为真,则执行代码块,并在每次循环结束后执行更新部分。只要条件表达式为真,for循环就会一直重复执行;一旦条件表达式为假,循环将停止,程序继续执行循环之后的代码。

11.14 FOR 循环结构优化

For语句先初始化条件变量,然后在判断是否符合条件,符合则执行循环体,不符合则跳过执行。For循环结构的效率最低,该语句的构建往往需要三个跳转来实现,首先需要初始化变量此处要进行一次判断,其次是内部循环体需要另一个判断通常用于实现跳出循环体,最后一步则需要一个无条件跳转指令跳回到循环首地址,但在开启了O2优化时编译器也会尽可能将其转换为While语句,如果可以还会继续将While转为带有IF语句的Do循环来提高执行效率。

  .386p
.model flat,stdcall
option casemap:none include windows.inc
include kernel32.inc
includelib kernel32.lib .data
count DWORD ?
.code
main PROC
mov dword ptr ds:[count],0 ; 设置 int x = 0;
jmp L2 L1:
mov eax,dword ptr ds:[count] ; x = x++
add eax,1
mov dword ptr ds:[count],eax L2:
cmp dword ptr ds:[count],10 ; 比较 x < 10
jge lop_end xor eax,eax ; 执行循环体
jmp L1 lop_end:
int 3
invoke ExitProcess,0
main ENDP
END main

虽然For语句在执行效率上来说是最低的,但该语句的使用确是最符合我们思维方式的,在高级语言中应用最为广泛,例如在Python中For循环体被简化成了for x in range(2,10)它可以指定一个循环范围,该语句利用汇编完全也可以被构建出来,我们接着尝试构建一下这个特别的循环体。

  .386p
.model flat,stdcall
option casemap:none include windows.inc
include kernel32.inc
includelib kernel32.lib .data
start_count DWORD ?
end_count DWORD ?
.code
main PROC
mov dword ptr ds:[start_count],2 ; 指定开始循环编号
mov dword ptr ds:[end_count],5 ; 指定结束循环编号 mov ecx,dword ptr ds:[start_count]
L1:
cmp dword ptr ds:[end_count],ecx
jle lop_end xor eax,eax ; 循环体内部 add ecx,1 ; 每次递增
mov dword ptr ds:[start_count],ecx
jmp L1 lop_end:
int 3
invoke ExitProcess,0
main ENDP
END main

11.20 仿写For水仙花数

该C++代码实现了水仙花数的查找算法,水仙花数是指一个三位数,它的每个位上的数字的立方和等于它本身。在循环中,遍历100~999之间的每一个数,将其分解为三个数(百、十、个位),再将三个数分别平方并相加,判断与原数是否相等,如果相等则输出该数即为水仙花数。

  • 例如: 153是一个水仙花数,因为153等于1的3次方加上5的3次方加上3的3次方
#include <stdio.h>
#include <Windows.h> int main(int argc, char *argv[])
{
int x, y, z, n;
for (n = 100; n < 1000; n++)
{
x = n / 100; // 分解百位
y = n / 10 % 10; // 分解十位
z = n % 10; // 分解个位
if (x * 100 + y * 10 + z == x*x*x + y*y*y + z*z*z)
{
printf("水仙花: %-5d \n", n);
}
} system("pause");
return 0;
}

尝试使用汇编实现计算逻辑,这段代码没有任何难度,因为并不会涉及到嵌套循环的问题,只是在计算四则运算时需要格外注意些。

  .386p
.model flat,stdcall
option casemap:none include windows.inc
include kernel32.inc
includelib kernel32.lib include msvcrt.inc
includelib msvcrt.lib .data
x DWORD ?
y DWORD ?
z DWORD ?
n DWORD ?
szFmt BYTE '水仙花: %-5d ',0dh,0ah,0 .code
main PROC
mov dword ptr ds:[n],100 ; n = 100
jmp L1
L2: mov eax,dword ptr ds:[n]
add eax,1 ; n++
mov dword ptr ds:[n],eax
L1: mov eax,dword ptr ds:[n]
cmp eax,1000 ; n < 1000
jge lop_end mov eax,dword ptr ds:[n]
cdq
mov ecx,100 ; x = n / 100;
idiv ecx
mov dword ptr ds:[x],eax mov eax,dword ptr ds:[n]
cdq
mov ecx,10
idiv ecx ; y = n / 10;
cdq
mov ecx,10
idiv ecx ; y = y % 10;
mov dword ptr ds:[y],edx mov eax,dword ptr ds:[n]
cdq
mov ecx,10
idiv ecx ; z = n % 10;
mov dword ptr ds:[z],edx ; 开始执行if()比较语句
imul eax,dword ptr ds:[x],100 ; x * 100
imul ecx,dword ptr ds:[y],10 ; y * 10
add eax,dword ptr ds:[z] ; + z
add ecx,eax mov edx,dword ptr ds:[x]
imul edx,dword ptr ds:[x] ; x*x*x
imul edx,dword ptr ds:[x] mov eax,dword ptr ds:[y]
imul eax,dword ptr ds:[y] ; y*y*y
imul eax,dword ptr ds:[y]
add edx,eax mov eax,dword ptr ds:[z]
imul eax,dword ptr ds:[z] ; z*z*z
imul eax,dword ptr ds:[z]
add edx,eax cmp ecx,edx ; (x * 100 + y * 10 + z) == (x*x*x + y*y*y + z*z*z)
jne L2 mov eax,dword ptr ds:[n]
invoke crt_printf,addr szFmt,eax
jmp L2 lop_end:
int 3 main ENDP
END main

11.21 For循环尝试判断

该C++代码实现了一个简单的循环,遍历数组中的所有元素并输出大于等于50的元素。在循环中,通过判断Array数组中每个元素与50的大小关系,如果元素大于等于50,则使用printf函数输出该元素的值。最终程序输出所有大于等于50的元素。

#include <stdio.h>
#include <Windows.h> int main(int argc,char *argv[])
{
int Array[10] = { 56,78,33,45,78,90,32,44,56,67 }; for (int x = 0; x < 10; x++)
{
if (Array[x] >= 50)
{
printf("out -> %d \n", Array[x]);
}
}
return 0;
}

上述C语言代码如果通过汇编语言实现可以写成如下样子,读者可自行理解流程;

  .386p
.model flat,stdcall
option casemap:none include windows.inc
include kernel32.inc
includelib kernel32.lib include msvcrt.inc
includelib msvcrt.lib .data
MyArray DWORD 56,78,33,45,78,90,32,44,56,67
count DWORD ?
szFmt BYTE 'out -> %d ',0dh,0ah,0 .code
main PROC mov dword ptr ds:[count],0 ; int x = 0
jmp L1
L2: mov eax,dword ptr ds:[count]
add eax,1 ; x ++
mov dword ptr ds:[count],eax
L1:
cmp dword ptr ds:[count],10 ; x < 10
jge lop_end mov eax,dword ptr ds:[count] ; 获取循环次数,当作因子
lea esi,dword ptr ds:[MyArray] ; 取数组基地址
mov ebx,dword ptr ds:[esi + eax * 4] ; 因子寻址
cmp ebx,50
jl L2 ; 如果小于50则跳转到下一次循环 invoke crt_printf,addr szFmt,ebx ; 调用系统crt
jmp L2 lop_end:
int 3 invoke ExitProcess,0
main ENDP
END main

在读者学会了上述代码编写之后,我们继续增加代码的复杂度,如下所示代码实现了对整型数组的最大值、最小值、元素总和以及平均值的计算。在循环中,通过依次遍历数组中的每一个元素,维护一个当前最大值max_result和最小值min_result,并对元素进行累加求和,最终计算出数组中所有元素的平均值avg_result。代码中使用printf函数输出求得的四个值(max、min、sum、avg),并使用system函数暂停程序以便观察输出结果。

#include <stdio.h>
#include <Windows.h> int main(int argc, char *argv[])
{
int Array[10] = { 56,78,33,45,78,90,32,44,56,67 };
int max_result = 0,min_result = 100,sum_result = 0,avg_result = 0; for (int x = 0; x < 10; x++)
{
if (Array[x] >= max_result)
{
max_result = Array[x];
}
if (Array[x] <= min_result)
{
min_result = Array[x];
}
sum_result = sum_result + Array[x];
avg_result = sum_result / 10;
}
printf("max = %d min = %d sum = %d avg = %d \n", max_result,min_result,sum_result,avg_result);
system("pause");
return 0;
}

上述代码读者可尝试使用汇编语言来实现一下,如下代码是笔者思考后编写出来的实现流程,读者可自行对照参考;

  .386p
.model flat,stdcall
option casemap:none include windows.inc
include kernel32.inc
includelib kernel32.lib include msvcrt.inc
includelib msvcrt.lib .data
MyArray DWORD 56,78,33,45,78,90,32,44,56,67
count DWORD ?
max_result DWORD 0
min_result DWORD 100
sum_result DWORD 0
avg_result DWORD 0 szFmt BYTE 'max = %d min= %d sum= %d avg = %d ',0dh,0ah,0 .code
main PROC
mov dword ptr ds:[count],0 ; int x = 0
jmp L1
L2: mov eax,dword ptr ds:[count]
add eax,1 ; x ++
mov dword ptr ds:[count],eax
L1:
cmp dword ptr ds:[count],10 ; x < 10
jge lop_end mov eax,dword ptr ds:[count]
lea esi,dword ptr ds:[MyArray] mov ebx,dword ptr ds:[esi + eax * 4]
cmp ebx,dword ptr ds:[max_result] ; Array[x] >= max_result
jl L3
mov dword ptr ds:[max_result],ebx ; max_result = Array[x];
L3:
mov ebx,dword ptr ds:[esi + eax * 4]
cmp ebx,dword ptr ds:[min_result] ; Array[x] <= min_result
jg L4
mov dword ptr ds:[min_result],ebx L4:
mov ebx,dword ptr ds:[esi + eax * 4] ; Array[x]
add dword ptr ds:[sum_result],ebx ; sum_result = sum_result + Array[x]; mov eax,dword ptr ds:[sum_result]
cdq ; 符号扩展
mov ecx,10 ; / 10
idiv ecx ; sum_result / 10;
mov dword ptr ds:[avg_result],eax ; avg_result
jmp L2 lop_end:
mov eax,dword ptr ds:[max_result]
mov ebx,dword ptr ds:[min_result]
mov ecx,dword ptr ds:[sum_result]
mov edx,dword ptr ds:[avg_result]
invoke crt_printf,addr szFmt,eax,ebx,ecx,edx
int 3
main ENDP
END main

11.22 For循环多重IF判断

该C++代码实现了对两个数组进行元素相加,并输出相加结果的奇偶性。在循环中,对SrcArrayDstArray两个数组中的元素相加,如果两个元素均不为0,则判断相加的结果是否为偶数,如果是,则使用printf函数输出偶数sum的形式,否则输出基数sum的形式。其中sum表示两个元素相加的结果。代码中使用system函数暂停程序以便观察输出结果。

#include <stdio.h>
#include <Windows.h> int main(int argc, char *argv[])
{
int SrcArray[10] = { 56,78,33,45,78,90,32,15,56,67 };
int DstArray[10] = { 59,77,89,23,11,45,67,88,93,27 };
int index = 0; for (index = 0; index < 10; index++)
{
if (SrcArray[index] != 0 && DstArray[index] != 0)
{
int sum = SrcArray[index] + DstArray[index];
if (sum % 2 == 0)
printf("偶数: %d \n", sum);
else
printf("基数: %d \n", sum);
}
}
system("pause");
return 0;
}

上述代码片段的逻辑并不复杂,仅仅只是循环内部嵌套双层判断,笔者思考片刻后即写出了与之对应的汇编代码;

  .386p
.model flat,stdcall
option casemap:none include windows.inc
include kernel32.inc
includelib kernel32.lib include msvcrt.inc
includelib msvcrt.lib .data
SrcArray DWORD 56,78,33,45,78,90,32,15,56,67
DstArray DWORD 59,77,89,23,11,45,67,88,93,27
index DWORD 0
sum DWORD 0 szFmt1 BYTE '基数: %d ',0dh,0ah,0
szFmt2 BYTE '偶数: %d ',0dh,0ah,0 .code
main PROC
mov dword ptr ds:[index],0 ; index = 0 jmp L1
L2: mov eax,dword ptr ds:[index]
add eax,1 ; index++
mov dword ptr ds:[index],eax
L1:
cmp dword ptr ds:[index],10 ; index < 10
jge lop_end mov eax,dword ptr ds:[index];
cmp dword ptr ds:[SrcArray + eax * 4],0
je L2 ; SrcArray[index] != 0 mov eax,dword ptr ds:[index]
cmp dword ptr ds:[DstArray + eax * 4],0 ; DstArray[index] != 0
je L2 ; ------------------------------------------
; 另类加法,通过一个SrcArray定位DstArray完成加法 mov eax,dword ptr ds:[index] ; 获取因子
lea esi,dword ptr ds:[SrcArray] ; 取数组首地址 mov ebx,dword ptr ds:[esi + eax * 4] ; 获取 SrcArray[index]
mov ecx,dword ptr ds:[esi + eax * 4 + 40] ; 获取 DstArray[index]
add ebx,ecx ; SrcArray[index] + DstArray[index]
mov dword ptr ds:[sum],ebx ; sum = SrcArray[index] + DstArray[index] mov eax,dword ptr ds:[sum]
and eax,080000001h ; sum % 2 == 0
test eax,eax
jne L3 invoke crt_printf,addr szFmt2,dword ptr ds:[sum] ; 偶数输出
jmp L2
L3:
invoke crt_printf,addr szFmt1,dword ptr ds:[sum] ; 基数输出
jmp L2
lop_end:
int 3 main ENDP
END main

11.23 For嵌套乘法口诀表

该C++代码实现了乘法口诀表的打印。在两个for循环中,分别对x和y进行遍历,对每一次的遍历输出一个乘法口诀表的元素。代码中使用printf函数实现输出,并使用\n进行换行。程序遍历打印了从11到99的所有乘积的结果,这就是乘法口诀表。

#include <stdio.h>
#include <Windows.h> int main(int argc, char *argv[])
{
for (int x = 1; x < 10; x++)
{
for (int y = 1; y <= x; y++)
{
int result = x*y;
printf("%d*%d=%-3d", y, x, result);
}
printf("\n");
}
system("pause");
return 0;
}

乘法口诀表的实现方法只需要嵌套两层FOR循环语句,在使用汇编语言实现之前我们可以先来构建出这个双层循环体,如下代码所示;

  .386p
.model flat,stdcall
option casemap:none include windows.inc
include kernel32.inc
includelib kernel32.lib include msvcrt.inc
includelib msvcrt.lib .data
x DWORD ?
y DWORD ?
szFmt BYTE '内层循环: %d 外层循环: %d ',0dh,0ah,0
szPr BYTE '----->',0dh,0ah,0 .code
main PROC
mov dword ptr ds:[x],1 ; int x = 1
jmp L1
L2: mov eax,dword ptr ds:[x]
add eax,1 ; x++
mov dword ptr ds:[x],eax
L1:
cmp dword ptr ds:[x],10 ; x < 10
jge lop_end mov dword ptr ds:[y],1 ; y = 1
jmp L3
L5: mov eax,dword ptr ds:[y]
add eax,1 ; y++
mov dword ptr ds:[y],eax
L3:
mov eax,dword ptr ds:[y]
cmp eax,dword ptr ds:[x] ; y <= x
jg L4 ; 执行的是循环体内部
mov eax,dword ptr ds:[x]
mov ebx,dword ptr ds:[y]
invoke crt_printf,addr szFmt,eax,ebx jmp L5
L4:
; 执行外层循环
invoke crt_printf,addr szPr jmp L2
lop_end:
int 3 main ENDP
END main

当有了双层循环体结构之后,我们只需要再其循环之上增加一个乘法计算功能即可,完整的计算流程如下所示;

  .386p
.model flat,stdcall
option casemap:none include windows.inc
include kernel32.inc
includelib kernel32.lib include msvcrt.inc
includelib msvcrt.lib .data
x DWORD ?
y DWORD ?
szFmt BYTE '%d * %d = %d ',0
szPr BYTE ' ',0dh,0ah,0
.code
main PROC
mov dword ptr ds:[x],1 ; int x = 1
jmp L1
L2: mov eax,dword ptr ds:[x]
add eax,1 ; x++
mov dword ptr ds:[x],eax
L1:
cmp dword ptr ds:[x],10 ; x < 10
jge lop_end mov dword ptr ds:[y],1 ; y = 1
jmp L3
L5: mov eax,dword ptr ds:[y]
add eax,1 ; y++
mov dword ptr ds:[y],eax
L3:
mov eax,dword ptr ds:[y]
cmp eax,dword ptr ds:[x] ; y <= x
jg L4 ; 执行的是循环体内部
mov eax,dword ptr ds:[x]
imul eax,dword ptr ds:[y]
invoke crt_printf,addr szFmt,dword ptr ds:[y],dword ptr ds:[x],eax jmp L5
L4:
; 执行外层循环
invoke crt_printf,addr szPr jmp L2
lop_end:
int 3 main ENDP
END main

11.24 For语句冒泡排序

该C++代码实现了冒泡排序算法对整型数组进行排序。在冒泡排序算法中,数组中每两个相邻的元素,如果前一个元素大于后一个元素,则交换这两个元素的位置。循环遍历数组多次,每次将未排序的最大值向数组末尾冒泡,直到数组中的所有元素都排好序。代码中使用两层for循环实现排序,内层循环从数组末尾开始,逐步向前遍历,交换相邻的两个元素。外层循环控制排序的遍历次数,只有在当前相邻两个数未排序时才进行交换。程序最终输出排序后的数组。

#include <stdio.h>
#include <Windows.h> int main(int argc, char *argv[])
{
int Array[10] = { 34,78,65,77,89,43,23,55,67,8 };
int x, y, temporary, ArraySize=10; for (x = 0; x < ArraySize - 1; x++)
{
for (y = ArraySize - 1; y > x; y--)
{
if (Array[y - 1] > Array[y])
{
temporary = Array[y - 1];
Array[y - 1] = Array[y];
Array[y] = temporary;
}
}
} for (int x = 0; x < 10; x++)
{
printf("%d \n", Array[x]); system("pause");
return 0;
}

由于冒泡排序牵扯到了数据交换所以汇编版本可能稍显负责,不过大体框架还是没有脱离二层循环,仅仅只是在二层循环内部增加了一个判断流程而已,其实如果认真构建相信读者也可以很容易的写出来。

  .386p
.model flat,stdcall
option casemap:none include windows.inc
include kernel32.inc
includelib kernel32.lib include msvcrt.inc
includelib msvcrt.lib .data
Array DWORD 34,78,65,77,89,43,23,55,67,8
x DWORD ?
y DWORD ?
Temporary DWORD ?
ArraySize DWORD ?
szFmt BYTE '%d --> %d ',0dh,0ah,0 .code
main PROC
; 初始化的部分
mov dword ptr ds:[x],0 ; x=0
mov dword ptr ds:[ArraySize],10 ; ArraySize=10 ; 外层循环体
jmp L1
L2: mov eax,dword ptr ds:[x]
add eax,1 ; x++
mov dword ptr ds:[x],eax L1: mov eax,dword ptr ds:[ArraySize]
sub eax,1 ; ArraySize - 1
cmp dword ptr ds:[x],eax ; x < ArraySize
jge lop_end ; 内层循环体内容
mov eax,dword ptr ds:[ArraySize]
sub eax,1
mov dword ptr ds:[y],eax jmp L3
L4: mov eax,dword ptr ds:[y]
sub eax,1 ; y--
mov dword ptr ds:[y],eax L3: mov eax,dword ptr ds:[y]
cmp eax,dword ptr ds:[x] ; Array[y - 1] > Array[y]
jle L2 ; 寻址y和y-1的位置
mov esi,dword ptr ds:[y] mov ebx,dword ptr ds:[Array + esi * 4] ; Array[y]
mov edx,dword ptr ds:[Array + esi * 4 - 4] ; Array[y - 1]
cmp edx,ebx
jle L4 ; 数据交换
mov dword ptr ds:[Array + esi * 4],edx ; Array[y] = Array[y - 1]
mov dword ptr ds:[Array + esi * 4 - 4],ebx ; Array[y - 1] = Array[y]
; invoke crt_printf,addr szFmt,ebx,edx jmp L4
jmp L2 lop_end:
nop ; 执行打印函数
mov dword ptr ds:[Temporary],0 jmp L5
L7: mov eax,dword ptr ds:[Temporary]
add eax,1
mov dword ptr ds:[Temporary],eax
L5:
mov eax,dword ptr ds:[Temporary]
cmp eax,10
jge L6 lea esi,dword ptr ds:[Array] ; 取数组基地址
mov esi,dword ptr ds:[Array + eax * 4] ; 比例因子寻址
invoke crt_printf,addr szFmt,esi,esi
jmp L7
L6:
int 3 main ENDP
END main

至此,汇编中的循环结构仿写就告一段落了,笔者提醒大家,由于汇编难度较大,且代码都是线性的,所以在编写之前要分析好主次关系,当有了主次关系之后,我们就需要静下心来,一个个构建,由外到内步步为营,其实汇编也并不是那么可怕。

5.13 汇编语言:仿写For循环语句的更多相关文章

  1. 10-16C#for...循环语句(2)

    for....循环语句 格式:for(初始条件:循环条件:状态改变) { 循环体: } 一.课前作业:打印等腰直角三角形 第一种方法:是运用一开始学习的从上往下执行控制台程序,用一个for循环语句执行 ...

  2. 【shell】shell编程(四)-循环语句

    上篇我们学习了shell中条件选择语句的用法.接下来本篇就来学习循环语句.在shell中,循环是通过for, while, until命令来实现的.下面就分别来看看吧. for for循环有两种形式: ...

  3. Java流程控制之循环语句

    循环概述 循环语句可以在满足循环条件的情况下,反复执行某一段代码,这段被重复执行的代码被称为循环体语句,当反复执行这个循环体时,需要在合适的时候把循环判断条件修改为false,从而结束循环,否则循环将 ...

  4. javascript总结13:循环语句

    1 While循环 While(条件表达式){ 只要条件表达式结果为true,循环一直执行,当条件表达式结果为false的时候,循环终止 } While循环语句需现在循环体外定义变量. 2 for循环 ...

  5. 写给.NET开发者的Python教程(三):运算符、条件判断和循环语句

    本节会介绍Python中运算符的用法,以及条件判断和循环语句的使用方法. 运算符 运算符包括算术运算符.赋值运算符.比较运算符.逻辑运算符等内容,大部分用法和C#基本一致,下面我们来看一下: 算数运算 ...

  6. SwiftUI - 一起来仿写微信APP之一首页列表视图

    简介 最近在学习 SwiftUI ,我一般都是先去学习界面布局,所以就想着仿写一下经常使用的软件的界面,所以先拿微信开刀.因为不想一次性发太多的内容,所以只好将主题分解,一部分一部分地去讲,接下来我们 ...

  7. 详解Python中的循环语句的用法

    一.简介 Python的条件和循环语句,决定了程序的控制流程,体现结构的多样性.须重要理解,if.while.for以及与它们相搭配的 else. elif.break.continue和pass语句 ...

  8. C#语句2——循环语句(for穷举、迭代和while循环)

    一.for循环拥有两类: (一).穷举: 把所有可能的情况都走一遍,使用if条件筛选出来满足条件的情况. 1.单位给发了一张150元购物卡,拿着到超市买三类洗化用品.洗发水15元,香皂2元,牙刷5元. ...

  9. Python学习(6)循环语句

    目录 Python循环语句 - while循环语句 -- 无线循环 -- 循环使用else语句 -- 简单语句组 - for循环语句 -- 通过序列索引迭代 -- 循环使用else语句 - 循环嵌套 ...

  10. delphi if 语句循环语句

    if语句------------------------------------------------------------------------------------------------ ...

随机推荐

  1. 不懂前端,我依然开发了一个机器学习APP

    人人都知道学习很重要,学习究竟是为了什么呢?根本目的只有一个,学以致用! 机器学习,大家都学了很多算法,搞了很多模型,但是极少拿来解决实际问题. 毕竟开发一个机器学习应用需要的技术栈不是每个人都能掌握 ...

  2. JupyterLab 桌面版 !!!

    JupyterLab 是广受欢迎的 Jupyter Notebook「新」界面.它是一个交互式的开发环境,可用于 notebook.代码或数据,因此它的扩展性非常强. 用户可以使用它编写 notebo ...

  3. WPF 组织机构摄像机树 全量加载 大数据量 分页加载摄像机节点

    WPF 组织机构摄像机树 全量加载 大数据量 分页加载摄像机节点 完整代码: https://gitee.com/s0611163/WpfTreeDemo 性能: 8000组织机构20万摄像机,全量加 ...

  4. AtCoder Beginner Contest 217 D~E

    比赛链接:Here ABC水题, D - Cutting Woods 题意:开始一根木棒长度为 \(n\) 并以 \(1\) 为单位在木棒上标记\((1\sim n)\) ,输出 \(q\) 次操作 ...

  5. 2013年 第四届蓝桥杯C/C++ B组(省赛)

    第一题:高斯日记 大数学家高斯有个好习惯:无论如何都要记日记. 他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210 后来人们知道,那个整数就是日期,它表示那一天是高斯出生 ...

  6. P2058

    这道不难的题引发了我不少思考 我第一个版本是用vector嵌套vector写成的,后来发现没必要还存储那些已经超过24h的船,完全可以删除前面的船,因此把外层vector换成了deque. 即用deq ...

  7. freeswitch的gateway配置方案优化

    概述 freeswitch是一款简单好用的VOIP开源软交换平台. 在之前的文章中,我们简单介绍过gateway的三种配置方案,但是实际应用之后发现,方案中的参数设置有缺陷,会导致一些问题. 本文档中 ...

  8. python之单线程、多线程、多进程

    一.基本概念 进程(Process) 是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础. 在当代面向线程设计的计算机结构中,进程是线程的容器.程 ...

  9. docker 服务,镜像,容器命令总结

    本文为博主原创,未经允许不得转载: 目录: 1. docker 服务相关命令 2. 镜像相关总结 3. 容器相关命令总结 1. docker 服务相关: 1. 查看docker版本及相关信息: doc ...

  10. CSS : 使用 z-index 的前提

    使用 z-index 前  , 需要将元素 定位设置为  position : relative .