算法竞赛入门经典算法实现pdf,算法竞赛基础

  算法竞赛入门经典算法实现pdf,算法竞赛基础

  目录

  第三章数组与字符串3.1数组程序3-1逆序输出示例3-1开灯。程序3-2开灯问题,逆序输出。例3-2蛇形数字填充。程序3-3蛇填充

  3.2字符数组例题3-3竖排问题。程序3-4竖排问题3.3最长回文子串示例3-4回文子串。程序3-5最长回文子串(1)程序3-6最长回文子串(2) 3.4总结和练习3.4.1必要的存储3.4.2用ASCII编码表示字符3.4.3补码表示法3.4.4库函数的重新实现3.4.5字符串处理常见问题实验1:添加字符串S的声明语句,无长度提示:在主函数内部还是外部?实验二:添加一条阅读语句,测试上面的程序是否输出了想要的结果。如果没有,请改正。实验三:注释掉输入的语句,添加语句,用程序生成长度至少为105的字符串,用程序验证字符串长度不小于105。实验四:用带计时功能的字符串的长度来检验这个程序运行时间的规律。如何改善?3.4.6关于I/O 1.getchar函数2.sscanf函数3.4.7 I/O效率3.4.8总结3.4.9练习3-1分数统计(stat)任务1:分数均为不超过100的非负整数。任务二:分数都是不超过100的非负实数,最多保留两位小数。练习3-2单词的长度(word)练习3-3乘积的最后3位数字练习3-4计算器练习3-5旋转练习3-6二进制转换1(base1)练习3-7二进制转换2(base2)练习3-8手机键盘

  第3章数组和字符串[与学习内容相关的章节]

  3.1数组3.2字符数组3.3最长回文子串3.4小结和练习

  [学习目标]

  (1)掌握一维数组的声明和用法;

  (2)掌握二维数组的声明和用法;

  (3)掌握字符串的声明、赋值、比较和连接方法;

  (4)熟悉ASCII码和ctype.h的人物;

  (5)正确理解可以修改变量的运算符,如=;

  (6)学会编译option -Wall,获取更多的预警信息;

  (7)掌握fgetc和getchar的用法;

  (8)了解换行在不同操作系统中的表示方式;

  (9)掌握fgets的用法,了解gets的“缓冲区溢出”漏洞;

  (10)了解预处理和迭代开发的技巧。

  [学习要求]

  (1)掌握一维数组和二维数组的声明和用法;

  (2)掌握字符串的语句及相关操作;

  (3)掌握fgetc和getchar的用法;

  (3)掌握fgets和gets的用法。

  [学习总结]

  通过第二章的学习,我们了解到了计算机的计算优势,但是没有充分发挥计算机的存储优势。只使用了少数几个变量。有些程序虽然也处理大量数据,但这些数据只是“过客”,只参与计算,不保存。

  本章介绍了数组和字符串,两者都可以存储大量的数据。字符串是数组(字符数组),但由于其特殊的应用,适合一些特殊的处理方法。

  【学习的重点和难点】

  学习重点:

  (1)掌握一维数组和二维数组的声明和用法;

  (2)掌握字符串的语句及相关操作;

  (3)掌握fgetc和getchar的用法;

  (3)掌握fgets和gets的用法。

  学习困难:

  (1)掌握一维数组和二维数组的声明和用法;

  (2)掌握字符串的语句、相关操作和字符串处理函数的使用。

  [课时表(共5小时)]

  3.1数组3.2字符数组3.3最长回文子串

  3.4小结和练习(1课时)

  3.1几个组

  根据下面的问题,解释为什么使用数组。

  问题:读入一些整数,逆序一行输出。已知不超过100个整数。

  [分析]

  首先,通过循环读取100个整数的输入,然后将每个数字存储在一个数组中,最后输出。

  程序3-1输出#以相反顺序包含

  #定义MAXN 100 10

  int a[MAXN];

  int main() {

  int i,x,n=0;

  while (scanf(%d ,x)==1)

  a[n]=x;

  for(I=n-1;我我-)

  printf(%d ,a[I]);

  printf(%d\n ,a[0]);

  返回0;

  }描述:

  语句int a[100]声明一个包含100个整型变量的数组,分别是:a[0],a[1],a[2],…,a[99]。注意没有a[100]。

  3-1:语句int a[MAXN]声明了一个包含MAXN个整数变量的数组,即a[0],a[1],a[2],…,a[MAXN-1],但不包含a[MAXN]。MAXN必须是常数,而不是变量。

  在这个过程中,MAXN被声明为100 ^ 10而不是100,主要是为了安全起见。

  技巧3-2:在算法竞赛中,往往很难精确计算出所需的数组大小,数组通常被声明为略大。在空间充足的前提下,浪费一点没关系。

  语句a[n]=x;相当于两个语句a[n]=x;n;循环结束后,数据分别存储在a[0],a[1],…,a[n-1]中,其中变量的个数为N个整数。

  将整数存入数组后,依次输出a[n-1],a[n],…,a[1]和a[0]。一般要求输出行的开头和结尾没有空格,相邻的两个数据用一个空格隔开。总共需要输出N个整数,但是只有n-1个空格,所以我们要分两个语句输出。

  在上面的程序中,数组A是在main函数外部声明的。简单来说,数组A只有放在外面才能开得很大;放在main函数中,数组稍微大一点就会异常退出。

  技巧3-3:更大的数组应该尽可能在main函数之外声明。

  C语言数组的使用有一些特殊情况。例如,数组不能赋值,也就是说,不能将整个数组赋值给另一个数组。如果你把从数组A到K的元素复制到数组B,你可以使用这个语句:

  memcpy(b,a,sizeof(int)k).如果数组A和B都是浮点型的,应该写成memcpy(b,A,

  sizeof(double k).还需要注意的是,在使用memcpy函数时应该包含头文件string.h。如果需要将数组A全部复制到数组B中,可以写成:memcpy(b,A,sizeof(a))。

  注意:memcpy函数原型如下:

  void *memcpy(void *dest,void *src,unsigned int count);

  其功能是将计数字节从src指示的存储区复制到dest指示的存储区。src和dest指示的内存区域不能重叠,函数返回一个指向dest的指针。主要功能是复制字符串,也可以对数组进行操作。头文件:#include string.h应该包含在程序中。

  例3-1开灯。灯有n个,编号从1到n,第一个人打开所有的灯,第二个人按下所有编号为2的倍数的开关(这些灯会熄灭),第三个人按下所有编号为3的倍数的开关(熄灭的灯点亮,点亮的灯熄灭),以此类推。总共有k个人。最后亮着什么灯?

  输入:n和k,输出亮着的灯的数量。kn1000 .

  样本输入:7 3

  样本输出:1 5 6 7

  [分析]

  用a[1],a[2],…,a[n]表示编号为1,2,3,…,n的灯是否亮。只是模拟这些操作。

  代码如下:

  程序3-2开机问题#的反向输出包括

  #包括

  #定义MAXN 1000 10

  int a[MAXN];/*一维数组存储N个电灯*/

  int main() {

  int i,j,n,k,first=1;

  memset(a,0,sizeof(a));/*初始化灯光状态*/

  scanf(%d%d ,n,

  /*模拟活动过程*/

  for(I=1;I)/*第I个人参加活动*/

  for(j=1;J)/*操作第I个灯*/

  if (j % i==0) a[j]=!a[j];

  /*输出活动结果*/

  for(I=1;我我)

  if (a[i]) {

  if(first)first=0;

  else printf( );

  printf(%d ,I);

  }

  printf( \ n );

  返回0;

  }描述:(1)memset(a,0,sizeof(a))用于清空数组A,数组A也是在string.h中定义的,memset比for循环更方便快捷。

  Memset函数原型如下:

  void *memset(void *buffer,char c,int count);

  它的作用是将buffer指向的内存区域的第一个count字节设置为字符C,第三个参数是指字节数,返回一个指向buffer的指针。头文件:#include string.h应该包含在程序中。从memset函数的头文件可以知道,它主要是设置字符数组,当然也可以对数组进行初始赋值(一般是0,-1)。

  (2)一招输出:为了避免输出多余的空格,设置了一个标志变量first,可以表示当前要输出的变量是否为第一个。第一个变量前不应该有空格,其他都是。

  例3-2蛇形填充。在nn方阵中填入1,2,…,NN,要求填入一个蛇形。例如,当n=4时,方阵为

  10 11 12 1

  9 16 13 2

  8 15 14 3

  7 6 5 4

  上面的方阵中,多出来的空格只是为了方便遵守规则,没必要严格输出。n8 .

  [分析]

  相对于数学中的矩,可以用一个所谓的二维数组来存储题目中的方阵。只要声明一个int a[MAXN][MAXN],就可以得到一个大小为MAXNMAXN的方阵。在声明的时候,两个维度不一定要一样大。

  技巧3-4:用int a[MAXN][MAXN]生成一个二维整数数组,其中MAXN和MAXN不必相等。这个数组中有MAXNMAXN个元素,分别是A [0] [0],A [0] [1],…,A [0] [maxn-1],A [1] [0]

  ,a[1][1],…,a[1][MAXN-1],…,a[MAXN-1][0],a[MAXN-1][1],…,a[MAXN-1][MAXN-1].

  假设你从1开始,依次填写这个写法。设“笔”的坐标为(x,y),那么首先x=0,y=n-1,即第0行,第n-1列(注意行列的范围是0 ~ n-1,没有第n列)。笔的运动轨迹是:下,下,左,左,上,上,右,右,下,下,左,上。一句话,先是往下,直到填不完,然后向左,再往上,最后向右。“不能填”是指出界(如45)或去之前填好的格子(如1213)。如果所有格式都初始化为0,就很容易判断了。

  程序3-3蛇形填充#包括

  #包括

  #定义最大数量10

  int a[MAXN][MAXN];

  int main() {

  int n,x,y,tot=0;

  scanf(%d ,

  memset(a,0,sizeof(a));

  tot=a[x=0][y=n-1]=1;

  while (tot n * n) {

  while (x 1 n!a[x ^ 1][y])a[x][y]=tot;/*下去*/

  while (y - 1=0!a[x][y-1])a[x][-y]=tot;/*向左*/

  while (x - 1=0!a[x-1][y])a[-x][y]=tot;/*向上*/

  while (y 1 n!a[x][y ^ 1])a[x][y]=tot;/*向右走*/

  }

  for(x=0;x x ) {

  for(y=0;y y ) printf(=,a[x][y]);

  printf( \ n );

  }

  返回0;

  }描述:这个程序利用了C语言的简单性。首先,赋值x=0,y=n-1作为数组A的下标可以组合。Tot和a[0][n-1]都应该被赋值为1,或者它们可以被组合。您可以用一条语句完成许多事情,而不会牺牲程序的可读性。

  技巧3-5:你可以利用C语言简洁的语法,但前提是代码是可读的。

  技巧3-6:很多情况下,最好在做某件事之前先检查一下这件事能不能做,而不是做了之后再后悔。因为“后悔棋”往往更麻烦。

  说明:对于类似于x 1 n的情况,比如x 1,这个过程是不是越界了?如果x ^ 1n为假,是短路算符,则不计算!A[x 1][y],也不会出格。

  3.2字符号码组

  文本处理在计算机应用中起着重要的作用。在C语言中,字符串实际上是字符数组——。可以像处理普通数组一样处理字符串,只需要注意输入输出和字符串函数的使用。

  例3-3垂直问题。找出所有类似abc*de(三位数乘以两位数)的公式,这样在一个完整的竖式中,所有的数都属于一组特定的数。输入一组数字(相邻数字之间没有空格),输出所有竖排形式。每条竖线前都要编号,后面是一个空行。最终输出解决方案的总数。具体格式见示例输出(为了便于观察,竖排形式中的空格以小数点显示,但你的程序应该输出空格而不是小数点)。

  样本输入:2357

  样本输出:

  一个

  .775

  x.33

  -

  .2325

  2325.

  -

  25575

  解的数量=1【解析】

  本题的解题策略是尝试所有的abc和de来确定是否满足条件。编写以下伪代码:

  char s[20];

  int count=0;

  scanf(%s ,s);

  for(ABC=111;abc=999abc)

  for(de=11;de=99德)

  If ("ABC * DE "是合法的垂直市场){

  printf( %d \n ,count);

  打印abc*de的垂直位置及其后的空行。

  数数;

  }

  printf(解的数量=%d\n ,计数);注意:(1)char s[20]是定义字符数组的语句,scanf(%s ,s)表示从键盘输入一个字符串到字符数组s。

  (2)char的意思是“字符类型”,而character是一个特殊的整数。每个字符都有一个整数代码,称为ASCII码。c语言允许以直接的方式表达字符,也允许以反斜杠(转义序列)开头的字符。

  (3)stdlib . h中有一个函数atoi,它的函数原型如下:

  int atoi(字符)

  意思是将字符串S中的内容转换成整数返回,比如字符串“1234”,函数的返回值是1234。

  (4)stdlib . h中有一个函数itoa,它的函数原型如下:

  char itoa(int value,char string,int radix)

  表示将整数值转换为字符串并存储在字符串中,radix是转换中使用的基数(字符串中存储的数据的基数是2 8 10 16),它返回一个指向转换后的字符串的指针。

  比如itoa(32,string,10)是一个字符串“32”,它把32变成十进制数,并返回指向这个字符串的指针;Itoa(32,string,16)是一个字符串“20”,它将32变成一个十进制数,并返回指向该字符串的指针。

  技巧3-7:C语言中的字符类型是用char表示的,它实际上存储的是字符的ASCII码。字符常量可以用单引号表示。从语法上讲,字符可以用作int类型。

  语句scanf(%s ,s);就是读取一个没有空格,制表符和回车的字符串,存储在字符数组S中,S前面没有符号。

  3-8:在scanf(%s ,s)中,不要在s前放符号,如果是字符数组char s[MAXN] [MAXL],可以用scanf(%s ,s[i])读取第I个字符串。

  接下来是两个问题:判断和输出。先考虑产量。先算第一线积x=abce,再算第二线积y=abcd,最后总积z=abcde,然后一下子打印出来:

  printf(]\ nXM \ n-\ n]\ nM \ n-\ n]\ n \ n ,abc,de,x,y,z);完整的过程如下:

  计划3-4垂直问题#包括

  #包括

  int main(){

  int i,ok,abc,de,x,y,z,count=0;

  char s[20],buf[99];

  scanf(%s ,s);

  for(ABC=111;abc=999abc)

  for(de=11;de=99de ) {

  x=abc*(de);y=ABC *(de/10);z=abc * de

  sprintf(buf, %d%d%d%d%d ,abc,de,x,y,z);

  ok=1;

  for(I=0;I strlen(buf);我)

  if(strchr(s,buf[I])==NULL)ok=0;

  如果(正常){

  printf( %d \n ,count);

  printf(]\ nXM \ n-\ n]\ nM \ n-\ n]\ n \ n ,abc,de,x,y,z);

  }

  }

  printf(解的数量=%d\n ,计数);

  返回0;

  }描述:(1)**sprint**f函数

  Sprintf是一个可变参数函数,定义如下:

  int sprintf( char *buffer,const char *format [,argument].);

  除了前两个参数的固定类型之外,还可以跟任意数量的参数。而它的本质显然在第二个参数格式字符串里。

  这个函数的作用是将格式化的数据写入一个字符串,它的返回值是字符串的长度。包含这个函数的头文件是stdio.h

  比如这个程序中的Sprintf (BUF, % d% d% d% d ,ABC,DE,X,Y,Z);该语句的作用是将整数abcdexyx打印为字符串,并存储在字符串buff中。

  (2) * * strrch * *函数

  Strchr函数定义如下:

  char *strchr(const char *s,char c);

  这个函数的作用是找到字符C在字符串s中第一次出现的位置。它的返回值是指向第一次出现的C的指针,如果s中没有C,则为NULL。包含这个函数的头文件是string.h

  比如这个程序的if语句中strrch (S,buf[i])的作用就是寻找字符串S中第一个字符BUF [I]的位置,如果strrch (s,buf[i]==null,则表示字符串S中没有BUF[I]字符。

  (3)3)sprintf函数、printf函数和fprintf函数之间的区别

  Printf输出到屏幕,fprintf输出到文件,sprintf输出到字符串。应该注意,应该有足够空间用于写入的字符串。

  技巧3-9:可以使用sprintf将信息输出到一个字符串,这与printf和fprintf类似。但是您应该确保该字符串足够大,能够容纳输出信息。

  字符串的空格应该是字符数加1,因为C语言中的字符串以空字符 \0 结尾。

  函数strlen(s)用于获取字符串s的实际长度,即函数strlen(s)返回结束标记之前的字符数。所以这个字符串中的字符依次是s[0],s[1],…,s[strlen(s)-1],s[strlen(s)]是结束标记 \0 。

  3-10:C语言中的字符串是以 \0 结尾的字符数组。可以使用strlen(s)返回字符串s中结束标记之前的字符数,字符串中的字符有:s[0],s[1],…,s[strlen(s)-1]。

  提示3-11:由于字符串的本质是数组,它也不是“一等公民”。只有strcpy(a,b)、strcmp(a,b)和strcat(a,b)可以用来执行“赋值”、“比较”、“连接”等操作。不能使用=、==、=等运算符。以上函数都是在string.h中声明的

  除了字符串,还要注意count和count的用法。count本身的值是加1之后,但是count的值是加1之前(原始值)。

  注意:滥用count和count会带来很多隐藏的错误,最好的办法就是避免。

  技巧3-12:滥用可以修改变量值如,-,=的运算符很容易带来隐藏的错误。建议每个语句最多只使用一次该运算符,它修改的变量在整个语句中只出现一次。

  提示3-13:但是用option -Wall编译程序时,会给出很多(但不是全部)警告信息,帮助程序员检查错误。但并不能解决所有问题:有些“错误”的程序是合法的,但这些行为并不是你所期望的。

  3.3最长的回文子串

  例3-4回文。输入一个字符串,找到最长的回文子串。substring的含义是:在原字符串中连续出现的字符串片段。回文的意思是:和向后看是一样的。比如abba和yyxyy。判断时,所有标点符号和空格都要忽略,大小写也要忽略,但输出要保持原样(不输出回文串开头和结尾的多余字符)。输入字符串的长度不超过5000,并且占用单独的一行。应该输出最长的回文字符串。如果有多个回文,起始位置在最左边。

  输入示例:confinius说:女士,我是adam。

  样本输出:夫人,我是亚当

  [分析]

  因为输入的字符比较复杂,首先不能用scanf(%s )输入字符串。以下两种方法可用于解决以下问题:

  第一种方法是使用fgetc(fin),它读取一个打开的文件fin,读取一个字符,然后返回一个int值。因为如果文件结束,fgetc会返回一个特殊的标志EOF,这个标志不是char。如果想从标准输入中读取一个字符,可以使用getchar(),它相当于fgetc(stdin)。

  提示3-14:使用fgetc(fin)从可以打开的文件fin中读取一个字符。一般来说,在将它转换为char值之前,应该检查它不是EOF。可以使用getchar()从标准输入中读取一个字符,相当于fgetc(stdin)。

  Fgetc()和getchar()将读取“下一个字符”。如果是空格,会正常读取;如果换行,将读取回车 \n 。

  潜在的陷阱:不同操作系统的回车和换行符不一致。Windows是 \r 和 \n ,Linux是 \n ,MacOS是 \r 。如果在Windows下读取Windows文件,fgetc()和getchar()会吃掉 \r ,只剩下 \ n ;但是如果你想在Linux下读同一个文件,他们会先读 \r ,再读 \n 。这个问题在比赛中一定要注意。

  技巧3-15:使用fgetc和getchar时,应避免编写与操作系统相关的程序。

  第二种方法是使用fgets(buf,MAXN,fin)读取一整行,其中buf的声明是char buf[MAXN]。这个函数读取不超过MAXN-1个字符,然后在末尾终止字符 \0 ,所以不会越界。这个函数之所以可以用来读取一个完整的行,是因为一旦读取了回车 \n ,读取就会停止,这个 \n 也将是buf字符串中的最后一个有效字符(后面跟着字符串结束符 \0 )。buf不以 \n 结尾的情况只有一种:读取文件结尾,最后一个文件不以 \n 结尾。

  3-16: FGETS (buf,MAXN,FIN)将读取的完整行放入字符数组buf中。您应该确保buf足以容纳文件的一行。除了在文件终止符前没有遇到 \n 之外,buf总是以 \n 结尾。当没有读取字符时,fgets返回NULL。

  Get (s)表示从标准输入设备读取的字符串存放在s指向的数组中,成功则返回指针s,否则返回NULL。但是gets(s)并不表示读取的最大字符数,gets函数并不关心S有多少可用空间。

  提示3-17: C语言并没有禁止程序读写“非法内存”。比如你声明char s[100],你完全可以赋值s[10000]=a (even -Wall不会警告你),但是后果自负。

  3-18:C语言的gets(s)有缓冲区溢出漏洞,不推荐使用。

  选择fgets函数可以解决“输入带空格”的问题。它可以一次读一行,最方便。

  接下来,要解决“判断时忽略标点,但保持输入输出原样”的问题,可以用一个通用的方案:预处理。构造一个不包含原标点的新字符串,所有字符都变成大写(顺便解决了大小写问题):

  n=strlen(buf);

  m=0;

  for(I=0;我我)

  if(is alpha(buf[I])s[m]=toupper(buf[I]);说明:ctype.h中包含了isalpha(c)的原型,用来判断字符c是字母(大写还是小写)。使用toupper(c)返回c的大写形式,经过这个处理后,buf保存原始字符串的所有字母。

  3-19:当任务复杂时,可以通过预处理简化输入,提供更多数据使用。复杂的字符串处理问题往往可以通过合理的预处理来简化任务,方便调试。

  提示3-20:头文件ctype.h中定义的isalpha、isdigit、isprint等工具可以用来判断字符的属性,而toupper、tolower等工具可以用来转换大小写。

  描述:(1)isalpha(c)用于检查C是否为字母,如果是则返回1;否则,它返回0。

  (2)isdigit(c)用于检查C是否为数字(0 ~ 9),如果是,则返回1;否则,它返回0。

  (3)isprint(c)用于检查C是否为可打印字符(不包括空格),其ASCII码值在0x21到0x7e之间。如果是可打印字符,则返回1;否则,它返回0。

  (4)toupper(c)用于将C字符转换成大写字母,并返回C对应的大写字母。

  (5)tolower(c)用于将C字符转换成小写字母,返回C对应的小写字母,我们先列举一个回文串的起点和终点,然后判断是否真的是回文串。

  int max=0;

  for(I=0;我我)

  for(j=I;j j)

  如果(s[i.j]是回文串j-I 1 max)max=j-I 1;“Current Maximum”变量max,保存目前为止找到的最长回文子串的长度。如果字符串s的第I到j个字符(表示为s[i.j])是回文,检查长度j-i 1是否超过max。

  最后,判断s[I]是否.j]是一个如下的回文:

  int ok=1;

  for(k=I;k k)

  if(s[k]!=s[I j-k])ok=0;s[k]的“对称”位置是s[i j-k],因为只要一次比较失败,标记变量ok就要设置为0。

  完整的过程如下:

  程序3-5最长回文子串(1)#包含

  #包括

  #包括

  #定义MAXN 5000 10

  char buf[MAXN],s[MAXN];

  int main() {

  int n,m=0,max=0;

  int i,j,k;

  fgets(buf,sizeof(s),stdin);

  n=strlen(buf);

  for(I=0;我我)

  if(is alpha(buf[I])s[m]=toupper(buf[I]);

  for(I=0;我我)

  for(j=I;j j ) {

  int ok=1;

  for(k=I;k k)

  if (s[k]!=s[I j-k])ok=0;

  if(ok j-i1 max)max=j-i1;

  }

  printf(max=%d\n ,max);

  返回0;

  }实际编程中,往往是先写一个有主要功能的程序,然后再完善。你甚至可以先写一个只有输入输出函数的“骨架”,但要确保它是正确的。这样每次只增加一点功能,比一次写完整个程序更不容易出错。这种方法被称为迭代开发。

  技巧3-21:程序复杂时,除了在设计阶段用伪代码理清思路,在编码阶段可以使用迭代开发3354,每次只实现一点点功能,但要充分测试,确保正常工作。

  程序3-5可以成功计算样本数据中最长回文串的长度。现在,下一个任务是输出这个回文:按原样输出,并尝试向左。既然是从左到右枚举,那就只剩下一个问题:按原样输出。

  因为在求max的值时,s[i]和s[j]在原字符串buf中的位置是未知的。所以必须加一个数组P,用p[i]来保存s[i]在buf中的位置。预处理后得到,然后在更新max的同时保存p[i]和p[j]到X和Y,最后输出buf[x]到buf[y]中的所有字符。

  但是上面的方法查找起来比较慢,所以还有一种方法就是枚举回文串的“中间”位置I,然后展开,直到出现不同的字符。提示:奇数和偶数长度的处理方式不同。

  完整的过程如下:

  程序3-6最长回文子串(2)#include

  #包括

  #包括

  #定义MAXN 5000 10

  char buf[MAXN],s[MAXN];

  int p[MAXN];

  int main() {

  int n,m=0,max=0,x,y;

  int i,j;

  fgets(buf,sizeof(s),stdin);

  n=strlen(buf);

  for(I=0;我我)

  if(is alpha(buf[I]){

  p[m]=I;

  s[m]=toupper(buf[I]);

  }

  for(I=0;i i ) {

  for(j=0;i - j=0 i j j ) {

  if (s[i - j]!=s[I j])break;

  if (j * 2 1最大值){

  max=j * 2 ^ 1;

  x=p[I-j];

  y=p[I j];

  }

  }

  for(j=0;i - j=0 i - j 1 j ) {

  if (s[i - j]!=s[I-j 1])break;

  if (j * 2最大值2){

  max=j * 2 ^ 2;

  x=p[I-j];

  y=p[I j 1];

  }

  }

  }

  for(I=x;我我)

  printf(%c ,buf[I]);

  printf( \ n );

  返回0;

  }

  3.4总结和练习

  至此,C语言的核心内容已经全部学完。理论上,算法前三章的知识足够写大部分算法竞赛程序了。

  3.4.1必要的存储容量3.4.2用ASCII编码表示C语言中的字符,除了字符常量以外,还有一种特殊形式的字符常量,即以一个字符“\”开头的字符序列。您也可以使用ASCII码(八进制数或十六进制数)来表示转义字符中的字符。

  提示3-22:字符也可以直接用ASCII码表示。如果是八进制,应该写成\ddd,代表1到3个八进制数字所代表的字符;如果用十六进制,应该写成\xhh,表示用1到2个十六进制数字表示的字符。

  3.4.3补码记数法计算机中的二进制是无符号的,但对于正号和负号可以是二进制位。有符号的32位整数,在计算机中采用“补码表示法”。

  例如,printf(%u\n ,-1)语句的输出是4294967295=232-1。用-2,-3,-4,…代替-1后,可以总结出一个规律:n的内部表示是232-n。

  提示3-23:在大多数计算机中,整数是用补码表示的。

  采用补码表示法的主要原因是符号位和其他位可以统一处理;同时,减法也可以当作加法。另外,当用补码表示的两个数相加时,如果最高位(符号位)有进位,则舍弃该进位。

  一般来说,int是32位(4字节)。

  3.4.4重新实现库函数在学习字符串时,重新实现一些库函数是有益的。

  练习1:只使用getchar函数读入一个整数。假设它占据一行直到行尾,包括换行符。确保输入的读入整数可以保存在int中。

  练习2:只使用fgets函数读入一个整数。假设它占据一行直到行尾,包括换行符。确保输入的读入整数可以保存在int中。

  练习3:只用getchar实现fgets的功能,即一次读取整行一个字符。

  练习4:实现strchr的功能,即在字符串中查找一个字符。

  回答:下面写一个函数strcr1,实现strcr1的功能:

  char *strchr1(char *str,int ch)

  {

  int I;

  for(I=0;str[i]!=\0;我)

  if(str[i]==ch)返回str I;

  返回NULL

  }练习5:实现isalpha和isdigit的功能,即判断字符是否为字母/数字。

  答:(1)下面写一个函数isalpha 1,实现is alpha的函数:

  int isalpha1(char ch)

  {

  if((ch= A ch= Z ) (ch= A ch= Z ))返回1;

  否则返回0;

  }(2)下面写一个函数isdigit1,实现isdigit的功能:

  int isdigit1(char ch)

  {

  if(ch=0 ch=9 )返回1;

  否则返回0;

  }3.4.5字符串处理常见问题tot=1;

  for(I=0;I strlen(s);我)

  if(s[I]==1)tot;

  printf(字符串中有%d个字符 1 。\n ,tot);这个程序的功能是计算一个字符串中字符1的个数。

  实验1:添加字符串S的声明语句,长度不小于107。提示:在主函数内部还是外部?答:添加字符串S的声明语句如下:

  #定义MAXN 10000000

  char s[MAXN];应该放在主函数之外。

  实验二:添加一条阅读语句,测试上面的程序是否输出了想要的结果。如果没有,请改正。回答:如果不能得到想要的结果,按如下方式改正:

  if(s[I]==1)tot;改为if(s[I]= 1 )tot;实验三:注释掉输入的语句,添加语句,用程序生成长度至少为105的字符串,用程序验证字符串长度不小于105。答:程序如下:#include

  #包括

  #定义MAXN 10000000

  char s[MAXN];

  int main() {

  int i,tot=0;

  /*获取;从键盘输入一个字符串到s */

  for(I=0;我100000;I) /*用程序生成长度至少为105的字符串*/

  s[I]= 1 ;

  for(I=0;I strlen(s);我)

  if(s[I]== 1 )tot;

  printf(字符串中有%d个字符 1 。\n ,tot);

  返回0;

  }实验四:用带计时功能的字符串的长度来检验这个程序运行时间的规律。如何改善?答:程序如下:

  #包括

  #包括

  #包括

  #定义MAXN 10000000

  char s[MAXN];

  int main() {

  int i,tot=0;

  clock_t开始,结束;

  start=时钟();

  for(I=0;我1000000;我)

  s[I]= 1 ;

  for(I=0;I strlen(s);我)

  if(s[I]== 1 )tot;

  printf(字符串中有%d个字符 1 。\n ,tot);

  finish=clock();

  printf(所用时间=%.5lf秒\n ,(完成-开始)

  /(双)时钟_每秒);

  返回0;

  }此程序在字符串长度为10000时的运行时间为0.05秒;字符串长度为100000时,运行时间为5.32秒;当字符串长度为1000000时,运行时间为558.56秒。所以这个程序运行时间的规律是,当字符串长度增加到10倍时,运行时间增加到近100倍。

  注:(1)时钟函数是C/C中的计时函数,其相关数据类型为clock _ t,在MSDN,Chad对时钟函数的定义如下:

  clock _ t clock(void);

  (2)clock函数返回从“启动本程序进程”到“调用程序中的clock()函数”的CPU时钟滴答数,称为wal-clock);在MSDN;如果挂钟时间不合适,返回-1。其中clock_t是用于节省时间的数据类型,其定义可以在头文件time.h中找到:

  #ifndef _CLOCK_T_DEFINED

  typedef长时钟_ t;

  #定义_时钟_时间_定义

  #endif表示clock_t是一个长整数。

  (3)在头文件time.h中,还定义了一个常数CLOCKS_PER_SEC,用来表示一秒钟内会有多少个时钟计数单位。其定义如下:

  # DEFINE CLOCKS _ PER _ SEC((CLOCK _ T)1000)3 . 4 . 6关于I/O 1.getchar函数当程序请求键盘输入时,只要用户输入键就可以返回getchar()函数。不一定要输入第一个字符,回车即可,也可以输入多个字符,最后回车即可。

  如果直接输入文件终止符(Windows中的Ctrl Z键),getchar()读取ASCII码中无法显示的控制字符(ASCII码值为10,LF表示该行已满,需要换行)。

  说明:(1)getchar有一个int返回值。当程序调用getchar时,程序等待用户按键,用户输入的字符存储在键盘缓冲区中,直到用户按enter(输入的字符也放在缓冲区中)。在用户输入之后,Getchar开始从stdio流中一次读取一个字符。

  (2)2)getchar函数的返回值是用户输入的第一个字符的ASCII码。如果出现错误,它返回-1,用户输入的字符显示回屏幕。

  (3)如果用户在按enter键之前输入了不止一个字符,其他字符将保留在键盘缓存区中,等待随后的getchar调用读取。也就是说,后续的getchar调用不会等待用户按键,而是直接读取缓冲区中的字符,等待用户按键,直到缓冲区中的字符读完。

  如果将getchar函数放在一个循环中,也可以读取一个字符串。例如,“读入一个字符串,直到按下回车键表示结束”,可以使用以下结构:

  char ch

  while((ch=getchar())!=\n )

  {

  …/*处理该字符ch */

  }上述循环的执行过程是:先从键盘读取一个字符,将该字符赋给ch,然后判断ch是否为换行符 \n 。如果是,则循环结束;否则,执行循环体。所以这个结构可以读入多个字符,直到按下回车键(按下回车键实际上输入了两个字符:“回车”字符和“换行”字符,ASCII码分别是13和10。

  2.sscanf函数(1)sscanf()的意思是从字符串中读取指定格式的数据。其功能原型如下:

  int sscanf( const char *,const char *,…)

  所需的头文件是stdio.h

  (2)sscanf和scanf类似,都是用来输入的,只不过后者使用键盘(stdin)作为输入源,前者使用固定字符串作为输入源。

  如果存在格式为HH:MM:SS的字符串S(例如,“12:34:56”),请使用sscanf语句获取HH,MM,SS的值,如下所示:

  sscanf(s, %d:%d:% ,HH,MM,SS);

  将s替换为‘12:34:56’,可以得到HH的值为12,MM为34,SS为56。

  3 . 4 . 7 I/O效率的题目是“直接输出”:输入一个不超过1000行的字符串,然后直接输出。每行都是长度不超过10000的字符串,包含大写字母和小写字母,不包含任何空格(如空格、制表符)。

  第一种方法是在c中使用流和字符串对象。

  #包括

  #包括

  使用命名空间std

  int main()

  {

  字符串s;

  while(CIN s)count s \ n ;

  返回0;

  }注意:(1)这里声明C中的字符串,否则不能使用iostream。

  (2)C语言中的C字符串和字符数组可以相互转换:如果s是字符数组,那么string(s)就是对应的字符串;如果s是一个字符串,那么s.c_str()就是对应的字符数组。

  (3)c _ str()返回的内容为只读。比如可以用printf(%s ,s.c_str())输出,但是不能用scanf(%s ,s.c_str())输入。

  第二种方法是使用getchar。

  #包括

  使用命名空间std

  int main()

  {

  int ch

  while((ch=getchar())!=EOF)putchar(ch);

  返回0;

  }注意:赋值语句本身是有值的,所以在读取一个字符的时候可以立刻判断是不是EOF。

  第三种方法是使用fgets。

  #包括

  使用命名空间std

  #定义MAXN 100010

  int main()

  {

  int ch

  while(fgets(s,MAXN,stdin)!=NULL)看跌期权;

  返回0;

  } C中还有一个“字符串流”,可以实现类似sscanf和sprintf的功能:

  #包括

  #包括

  使用命名空间std

  #定义MAXN 100010

  int main()

  {

  char s[1000];

  cin.getline(s,1000, \ n );

  string stream ss(s);

  int a,b;

  ss a b;

  计数a b \ n

  返回0;

  }上面的函数首先读取cin的一行。Getline函数的第三个参数是行分隔符。它的默认值是 \n ,所以可以简化为cin.getline(s,1000),其中1000的含义类似于fgets中的含义。

  3.4.8汇总数组和字符串意味着数据量很大,在处理大量数据时,通常会遇到“访问非法内存”的错误。从语法上来说,C语言并没有禁止程序访问非法内存,但是后果是无法预料的。有两种方法可以解决这个问题:在访问数组之前检查下标是否合法;适当放大数组。gets函数存在缓冲区溢出漏洞。strcpy (3354)也有类似的问题。如果源字符串没有以 \0 结尾,那么副本可能会覆盖缓冲区之外的内存。

  在数组和字符串处理程序中,下标的计算极其重要。

  理解字符编码对于正确使用字符串至关重要。算法中涉及的字符一般是ASCII表中可打印的字符。对于中文GBK编码,如果char值为正,则为西文字符;如果为负数,则为汉字的前半部分(此时需要读取另一个char)。

  3.4.9电脑上的练习3-1分数统计(stat)输入部分学生的分数。哪个乐谱出现的频率最高?如果有多个并行,输出从小到大。注:(1)假设输入分数个数不超过10000;没有这个假设,这个问题就难了。

  (2)如果有多个并列,从小到大输出。(注意书中这里有一个模糊的定义。我说清楚:对于同一个分数,只输出一次。

  1:分数都是不超过100的非负整数。输入:练习3-1,分数统计

  输出到屏幕

  [分析]

  用于解决问题的数据结构:

  (1)使用数组标记来存储输入的分数。

  (2)使用另一个数组计数来存储相应分数出现的次数。

  解决问题的思路和步骤:

  (1)输入数据并处理标记和计数数组中的数据;

  (2)扫描计数一次,看哪一个出现频率最高。这是什么?写为maxTimes

  (3)输出maxTimes出现次数从小到大的分数。

  由于学生到目前为止还没有学会排序算法,这一步比较麻烦。

  具体做法如下:

  (1)扫描counts数组,用maxTimes找到最小的分数并输出。

  (2)将刚刚输出的分数对应的maxTimes值减1(为了下次不输出这个值)。

  (3)重复步骤(1)和(2),直到再也找不到有maxTimes的分数。

  完整的过程如下:

  #包括

  #定义最大10000 /*最多有几个输入数据*/

  #define NOMARK -1 /*表示“无效”分数;或者可以理解为“不得分”*/

  int main() {

  Intdata,/*新输入的数据*/

  I,j,/*辅助变量*/

  存在,/*输出结果时使用的辅助变量*/

  MaxTimes,/*最大出现次数*/

  min

  Int标志[MAX],/*存储输入数据*/

  计数[MAX];/*存储数据的计数*/

  Freopen(练习3-1,分数统计(stat)a.in , r ,stdin);

  for(I=0;任务二:分数都是不超过100的非负实数,最多保留两位小数。[分析]

  与任务1相同的分析。

  完整的过程如下:

  #包括

  #定义最大10000 /*最多有几个输入数据*/

  #define NOMARK -1 /*表示“无效”分数;或者可以理解为“不得分”*/

  int main() {

  Int,j,/*辅助变量*/

  存在,/*输出结果时使用的辅助变量*/

  maxTimes/*最大出现次数*/

  浮动最小值,

  newData/*新输入的数据*/

  浮动标记[最大值];/*存储输入数据*/

  int counts[MAX];/*存储数据的计数*/

  Freopen(练习3-1,分数统计(stat)b.in , r ,stdin);

   for (i=0; i习题3-2 单词的长度(word)输入若干个单词,输出它们的平均长度。单词只包含大写字母和小写字母,用一个或多个空格隔开。

  【分析】

  解决本题,需要用到字符串的知识。字符串,也就是一维的字符数组。结束输入的方法按Ctrl+Z键,回车,回车。

  使用的策略是:scanf("%s",...); 遇到空格时,会自动截断,很适合用在这种环境。strlen(); 用于计算字符串的长度

  操作步骤如下:

  (1)读入一个单词;

  (2)计数器增量1;

  (3)计算单词长度,累加总长度;

  (4)总长度/计数器---- 平均长度。

  完整的程序如下:

  #include

  #define MAXLENGTH 189819 /*最长的单词有多长?请看:http://en.wikipedia.org/

  wiki/Longest_word_in_English*/

  int main() {

   char word[MAXLENGTH]; /*单词*/

   int lengthSum=0, /*单词长度总和*/

   count=0;

   while(scanf("%s",word)!=0) { /*表示有数据输入*/

   count=count+1;

   lengthSum=lengthSum+strlen(word);

   }

   if (count==0)

   printf("没有单词输入");

   else

   printf("输入的单词平均长度为:%f",lengthSum/(count*1.0));

   return 0;

  }习题3-3 乘积的末3位(product)输入若干个整数(可以是正整数、负数或者零),输出它们的乘积的末3位。这些整数中会混入一些由大写字母组成的字符串,你的程序应当忽略它们。提示:试试看,在执行scanf("%d")时输入一个字符串会怎样?

  【分析】

  每个输入的数据(无论是整数还是字符串)之间,都用回车或空格来分隔。对于乘积不足3位的情况,就输出完整的乘积,左侧不用补0。对于乘积为负数的情况,左侧不必加上-。输入的整数可能有很多个,所以最后的乘积可能会很大。“由大写字母组成的字符串”指的是字符串中全部都是大写字母。输入数据,以“Ctrl+Z,回车,回车”结束。

  假设输入的整数不会超过int的表示范围,如果没有任何输入数据,则输出0。

  采取的策略如下:

  (1)对于输入的数据都要做为字符串来看待。

  (2)对于每一个输入的数据,要判断其是否为数字。若是,要将“数字字符串”转为“整型数据”;否则,忽略这个数据。

  (3)为了计算(xy)的末三位,其实只要计算(x的末三位)(y的末三位),看其结果的末三位即可。

  完整的程序如下:

  #include

  #include

  #include

  int main() {

   int newData, /*新输入数据的后三位*/

   result = 0, /*得到的结果。之所以初始化为0,而非1;是要考虑到用户可能没有输入任何整数的情况。*/

   p, counts = 0; /*count为计数器,用于统计用户输入的数字个数*/

   char inStr[100]; /*输入的字符串数据*/

   while (scanf("%s", inStr) != 0) {

   if (inStr[0] = A inStr[0] = Z) /*说明读到的数据是“由大写字母组成的字符串”*/

   continue;

   /*有数字字符串输入*/

   counts = counts + 1;

   if (counts == 1) result = 1;

   /*printf("字符串:%s\t",inStr);*/

   /*将“数字字符串”的后3位转为整数*/

   p = strlen(inStr) - 1;

   newData = 0;

   if (p = 0 inStr[p] = 0 inStr[p] = 9)

   newData = inStr[p] - 0;

   p = p - 1;

   if (p = 0 inStr[p] = 0 inStr[p] = 9)

   newData = newData + (inStr[p] - 0) * 10;

   p = p - 1;

   if (p = 0 inStr[p] = 0 inStr[p] = 9)

   newData = newData + (inStr[p] - 0) * 100;

   /*printf("后三位转为整数:=%d\n",newData);*/

   result = (result * newData) % 1000; /*乘积取最后三位*/

   /*printf("....%d\n",result);*/ /*调试信息*/

   }

   printf("%d", result);

   return 0;

  }习题3-4 计算器(calculator)编写程序,读入一行恰好包含一个加号、减号或乘号的表达式,输出它的值。这个运算符保证是二元运算符,且两个运算数均为不超过100的非负整数。运算数和运算符可以紧挨着,也可以用一个或多个空格、TAB隔开。行首末为均可以有空格。提示:选择合适的输入方法可以将问题简化。

  样例输入:1+1

  样例输出:2

  样例输入:2- 5

  样例输出:-3

  样例输入:0 *1982

  样例输出:0

  【分析】

  使用的策略如下:

  (1)读取一行str

  (2)扫描str,忽视其中的“空格,\t, \n”,生成strX, strY, 和 operator

  (3)把 strX 转为 x, strY 转为 y

  (4)根据 operator,计算 x operator y

  (5)输出结果

  说明:(1)使用gets()读取字符串,可以将输入字符串中的 空格, \t 一起读入;但不会读入字符串最后的回车;

  (2)x, y 位于[0,100]之间;

  (3)假设输入的字符串总长度不超过MAXLEN=10000(题目没有说明空格等字符的上限);

  (4)假设用户输入的数据总是合法的。

  完整的程序如下:

  #include

  #include

  #define MAXLEN (10000)

  int main() {

   int x,y, /*用于计算*/

   i,j, /*临时变量*/

   p, /*指针*/

   power; /*位权*/

   char str[MAXLEN], /*输入的字符串*/

   strX[4], /*x,位于[0,100],所以长度4就足够了*/

   strY[4], /*y,位于[0,100],所以长度4就足够了*/

   operator;

   gets(str);

   /*printf("strlen(str)=%d\n",strlen(str));*//*调试代码*/

   /*============ 解析出str中的 strX ===============*/

   p=0;

   for (i=0; str[i]!=+ str[i]!=- str[i]!=*; i=i+1) {

   if (str[i] =0 str[i] =9) {

   strX[p]=str[i];

   p=p+1;

   }

   }

   strX[p]=0; /*给字符串的末尾加上结束标记*/

   /*printf("%s\t%d\n",strX,strlen(strX));*//*调试代码*/

   /*============ 解析出str中的 operator ===============*/

   operator=str[i];

   /*============ 解析出str中的 strY ===============*/

   p=0;

   while (i =strlen(str)-1){

   if (str[i] =0 str[i] =9) {

   strY[p]=str[i];

   p=p+1;

   }

   i=i+1;

   }

   strY[p]=0; /*给字符串的末尾加上结束标记*/

   /*printf("%s\t%d\n",strY,strlen(strY));*/ /*调试代码*/

   /*========== 将strX转为x,strY转为y ============*/

   x=0;

   for(i=strlen(strX)-1; i i=i-1) {

   power=1;

   for(j=1; j =(strlen(strX)-1)-i; j=j+1) power=power*10;

   x=x+(strX[i]-0)*power;

   }

   y=0;

   for(i=strlen(strY)-1; i i=i-1) {

   power=1;

   for(j=1; j =(strlen(strY)-1)-i; j=j+1) power=power*10;

   y=y+(strY[i]-0)*power;

   }

   /*printf("x=%d\ty=%d\n",x,y);*/ /*调试代码*/

   if (operator==+) printf("%d",x+y);

   if (operator==-) printf("%d",x-y);

   if (operator==*) printf("%d",x*y);

   return 0;

  }习题3-5 旋转(rotate)输入一个nn字符矩阵,把它左转900后输出。

  【分析】

  本题描述存在一个问题:没有明确指出nn字符矩阵是以何种格式输入的。在解决问题的时候,程序员需要自己定义输入数据的格式。在此,我们定义输入数据的格式如下:

  (1)先输入一个整数n,表示nn字符矩阵;

  (2)再输入nn个字符,表示矩阵中的数据;

  (3)假设用户输入的数据都是合法的,设 0 =n =100。

  输出数据:逆时针转90度后的nn矩阵

  举例说明:

  输入:

  4

  a b c d

  e f g h

  i j k l

  m n o p

  输出:

  d h l p

  c g k o

  b f j n

  a e i m

  采用的数据结构是用100100的二维数组来存储数据。

  使用的策略是仔细观察输入和输出的样例。和输入矩阵对比,输出矩阵是以行为单位输出,对于n个输出行而言,是从右向左按列输出“输入矩阵”。

  完整的程序如下:

  #include

  int main() {

   char m[100][100]; /* n*n矩阵 */

   int n, /* 矩阵每行的元素个数 */

   x, /* 行 */

   y; /* 列 */

  /*=============== 数据输入 =================*/

   scanf("%d",

   for (x=0; x =n-1; x=x+1) {

   for (y=0; y =n-1; y=y+1) {

   scanf("%c", m[x][y]);

   /* 由于输入的是字符数据,所以要跳过可能存在回车、换行、空格、制

  表符等不可见字符 */

   while (m[x][y]==\n m[x][y]==\t m[x][y]== )

   scanf("%c", m[x][y]);

   }

   }

  /*调试代码:打印刚刚输入的用户数据*/

  /*

   for (x=0; x =n-1; x=x+1) {

   for (y=0; y =n-1; y=y+1) {

   printf("%c ",m[x][y]);

   }

   printf("\n");

   }

  */

  /*=============== 输出数据 ================*/

   for (y=n-1; y y=y-1) {

   for (x=0; x =n-1; x=x+1) {

   printf("%c ",m[x][y]);

   }

   printf("\n");

   }

   return 0;

  }说明:使用输入输出重定向的办法,可以更方便地测试更大规模的数据。

  习题3-6 进制转换1(base1)输入基数b(2 =b =10)和正整数n(十进制),输出n的b进制表示。

  【分析】

  假设0 n 100000,用户输入的都是合法数据。例如,

  输入:2 11

  输出:1011

  采用的数据结构是用一个一维数组存储输出结果中的每一位。

  采取的策略是模拟手工转换的过程。关键是,在计算的过程中,从一维数组的低位开始向高位存储;而输出的时候,从高位开始向低位输出。

  完整的程序如下:

  #include

  int main() {

   int b, /*基数*/

   n, /*正整数*/

   i;

   int ans[100]; /*结果*/

   scanf("%d%d", b,

   i=0;

   while (n!=0) {

   ans[i]=n%b;

   n=n/b;

   i=i+1;

   }

   for (i=i-1;i i=i-1) {

   printf("%d",ans[i]);

   }

   return 0;

  }习题3-7 进制转换2(base2)输入基数b(2 =b =10)和正整数n(b进制),输出n的十进制表示。

  【分析】

  假设用户输入的数据都是合法的,假设n作为十进制来看待的时候,位数不超过19位。这时候,就需要用64位整数来存储n。例如,

  输入:3 212

  输出:23

  输入:2 101

  输出:5

  采用的策略是模拟手工计算的过程。采取的数据结构是本题的解决可以不采用数组的数据结构的,这样做似乎更加方便,代码更加简洁明了。但是由于本章讲的是数组。所以我使用一个一维数组,来存储输入的正整数n中的每一位。n的最低位,存放在数组下标为0的元素上,以此类推。

  完整的程序如下:

  #include

  int main() {

   int b, /*基数(2 =b =10)*/

   i,j,k;

   long long m, /*位权*/

   n, /*b进制的正整数n*/

   result; /*结果*/

   int s[20];

   scanf("%d%I64d", b,

   /*printf("%d% I64d\n",b,n);*/ /*测试代码*/

  /*======= 把n的每一位存入一维数组 =================================*/

  /*======= n的最低位,存放在数组下标为0的元素上,以此类推。 ========*/

   i=0;

   while (n!=0) {

   s[i]=n%10;

   n=n/10;

   i=i+1;

   }

   result=0;

   m=1;

   for (k=0; k =(i-1); k=k+1) { /*从下标0开始,向高位计算,可以节省计算位权的时间*/

   result=result+s[k]*m;

   m=m*b; /*计算更高一位的位权*/

   }

   printf("%I64d",result);

   return 0;

  }习题3-8 手机键盘(keyboard)输入一个由小写字母组成的英文单词,输出用手机的默认英文输入法的敲键序列。例如要打出pig这个单词,需要按1次p,3次i,(稍作停顿后)1次g,记为p1i3g1(显然,书中这部分描述存在明显的错。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • php读取pdf数据,php pdf读取
  • php读取pdf数据,php pdf读取,PHP中使用mpdf 导出PDF文件的实现方法
  • kotlon协程,深入理解kotlin协程pdf,一文彻底搞懂Kotlin中的协程
  • 深入解析C#(第4版),深入解析css pdf,深入解析contentWindow, contentDocument
  • java 反射机制原理与用法详解视频,java 反射机制原理与用法详解pdf
  • java 反射机制原理与用法详解视频,java 反射机制原理与用法详解pdf,Java 反射机制原理与用法详解
  • ,,Java使用iTextPDF生成PDF文件的实现方法
  • ,,Python利用PyMuPDF实现PDF文件处理
  • 漫画算法小灰的算法之旅pdf,漫画算法2-小灰的算法进阶
  • devops和自动化运维实践 PDF,devops思想在运维方面的具体实践
  • pdf如何去除水印,pdf去水印的三种方法
  • 把a4的内容打印成a3小册子,a4的pdf文档如何打印成a3
  • nlp自然语言处理入门pdf,精通python自然语言处理 pdf
  • 容器docker基本操作,每天5分钟玩转docker容器技术 pdf
  • sklearn中文手册pdf下载,sklearn库模块及函数
  • 留言与评论(共有 条评论)
       
    验证码: