Guo Qiang

常用代码示例 (C/C++ & Shell)

Common code examples
image
当你有兴趣去做一件事情,它将变得不再枯燥

这里将会记录一些实用性比较强的代码片段,主要以 c/c++ 语言和 shell 脚本为主,只要对我有帮助的代码,我都会尽可能的保留下来,这样也方便查询和学习。

蛇形填数问题

在 n*n 的方阵里填入 1,2,...,n*n,要求填成蛇形。


#include <stdio.h>

#define MAX 10

int a[MAX][MAX] = {0};

int main()
{
	int i, j, n = 0;
	n = a[i = 0][j = MAX - 1] = 1;

	while (n < MAX * MAX) {
		while (i+1<MAX && !a[i+1][j]) a[++i][j] = ++n;
		while (j-1>=0 && !a[i][j-1])  a[i][--j] = ++n;
		while (i-1>=0 && !a[i-1][j])  a[--i][j] = ++n;
		while (j+1<MAX && !a[i][j+1]) a[i][++j] = ++n;
	}

	for (i = 0; i < MAX; i++) {
		for (j = 0; j < MAX; j++)
			printf("%4d", a[i][j]);
		printf("\n");
	}

	return 0;
}


身份证号校验码的验证

身份证号码18位数字,按从左到右数1-6位表示出生地编码,7-10位出生年份,11、12位出生月份,13、14位出生日期,15、16位出生顺序编号,17位性别标号,18位效验码。此算法只实现对第18位校验码的验证。


/*
设计函数检查身份证号校验码的正确性,该函数的原型和输入/出分别为:
int id_verifer(char id[]);
输入:表示身份证号的字符串;
输出:1--正确,0--错误

注:
18位身份证号码中的最后一位是校验码,它根据前面17位数字自动生成,校验码计算过程为:先求17位数的加权和S,然后求S对11的模,根据求模结果得到对应的校验码,主要公式及数据如下:

(1)十七位数字本体码加权求和公式
S = Sum(Ai * Wi),  i = 0, ... , 16,先对前17位数字的权求和
其中,Ai:表示第i位置上的身份证号码数字值,Wi:表示第i位置上的加权因子:
Wi:  7  9  10  5  8  4  2  1  6  3  7  9  10  5  8  4  2

(2)计算模
Y = mod (S, 11)

(3)通过模得到对应的校验码
Y:  0  1  2  3  4  5  6  7  8  9  10
校验码:   1   0   X   9   8   7   6   5   4   3   2
*/

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

int id_verifer(char id[])
{
	int w[17] = {7, 9 ,10 ,5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
	char check[17] = {'1','0','X','9','8','7','6','5','4','3','2'};

	int sum = 0;
	for (int i = 0; i < 17; i++)
		sum += (id[i] - '0') * w[i];

	int y = sum % 11;

	return (check[y] == id[17]);
}

int main()
{
	char id[19];

	printf("ID:");
	scanf("%s",id);

	if (id_verifer(id) == 1)
		printf("OK\n");
	else
		printf("ERROR\n");

	return 0;
}


const char*, char const*, char* const的区别


/* ------------------------------
  一共3种写法:
  1、const char*
  2、char const*
  3、char* const

  第1种和第2种其实是一样的,只是写法不同而已,const 作用的是 char* ,
  也就是指针所指的内容为常量,但指针是可变的。

  第3种 const 作用的是指针,指针为常量,不可变,而指针所指的内容是可变的。
------------------------------ */

int main()
{
	char p[] = "point";
	char const *p1 = "abc";
	p1++;

	const char *p2 = "123";
	p2++;

	char *const p3 = p;
	p3[2] = 'I';

	printf("p1=%s\n", p1);
	printf("p2=%s\n", p2);
	printf("p3=%s\n", p3);

	return 0;
}


迷宫问题 JavaKarel

Java Karel 机器人的模拟迷宫算法,短小精悍,值得借鉴。


import stanford.karel.*;
public class MazeKarel extends SuperKarel {
	public void run() {
		while(noBeepersPresent()) {
			if(leftIsClear())
				turnLeft();
			else
				while(frontIsBlocked())
					turnRight();
			move();
		}

		pickBeeper();
	}
}


汉诺塔问题

汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从上往下从小到大顺序摞着64片黄金圆盘。上帝命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一回只能移动一个圆盘,只能移动在最顶端的圆盘。有预言说,这件事完成时宇宙会在一瞬间闪电式毁灭,也有人相信婆罗门至今仍在一刻不停地搬动着圆盘。


/* 这里代表将a柱子上的盘子借助b柱子移动到c柱子 */
void hanoi(int n, char a, char b, char c)
{
	/* 如果是一个盘子直接将a柱子上的盘子移动到c */
	if (n == 1)
		printf("%c-->%c\n", a, c);
	else
	{
		/* 将a柱子上n-1个盘子借助c柱子,移动到b柱子 */
		hanoi(n - 1, a, c, b);

		/* 再直接将a柱子上的最后一个盘子移动到c */
		printf("%c-->%c\n", a, c);

		/* 然后将b柱子上的n-1个盘子借助a移动到c */
		hanoi(n - 1, b, a, c);
	}
}


正整数反转

递归在编程中使用非常广泛,它能使代码的逻辑变得清晰,且代码也很精简,只是一定要记住要有一个出口,否则就无限递归下去,直至系统崩溃。


void reverse(int n)
{
	if (!n) {
		printf("\n");
		return;
	}

	printf("%d", n % 10);
	reverse(n / 10);
}