2015 年蓝桥杯 C 语言 B 组省赛第 1 题: 奖券数目 (四种解法 + 详细分析)

题目

奖券数目

有些人很迷信数字,比如带“4”的数字,认为和“死”谐音,就觉得不吉利。 虽然这些说法纯属无稽之谈,但有时还要迎合大众的需求。某抽奖活动的奖券号码是5位数(10000-99999),要求其中不要出现带“4”的号码,主办单位请你计算一下,如果任何两张奖券不重号,最多可发出奖券多少张。

请提交该数字(一个整数),不要写任何多余的内容或说明性文字。

题目分析

本题的主要解题思路就是枚举 10000-99999 之间的所有数字, 然后判断其中是否含有 4 , 如果不含有 4 则计数器加 1.

在具体实现上, 有四种解法. 第一种解法是对每个枚举结果都进行分解, 将原来的 5 位数分解成 5 个 1 位数, 之后逐个数字判断是否含有数字 4; 第二种方法是把每个枚举的结果都转换成字符串, 之后判断这个字符串中是否包含字符”4″, 如果不包含则计数器加 1; 第三种解法是使用 5 个 for 循环, 模拟奖券的五位数, 之后进行枚举和判断; 第四种解法是使用数学方法求解. 由于除了数字 4 之外, 一共有 9 个数字可以使用, 而且最高位不能为 0, 那么可以计算出符合条件的个数为:

8*9*9*9*9=52488

本题的正确答案是:

52488

下面针对上述分析, 分别求解如下.

方法一

将 10000-99999 之间的所有 5 位数都逐个分解成 5 个 1 位数, 之后逐个数字判断是否为数字 4.

程序:

#include<iostream>
using namespace std;
int main(){
	int ans = 0;
	for(int i=10000;i<=99999;i++){
		
		//将每一位上的数字都分离出来
		//(i%1000) 取余将去掉当前最高位后形成新的数字
		//(i%10000)-(i%1000) 将把当前最高位之后的数字都变成 0
		//((i%10000)-(i%1000))/1000 将去掉最高位后面的 0, 形成一个个位数 
		int a = (i-(i%10000))/10000;	
		int b = ((i%10000)-(i%1000))/1000;
		int c = ((i%1000)-(i%100))/100;
		int d = ((i%100)-(i%10))/10;
		int e = (i%10);
		
		//如果每个位上的数字都不是 4 则计数器加 1 
		if(a!=4&&b!=4&&c!=4&&d!=4&&e!=4){
			ans++;
		}		
	}
	cout<<ans<<endl;
	return 0;
}

方法二

把 10000-99999 之间的每个枚举的结果都转换成字符串, 之后判断这个字符串中是否包含字符”4″.

程序:

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
void i2s(int num, string &str){
//stringstream 类的作用是将数字转换成字符串
		stringstream ss;

//将需要转换的数字 sum 使用 << 运算符传递给 ss 对象 
		ss << num;
		
//将转换后的字符串使用 >> 运算符传递给 str 变量 
		ss >> str;
	}
int main(){
	int ans=0;
	for(int i=10000;i<=99999;i++){
		string s;
		i2s(i,s);
		
//查找字符串 s 中是否不包含(注意: 不包含用的是 ==)'4'这个字符串 
		if(s.find('4')==string::npos){
			ans++;
		}
	}
	cout<<ans<<endl;
	return 0;
}

方法三

使用 5 个 for 循环, 模拟奖券的五位数, 之后进行枚举和判断. 程序:

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
int main(){
	int ans=0;
	for(int a=1;a<=9;a++){
		if(a!=4){
			for(int b=0;b<=9;b++){
				if(b!=4){
					for(int c=0;c<=9;c++){
						if(c!=4){
							for(int d=0;d<=9;d++){
								if(d!=4){
									for(int e=0;e<=9;e++){
										if(e!=4){
											ans++;
										}
									}
								}
							}
						}
					}
				}
			}
		}

	}
	cout<<ans<<endl;
	return 0;
}

方法四

由于除了数字 4 之外, 一共有 9 个数字可以使用, 而且最高位不能为 0, 那么可以计算出符合条件的奖券个数为:

8*9*9*9*9=52488

2015 年蓝桥杯 C 语言 B 组省赛第 4 题: 格子中输出 (详细分析)

题目

格子中输出

