一点小问题

关于判断素数的几点

//该函数有严重缺点:

//不能用于n==1和n较大的情况

//在n接近int的最大值时:

//若i=46340时,i*i=2147395600//若i=46341时,i*i=2147488281超过了int的最大值,溢出变成了负数,就会继续进行下去

int is_prime(int n)

{

for (int i = 2; i * i <= n; i++)

{

if (n % i == 0)

return 0;

}

return 1;

}

//编写函数的时候,应该尽量保证该函数能对任何合法参数得到正确的结果

//改进后

//优点:避免了每次重复计算sqrt(n)

//通过四舍五入避免了浮点误差

int is_prime(int n)

{

if (n <= 1)

return 0;

int m = floor(sqrt(n) + 0.5);

for (int i = 2; i<=m; i++)

{

if (n % i == 0)

return 0;

}

return 1;

}

谨慎地使用全局变量

调用栈

调用栈描述的是函数之间的调用关系

由多个栈帧组成,每个栈帧对应着一个未运行完的函数

栈帧中保存了该函数的返回地址和局部变量,因而不仅能在执行完毕后找到正确的返回地址,还能自然地保证了不同函数间的局部变量互不相干——因为不同函数之间对应不同的栈帧

指针易翻

这有一段错误的程序

void swap(int* a, int* b)

{

int* t;

*t = *a;

*a = *b;

*b = *t;

}

这个程序错误的原因是:

指针 t 在使用之前必须赋值

t在赋值之前是不确定的。如果这个不确定的值所代表的内存单元恰好是能写入的,那么这段程序将正常工作;但如果不是,而是只读的,那么程序就会可能崩溃

数组作参数易翻

这有一段错误的程序:

int sum(int a[])

{

int ans = 0;

for (int i = 0; i < sizeof(a); i++)

{

ans += a[i];

}

return ans;

}

错误的原因:

sizeof(a)是无法得到数组的大小的

因为,数组作为参数传递给函数时,实际上只有数组的首地址作为指针传递给了函数。

在函数定义中的int a[]等价于int *a。

在只有地址信息的情况下,是无法知道数组里有多少个元素的

正确的做法:

加一个参数,即数组的元素个数

一般的,若p是指针,k是正整数,那么p+k就是指针p后面的第k个元素,p-k是p前面的第k个元素,而如果p1和p2是类型相同的指针,则p2-p1是从p1到p2的元素个数

那么我们对计算数组和的函数可以用两种写法:

1.

int sum(int* begin, int* end)

{

int n = end - begin;

int ans = 0;

for (int i = 0; i < n; i++)

{

ans += begin[i];

}

return ans;

}

int sum(int* begin, int* end)

{

int* p = begin;

int ans = 0;

for (int* p = begin; p != end; p++)

{

ans += *p;

}

return ans;

}

上述两种写法都是左闭右开

第二种写法更为普遍

把数组作为指针传递给函数时,数组内容是可以修改的。

如果要写一个“返回数组“的函数,可以加一个数组参数,然后在函数中修改这个数组的内容

递归

在C语言的函数中,调用自己和调用其他函数并没有任何本质区别,都是建立新栈帧,传递参数并修改当前代码行。

在函数体执行完毕后,删除栈帧,处理返回值并修改当前代码行。

段错误

编译后产生的可执行文件里都保存着与操作系统相关的内容。

段。是指二进制文件内的区域,所有某种特定类型的信息被保存在里面。

在可执行文件里,正文段用于存储指令

数据段用于存储已初始化的全局变量

BSS段用于存储未赋值的全局变量所需的空间

调用栈不存储在可执行文件中,而是在运行时创建

调用栈所在段称为堆栈段

堆栈段也有自己的大小,不能被越界访问,否则就会出现段错误

栈溢出,那么就是每次递归调用都会往调用栈里增加一个栈帧,久而久之,就越界了。

在运行时,程序会动态创建一个堆栈段,里面存放着调用栈,因此保存着函数的调用关系和局部变量

局部变量也是存放在堆栈段内的。

栈溢出不一定是递归调用太多,也可能是局部变量太大

因此,我们一般把较大的数组存放在main函数外

例题子

例题4-1 古老的密码 UVa1339

//qsort函数的声明

void qsort(void* base, size_t num, size_t size, int (*comparator)(const void*, const void*))

//qsort函数实现的是快速排序算法

//参数说明:

//待排序的数组起始地址

//元素个数

//元素的大小

//一个指向函数的指针,该函数必须具有以下行书

int cmp(const void *,const void *) {...}

//这个函数中,const void *的意思是:

