算法竞赛入门经典第2章【读书笔记】

【学习目标】

01掌握for循环的使用方法(OK)

02掌握while循环的使用方法(OK)

03学会使用计数器和累加器(OK)

04学会使用输出中间结果的方法调试(OK)

05学会用计时函数测试程序效率(不熟悉)

06学会用重定向的方法读写文件(基本不会)

07学会用fopen的方式读写文件(基本不会)

08了解算法竞赛对文件读写方式和命名的严格性(嗯)

09记住变量在赋值之前的值是不确定的(OK)

10学会使用条件编译指示构架本地运行环境(不会)




P18

注意浮点数的运算(包括返回浮点数的函数)可能有误差!

编写一个程序判断输出的数(n<10^9)是不是完全平方数,是输出yes,否则输出no;

#include <stdio.h>
#include <math.h>

int
main(void)
{
	int n;
	double r;

	scanf("%d", &n);
	r = sqrt(n);//or r = sqrt((double)n);
	printf(floor(r+0.5) == r ? "yes\n" : "no\n");	
	return 0;
}


for (i = 0; i != N; i++)
break;语句退出循环时,i++还会执行么?continue呢?

#include <stdio.h>
#define N 100

int
main(void)
{
	int i;

	for (i = 0; i != N; i++) {
		if (i == 5)
			continue;
			
		if (i == 10)
			break;
	}
	printf("%d\n",i);
	return 0;
}

执行这个程序,输出会是10,说明退出循环时i++没有执行,而continue执行后,如果i++不执行,那么必定陷入无限循环了。所以i++必须要执行。

可见循环出口一旦执行,i++肯定不会再执行;而继续循环(中途就继续或者正常继续),i++肯定会执行。


05学会用计时函数测试程序效率

#include <stdio.h>
#include <time.h>
int
main(void)
{	
	int n, i, j;
	clock_t star, end;
	
	scanf("%d", &n);
	star = clock();
	for (i = 0; i != n; i++)
		for (j = 0; j != n; j++)
			;
	end = clock();
	printf("%lf\n", (double)(end-star) / CLOCKS_PER_SEC);
	//notice! is CLOCKS including 'S'
	return 0;
}

这样写可以避免把等待输入的时间也算上,注意常量CLOCKS_PER_SEC带'S'。

linux中重定向输入是echo 12321 | ./program_name


06学会用重定向的方法读写文件

学会这个主要是可以把输入输出放在一个文本,省的在终端输入或粘贴测试数据,特别是输入一些矩阵时。

下面默认输入文件名是test.in,输出文件名是test.out

下面写一个程序,输入一个n*n的矩阵(n<=100),输出矩阵的转置矩阵;

比如,

输入:

3

1 2 3

1 2 3

1 2 3

输出:

1 1 1

2 2 2

3 3 3

(注意:每一行最后一个元素后面没有空格)

【普通版本】

#include <stdio.h>
#define N 110
int a[N][N];

int
main(void)
{
	int i, j, n;
	
	scanf("%d", &n);
	for (i = 0; i != n; i++)
		for (j = 0; j != n; j++) {
			scanf("%d", &a[i][j]);
		}
	
	for (j = 0; j != n; j++)
		for (i = 0; i != n; i++) {
			printf(i == n-1 ? "%d\n" : "%d ", a[i][j]);
		}
				
	return 0;
}


【重定向版本】

#include <stdio.h>
#define N 110
int a[N][N];

int
main(void)
{
	int i, j, n;

	freopen("test.in", "r", stdin);
	freopen("test.out", "w", stdout);
	
	scanf("%d", &n);
	for (i = 0; i != n; i++)
		for (j = 0; j != n; j++) {
			scanf("%d", &a[i][j]);
		}
	
	for (j = 0; j != n; j++)
		for (i = 0; i != n; i++) {
			printf(i == n-1 ? "%d\n" : "%d ", a[i][j]);
		}
				
	return 0;
}
可以看到重定向版本就多了两行代码!就是读取test.in的内容作为标准输入流(stdin),把标准输出流(stdout)的内容写入到test.out。


【fopen版】

#include <stdio.h>
#define N 110
int a[N][N];

int
main(void)
{
	int i, j, n;

	FILE *fin, *fout;//file pointer indicated file name;
	fin = fopen("test.in", "r");
	fout = fopen("test.out", "w");
		
	fscanf(fin, "%d", &n);
	for (i = 0; i != n; i++)
		for (j = 0; j != n; j++) {
			fscanf(fin, "%d", &a[i][j]);
		}
	
	for (j = 0; j != n; j++)
		for (i = 0; i != n; i++) {
			fprintf(fout, i == n-1 ? "%d\n" : "%d ", a[i][j]);
		}
	
	fclose(fin);
	fclose(fout);
	
	return 0;
}
其实这个版本也很容易理解,首先打开文件,fin是文件的指针,并且可以读文件,然后scanf()改为fscanf(),即从文件中读取,参数也相应加了一个,并在最开始部分指定文件的地址(指针);写入的原理以此类推。


感觉重定向相当好用哦!

书中介绍本地用重定向,提交则删除“重定向”语句,感觉不是太实用,但不妨一学。

10学会使用条件编译指示构架本地运行环境

#include <stdio.h>
#define N 110
int a[N][N];

int
main(void)
{
	int i, j, n;

#ifdef LOCAL
	freopen("test.in", "r", stdin);
	freopen("test.out", "w", stdout);
#endif
	
	scanf("%d", &n);
	for (i = 0; i != n; i++)
		for (j = 0; j != n; j++) {
			scanf("%d", &a[i][j]);
		}
	
	for (j = 0; j != n; j++)
		for (i = 0; i != n; i++) {
			printf(i == n-1 ? "%d\n" : "%d ", a[i][j]);
		}
				
	return 0;
}
上述程序文件名为test.c

那么我们通过编译命令:(注意是:-DLOCAL)

gcc -g -Wall -DLOCAL test.c -o test
就会执行重定向那两句代码了,反之去掉-DLOCAL就不会执行



你可能感兴趣的:(算法竞赛入门经典第2章【读书笔记】)