StringInGrid函数会在一个指定大小的格子中打印指定的字符串。 要求字符串在水平、垂直两个方向上都居中。 如果字符串太长,就截断。 如果不能恰好居中,可以稍稍偏左或者偏上一点。

下面的程序实现这个逻辑,请填写划线部分缺少的代码。

#include <stdio.h>
#include <string.h>

void StringInGrid(int width, int height, const char* s)
{
	int i,k;
	char buf[1000];
	strcpy(buf, s);
	if(strlen(s)>width-2) buf[width-2]=0;
	

```
printf("+");
for(i=0;i<width-2;i++) printf("-");
printf("+\n");

for(k=1; k<(height-1)/2;k++){
	printf("|");
	for(i=0;i<width-2;i++) printf(" ");
	printf("|\n");
}

printf("|");

printf("%*s%s%*s",_____________________________________________);  //填空
          
printf("|\n");

for(k=(height-1)/2+1; k<height-1; k++){
	printf("|");
	for(i=0;i<width-2;i++) printf(" ");
	printf("|\n");
}	

printf("+");
for(i=0;i<width-2;i++) printf("-");
printf("+\n");	
```

}

int main()
{
	StringInGrid(20,6,"abcd1234");
	return 0;
}

对于题目中数据,应该输出:

+------------------+
|                  |
|     abcd1234     |
|                  |
|                  |
+------------------+

(如果出现对齐问题,参看【图1.jpg】)

注意:只填写缺少的内容,不要书写任何题面已有代码或说明性文字。

图 1
图 1

题目分析

对于代码填空题, 我们不需要读完全部代码, 只需要知道需要填空的地方完成的是什么样的功能即可.

首先, 我们可以先把需要填空的地方注释掉, 看看没有这一句代码的话程序的执行结果是怎样的(如果缺少该句代码之后程序可以执行的话). 在本题中注释掉需要填空的代码之后, 运行结果如图 2 所示:

图 2

根据显示的结果可以看出, 缺少的代码就是用来打印格子中的字符串和用于对齐的空格的.

本题考查的是 C++ 中的 printf() 函数的 * , 在 C++ 的官网上可以查找到相关的 API. 在 C++ 官网搜索 printf 即可打开关于 printf() 函数的 API 说明文档 (蓝桥杯比赛的计算机上也提供有 C/C++ 的 API 说明文档), 地址如下:

http://www.cplusplus.com/reference/cstdio/printf/?kw=printf

从官网上我们可以找到这样一个说明, 如图 3:

图 3
图 3

在其下的示例中我们可以看到对 * 用法的演示 (如图 4):

图 4
图 4

题目中用到的是 %*s , 这里用到的是 %*d, 根据之前学习到的 printf() 函数中 %d 表示整型变量, %s 表示字符型变量的知识可以推测, %*d%*s 也是分别对应整型变量和字符型变量的. 为了验证, 我们可以写这样一段程序:

#include<stdio.h>
int main(){
	printf("%*d",3, 9);
	printf("\n"); 
	printf("%*s",6, "aa");
	return 0;
} 

运行结果如下:

  9
    aa

从输出结果可以发现, 第一行打印出了 2 个空格和 1 个数字 (2+1=3), 第二行打印出了 4 个空格和 2 个字符 (4+2=6).

由此可以看到, printf() 函数中的 * 是用来确定输出的”宽度”的, 需要向其传送两个变量, 一个是宽度值, 一个是要打印的变量, 当要打印的变量的长度小于宽度值时就用空格填充.

再来看需要填空的那行代码:

printf("%*s%s%*s",_____________________________________________);

关键之处是 %*s%s%*s . 根据上面的分析我们知道, 其中间的 %s 是用来打印字符串的, 两边的 %*s 是用来打印空格的. 由于需要对齐, 所以需要知道每行的总长度和字符串的长度才可以计算出要打印的空格的个数.

根据题目中的下面这些代码可以知道每行的长度为 width:

printf("+");
for(i=0;i<width-2;i++) printf("-");
printf("+\n");

由下面这行代码可以确定字符串变量 s 被复制给了变量 buf :

strcpy(buf, s);

strcpy() 函数的功能为:

复制字符串from 中的字符到字符串to,包括空值结束符。返回值为指针to。

来自 C/C++ API 文档

由下面这行代码可以知道字符串变量 s 的长度为 strlen(s) :