//指向常数的万能的指针,它可以通过强制类型转化变成任意类型的指针

//例如,如果排序的对象是个整型数组,那么:

int cmp(const void* a, const void* b)

{

return *(int*)a - *(int*)b;

}

//一般的,需要先把参数a和参数b转化为真实的类型,然后让cmp函数当ab时分别返回负数,0,和正数即可。

qsort在算法竞赛中不经常使用

经常使用sort函数

这里是为了告诉“将一个函数作为参数传递给另外一个函数”是很有用的

例题4-2 刽子手游戏 UVa489

我们先来考虑,程序设计的方式

一般有两种:

自顶向下和自底向上

算法竞赛中一般是自顶向下

即:

先写伪代码,然后转化为实际的代码

先写主程序,包括对函数的调用,在实现函数本身。

这个题没有什么难点,只是说注意一点就可以

代码的注释我都不想写了

太简单了

#include

#include

#define maxn 100

int left, chance;

char s[maxn], s2[maxn];

int win, lose;

void guess(char ch)

{

int bad = 1;

for (int i = 0; i < strlen(s); i++)

{

if (s[i] == ch)

{

left--;

s[i] = ' ';//字符串序列中有当前猜的字母,则对这个清为空格

bad = 0;

}

}

if (bad)

--chance;

if (!chance)

lose = 1;

if (!left)

win = 1;

}

int main()

{

int rnd;

while (scanf("%d%s%s", &rnd, s, s2) == 3 && rnd != -1)

{

printf("Round %d\n", rnd);

win = lose = 0;

left = strlen(s);

chance = 7;

for (int i = 0; i < strlen(s2); i++)

{

guess(s2[i]);

if (win || lose)

break;

}

if (win)

printf("You win.\n");

else if (lose)

printf("You lose.\n");

else

printf("You chickened out.\n");

}

return 0;

}

例题4-3 救济金发放 UVa133

这个需要注意的地方就是

循环的处理方式

这个算作是约瑟夫环的进阶版

int go(int p, int d, int t)

{

while (t--)

{

do

{

p = (p + d + n - 1) % n + 1; //向前、后走

}while (a[p] == 0);//跳过为0项

}

return p;

}

例题4-4 信息解码 UVa213

书上代码:

#include

#include

int readchar()

{

for (;;)

{

int ch = getchar();

if (ch != '\n' && ch != '\r')

return ch;//一直读到换行符为止

}

}

//readint主要用于读取01序列

int readint(int c)//用于读取c位二进制字符,并转换为十进制数

{

int v = 0;

while (c--)

{

v = v * 2 + readchar() - '0';

}

return v;

}

int code[8][1 << 8];

int readcodes()//用于读取编码,并形成编码序列

{

memset(code, 0, sizeof(code));//对编码序列清零

code[1][0] = readchar();//读取编码头的第一个字符

for (int len = 2; len < 7; len++)//len表示 编码长度,len=2,即表示下面进行对00,01,10的编码对应

{

for (int i = 0; i < (1 << len) - 1; i++)//例如,当len=2时,那么会有三个字符输入,即(1

int ch = getchar();//读字符

if (ch == EOF)//程序结束,整个程序的结束

return 0;

if (ch == '\n' || ch == '\r')//编码头的读取结束

return 1;

code[len][i] = ch;//将字符存入所对应的位置。例如01,就存储长度为2的,第2个位置;10在存入长度为2的,第3个位置

}

}

return 1;

}

int main()

{

while (readcodes())//读取编码头,形成编码序列

{

for (;;)

{

int len = readint(3);//读取三位二进制数,以形成编码长度

if (len == 0)//标志结束,即000

break;

for (;;)

{

int v = readint(len);

if (v == (1 << len) - 1)//标志读到了全1序列,则直接退出。进行下一个长度的读取

break;

putchar(code[len][v]);

}

}

putchar('\n');

}

return 0;

}

习题

习题4-1 UVa1589

习题4-2 UVa201

习题4-3 UVa220

习题4-4 UVa253

习题4-5 UVa1590

习题4-6 UVa508

习题4-7 UVa509

习题4-8 UVa12108

习题4-9 UVa1591

习题4-10 UVa815

习题4-11 UVa1588

习题4-12 UVa11809

