1 ) 任务
2 ) 一般思路
#include
#include
using namespace std;
int m[6][6] = {{0}};
void Show() {
for (int i=0; i<6; i++) {
for (int j=0; j<6; j++)
cout << setw(2) << m[i][j] << ' '; cout << endl;
}
}
void Fill(int num, int begin, int size);
int main() {
Fill(1, 0, 6);
Show();
return 0;
}
void Fill(int num, int begin, int size) {
if (size == 0) return;
if (size == 1) {
m[begin][begin] = num;
return;
}
// 四个边的遍历
for (int j=0; j<size-1; j++) m[begin+j][begin+0] = num++;
for (int j=0; j<size-1; j++) m[begin+size-1][begin+j] = num++;
for (int j=size-1; j>0; j--) m[begin+j][begin+size-1] = num++;
for (int j=size-1; j>0; j--) m[begin+0][begin+j] = num++;
Fill(num, begin+1, size-2);
}
1 20 19 18 17 16
2 21 32 31 30 15
3 22 33 36 29 14
4 23 34 35 28 13
5 24 25 26 27 12
6 7 8 9 10 11
3 ) 使用OOP的思路来做(优化版)
#include
#include
using namespace std;
class matrix {
int **M;
int N;
public:
void init(int size);
void fill(int num, int begin, int size);
void print();
void clear();
};
void matrix::init(int size) {
// 初始化数据结构:N*N的矩阵
// 用下面这种方式初始化一个N*N的矩阵
M = new int*[size];
N = size; // 用于后面的打印和清理
// r means 'row'
for (int r=0; r<size; r++) {
M[r] = new int[size];
memset(M[r], 0, sizeof(int)*size); // 矩阵清零,表示无数字
}
}
void matrix::fill(int num, int begin, int size) {
if (size == 0) {
return;
}
if (size == 1) {
M[begin][begin] = num;
return;
}
// 四个边的遍历
for (int j=0; j<size-1; j++) M[begin+j][begin+0] = num++;
for (int j=0; j<size-1; j++) M[begin+size-1][begin+j] = num++;
for (int j=size-1; j>0; j--) M[begin+j][begin+size-1] = num++;
for (int j=size-1; j>0; j--) M[begin+0][begin+j] = num++;
fill(num, begin+1, size-2);
}
// print 打印矩阵格子
void matrix::print() {
for (int i = 0; i < N; i++) {
for (int j=0; j< N; j++) {
cout << setw(2) << M[i][j] << ' ';
}
cout << endl;
}
}
void matrix::clear() {
for (int r=0; r<N; r++) delete[] M[r];
delete[] M;
}
int main() {
matrix obj;
cout << "Please input N: ";
int size;
cin >> size;
obj.init(size); // 根据输入大小做准备
obj.fill(1, 0, size); // 按规则完成数字填充
obj.print(); // 输出填充结果
obj.clear(); // 一些必要的善后处理
return 0;
}
class matrix {
char dir; // 'D', 'R', 'U', 'L' 注:这里有四个边,左下右上,逆时针方向,其中左边的方向是向下,用D来表示,其他依次类推
}
// 'D', 'R', 'U', 'L' 注:这里有四个边,左下右上,逆时针方向,其中左边的方向是向下,用D来表示,其他依次类推
void matrix::place(int num) {
// 根据前一位置、方向,以及摆放规则(DRUL)确定下一个摆放数据的位置
switch (dir) {
case 'D':
// 先保证row在合法范围内,再考虑该处是否已有数字(是否为0)
if (row < N-1 && M[row+1][col] == 0) row++;
else {
dir = 'R'; // next direction
col++;
}
break;
// 仅展示部分源码
// ...
}
#ifndef MATRIX_H
#define MATRIX_H
#include
using namespace std;
class matrix
{
int row, col, **buf;
public:
matrix(int, int); // 矩阵初始化
~matrix(); // 矩阵的析构
int& operator() (int r, int c); // matrix_obj(r,c) 这里取一个值出来,返回一个引用
friend ostream& operator << (ostream&, const matrix&); // 运算符的重载输出
};
#endif
#include "matrix.h"
#include // cout
#include // setw()
using namespace std;
matrix::matrix(int r, int c)
: row(r), col(c)
{
buf = new int*[row];
for (int i=0; i<row; i++)
buf[i] = new int[col];
}
matrix::~matrix() {
for (int i=0; i<row; i++)
delete[] buf[i];
delete buf;
}
// 用函数运算符(),实现对矩阵多下标访问的支持
int& matrix::operator() (int r, int c)
{
return buf[r][c];
}
ostream& operator << (ostream& o, const matrix& m)
{
for (int i=0; i<m.row; i++) {
for (int j=0; j<m.col; j++)
o << setw(2) << m.buf[i][j] << ' ';
o << endl;
}
return o;
}
#ifdef TEST_MATRIX // 下面是matrix类的测试代码
int main()
{
matrix m(4, 5);
for (int i=0; i<4; i++)
for (int j=0; j<5; j++)
m(i, j) = i*j;
cout << "Matrix 4X5:" << endl;
cout << m << endl;
return 0;
}
#endif
// g++ -DTEST_MATRIX matrix.cpp
// 根据前一位置,方向以及拜访规则(DRUL)确定下一个摆放数据的位置
// dir: 'D', 'R', 'U', 'L' 注:这里有四个边,左下右上,逆时针方向,其中左边的方向是向下,用D来表示,其他依次类推
switch(dir) {
case 'D':
// 先保证row在合法范围内,再考虑该处是否已有数字(是否为0)
if(row < N-1 && M[row+1][col] == 0) {
row ++;
} else {
dir = 'R'; // 下个方向
col ++;
}
break;
// ...
}
#ifndef FILLER_H
#define FILLER_H
struct location { int row, col; };
class filler {
location pos ;
char rule[4];
int idx; // 填充方向 dir = rule[idx]
int row_num, col_num;
int r_min, r_max, c_min, c_max; /// 用于实现旋转方阵
public:
filler(int, int); // range
void reset(); // 重置
void set_rule(const char*); // 用于更换规则
location operator * (); // get current location
filler operator ++ (int); // post ++, next location
};
#endif
#include "filler.h"
#include // strncpy
using namespace std;
filler::filler(int rn, int cn)
: row_num(rn), col_num(cn) { reset(); }
void filler::reset() {
pos.row = pos.col = 0;
idx = 0;
r_min = c_min = 0;
r_max = row_num - 1;
c_max = col_num - 1;
}
void filler::set_rule(const char* r) {
strncpy(rule, r, 4);
}
location filler::operator * () {
return pos;
}
filler filler::operator ++(int) {
filler res = *this;
// 规则可以周而复始地使用,故取模
switch (rule[idx%4]) {
// 以下为旋转方阵的规则,矩阵的大小是在不断变化的
// ESVM: anti-clockwise
case 'E': // 旋转阵比较特殊,用'E'表示向下(与'D'对应)
pos.row++;
if (pos.row == r_max) {
idx++;
c_min++; // 最左列已填充, 故 c_min 加 1
}
break;
// 旋转阵比较特殊,用'S'表示向右(与'R'对应)
case 'S':
pos.col++;
if (pos.col == c_max) {
idx++;
r_max--; // 最下行已填充, 故 r_max 减 1
}
break;
case 'V': // 向上 'U'
pos.row--;
if (pos.row == r_min) {
idx++;
c_max--; // 最右列已填充, 故 c_max 减 1
}
break;
case 'M': // 向左
pos.col--;
if (pos.col == c_min) {
idx++;
r_min++; // 最顶行已填充, 故 r_min 加 1
}
break;
// semv: 顺时针旋转的规则,分别为“s向右、e向下、m向左、v向上”
case 'e': // 向下
pos.row++;
if (pos.row == r_max) {
idx++;
c_max--;
}
break;
case 's': // 向右
pos.col++;
if (pos.col == c_max) {
idx++;
r_min++;
}
break;
case 'v': // 向上
pos.row--;
if (pos.row == r_min) {
idx++;
c_min++;
}
break;
case 'm': // 向左
pos.col--;
if (pos.col == c_min) {
idx++;
r_max--;
}
break;
// 以上是旋转方阵使用的规则(顺时针和逆时针)
// D, R, U, L前进多步,直到边界
case 'D':
pos.row++;
if (pos.row == row_num - 1) idx++;
break;
case 'R':
pos.col++;
if (pos.col == col_num - 1) idx++;
break;
case 'U':
pos.row--;
if (pos.row == 0) idx++;
break;
case 'L':
pos.col--;
if (pos.col == 0) idx++;
break;
// d, u, r, l 只前进一步
case 'd':
pos.row++;
idx++;
break;
case 'r':
pos.col++;
idx++;
break;
case 'u':
pos.row--;
idx++;
break;
case 'l':
pos.col--;
idx++;
break;
// up-right
case 'Z':
pos.row--;
pos.col++;
if (pos.row == 0 || pos.col == col_num - 1) idx++;
if (rule[idx%4] == 'r' && pos.col == col_num - 1) rule[idx%4] = 'd'; // 根据Z型规则, 此处需要变更方向
break;
// down-left
case 'z':
pos.row++;
pos.col--;
if (pos.row == row_num - 1 || pos.col == 0) idx++;
if (rule[idx%4] == 'd' && pos.row == row_num - 1) rule[idx%4] = 'r'; // 根据z型规则, 此处需要变更方向
break;
}
// SWITCH-END
return res;
}
// class filler 的“单元”测试
#ifdef TEST_FILLER
#include
using namespace std;
void test(const char* rule, int rn, int cn) {
filler obj(rn, cn);
obj.set_rule(rule);
for (int i=0; i<rn*cn; i++) {
location pos = *obj++;
cout << '[' << pos.row << ',' << pos.col << ']';
cout << ( (i+1) % cn == 0 ? '\n' : ' ');
}
}
int main() {
int rn, cn;
cout << "Please input row num & col num:";
cin >> rn >> cn;
const char* C2 = "semv"; // clockwise
const char* Z1 = "dZrz"; // Z1
cout << "CLOCKWISE\n";
test(C2, rn, cn);
cout << "Z1\n";
test(Z1, rn, cn);
return 0;
}
#endif
// filler.cpp
#include "matrix.h"
#include "filler.h"
#include
using namespace std;
int main() {
int rn = 9, cn = 9;
filler obj(rn, cn);
obj.set_rule("ESVM"); // anti-clockwise
matrix m(rn, cn);
for (int i=0; i<rn*cn; i++) {
location pos = *obj++;
m(pos.row, pos.col) = i;
}
cout << m;
return 0;
} // fill-matrix.cpp
1 ) 容器,算法,迭代器
class rule {
char* data;
int idx, len;
public:
rule(const char*);
~rule();
char operator* ();
rule& operator++ (); // prefix ++
};
// 规则中的不同字符表示不同的填充(前进)命令
rule::rule(const char* r) {
len = strlen(r);
data = new char[len];
strncpy(data, r, len);
idx = 0;
}
rule::~rule() {
delete data;
}
char rule::operator* () {
return data[idx];
}
rule& rule::operator++ () {
idx = (idx + 1) % len; // 设规则指令是循环使用的 return *this;
}
class filler {
location pos ;
int row_num, col_num;
int r_min, r_max, c_min, c_max;
rule* cmd;
public:
filler(int, int); // range
void reset();
void set_rule(rule*);
location opeator * (); // current location
filler operator ++ (int); // post ++, next location
}
filler filler::operator ++(int) {
filler res = *this;
// *cmd 指向 rule object
switch (**cmd) {
case 'D': /// D, U, R, L 大写字母表示进行多步 pos.row++;
if (pos.row == row_num - 1) ++(*cmd);
break;
// ..... URL类似,略
case 'd': /// d, u, r, l 小写字母表示只前进一步
pos.row++;
++(*cmd);
break;
// ..... url 类似,略
case 'E': // down, anti-clockwise
pos.row++;
if (pos.row == r_max) {
++(*cmd);
c_min++;
}
break;
case 'e': // down, clockwise
pos.row++;
if (pos.row == r_max) {
++(*cmd);
c_max--;
}
break;
// 其他指令字母的处理类似.....略
}
}
2 ) 正则表达式
printf() 函数中的格式串参数
格式符 | 含义 |
---|---|
%d | 按十进制整型数据的实际长度输出 |
%ld | 输出长整型数据 |
%md | 如果数据位数小于 m,则左端补以空格,若大于 m,则按实际位数输出 |
%u | 输出无符号整型(unsigned) |
%c | 用来输出一个字符 |
%f | 用来输出实数,包括单精度和双精度,以小数形式输出。不指定字段宽度 时,由系统自动指定,整数部分全部输出,小数部分输出6位,超过6位的四舍五入 |
%.mf | 输出实数时小数点后保留 m 位 |
%o | 以八进制整数形式输出 |
%s | 用来输出字符串 |
%x,%X | 以十六进制形式输出整数 |
正则表达式工具grep简版
#include
#include
#include
int matchstar(int c, char *regexp, char *text);
int matchhere(char *regexp, char *text);
int match(char *regexp, char *text);
// 函数grep扫描一个文件,对其中的每一行调用 match 函数
int grep(char *regexp, FILE *f, char *name);
int main(int argc, char *argv[]) {
int i, nmatch;
FILE *f;
// 命令行参数 < 2 提示并退出
if (argc < 2) {
printf("argc < 2\n");
return 1;
}
nmatch = 0;
if (argc == 2) {
// 正则表达式存入到 argv[1] 中了,argv[0] 是程序的名字
if (grep(argv[1], stdin, NULL)) nmatch++;
} else {
for (i=2; i<argc; i++) {
f = fopen(argv[i], "r");
if (f == NULL) {
printf("fopen() == NULL\n");
continue;
}
if (grep(argv[1], f, argc > 3 ? argv[i] : NULL) > 0) nmatch++;
fclose(f);
}
}
return nmatch == 0;
}
int grep(char *regexp, FILE *f, char *name) {
int n, nmatch;
char buf[BUFSIZ];
nmatch = 0;
while (fgets(buf, sizeof buf, f) != NULL) {
n = strlen(buf);
if (n > 0 && buf[n-1] == '\n') buf[n-1] = '\0';
if (match(regexp, buf)) {
nmatch++;
if (name != NULL) printf("%s:", name);
printf("%s\n", buf);
}
}
return nmatch;
}
int match(char *regexp, char *text) {
if (regexp[0] == '^') return matchhere(regexp+1, text);
do {
if (matchhere(regexp, text)) return 1;
} while (*text++ != '\0');
return 0;
}
int matchhere(char *regexp, char *text) {
if (regexp[0] == '\0') return 1;
if (regexp[1] == '*') return matchstar(regexp[0], regexp+2, text);
if (regexp[0] == '$' && regexp[1] == '\0') return *text == '\0';
if (*text != '\0' && (regexp[0] == '.' || regexp[0] == *text)) return matchhere(regexp+1, text+1);
return 0;
}
int matchstar(int c, char *regexp, char *text) {
do {
if (matchhere(regexp, text)) return 1;
} while (*text != '\0' && (*text++ == c || c == '.'));
return 0;
}
// 第一个参数是星号的参数(即*之前的那个字符)