if(strlen(s)>width-2) buf[width-2]=0;

由于题目中有如下的说明:

如果不能恰好居中,可以稍稍偏左或者偏上一点。

因此, 当行长度为 20, 字符长度为 8 的时候, 左边的空格应该有 (20-8-2)/2=5 个, 右边的空格应该有 (20-8-2)/2=(20-8-1)/2=5 个. 如果行长度为 21, 字符长度为 8 的时候, 左边的空格应该有 (21-8-2)/2=5 个, 右边的空格应该有 (21-8-1)/2=6 个

由此可以确定, 字符串变量 s 的左边需要打印的空格数为:

(width-strlen(s)-2)/2

右边应该打印的空格数为:

(width-strlen(s)-1)/2

因此空格中应该填写的内容是:

width-2-strlen(s))/2," ",buf,(width-strlen(s)-1)/2," "

完整的程序代码如下:

#include <stdio.h>
#include <string.h>

void StringInGrid(int width, int height, const char* s)
{
	int i,k;
	char buf[1000];
	strcpy(buf, s);
	if(strlen(s)>width-2) buf[width-2]=0;
	

printf("+");
for(i=0;i<width-2;i++) printf("-");
printf("+\n");

for(k=1; k<(height-1)/2;k++){
	printf("|");
	for(i=0;i<width-2;i++) printf(" ");
	printf("|\n");
}

printf("|");

printf("%*s%s%*s",(width-2-strlen(s))/2," ",buf,(width-strlen(s)-1)/2," ");  //填空
          
printf("|\n");

for(k=(height-1)/2+1; k<height-1; k++){
	printf("|");
	for(i=0;i<width-2;i++) printf(" ");
	printf("|\n");
}	

printf("+");
for(i=0;i<width-2;i++) printf("-");
printf("+\n");	

}

int main()
{
	StringInGrid(20,6,"abcd1234");
	return 0;
}

2015 年蓝桥杯 C 语言 B 组省赛第 3 题: 三羊献瑞 (三种方法 + 详细分析)

题目

三羊献瑞

观察下面的加法算式:

      祥 瑞 生 辉
  +   三 羊 献 瑞
-------------------
   三 羊 生 瑞 气

(如果有对齐问题,可以参看【图1.jpg】)

其中,相同的汉字代表相同的数字,不同的汉字代表不同的数字。

请你填写“三羊献瑞”所代表的4位数字(答案唯一),不要填写任何多余内容。

图 1
图 1

题目分析

将这八个汉字分别用字母 a~h 和数组 aa[0]~aa[7] 对应表示如下:

三 -> a -> aa[0]

羊 -> b -> aa[1]

献 -> c -> aa[2]

瑞 -> d -> aa[3]

祥 -> e -> aa[4]

生 -> f -> aa[5]

辉 -> g -> aa[6]

气 -> h -> aa[7]

换算成题目中的形式分别是:

      e d f g
  +   a b c d
-------------------
    a b f d h

      aa[4] aa[3] aa[5] aa[6]
  +   aa[0] aa[1] aa[2] aa[3]
-------------------------------
aa[0] aa[1] aa[5] aa[3] aa[7]


这里之所以要分别使用字母和数组表示一个汉字是因为下面提到的三种方法要用到.

本题的要求可以总结如下:

  • 每个汉字对应的数字都是不同的.
  • a~h 这 8 个字母 (或者说 8 个数组元素) 的取值范围是从 0 到 9 十个数字.
  • 其中 a (aa[0]) 不能等于 0, e (aa[4]) 也不能等于 0.
  • 要求填入的结果是”三羊献瑞”所代表的四位数字, 而不是一共有多少种组合方式 (根据题意可知满足题目条件的组合方式只有一种).

解法一

这个解法基于 C++ 标准函数库 STL 中的 next_permutation() 全排列函数进行. 对 0~9 十个数字进行全排列, 取每次排列的前 8 个代入公式进行计算并检验是否满足要求. 由于进行的是全排列, 所以数组 aa[] 的前 8 个元素都有机会包含 0~9 这 10 个数字.

代码如下:

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
int main(){
	int aa[10]={0,1,2,3,4,5,6,7,8,9};
	int sum=0;
	int sum1=0;
	int sum2=0; 
	int ans=0;
	while(next_permutation(aa,aa+10)){
		if(aa[0]!=0&&aa[4]!=0){
			sum1=aa[4]*1000+aa[3]*100+aa[5]*10+aa[6];
			sum2=aa[0]*1000+aa[1]*100+aa[2]*10+aa[3];
			sum=aa[0]*10000+aa[1]*1000+aa[5]*100+aa[3]*10+aa[7];
			if(sum==(sum1+sum2)){
			break;
			}
		}
		
		
	}
	cout<<"祥瑞生辉:"<<endl; 
	cout<<" "<<sum1<<endl;
	
	cout<<"三羊献瑞:"<<endl; 
	cout<<" "<<sum2<<endl;
	
	cout<<"三羊生瑞气:"<<endl;
	cout<<sum<<endl;
	return 0;
}

正确答案:

1085

解法二

这个解法的思路和解法一类似, 只不过不使用 STL 提供的 next_permutation() 全排列函数, 而改用 8 个 for 循环进行暴力破解.

代码如下:

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
int main(){
	int sum, sum1, sum2;
	for(int a=1;a<=9;a++){ //a 不能等于 0 
		for(int b=0;b<=9;b++){
			if(b!=a){
				for(int c=0;c<=9;c++){
					if(c!=a&&c!=b){
						for(int d=0;d<=9;d++){
							if(d!=a&&d!=b&&d!=c){
								for(int e=1;e<=9;e++){ //e 不能等于 0 
									if(e!=a&&e!=b&&e!=c&&e!=d){
										for(int f=0;f<=9;f++){
											if(f!=a&&f!=b&&f!=c&&f!=d&&f!=e){
												for(int g=0;g<=9;g++){
													if(g!=a&&g!=b&&g!=c&&g!=d&&g!=e&&g!=f){
														for(int h=0;h<=9;h++){
															if(h!=a&&h!=b&&h!=c&&h!=d&&h!=e&&h!=f&&h!=g){
																sum1=e*1000+d*100+f*10+g;
																sum2=a*1000+b*100+c*10+d;
																sum=a*10000+b*1000+f*100+d*10+h;
																if(sum==(sum1+sum2)){
																	printf("%d\n",sum2);
																}
															}
															
														}
													}
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}
	return 0;
}

正确答案:

1085


为了进一步验证结果的正确性, 也可以将 8 个汉字对应的结果都输出数来. 由于解法一中已经这么做, 这里就不再加入输出全部计算结果的代码. 输出全部计算结果后需要注意的是, 看清题意和计算结果, 不要误提交不符合题目要求的答案

解法三

这个解法用到了一些数学原理, 可以减少 for 循环的个数, 能够提高计算效率. 虽然对于填空题而言没必要考虑计算效率的问题, 但是这也是一种计算方式, 有必要尝试一下.

首先, 我们看一下这个式子:

      e d f g
  +   a b c d
-------------------
    a b f d h

两个四位数相加得出了一个五位数, 根据加法中”满十进一”的法则, 五位数的最高位一定是 1, 即:

a=1

于是, 原式就变成了:

      e d f g
  +   1 b c d
-------------------
    1 b f d h

这样我们就可以去掉对 a 的 for 循环, 对解法二中的代码进行一下修改即可.

代码如下:

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
int main(){
	int sum, sum1, sum2;
	int a=1;
		for(int b=0;b<=9;b++){
			if(b!=a){
				for(int c=0;c<=9;c++){
					if(c!=a&&c!=b){
						for(int d=0;d<=9;d++){
							if(d!=a&&d!=b&&d!=c){
								for(int e=1;e<=9;e++){ //e 不能等于 0 
									if(e!=a&&e!=b&&e!=c&&e!=d){
										for(int f=0;f<=9;f++){
											if(f!=a&&f!=b&&f!=c&&f!=d&&f!=e){
												for(int g=0;g<=9;g++){
													if(g!=a&&g!=b&&g!=c&&g!=d&&g!=e&&g!=f){
														for(int h=0;h<=9;h++){
															if(h!=a&&h!=b&&h!=c&&h!=d&&h!=e&&h!=f&&h!=g){
																sum1=e*1000+d*100+f*10+g;
																sum2=a*1000+b*100+c*10+d;
																sum=a*10000+b*1000+f*100+d*10+h;
																if(sum==(sum1+sum2)){
																	printf("%d\n",sum2);
																}
															}
															
														}
													}
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
	return 0;
}

一段错误的代码

下面这段代码是错误的:

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
int main(){
	int aa[10]={0,1,2,3,4,5,6,7,8,9};
	int sum=0;
	int sum1=0;
	int sum2=0; 
	int ans=0;
	while(next_permutation(aa,aa+10)){
		if(aa[0]!=0&&aa[4]!=0){
			sum1=aa[4]*1000+aa[3]*100+aa[5]*10+aa[6];
			sum2=aa[0]*1000+aa[1]*100+aa[2]*10+aa[3];
			sum=aa[0]*10000+aa[1]*1000+aa[5]*100+aa[3]*10;
			if(sum==(sum1+sum2)){
			break;
			}
		}	
	}
	cout<<sum1<<endl;
	cout<<sum2<<endl;
	cout<<sum<<endl;
	return 0;
}

运行结果是:

9347
1083
10430

由运行结果可以看到, 最后计算的和为”10430″, 出现了重复的 “0”, 而在题目中的结果里 “三 羊 生 瑞 气” 并没有重复的汉字, 因此这个结果是错误的, 原因在下面这段代码:

sum=aa[0]*10000+aa[1]*1000+aa[5]*100+aa[3]*10;

上面这段代码中没有加入个位, 因此导致错误.

在做题时要注意以下三点:

  • 认真读题, 充分理解题意后再做题.
  • 认真写代码, 长代码能分行写的就分开写, 不要出现不符合题意的代码.
  • 计算出结果后如果能手动验算, 一定要手动验算一遍.

在 Linux 下的 gcc 或 clang 编译器中调用不同版本的 C 语言标准编译程序以及查看本机默认编译标准的方法

假设我们要编写的 C 语言源代码文件的文件名称是 a.c

则,在 gcc 下指定编译器编译标准的命令为:

gcc -std=c99 a.c //调用 C99 标准
gcc -std=c1x a.c //调用 GCC 接受 C11 之前的草案标准
gcc -std=c11 a.c //调用 C11 标准

clang 编译器与 gcc 编译器用法相同, 如果要使用 clang 编译器, 则将 gcc 替换成 clang 即可.

如果想查看当前使用的 gcc 编译器默认的编译标准, 在 Ubuntu Linux 中可以使用如下命令查看 C 语言的所有预编译宏:

gcc -E -dM - </dev/null

在输出的结果中查看 #define __STDC_VERSION__ 的值, 不同值代表的不同编译标准如下:

#define __STDC_VERSION__ 199901L //C99 标准
#define __STDC_VERSION__ 201112L //C11 标准
继续阅读“在 Linux 下的 gcc 或 clang 编译器中调用不同版本的 C 语言标准编译程序以及查看本机默认编译标准的方法”

在 Windows 10 上使用 WSL 配置和运行 Kali Linux / Ubuntu Linux

操作环境

Windows 10 中文家庭版 64 位

(需要 Windows 10 16215.0 或更高版本的 Windows 10 才可以)

操作说明

WSL 全称为 Windows Subsystem for Linux (Windows 下的 Linux 子系统). Wikipedia 对 WSL 的描述摘录如下 (Source: HERE)

适用于 Linux 的 Windows 子系统(英语:Windows Subsystem for Linux,简称WSL)是一个为在Windows 10和Windows Server 2019上能够原生运行Linux二进制可执行文件(ELF格式)的兼容层。
WSL提供了一个由微软开发的Linux兼容的内核接口(不包含Linux内核代码),然后可以在其上运行GNU用户空间,例如Ubuntu,openSUSE,SUSE Linux Enterprise Server,Debian和Kali Linux。这样的用户空间可能包含Bash shell和命令语言,使用本机GNU/Linux命令行工具(sed,awk等),编程语言解释器(Ruby,Python等),甚至是图形应用程序(使用主机端的X窗口系统)。

来自维基百科词条: 适用于 Linux 的 Windows 子系统

由于 Windows 下的 Linux 子系统并不包含 Linux 内核, 所以这严格上讲并不是一个真正的 Linux 系统, 但是对终端用户而言, 使用感受上是和真正的 Linux 系统很接近的. 使用 Linux 子系统既避免了在一台计算机上使用双系统时同一时间内只能运行其中一个的问题, 也避免了使用虚拟机时系统资源的大量消耗, 如果喜欢使用 Linux 命令的话, Linux 子系统还是值得一试的.

继续阅读“在 Windows 10 上使用 WSL 配置和运行 Kali Linux / Ubuntu Linux”

解决 PHP 输出中文乱码的问题

问题描述

今天给导航狗(https://daohanggou.cn/)的 PHP 程序和数据库文件迁移了服务器, 但是迁移到新的服务器上之后 PHP 输出的中文和 PHP 输出的从 MySQL 数据库查询出来的数据中的中文都出现了乱码的情况. 下面记录一下我解决该问题的过程.

继续阅读“解决 PHP 输出中文乱码的问题”

解决 Orange Pi 烧录完系统后剩余可用空间过少的问题

操作环境

香橙派使用的 SD 卡容量:16 GB
香橙派使用的 SD 卡文件系统类型:FAT32
香橙派型号:Orange Pi One
香橙派操作系统:Ubuntu 14.04.1 LTS
SSH 远程连接软件:Xshell 6
SSH 远程连接软件的运行平台:Windows 10 中文家庭版 64 位

问题背景

今天在向 Orange Pi 中克隆一个 GitHub 项目的时候,系统无法执行该指令并给出了如下提示:

fatal: could not create work tree dir ‘/home/orangepi/***’.: No space left on device

继续阅读“解决 Orange Pi 烧录完系统后剩余可用空间过少的问题”

Git Error: failed to push some refs to ‘git@github.com:**.git’

操作环境

操作系统:Windows 10 家庭中文版 64位
Git 客户端:mintty 2.9.0 (x86_64-pc-msys)
Git version: 2.19.0.windows.1
Git 仓库:github.com

报错说明

今天 Push 代码的时候遇到一个报错:

! [rejected]        master -> master (fetch first)
error: failed to push some refs to 'git@github.com:somebodyblog/somebodyblog.git'

报错截图如下:

图 1 报错截图
图 1 报错截图

解决方案

出现这样的报错一般是因为本地仓库分支的代码和远程仓库分支的代码不一致了。需要先拉取(fetch)远程分支的代码并在本地对两个分支的代码进行合并(merge / rebase)后才能继续向远程仓库分支 push 代码。
合并代码:

git pull --rebase origin master

代码解释:

  • git pull –rebase = git fetch + git rebase

推送代码:

git push

至此,问题解决。

又拍社区(yupoo.com)宣布进行业务升级维护

2018年11月05日,又拍社区(yupoo.com)发布公告称,将于2018年11月28日起关闭注册和上传等服务,进入关闭维护状态。在2019年5月31日之前,又拍社区用户可以使用官方提供的 数据备份工具备份自己在又拍社区中的照片。

本次停止服务的仅仅是又拍社区,又拍图片管家(http://x.yupoo.com/)仍然可用。

如果本站读者有存储在又拍社区中的图片,请记得及时下载。

继续阅读“又拍社区(yupoo.com)宣布进行业务升级维护”

神奇的异或:在不引入第三个变量的情况下交换两个变量的数值

运行环境

操作系统:Windows 7
Python版本:Python 3.7

正文

一般情况下,当我们需要交换两个变量的值的时候,至少需要引入1个第三方变量(当然,如果愿意的话,也可以引入第四方和第五方变量>_<),但是,当我们使用异或的时候就不必这么做,只需要这两个变量就可以完成他们之间数值的交换。

设,有两个变量 a 和 b.
其中,a = 10, b = 20.

现在使用 Python 进行如下的运算:

图 1 使用 Python 异或运算交换变量的数值
图 1 使用 Python 异或运算交换变量的数值

可以看到,经过三次异或操作,成功的交换了a和b的数值。

其实,只要明白了异或的规律,就知道了这其中的原因,异或的运算规则是:

相同为0, 不同为1.

将上面的运算过程展开写就是这样的:

a = a ^ b = 10 ^ 20 = 0b(01010) ^ 0b(10100) = 0b(11110) = 30
b = a ^ b = 30 ^ 20 = 0b(11110) ^ 0b(10100) = 0b(01010) = 10
a = a ^ b = 30 ^ 10 = 0b(11110) ^ 0b(01010) = 0b(10100) = 20

Kali Linux 更换系统主题

操作环境

物理机操作系统:Windows 10 家庭版
虚拟机操作系统:Kali Linux 2018.4
虚拟化软件:VMware Workstation 15 Pro (15.0.2 build-10952284)

工具准备

GNOME 主题下载:
https://www.gnome-look.org/

这里我使用的主题是:
https://www.opendesktop.org/p/1263666/

我下载的文件名称是:

McOS-MJV-Dark-mode-Gnome-3.30-1.1.tar.xz

操作步骤

将该主题文件复制进/usr/share/themes/目录:

cp McOS-MJV-Dark-mode-Gnome-3.30-1.1.tar.xz /usr/share/themes/

进入系统主题所在的目录:

cd /usr/share/themes/

解压 .xz 文件:

xz -d McOS-MJV-Dark-mode-Gnome-3.30-1.1.tar.xz

解压 .tar 文件:

tar -xvf McOS-MJV-Dark-mode-Gnome-3.30-1.1.tar

点击打开“优化”工具:

图 1 中文状态下的优化工具
图 1 中文状态下的优化工具

如果在英文状态下,是这样的,点击”Tweaks”:

图 2 英文状态下的优化工具
图 2 英文状态下的优化工具

依次找到“外观/主题/”,选中刚才下载的主题即可更换主题:

图 3 使用优化工具更换系统主题
图 3 使用优化工具更换系统主题

更换系统主题后的Kali Linux:

图 4 系统主题更换完成
图 4 系统主题更换完成

Android开发实战:点击按钮显示一个带有“取消”和“确定”两个选项的对话框

操作环境

  • Windows 10
  • Android Developer Tools (Build: v22.2.1-833290)
  • Android 4.3

代码

res/layout/activity_main.xml 代码如下:

<pre class="wp-block-code"><code><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textView1"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="90dp"
        android:text="点击开启一个对话框"
        android:onClick="onclick" />

</RelativeLayout></code></pre>

src/com/example/duihuakuang/MainActivity.java 代码如下:

package com.example.duihuakuang;


import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}
	
	public void onclick(View view)
	{
		AlertDialog.Builder builder = new Builder(this);
		builder.setIcon(null);//设置图标, 这里设为空值
		builder.setTitle("ZhaoKaifeng.com");
		builder.setMessage("确定要取消吗");
		builder.setPositiveButton("确定", new OnClickListener(){
			
			public void onClick(DialogInterface arg0, int arg1){
				Toast.makeText(MainActivity.this,"确定成功!",Toast.LENGTH_SHORT).show();
			}
		});
		
		builder.setNegativeButton("取消", new OnClickListener(){
			public void onClick(DialogInterface arg0,int arg1){
				Toast.makeText(MainActivity.this, "取消成功!", Toast.LENGTH_SHORT).show();
			}
		});
		AlertDialog b = builder.create();
		b.show();//显示对话框
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

}

运行效果

程序首页效果:

图 1
图 1

点击“点击开启一个对话框”按钮后的效果:

图 2
图 2

点击“确定”按钮后的效果:

图 3
图 3

点击“取消”按钮后的效果:

图 4
图 4

使用 MSU StegoVideo 将信息隐藏进 AVI 视频文件中(两种方法 + 详细图文过程)

环境部署

操作系统:
Windows 7 专业版 64位

软件:

  • 下载 MSU StegoVideo

下载地址:http://www.compression.ru/video/stego_video/index_en.html
接下来还需要下载并安装如下两个解码器,否则在使用 MSU StegoVideo 的 .exe 程序的时候会报错:

Can’t find suitable decompresso

如果是在 VirtualDub 中使用 MSU StegoVideo 插件,则会报错:

Couldn’t locate decompressor for format XviD (Unknown)
VirtualDub requires a Video for Windows (VFW) compatible codec to decompress video. DirectShow codecs, such as those used by Windows Media Player are not suitable

继续阅读“使用 MSU StegoVideo 将信息隐藏进 AVI 视频文件中(两种方法 + 详细图文过程)”

荒原之梦网全部内容均为原创,提供了涵盖考研数学基础知识、考研数学练习题、考研数学真题等方面,大量精心研发的学习资源。

豫ICP备17023611号-1 | 公网安备 - 荒原之梦 豫公网安备41142502000132号
Copyright©2017-2025 ZhaoKaifeng.com 版权所有 All Rights Reserved.

豫ICP备17023611号-1
 豫公网安备41142502000132号
Copyright©2025   ZhaoKaifeng.com   All Rights Reserved.

荒原之梦 自豪地采用WordPress