约瑟夫环c语言出现段错误,算法竞赛入门经典 紫书 第四章相关推荐

  1. 约瑟夫环c语言代码 指针,约瑟夫环C语言实现源代码(1)

    前天笔试有个约瑟夫环的问题,怪不得人家没通知我面试,原来我的约瑟夫环做的确实有问题,昨天晚上又重新做了下,下面上源代码: /* file:osephu.cpp author:www.5dkx.com ...

  2. 约瑟夫环c语言代码顺序存储,顺序表实现约瑟夫环地问题,C语言.doc

    顺序表实现约瑟夫环地问题,C语言 计算机科学与工程学院 PAGE PAGE 2 <算法与数据结构>试验报告 计算机科学与工程学院 <算法与数据结构>试验报告[一] 专业班级 1 ...

  3. 约瑟夫环c语言计蒜客链表,约瑟夫环的故事 - osc_3n35hvex的个人空间 - OSCHINA - 中文开源技术交流社区...

    usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading. ...

  4. 约瑟夫环c语言程序完整版,C语言:约瑟夫环问题(源代码)

    本帖最后由 geige 于 2015-7-26 00:48 编辑 #include #include struct stu //构建一个新的数据类型 { int num; struct stu *ne ...

  5. 用C语言编写约瑟夫环程序,约瑟夫环C语言,请高手检查我的程序

    /*TC2编译通过*//*测试了几组数据,没有发现问题*//*如果有问题,再M我*/#include typedef struct Cnode {int data; int password; str ...

  6. 约瑟夫环c语言单链表的解题思路,太透彻了:约瑟夫环的三种解法

    [CSDN 编者按]极大概率出现在面试中的约瑟夫环问题来啦,本文三种方法描述解题思路,这样讲解绝对让面试官眼前一亮. 作者 | bigsai 责编 | 欧阳姝黎 前言 约瑟夫环问题是算法中相当经典的一 ...

  7. 约瑟夫环c语言循环指针,约瑟夫环(c语言)(双循环、单循环)

    /*题目: 耶稣又15个门徒,其中有一个时出卖耶稣的叛徒,请用排除法找出这位门徒:15人围坐一圈,从第一个开始报号:1,2,3,1,2,3...凡是报到"3"的退出圈子,最后留在圈 ...

  8. c语言算法竞赛入门经典百度云,《算法竞赛入门经典》CH-2(C语言)

    中国剩余定理,题目要求: 每组数据包含3个非负整数a,b,c,表示队尾人数(a<3, b<5, c<7),输出总人数的最小值(或报告无解).已知总人数不小于10,不超过100.输入到 ...

  9. c语言 如果 n 是素数,且 n+2 也是素数,则称为孪生素数.,算法竞赛入门经典: 第四章 函数与递归 4.3孪生素数...

    /* 孪生素数: 如果n和n+2都是素数,则称他们是孪生素数.输入m,输出两个数均不超过m的最大孪生素数.5<=m<=10000.例如m=20时答案是17,19,m=1000时答案是881 ...

最新文章

  1. 用Leangoo看板工具做办公室采购流程管理
  2. CentOS6 英文系统安装ibus
  3. 网站建设优质内容页面如何打造?
  4. 微信小程序(11)--购物车
  5. flume的概述和运行机制
  6. EXCEL中与数据库打交道的好工具-JXL
  7. 用ASP.NET Core 2.0 建立规范的 REST API -- GET 和 POST
  8. 中对缺失数据的预处理_数据预处理也有套路的
  9. 样本分成训练集和测试集_吴恩达深度学习笔记(64)-开发集和测试集的大小分配...
  10. 在github上实现页面托管预览功能
  11. 2019年春季学期《软件工程》教学总结
  12. Evo使用过程问题汇总
  13. SAP 上线 新旧科目映射 辅助核算
  14. sptd.sys不是病毒?
  15. 【redis集群:2. 集群伸缩】
  16. 理论小知识:集合之scard
  17. 又拍云叶靖:基于Docker的云处理服务平台
  18. IOS 固定定位失效的分析与解决办法
  19. SQL查询学生表中每课大于85分的同学名称
  20. 云呐医疗行业条码固定资产管理系统

热门文章

  1. vue 项目中神策埋点
  2. 【LoadRunner】The above not found error(s) may be explained by header and body byte counts being 0 .
  3. 如何分辨on-policy和off-policy
  4. 【计算机网络】BitTorrent技术对网络的潜在危害
  5. 移动数据和软件更新系统及方法
  6. eureka java_Eureka服务注册入门,服务启动
  7. linux_端口占用扫描port scan(lsof/ss/netstat/Nmap)使用实例
  8. 食亨CEO王泰舟对话新华社:餐饮数字化经营时代已经到来
  9. smartdeblur有手机版吗_SmartDeblur下载-SmartDeblur官方最新版下载[照片处理]-下载之家...
  10. 从零开始构建矽璓工业物联操作系统:使用risc-v架构的hifive1 emulator