方法一:用display:table 实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.parent {
display: table;
height: 300px;
background: yellow;
}
.child {
display: table-cell;
vertical-align: middle;
background: red;
}

.content {
width: 50px;
margin: auto;
background: blue;
}

HTML

1
2
3
4
5
<div class="parent">
<div class="child">
<div class="content">XXX</div>
</div>
</div>
## 方法二:用position:absolute
1
2
3
<div class="parent">
<div class="box"><img src="cat.jpg" alt=" /></div>
</div>

先用浏览器看一下效果如下:

使用css语法来调整位置

1
2
3
4
5
6
7
8
9
10
11
12
.parent{
width: 500px;
height: 500px;
position: relative;
background-color: gray;
}
.box{
width: 233px;
position: absolute;
left: 50%;
top: 50%;
}

我们设置的位置是 left:50%; 和 top:50%; 刚好就是中心位置,因为 CSS 的 position:absolute; 是以 div 的左上角当作计算点,所以才会产生这样的结果,如下图:

接下来再让div.box 左、上移一半的宽度、高度就可以了

1
2
3
4
5
6
7
8
.box{
width: 233px;
position: absolute;
left: 50%;
top: 50%;
margin-left: -116px;
margin-top: -99px;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<iostream>
using namespace std;
void func();
int n=1;
int main() {
int a=0, b=10;
cout<<"a="<<a<<", b="<<b<<", n="<<n<<endl;
func();
cout<<"a="<<a<<", b="<<b<<", n="<<n<<endl;
func();
}
void func() {
static int a=2;
int b=5;
a += 2, b += 5;
n +=12;
cout<<"a="<<a<<", b="<<b<<", n="<<n<<endl;
}

程序中函数main两次调用了func函数,从运行结果可以看出,程序控制每次进入func函数时,局部变量b都被重新初始化,而静态局部变量a仅在第一次调用时被初始化,第二次进入该函数时,不再进行初始化,这时它的值是第―次调用后的结果值4。main函数中的变量a和b与func函数中的变量a和b的空间位置是不样的,所以相应的值也不一样。

国内一些学生在用VC6,但VC6的编译器不是标准C++规范它规定for循环中定义的循环变量的作用域为包含for语句的快,即沿用C规则,而标准C++规定在for中的循环变量作用域为for语句块。即:

1
2
3
4
int sum=0;
for(int i=0; i<10; i++)
sum += i;
cout<<sum<<" "<<i<<endl; //错i不存在

  1. | 或 ,^ 异或, ~ 非
1
2
3
4
5
6
//函数参数默认值只能从后往前设置,例如:
void func(int a=1, int b, int c=3); //错:b和a的位置违规
void func(int a, int b=2, int c=3); //ok
//调用时的实参按位置解析,默认实参也只能从后往前逐个替换尾部的“漏缺”,例如
func(12, 12) //ok: c和d默认
func(2, 14, , 3) //错:d不默认则c也无法默认

abc.txt文件中有一些整数,试编程实现循环输入文件中的整数,判断其能否被3,5,7整除。

三种信息有是和否可能,排列起来一共有8种情况,将这三种信息按二进制进行制作,即被3整除放在第三位,被5整除放在第二位,被7整除放在第一位,构成三位二进制数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<iostream>
#include<fstream>
using namespace std;
void main() {
ifstream in("abc.txt");
for(int n; in>>n; ) {
switch( (!(n%3)<<2) + (!(n%5)<<1) + !(n%7) ) {
case 0: cout<<n<<" "<<"none";break;
case 1: cout<<n<<" "<<"7";break;
case 2: cout<<n<<" "<<"5";break;
case 3: cout<<n<<" "<<"5,7";break;
case 4: cout<<n<<" "<<"3";break;
case 5: cout<<n<<" "<<"3,7";break;
case 6: cout<<n<<" "<<"3,5";break;
case 7: cout<<n<<" "<<"3,5,7";break;
}
cout<<endl;
}
}

某任务需要在A、B、C、D、E这五人中物色人员去完成,但派人受限于下列条件:

  1. 若A去,则B跟去
  2. D,E两人中必有人去
  3. B,C两人中必有人去,但只去一人
  4. C,D两人要么都去,要么都不去
  5. 若E去,则A、B都去
问这五个条件如何表示?

令A、B、C、D、E都为逻辑型值true或false。则:

条件1可以表示为逻辑表达式:A—>B,它等价于!A || B,意即A不去是一种方案, 另一种方案当然是A和B一起去。

条件2可以表示为:D || E,意即D去,E去,D和E都去,这三种方案都行.

条件3可以表示为:(B&&!C) || (!B&&C)。推演为B != C.意即,B去C不去是一种 方案,另一种方案是C去B不去。

条件4可以表示为:( !C || D ) && ( C || !D).更简单的形式为C == D·意即C和D一起去 是一种方案,C和D都不去是另一种方案

条件5可以表示为:!E || (A&&B),意即E不去是一种方案,另一种方案是E和A和 B都去

求解模式

如果将每个人的去与不去看成是5位整数的其中1位,其中A对应最高位,E对应最低位,那么,所有可能的调派方案为从全部不派的00000到全部派去的11111之间变化。显然有32种方案。全部遍历的循环为:
1
for( int i=0; i<32; i++ )

其中每个i对应一个二进制数,为一种调派方案。在某一种调派方案i中:

A为最高位 (i & 16 ) >> 4或者 i>>4  (将低位都挤掉)
B为次高位 ( i & 8 ) >> 3
C为中间位 ( i &4 ) >> 2
D为次低位( i & 2 )>>1
E为最低位 i&1

根据求解模式,把这五个条件表示成否定的形式:

否定条件1为 !( !A || B ) = A && !B
否定条件2为!(D || E )
否定条件3为 B=C
否定条件4为C != D
否定条件5为E && !( A && B)

再将A、B、C、D、E的式子带入条件表达式,既可以构成程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include<iostream>
using namespace std;
void print(int n);
void main() {
for( int i=0; i < 32; i++ ) {
bool A=i&16, B=i&8, C=i&4, D=i&2, E=i&1;
if( A && !B )
continue;
if( !D && !E )
continue;
if( B==C )
continue;
if( C != D )
continue;
if( E && !(A && B) )
continue;
print(i);
}
}
void print(int n) {
cout<<( n&16 ? &quot; A &quot;:&quot;~A &quot; )
<<( n&8 ? &quot; B &quot;:&quot;~B &quot; )
<<( n&4 ? &quot; C &quot;:&quot;~C &quot; )
<<( n&2 ? &quot; D &quot;:&quot;~D &quot; )
<<( n&1 ? &quot; E &quot;:&quot;~E &quot; )<<endl;
}

若一头母牛,从出生起第四个年头开始每年生一头母牛,按此规律,第n年有多少头母牛?

分析的关键,统计当年倒退到3年前母牛数,就知道当前有几头母牛能添加,再加上现行的母牛数,就是当前的母牛数。

令f(n)表示第n年的母牛数,则可以列出的数学递推函数为:

f(1) = 1

f(2) = 1

f(3) = 1

f(n) = f(n-3) + f(n-1)     n>3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<iostream>
using namespace std;
void main() {
int a=1,b=1,c=1; //最初三个年份的初值
int n;
cin>>n;
for( int i=4,tmp; i<=n; i++) {
tmp = a + c;
a = b;
b = c;
c = tmp;
}
cout<<c;
}

文件aaa.txt中含有一些行,每行中有一些整数,可以构成—个向量,整个文件可以看成是一组向量,其中每个元素又都是向量,只不过作为元素的向量其长度参差不齐。设计一个个排序程序,使得按从短到长的顺序输出每个向量,这时候,程序代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include<iostream>
#include<fstream>
#include<sstream>
#include<vector>
using namespace std;

typedef vector< vector<int> > Mat;
Mat input();
void mySort(Mat& a);
void print(const Mat& a);

int main() {
Mat a = input();
mySort(a);
print(a);
return 0;
}
Mat input() {
ifstream in("aaa.txt");
Mat a;
for(string s; getline(in,s); ) {
vector<int> b;
istringstream sin(s);
for( int ia; sin>>ia; )
b.push_back(ia);
a.push_back(b);
}
return a;
}
void mySort(Mat& a) {
for( int pass=1; pass<a.size(); pass++ ) {
for( int i=0; i<a.size()-pass; i++ )
if( a[i+1].size() < a[i].size() )
a[i].swap( a[i+1] );
}
}
void print(const Mat &a) {
for( int i=0; i<a.size(); i++ ) {
for(int j=0; j<a[i].size(); j++ )
cout<<a[i][j]<<" ";
cout<<endl;
}
}

求π的近似值,精确到小数点后6位。

分析:

  1. 整数不能表示小数,所以元的值用浮点小double表示。
  2. 按公式.先求元π/4。
  3. 数列的第n项是 (-1)n-1//(2n-1),第n项与第n-1项的关系为符号变一下,分母加2。
  4. 一种方法是根据循环变量n,求得第n项的值,累计,然后条件判断,若满足结束条件,则退出,循环结束条件为前一个累计和与后一个累计和的差小于10的6次方,由于前后两次累计的结果之差的绝对值等于后一次加上去的值,所以,也可以通过判断项的绝对值小于10的6次方而得到循环退出条件。
1
2
3
4
5
6
7
8
9
10
11
#include
using namespace std;
int main() {
double sum=0, item=1;
for(int n=1; fabs(item) > 1e-6; n++) {
item *= (-1.0)*(2*n-3)/(2*n-1);
sum += item;
}
cout<<sum;
return 0;
}

输出内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
using namespace std;
void paint(int a);
int main() {
int num;
cout<<"请输入层数(0结束输入):";
cin>>num;
while(num) {
paint(num);
cout<<"层数(0结束输入):";
cin>>num;
}

cout<<endl;
return 0;
}
void paint(int a) {
int i,j,k;
for(i=1; i<=a; i++) {
for(j = 0; j<a-i; j++) {
cout<<' ';
}
for(k=0; k<2*i-1; k++) {
cout<<'*';
}
cout<<'\n';
}
for(i=a-1; i>=1; i--) {
for(j = 0; j<a-i; j++) {
cout<<' ';
}
for(k=0; k<2*i-1; k++) {
cout<<'*';
}
cout<<'\n';
}
}

利用输入输出流可以将paint函数做如下精简:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void paint(int a) {
int i,j,k;
for(i=1; i<=a; i++) {
//输出a-i个空格
if(a-i)
cout<<setfill(' ')<<setw(a-i)<<' ';
//输出2*i-1个*
cout<<setfill('*')<<setw(2*i-1)<<'*'<<'\n';
}
for(i=a-1; i>=1; i--) {
//输出a-i个空格
if(a-i)
cout<<setfill(' ')<<setw(a-i)<<' ';
//输出2*i-1个*
cout<<setfill('*')<<setw(2*i-1)<<'*'<<'\n';
}
}

对于判断一个数m是否为素数,最朴素的法是按素数的定义,试除以从2开始到m-1的整数,如果无一例外地不能整除,则该数定是素数,例如,实现的程序如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
using namespace std;
void paint(int a);
int main() {
cout<<"please input a number:";
int m;
cin>>m;
for(int i=2; i<m; i++) {
if(m%i == 0 ) {
cout<<m<<" isn't a prime.\n";
return 1;
}
}
cout<<m<<" is a prime.\n";
}

想一想,若2都不能除尽.还要试4,6,8…..吗?若3都不能除尽,还要试9,15,21…吗?等等。一个数,如果有因子的话那么在它的平方根数以内就应该有,否则就没有因子,例如,77的平方根值在8与9之间,因为77不是素数,则它一定有比8还小 的因子,它能被7整除,是理所当然的。

在数学上,假定某个整数m不是素数,则一定可以表示成两个因子的积:

m = i * j     假定 i  <= j

则 i² ≤ m  ≤ j²

即 i ≤ √m ≤ j

所以必定有—个因子不大于m的平方根,故判断m是否是素数,只要除到m的平方根就可以了,不必一直到m-1:因此,上面的程序可以修改为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <cmath>
using namespace std;
void paint(int a);
int main() {
cout<<"please input a number:";
int m;
cin>>m;
double sqrtm = sqrt(m * 1.0);
for(int i=2; i<sqrtm; i++) {
if(m%i == 0 ) {
cout<<m<<" isn't a prime.\n";
return 1;
}
}
cout<<m<<" is a prime.\n";
}

修改后的程序,效率提高了一些,例如,判断101是否为素数,本来要从2试除到100. 现在只要从2试除到10就行了。

事实上,中间的4,6,8也都无须试,大家可以想一想,在不明显增加程序复杂性 的基础上怎么修改程序,效率还会更高呢?

筛选法判断素数

从2开始的某个连续整数集合,留下2,除去所有2的倍数,留下3,除去所有3的倍数留下5再除去所有5的倍数,如此等等,留下某个最先遇到的素数,将其所有的倍数从该数集中去掉,最后,数集中就全是素数了,接下来要判断一个数是否为素数,可以该数为下标,访问素数集合,如果是则为素数,否则不是素数,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<iostream>
#include<vector>
#include<fstream>
using namespace std;
int main() {
vector<int> prime(10000,1);
for(int i=2; i<100; i++) //构造素数集合
if(prime[i])
for(int j=i; j*i<10000; j++)
prime[i*j] = 0;
ifstream in("a.txt");
for(int a; in>>a && a>1 && a<10000; ) //判断素数
cout<<a<<" is "<<(prime[a] ? "":"not ")<<"a prime.\n";
}

在程序中,对于3来说,要去掉所有3的因子,包括6,12,18等,但事实上,偶数 在上一轮中已经作为2的倍数而去掉了,所以,这个过程还有一些重复操作,算法还有可以改进的地方。