以下88案例打包下载地址
案例ex67: 斐波那契数列
1 题目
功能:斐波那契数列 描述:实现一个斐波那契数列,并且打印出来
2 思路
斐波那契数列(Fibonacci sequence),又称黄金分割数列 斐波那契数列以如下被以递推的方法定义:F(0)=0,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*) 即这样的一个序列:这样一个数列:0、1、1、2、3、5、8、13、21、34
3 代码
#include <stdio.h>
#include <stdlib.h>
/**
功能:斐波那契数列
描述:实现一个斐波那契数列,并且打印出来
**/
int main(int argc, char const *argv[]) {
int i; // 定义整型变量i
long f[51]; // 意义数组为长整形
f[1] = 1, f[2] = 1; // 数组中的f[1]、f[2]赋初值为1
for (i = 3; i < 51; i++)
f[i] = f[i - 1] + f[i - 2]; // 数列中从第3项开始每一项等于前两项之和
for (i = 1; i < 51; i++) {
printf("%12ld", f[i]); // 输出数组中的 30 个元素
if (i % 5 == 0)
printf("\n"); // 每 5 个元素进行一次换行
}
}
示例结果:
$ gcc ex067.c -o demo
$ ./demo
1 1 2 3 5
8 13 21 34 55
89 144 233 377 610
987 1597 2584 4181 6765
10946 17711 28657 46368 75025
121393 196418 317811 514229 832040
1346269 2178309 3524578 5702887 9227465
14930352 24157817 39088169 63245986 102334155
165580141 267914296 433494437 701408733 1134903170
1836311903 2971215073 4807526976 7778742049 12586269025
案例ex68: 哥德巴赫猜想
1 题目
功能:哥德巴赫猜想 描述: 任一大于2的整数都可写成两个质数之和 验证从 3 到 50 之间所有数都是否可以写成两个素数之和
2 思路
- 创建判断是否为素数的函数
- 从 3 到 50 循环判断是否可以有 2 个素数加和
3 代码
#include <stdio.h>
#include <stdlib.h>
/**
功能:哥德巴赫猜想
描述:
任一大于2的整数都可写成两个质数之和
验证从 3 到 50 之间所有数都是否可以写成两个素数之和
**/
int ss(int i) { // 素数的判断
int j;
if (i <= 1) // 小于1的数不是素数
return 0;
if (i == 2) // 2是素数
return 1;
for (j = 2; j < i; j++) { // 对大于2的数进行判断
if (i % j == 0)
return 0;
else if (i != j + 1)
continue;
else
return 1;
}
}
int main(int argc, char const *argv[]) {
int i, j, k, flag1, flag2, n = 0;
for (i = 3; i <= 50; i++)
for (k = 2; k <= i / 2; k++) {
j = i - k;
flag1 = ss(k); // 判断拆分出的数是否是素数
if (flag1) {
flag2 = ss(j);
if (flag2) { // 如果拆分出的两个数均是素数则输出
printf("%d = %d+%d,\t", i, k, j);
n++;
if (n % 5 == 0)
printf("\n");
}
}
}
printf("\n");
}
示例结果:
$ gcc ex068.c -o demo
$ ./demo
4 = 2+2, 5 = 2+3, 6 = 3+3, 7 = 2+5, 8 = 3+5,
9 = 2+7, 10 = 3+7, 10 = 5+5, 12 = 5+7, 13 = 2+11,
14 = 3+11, 14 = 7+7, 15 = 2+13, 16 = 3+13, 16 = 5+11,
18 = 5+13, 18 = 7+11, 19 = 2+17, 20 = 3+17, 20 = 7+13,
21 = 2+19, 22 = 3+19, 22 = 5+17, 22 = 11+11, 24 = 5+19,
24 = 7+17, 24 = 11+13, 25 = 2+23, 26 = 3+23, 26 = 7+19,
26 = 13+13, 28 = 5+23, 28 = 11+17, 30 = 7+23, 30 = 11+19,
30 = 13+17, 31 = 2+29, 32 = 3+29, 32 = 13+19, 33 = 2+31,
34 = 3+31, 34 = 5+29, 34 = 11+23, 34 = 17+17, 36 = 5+31,
36 = 7+29, 36 = 13+23, 36 = 17+19, 38 = 7+31, 38 = 19+19,
39 = 2+37, 40 = 3+37, 40 = 11+29, 40 = 17+23, 42 = 5+37,
42 = 11+31, 42 = 13+29, 42 = 19+23, 43 = 2+41, 44 = 3+41,
44 = 7+37, 44 = 13+31, 45 = 2+43, 46 = 3+43, 46 = 5+41,
46 = 17+29, 46 = 23+23, 48 = 5+43, 48 = 7+41, 48 = 11+37,
48 = 17+31, 48 = 19+29, 49 = 2+47, 50 = 3+47, 50 = 7+43,
50 = 13+37, 50 = 19+31,
案例ex69: 尼科彻斯定理
1 题目
功能:尼科彻斯定理
描述: 验证尼科彻斯定理。即:任何一个整数 m 的立方都可以写成 m 个连续奇数之和。m属于[1,100],超出范围则报错。 例如: 1^3=1 2^3=3+5 3^3=7+9+11 4^3=13+15+17+19
2 思路
循环判断实现尼科彻斯定理
3 代码
#include <stdio.h>
#include <stdlib.h>
/**
功能:尼科彻斯定理
描述:
验证尼科彻斯定理。即:任何一个整数 m 的立方都可以写成 m 个连续奇数之和。m属于[1,100],超出范围则报错。
例如:
1^3=1
2^3=3+5
3^3=7+9+11
4^3=13+15+17+19
**/
int main(int argc, char const *argv[]) {
int i, j, k = 0;
int l, n, m, sum, flag=1;
printf("请输入一个数:\n");
scanf("%d", &n); // 从键盘中任意输入一个数
m = n * n * n; // 计算出该数的立方
i = m / 2;
if (i % 2 == 0) // 当i为偶数时i值加1
i = i + 1;
while (flag == 1 && i >= 1) { // 当i大于等于1且flag=1时执行循环体语句
sum = 0;
k = 0;
while (1) {
sum += (i - 2 * k); // 奇数累加求和
k++;
if (sum == m) { // 如果sum与m相等,则输出累加过程
printf("%d*%d*%d=%d=", n, n, n, m);
for (l = 0; l < k - 1; l++)
printf("%d+", i - l * 2);
printf("%d\n", i - (k - 1) *2); // 输出累加求和的最后一个数
flag=0;
break;
}
if (sum > m)
break;
}
i -= 2; // i等于下一个奇数继续上面过程
}
}
示例结果:
$ gcc ex069.c -o demo
$ ./demo
请输入一个数:
12
12*12*12=1728=865+863
案例ex70: 创建单向链表
1 题目
功能:创建单向链表
描述:创建Node结构体,构造一个单链表
2 思路
- 创建结点的结构体,分布由结点值和指针组成
- 循环创建每个结点,使得上一个结点指向下一个结点
3 代码
#include <stdio.h>
#include <stdlib.h>
/**
功能:创建单向链表
描述:创建Node结构体,构造一个单链表
**/
struct LNode {
int data;
struct LNode *next;
};
struct LNode *create_listnode(int n) {
int i;
struct LNode *head, *p1, *p2;
int a;
head = NULL;
printf("输入结点内容:\n");
for (i = n; i > 0; i--) {
p1 = (struct LNode*)malloc(sizeof(struct LNode)); // 分配空间
scanf("%d", &a); // 输入数据
p1->data = a; // 数据域赋值
if (head == NULL) { // 指定头结点
head = p1;
p2 = p1;
}
else {
p2->next = p1; // 指定后继指针
p2 = p1;
}
}
p2->next = NULL;
return head;
}
int main(int argc, char const *argv[]) {
int n;
struct LNode *lnode;
printf("输入要创建单链表的结点个数:");
scanf("%d", &n); // 输入链表结点个数
lnode = create_listnode(n);
printf("结果是:\nhead->");
while (lnode) {
printf("%d -> ", lnode->data); // 输出链表
lnode = lnode->next;
};
printf("\n");
}
示例结果:
$ gcc ex070.c -o demo
$ ./demo
输入要创建单链表的结点个数:5
输入结点内容:
1
2
3
4
5
结果是:
head->1 -> 2 -> 3 -> 4 -> 5 ->
案例ex71: 创建双向链表
1 题目
功能:创建双向链表 描述: a. 创建一个双链表,实现输入链表中的数据,并且可以将链表中的数据进行输出 b. 输入一个结点内容,把这个结点从链表中删除,随后输出链表内容
2 思路
单链表,存储形式只有一个指向直接后继的指针域,所以只能是从头结点顺着指针域指向的下一个结点进行不断的查找 双向链表,一个结点既可以指向前驱也可以指向后继,对于数据查找来说更加的便捷
3 代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/**
功能:创建双向链表
描述:
a. 创建一个双链表,实现输入链表中的数据,并且可以将链表中的数据进行输出
b. 输入一个结点内容,把这个结点从链表中删除,随后输出链表内容
**/
typedef struct node {
char name[20];
struct node *prior, *next;
} stud; // 双链表的结构定义
stud *creat(int n) {
stud *p, *h, *s;
int i;
h = (stud*)malloc(sizeof(stud)); // 申请结点空间
h->name[0] = '\0';
h->prior = NULL;
h->next = NULL;
p = h;
for (i = 0; i < n; i++) {
s = (stud*)malloc(sizeof(stud));
p->next = s; // 指定后继结点
printf("输入第%d个学生的姓名: ", i + 1);
scanf("%s", s->name);
s->prior = p; // 指定前驱结点
s->next = NULL;
p = s;
}
p->next = NULL;
return (h);
}
// 查找
stud *search(stud *h, char *x) {
stud *p; // 指向结构体类型的指针
char *y;
p = h->next;
while (p) {
y = p->name;
if (strcmp(y, x) == 0) // 如果是要删除的节点,则返回地址
return (p);
else
p = p->next;
}
printf("没有找到数据!\n");
return NULL;
}
// 删除
void del(stud *p) {
p->next->prior = p->prior; // p的下一个结点的前驱指针指向p的前驱结点
p->prior->next = p->next; // p的前驱结点的后继指针指向p的后继结点
free(p);
}
int main(int argc, char const *argv[]) {
int number;
char sname[20];
stud *head, *sp;
puts("请输入链表的大小:");
scanf("%d", &number); // 输入链表结点数
head = creat(number); // 创建链表
sp = head->next;
printf("\n现在这个双链表是:\n");
while (sp) { // 输出链表中数据
printf("%s ", &*(sp->name));
sp = sp->next;
}
printf("\n请输入你想查找的姓名:\n");
scanf("%s", sname);
sp = search(head, sname); // 查找指定结点
printf("你想查找的姓名是:%s\n", * &sp->name);
del(sp); // 删除结点
sp = head->next;
printf("\n现在这个双链表是:\n");
while (sp) {
printf("%s ", &*(sp->name)); // 输出当前链表中数据
sp = sp->next;
}
printf("\n");
}
示例结果:
$ gcc ex071.c -o demo
$ ./demo
请输入链表的大小:
5
输入第1个学生的姓名: a
输入第2个学生的姓名: b
输入第3个学生的姓名: c
输入第4个学生的姓名: d
输入第5个学生的姓名: e
现在这个双链表是:
a b c d e
请输入你想查找的姓名:
d
你想查找的姓名是:d
现在这个双链表是:
a b c e
按任意键退出...
案例ex72: 创建一个单循环链表
1 题目
功能:创建一个单循环链表 描述:输入链表中各个结点中的值,然后进行进行整合成单循环链表进行输出
2 思路
一个循环链表是从简单的链表中发展而来,简单链表带来的弊端是,必须要保存头结点才能不断的遍历链表,否则当遍历到 结点尾部的时候,便没办法进行后续的工作。 简单循环链表带来的优势是,当遍历到链表尾部的时候,由于尾部的next指针指向头部,所以是要比简单的单链表灵活一些的
3 代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/**
功能:创建一个单循环链表
描述:输入链表中各个结点中的值,然后进行进行整合成单循环链表进行输出
**/
typedef struct Node {
char num;
struct Node *next;
} LNode, *LinkList;
LinkList create(void) {
LinkList head;
LNode *p1, *p2;
char a;
head = NULL;
a = getchar();
while (a != '#') {
p1 = (LNode*)malloc(sizeof(LNode)); // 分配空间
p1->num = a; // 数据域赋值
if (head == NULL)
head = p1;
else
p2->next = p1;
p2 = p1;
a = getchar();
}
p2->next = head; // 尾节点指向头结点
return head;
}
int main(int argc, char const *argv[]) {
LinkList L1, head;
printf("请输入循环链表:(以 # 结束)\n");
L1 = create(); // 创建循环链表
head = L1;
printf("形成的循环链表是:\n");
printf("%c -> ", L1->num);
L1 = L1->next; // 指向下一个结点
while (L1 != head) { // 判断条件为循环到头结点结束
printf("%c -> ", L1->num);
L1 = L1->next;
}
printf("\n");
}
示例结果:
$ gcc ex072.c -o demo
$ ./demo
请输入循环链表:(以 # 结束)
apple#
形成的循环链表是:
a -> p -> p -> l -> e ->
案例ex73: 头插入法建立单链表
1 题目
功能:头插入法建立单链表 描述:输入链表中各个结点中的值,然后利用头插入法整合成单循环链表进行输出
2 思路
头插法的基本思路是: a. 首先创将一个空的单链表 b. 生成新的结点插入到头部,然后一直循环直到所有的元素结点都插入到链表中 最后,由于是循环向头部插入,那么导致的一个现象就是,从头部开始遍历的时候,一定与形成时元素结点相反
3 代码
#include <stdio.h>
#include <stdlib.h>
/**
功能:头插入法建立单链表
描述:输入链表中各个结点中的值,然后利用头插入法整合成单循环链表进行输出
**/
typedef struct Node {
char num;
struct Node *next;
} LNode, *LinkList;
LinkList create(void) {
LinkList head;
LNode *p1;
char a;
head = NULL;
printf("请输入链表元素(字符采集,不需要分隔符):\n");
a = getchar();
while (a != '\n') {
p1 = (LinkList)malloc(sizeof(LNode)); // 分配空间
p1->num = a; // 数据域赋值
p1->next = head;
head = p1;
a = getchar();
}
return head; // 返回头结点
}
int main(int argc, char const *argv[]) {
LinkList L1;
L1 = create();
printf("这个链表是:\n");
while (L1) {
printf("%c ", L1->num);
L1 = L1->next;
}
printf("\n");
}
示例结果:
$ gcc ex070.c -o demo
$ ./demo
请输入链表元素(字符采集,不需要分隔符):
apple
这个链表是:
e l p p a
案例ex74: 约瑟夫环
1 题目
功能:约瑟夫环 描述:使用循环链表实现约瑟夫环,给定一组结点数据 {1,2,3,4,5,6,7,8,9,10},然后从报数开始,进行打印
2 科普-什么是约瑟夫环
**约瑟夫环 **
约瑟夫问题是个有名的问题:N个人围成一圈,从第一个开始报数,第M个将被杀掉,最后剩下一个,其余人都将被杀掉。例如N=6,M=5,被杀掉的顺序是:5,4,6,2,3。
具体例子:
比如说有一个圈中的数字为 {1, 2, 3, 4, 5, 6, 7, 8, 9, 10},第 3 个被杀掉,即从头开始数到 3 的被杀掉
第 1 轮 3 被杀掉,剩余 {1, 2, 【3】, 4, 5, 6, 7, 8, 9, 10}
第 2 轮 6 被杀掉,剩余 {1, 2, 【3】, 4, 5, 【6】, 7, 8, 9, 10}
第 3 轮 9 被杀掉,剩余 {1, 2, 【3】, 4, 5, 【6】, 7, 8, 【9】, 10}
第 4 轮 2 被杀掉,剩余 {1, 【2】, 【3】, 4, 5, 【6】, 7, 8, 【9】, 10}
第 5 轮 7 被杀掉,剩余 {1, 【2】, 【3】, 4, 5, 【6】, 【7】, 8, 【9】, 10}
第 6 轮 1 被杀掉,剩余 {【1】, 【2】, 【3】, 4, 5, 【6】, 【7】, 8, 【9】, 10}
第 7 轮 8 被杀掉,剩余 {【1】, 【2】, 【3】, 4, 5, 【6】, 【7】, 【8】, 【9】, 10}
第 8 轮 5 被杀掉,剩余 {【1】, 【2】, 【3】, 4, 【5】, 【6】, 【7】, 【8】, 【9】, 10}
第 9 轮 10 被杀掉,剩余 {【1】, 【2】, 【3】, 4, 【5】, 【6】, 【7】, 【8】, 【9】, 【10】}
第 10 轮 4 被杀掉,剩余 {【1】, 【2】, 【3】, 【4】, 【5】, 【6】, 【7】, 【8】, 【9】, 【10】}
3 代码
# include <stdio.h>
# include <stdlib.h>
# define N 10
# define OVERFLOW 0
int KeyW[10] = {1,2,3,4,5,6,7,8,9,10};
/**
功能:约瑟夫环
描述:使用循环链表实现约瑟夫环,给定一组结点数据 {1,2,3,4,5,6,7,8,9,10},然后从报数开始,进行打印
**/
typedef struct LNode {
int keyword;
struct LNode *next;
} LNode,*LinkList;
void Joseph(LinkList p,int m,int x) {
LinkList q; // 声明变量
int i;
if(x == 0)return;
q = p;
m%= x;
if(m == 0) m = x;
for(i = 1; i <= m; i++){ // 找到下一个结点
p = q;
q = p->next;
}
p->next = q->next;
i = q->keyword;
printf("\n出队元素: %d \t",q->keyword);
printf("剩余元素: ");
LinkList tmp = p;
int tmp_x = x;
while(tmp && tmp_x > 1) {
printf("%d -> ", tmp->keyword);
tmp = tmp->next;
tmp_x--;
}
free(q);
Joseph(p, i, x-1); // 递归调用
}
int main(int argc, char const *argv[]) {
int i,m;
LinkList Lhead,p,q;
Lhead = (LinkList)malloc(sizeof(LNode)); // 申请结点空间
if(!Lhead) return OVERFLOW;
Lhead->keyword = KeyW[0]; // 数据域赋值
Lhead->next = NULL;
p = Lhead;
for(i = 1;i<10;i++){ // 创建循环链表
if(!(q = (LinkList)malloc(sizeof(LNode))))return OVERFLOW;
q->keyword = KeyW[i];
p->next = q;
p = q;
}
p->next = Lhead;
printf("请输入第一次计数值m: \n");
scanf("%d", &m);
printf("\n输出的队列结点是:\n");
Joseph(p, m, N);
getchar();
return 1;
}
示例结果:
$ gcc ex074.c -o demo
$ ./demo
请输入第一次计数值m:
3
输出的队列结点是:
出队元素: 3 剩余元素: 2 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 1 ->
出队元素: 6 剩余元素: 5 -> 7 -> 8 -> 9 -> 10 -> 1 -> 2 -> 4 ->
出队元素: 2 剩余元素: 1 -> 4 -> 5 -> 7 -> 8 -> 9 -> 10 ->
出队元素: 5 剩余元素: 4 -> 7 -> 8 -> 9 -> 10 -> 1 ->
出队元素: 1 剩余元素: 10 -> 4 -> 7 -> 8 -> 9 ->
出队元素: 4 剩余元素: 10 -> 7 -> 8 -> 9 ->
出队元素: 10 剩余元素: 9 -> 7 -> 8 ->
出队元素: 7 剩余元素: 9 -> 8 ->
出队元素: 8 剩余元素: 9 ->
出队元素: 9 剩余元素:
案例ex75: 创建顺序表并插入元素
1 题目
功能:创建顺序表并插入元素 描述:创建一个顺序表,插入元素,并且打印出来
2 思路
创建一个链表的结构体,规定了元素最大长度,循环将要插入的元素进行往链表中插入
3 代码
#include <stdio.h>
#include <stdlib.h>
#define Listsize 100
/**
功能:创建顺序表并插入元素
描述:创建一个顺序表,插入元素,并且打印出来
**/
struct sqlist {
int data[Listsize];
int length;
};
void InsertList(struct sqlist *l, int t, int i) {
int j;
if (i < 0 || i > l->length) {
printf("位置错误");
exit(1);
}
if (l->length >= Listsize) { // 如果超出顺序表范围,则溢出
printf("溢出");
exit(1);
}
for (j = l->length - 1; j >= i; j--) // 插入元素
l->data[j + 1] = l->data[j];
l->data[i] = t;
l->length++;
}
int main(int argc, char const *argv[]) {
struct sqlist *sq;
int i, n, t;
sq = (struct sqlist*)malloc(sizeof(struct sqlist)); // 分配空间
sq->length = 0;
printf("请输入链表大小:");
scanf("%d", &n);
printf("请输入链表的元素:\n");
for (i = 0; i < n; i++) {
scanf("%d", &t);
InsertList(sq, t, i); // 插入元素
} printf("这个链表现在是:\n");
for (i = 0; i < sq->length; i++) {
printf("%d ", sq->data[i]);
}
getchar();
}
示例结果:
$ gcc ex075.c -o demo
$ ./demo
请输入链表大小:10
请输入链表的元素:
1 2 3 4 5 6 7 8 9 10
这个链表现在是:
1 2 3 4 5 6 7 8 9 10 %
案例ex76: 合并两个链表
1 题目
功能:合并两个链表 描述:两个链表进行合并,将第二个单链表连接在第一个单链表的尾部
2 思路
通过不断的遍历第一个链表,知道链表尾部,即 L1->next = NULL,之后将 L1->next 指向 L2 的头结点
3 代码
#include <stdio.h>
#include <stdlib.h>
/**
功能:合并两个链表
描述:两个链表进行合并,将第二个单链表连接在第一个单链表的尾部
**/
typedef struct student {
int num;
struct student *next;
} LNode, *LinkList;
LinkList create() {
LinkList head;
LNode *p1, *p2;
char a;
head = NULL;
a = getchar();
while (a != '\n') {
p1 = (LNode*)malloc(sizeof(LNode)); // 分配空间
p1->num = a; // 数据域赋值
if (head == NULL)
head = p1;
else
p2->next = p1;
p2 = p1;
a = getchar();
}
p2->next = NULL;
return head;
}
LinkList coalition(LinkList L1, LinkList L2) {
LNode *temp;
if (L1 == NULL)
return L2;
else {
if (L2 != NULL) {
for (temp = L1; temp->next != NULL; temp = temp->next);
temp->next = L2; // 遍历L1中节点直到尾节点
}
}
return L1;
}
int main(int argc, char const *argv[]) {
LinkList L1, L2, L3;
printf("请输入两个链表:\n");
printf("第一个链表是:\n");
L1 = create(); // 创建一个链表
printf("第二个链表是:\n");
L2 = create(); // 创建第二个链表
coalition(L1, L2); // 连接两个链表
printf("合并后的链表是:\n");
while (L1){ // 输出合并后的链表*
printf("%c", L1->num);
L1 = L1->next;
}
getchar();
}
示例结果:
$ gcc ex076.c -o demo
$ ./demo
请输入两个链表:
第一个链表是:
apple and
第二个链表是:
orage
合并后的链表是:
apple and orage
案例ex77: 单链表节点逆置
1 题目
功能:单链表节点逆置 描述:创建一个单链表,实现将创建好的单链表进行逆置
2 思路
创建两个指向结点的临时指针,一个指向 NULL,另外一个执行头结点,然后不断向后遍历,进行原地链表反转
3 代码
#include <stdio.h>
#include <stdlib.h>
/**
功能:单链表节点逆置
描述:创建一个单链表,实现将创建好的单链表进行逆置
**/
struct Node {
int num;
struct Node *next;
};
struct Node *create(int n) {
int i;
struct Node *head, *p1, *p2;
int a;
head = NULL;
printf("链表元素:\n");
for (i = n; i > 0; --i) {
p1 = (struct Node*)malloc(sizeof(struct Node)); // 分配空间
scanf("%d", &a);
p1->num = a; // 数据域赋值
if (head == NULL) {
head = p1;
p2 = p1;
}
else {
p2->next = p1; // 指定后继指针
p2 = p1;
}
}
p2->next = NULL;
return head; // 返回头结点指针
}
struct Node *reverse(struct Node *head) {
struct Node *p, *r;
if (head->next && head->next->next) {
p = head; // 获取头结点地址
r = p->next;
p->next = NULL;
while (r) {
p = r;
r = r->next;
p->next = head;
head = p;
} return head;
}
return head; // 返回头结点
}
int main(int argc, char const *argv[]) {
int n, i;
int x;
struct Node *q;
printf("输入你想创建的结点个数:");
scanf("%d", &n);
q = create(n); // 创建单链表
q = reverse(q); // 单链表逆置
printf("逆置后的单链表是:\n");
while (q) { // 输出逆置后的单链表
printf("%d ", q->num);
q = q->next;
}
getchar();
}
示例结果:
$ gcc ex077.c -o demo
$ ./demo
输入你想创建的结点个数:5
链表元素:
1
2
3
4
5
逆置后的单链表是:
5 4 3 2 1
案例ex78: 明码序列号保护
1 题目
功能:明码序列号保护 描述:使用明码序列号保护
2 思路
采用明码序列号保护是通过使用序列号对应用程序进行保护的最初级的方法 通过使用序列号对程序进行注册,获取使用程序某些功能的权限 采用明码序列号保护的方式是通过对用户输入的序列号与程序自动生成的合法序列号或内置序列号进行比较,采用这种方式并不是很安全,容易被截获到合法的序列号。
3 代码
#include <stdio.h>
#include <string.h>
/**
功能:明码序列号保护
描述:使用明码序列号保护
**/
int main(int argc, char const *argv[]) {
char *ysn; // 声明字符指针
char *sn;
printf("\nPlease input the serial number:\n"); // 指定合法序列号
sn="1001-1618-2903";
scanf("%s",ysn);
if(!strcmp(ysn,sn)) // 进行序列号比较
printf("register succeed"); // 注册成功
else
printf("register lose"); // 注册失败
exit();
}
示例结果:
$ gcc ex078.c -o demo
$ ./demo
Please input the serial number:
123
register lose
Please input the serial number:
1001-1618-2903
register succeed
案例ex79: 非明码序列号保护
1 题目
功能:非明码序列号保护 描述: 本实例的验证算法是将序列号分为 4 段,每段 5 个字符,每段之间以字符“-”分隔。计算每段所有 ASCI 码的和,如果第一段 ASC 码的和模 6 的值为 1, 第二段 ASC 码的和模 8 的值为 1, 第三段 ASC 码的和模 9 的值为 2, 第四段 ASCⅡ码的和模 3 的值为 0, 那么该序列号视为合法,否则非法。
2 思路
采用菲明码序列号保护的方式验证序列号比采用明码序列号保护的方式安全。因为,非明码序列号保护是通过将输入的序列号进行算法验证实现的,而明码序列号保护是通过将输入的序列号与计算生成的合法序列号进行字符串比较实现的。采用明码序列号保护的程序在注册时会生成合法的序列号,该序列号可以通过内存设断的方式获取。一而采用非明码序列号保护的方式无法通过内在设断的方式获取。
本实例的验证算法是将序列号分为 4 段,每段 5 个字符,每段之间以字符“-”分隔。计算每段所有 ASCI 码的和,如果第一段 ASC 码的和模 6 的值为 1, 第二段 ASC 码的和模 8 的值为 1, 第三段 ASC 码的和模 9 的值为 2, 第四段 ASCⅡ码的和模 3 的值为 0, 那么该序列号视为合法,否则非法。
3 代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
/**
功能:非明码序列号保护
描述:
本实例的验证算法是将序列号分为 4 段,每段 5 个字符,每段之间以字符“-”分隔。计算每段所有 ASCI 码的和,如果第一段 ASC 码的和模 6 的值为 1, 第二段 ASC 码的和模 8 的值为 1, 第三段 ASC 码的和模 9 的值为 2, 第四段 ASCⅡ码的和模 3 的值为 0, 那么该序列号视为合法,否则非法。
**/
int getsn1(char *str) {
int i;
int sum;
sum=0;
for(i=0;i<5;i++) {
sum=sum+toascii(str[i]);
}
printf("%d\n", sum%6);
return sum;
}
int getsn2(char *str) {
int i;
int sum;
sum=0;
for(i=6;i<11;i++) {
sum=sum+toascii(str[i]);
}
printf("%d\n", sum%8);
return sum;
}
int getsn3(char *str) {
int i;
int sum;
sum=0;
for(i=12;i<17;i++) {
sum=sum+toascii(str[i]);
}
printf("%d\n", sum%9);
return sum;
}
int getsn4(char *str) {
int i;
int sum;
sum=0;
for(i=18;i<23;i++) {
sum=sum+toascii(str[i]);
}
printf("%d\n", sum%3);
return sum;
}
int main(int argc, char const *argv[]) {
char str[23];
printf("\nplease input the serial number:\n");
scanf("%s", str);
if(strlen(str)==23 && str[5]=='-' && str[11]=='-' && str[17]=='-') {
if(getsn1(str)%6==1 && getsn2(str)%8==1 && getsn3(str)%9==2 && getsn4(str)%3==0) {
printf("%s\n", "register succeed");
return 0;
} else{
printf("%s\n", "register Lose");
return -1;
}
} else {
printf("%s\n", "register Lose");
return -1;
}
}
示例结果:
$ gcc ex070.c -o demo
$ ./demo
please input the serial number:
11113-22221-33332-11112
register succeed
$ ./demo
please input the serial number:
11113-22221-33332-11111
register Lose
案例ex80: 恺撒加密
1 题目
功能:恺撒加密 描述:利用凯撒密码进行加密
2 凯撒密码
维基百科对凯撒密码的解释:zh.wikipedia.org/wiki/%E5%87…
凯撒密码是一种替换加密技术,明文中的所有字母都在字母表上向后(或向前)按照一个固定数目进行偏移后被替换成密文。例如,当偏移量是3的时候,所有的字母A将被替换成D,B变成E,以此类推
例如,当偏移量是左移3的时候(解密时的密钥就是3):
明文字母表:ABCDEFGHIJKLMNOPQRSTUVWXYZ
密文字母表:DEFGHIJKLMNOPQRSTUVWXYZABC
3 代码
# include <stdio.h>
# include <string.h>
/**
功能:恺撒加密
描述:利用凯撒密码进行加密
**/
void encode(char str[], int n) {
char c;
int i;
for (i = 0; i < strlen(str); i++) {
c = str[i];
if (c >= 'a' && c <= 'z')
if (c + n % 26 <= 'z')
str[i] = (char)(c + n % 26);
else
str[i] = (char)('a' + ((n - ('z' - c) - 1) % 26));
else if (c >= 'A' && c <= 'Z')
if (c + n % 26 <= 'Z')
str[i] = (char)(c + n % 26);
else
str[i] = (char)('A' + ((n - ('Z' - c) - 1) % 26));
else
str[i] = c;
}
printf("\nout:");
puts(str);
}
void decode(char str[], int n) {
char c;
int i;
for (i = 0; i < strlen(str); i++) {
c = str[i];
if (c >= 'a' && c <= 'z')
if (c - n % 26 >= 'a')
str[i] = (char)(c - n % 26);
else
str[i] = (char)('z' - (n - (c - 'a') - 1) % 26);
else if (c >= 'A' && c <= 'Z')
if (c - n % 26 >= 'A')
str[i] = (char)(c - n % 26);
else
str[i] = (char)('Z' - (n - (c - 'A') - 1) % 26);
else
str[i] = c;
}
printf("\nout:");
puts(str);
}
int main(int argc, char const *argv[]) {
void encode(char str[], int n);
void decode(char str[], int n);
//char str[]="abcdef";
char str[20];
int k = 0, n = 0, i = 1;
printf("\nPlease input strings:");
scanf("%s", str);
printf("\n1:Encryption");
printf("\n2:Decryption");
printf("\n3:Violent Crack");
printf("\nPlease choose:");
scanf("%d", &k);
if (k == 1) {
printf("\nPlease input number:");
scanf("\n%d", &n);
encode(str, n);
}
else if (k == 2) {
printf("\nPlease input number:");
scanf("%d", &n);
decode(str, n);
}
else if (k == 3) {
for (i = 1; i <= 25; i++) {
printf("%d ", i);
decode(str, 1);
}
}
}
示例结果:
$ gcc ex080.c -o demo
$ ./demo
Please input strings:python
1:Encryption
2:Decryption
3:Violent Crack
Please choose:1
Please input number:1
out:qzuipo
该例子中有以下三种选择,结合上述对于凯撒密码的原理,试着进行理解
- Encryption
- Decryption
- Violent Crack
案例ex81: 编写循环移位函数
1 题目
功能:编写循环移位函数 描述:编写个移位函数,使移位函数既能循环左移又能循环右移。参数 n 大于 0 时表示左移,参数 n 小于 0 时表示右移。例如 n=-4, 表示要右移四位
2 思路
利用 << 或者 >> 进行移位计算
3 代码
#include <stdio.h>
#include <stdlib.h>
/**
功能:编写循环移位函数
描述:编写个移位函数,使移位函数既能循环左移又能循环右移。参数 n 大于 0 时表示左移,参数 n 小于 0 时表示右移。例如 n=-4, 表示要右移四位
**/
unsigned move(unsigned value, int n) { // 自定义移位函数
unsigned z;
if(n>0) {
z = (value >> (32-n)) | (value << n); // 循环左移的实现过程
}
else {
n=-n;
z = (value << (32-n)) | (value >> n); // 循环右移的实现过程
}
return z;
}
int main(int argc, char const *argv[]) {
unsigned a;
int n;
printf("请输入一个八进制数:\n");
scanf("%o", &a); // 输入一个八进制数
printf("请输入要移位的位数:\n");
scanf("%d", &n); // 输入要移位的位数
printf("移位后的结果是:%o\n", move(a, n)); // 将移位后的结果输出
}
示例结果:
请输入一个八进制数:
12
请输入要移位的位数:
1
移位后的结果是:24
案例ex82: 取出给定 16 位二进制数的奇数位
1 题目
功能:取出给定 16 位二进制数的奇数位 描述:取出给定的 16 位二进制数的奇数位,计算后打印出来
2 思路
本例的解题关键在于如何将给定的 16 位二进制数的奇数位取出。首先定义个可以借助的中间变量 m,为其赋值,使箕成为最高位是1、其余 15 位为 0 的 16 位进制数
将给定的数 a 的值左移一位,让其原来值的第 15 位成为最高位,将 a 和 m 进行与运算进行判断,若运算结果是 1, 则将此位取出转换为对应的十进制数:若运算结果是 0, 则将 a 的值左移两位,使其原来值的第 13 位成为最高位,再进行判断,直到将 8 位奇数位全部取出
3 代码
#include <stdio.h>
#include <stdlib.h>
/**
功能:取出给定 16 位二进制数的奇数位
描述:取出给定的 16 位二进制数的奇数位,计算后打印出来
**/
int main(int argc, char const *argv[]) {
unsigned short a,s=0,q;
int i,j,n=7,m;
printf("请输入一个八进制数:\n");
scanf("%ho", &a); // 输入一个八进制数
m=1<<15; // m 的最高位为 1,其他位为 0
a<<=1; // 左移一位,使第15位成为最高位
for(i=1;i<=8;i++) { // 得到 8 位数
q=1;
if(m & a) { // 如果本位上值为1则进行计算
for(j=1;j<=n;j++)
q*=2; // 得到权值
s+=q; // 累加
}
a<<=2; // 向左移位
n--;
}
printf("结果是:%o\n", s); // 将结果输出
}
示例结果:
$ gcc ex082.c -o demo
$ ./demo
请输入一个八进制数:
013
结果是:1
案例ex83: 求一个数的补码
1 题目
功能:求一个数的补码 描述:输入一个八进制数,然后输出它的补码
2 思路
一个正数的补码等于该数原码,一个负数的补码等于该数的反码加 1。 本例的关键是如何判断一个数是正数还是负数。当最高位为 1 时,则该数是负数;当最高位为 0 时,则该数是正数。 因此,数据 a 和八进制数据 010000 进行与运算,保留最高位得到数据的正负
3 代码
#include <stdio.h>
#include <stdlib.h>
/**
功能:求一个数的补码
描述:输入一个八进制数,然后输出它的补码
**/
int main(int argc, char const *argv[]) {
unsigned short a,z;
printf("请输入一个八进制数:\n");
scanf("%ho", &a); // 输入一个八进制数
z=a & 0100000; // 0100000的二进制形式为最高位为1,其余为0
if(z==0100000) // 如果a小于0
z=~a+1; // 取反加1
else
z=a;
printf("结果是: %o\n", z); // 将结果输出
}
示例结果:
$ gcc ex083.c -o demo
$ ./demo
请输入一个八进制数:
115333
结果是: 62445
案例ex84: 普通的位运算
1 题目
功能:普通的位运算 描述: 求下面各个位运算的值 a&c b|d a^d ~a
2 思路
运算符 | 含义 | 示例 | 举例 |
---|---|---|---|
& | 位AND | x&y | 如果x和y都为1,则得到1;如果x或y任何一个为0,或都为0,则得到0 |
| | 位OR | x|y | 如果x或y为1,或都为1,则得到1;如果x和y都为0,则得到0 |
位XOR | x^y | 如果x或y的值不同,则得到1;如果两个值相同,则得到0 | |
~ | 位NOT(I的补码) | ~x | 如果x为0,则得到1,如果x是1,则得到0 |
3 代码
#include <stdio.h>
#include <stdlib.h>
/**
功能:普通的位运算
描述:
求下面各个位运算的值
a&c
b|d
a^d
~a
**/
int main(int argc, char const *argv[]) {
unsigned result;
int a, b, c, d;
a = 2;
b = 4;
c = 6;
d = 8;
printf("a=%d,b=%d,c=%d,d=%d", a, b, c, d); // 输出变量a、b、c、d四个数的值
result = a &c; // a与c的结果赋给result
printf("\na&c=%u\n", result); // 将结果输出
result = b | d; // b|d的结果赋给result
printf("b|d=%u\n", result); // 将结果输出
result = a ^ d; // a^d的结果赋给result
printf("a^d=%u\n", result); // 将结果输出
result = ~a; // ~a的结果赋给result
printf("~a=%u\n", result); // 将结果输出
}
示例结果:
$ gcc ex084.c -o demo
$ ./demo
a=2,b=4,c=6,d=8
a&c=2
b|d=12
a^d=10
~a=4294967293
案例ex85: 整数与 0 异或
1 题目
功能:整数与 0 异或
描述:计算输入整数与 0 异或
2 思路
异或:相同为 1,不同为 0
运算符 | 含义 | 示例 | 举例 |
---|---|---|---|
^ | 位 XOR | x^y | 如果 x 或 y 的值不同,则得到 1;如果两个值相同,则得到 0 |
3 代码
#include <stdio.h>
#include <stdlib.h>
/**
功能:整数与 0 异或
描述:计算输入整数与 0 异或
**/
int main(int argc, char const *argv[]) {
unsigned result; // 定义无符号数
int a, b;
printf("请输入a:");
scanf("%d",&a);
b=0; // 与0异或
printf("a=%d,b=%d", a, b);
result = a^b; // 求整数与0异或的结果
printf("\na^b=%u\n", result);
}
示例结果:
$ gcc ex085.c -o demo
$ ./demo
请输入a:10
a=10,b=0
a^b=10
案例ex86: 打印杨辉三角
1 题目
功能:打印杨辉三角
描述:打印给定行数的杨辉三角
2 思路
杨辉三角形
又称帕斯卡三角形、贾宪三角形、海亚姆三角形、巴斯卡三角形,是二项式系数的一种写法,形似三角形,在中国首现于南宋杨辉的《详解九章算法》得名,书中杨辉说明是引自贾宪的《释锁算书》,故又名贾宪三角形。
最基本的几个性质 每个数等于它上方两数之和 每行数字左右对称,由1开始逐渐变大 第n行的数字有n项 前n行共[(1+n)n]/2 个数
举例
打印出前 9 行的数字
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
3 代码
#include <stdio.h>
#define N 15
/**
功能:打印杨辉三角
描述:打印给定行数的杨辉三角
**/
int main(int argc, char const *argv[]) {
int i, j, k, n, a[N][N];
while(1) {
printf("请输入要打印的行数[范围在1~15之间]:"); // 控制在 15 行之内
scanf("%d",&n);
if (n>=1 && n<=15){
break;
} else {
printf("输入的行数不在规定范围内!\n");
continue;
}
}
printf("%d行杨辉三角打印如下:\n",n);
for(i=1; i<=n; i++)
a[i][1] = a[i][i] = 1;
for(i=3; i<=n; i++)
for(j=2; j<=i-1; j++)
a[i][j]=a[i-1][j-1]+a[i-1][j];
for(i=1; i<=n; i++){
for(k=1; k<=n-i; k++)
printf(" ");
for(j=1; j<=i; j++)
printf("%6d",a[i][j]);
printf("\n");
}
printf("\n");
}
示例结果:
请输入要打印的行数[范围在1~15之间]:20
输入的行数不在规定范围内!
请输入要打印的行数[范围在1~15之间]:30
输入的行数不在规定范围内!
请输入要打印的行数[范围在1~15之间]:10
10行杨辉三角打印如下:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1
案例ex87: 循环显示随机数
1 题目
功能:循环显示随机数 描述:随机产出 10 个随机数
2 思路
在产出随机数的时候,需要将设置随机发生的种子 srand(n); 随后才能进行产出不同的随机数
3 代码
#include <stdio.h>
#include <stdlib.h>
/**
功能:循环显示随机数
描述:随机产出 10 个随机数
**/
int main(int argc, char const *argv[]) {
int i;
int rd; // 随机发生数
for (i = 0; i < 10; i++) {
// 随机发生数的种子
srand(i+5);
// 产出随机发生数
rd = rand();
printf("种子 %d 产出的随机数为%d\n", i+5, rd);
}
}
示例结果:
$ gcc ex087.c -o demo
$ ./demo
种子 5 产出的随机数为84035
种子 6 产出的随机数为100842
种子 7 产出的随机数为117649
种子 8 产出的随机数为134456
种子 9 产出的随机数为151263
种子 10 产出的随机数为168070
种子 11 产出的随机数为184877
种子 12 产出的随机数为201684
种子 13 产出的随机数为218491
种子 14 产出的随机数为235298
案例ex88: 阿姆斯特朗数
1 题目
功能:阿姆斯特朗数
描述:打印从100到999之间所有的阿姆斯特朗数
2 思路
阿姆斯特朗数
如果一个n位正整数等于其各位数字的n次方之和,则称该数为阿姆斯特朗数。 例如1^3 + 5^3 + 3^3 = 153
水仙花数
当n=3时,又称水仙花数,特指一种三位数,其各个数之立方和等于该数。 水仙花数共有4个,分别为:153、370、371、407
3 代码
#include <stdio.h>
#include <stdlib.h>
/**
功能:阿姆斯特朗数
描述:打印从1到10000之间所有的阿姆斯特朗数
**/
int main(int argc, char const *argv[]) {
int i, j, k, n;
for (i = 1; i < 10000; i++) { // 遍历从 1 到 10000 的阿姆斯特朗数
j = i % 10; // 分离出个位上的数
k = i / 10 % 10; // 分离出十位上的数
n = i / 100; // 分离出百位上的数
if (j *j * j + k * k * k + n * n * n == i) // 进行判断各位上的立方和是否等于遍历数本身
printf("%5d", i);
}
printf("\n");
}
示例结果:
$ gcc ex088.c -o demo
$ ./demo
1^3 + 5^3 + 3^3 = 153
3^3 + 7^3 + 0^3 = 370
3^3 + 7^3 + 1^3 = 371
4^3 + 0^3 + 7^3 = 407
最后
在这里给大家准备了几百本的互联网技术类书籍,需要的来下载吧!mp.weixin.qq.com/s/KAYLiHFc5… 有任何问题,欢迎随时交流