C:数组
与字符串处理有关的函数:
头文件:<stdio.h> gets()、puts()
头文件:<string.h>
(1)、字符串长度测量函数 :strlen(字符数组名),返回一个整型值:字符串中的实际字符数(不包括 '\0')
(2)、字符串赋值函数:strcpy(字符数组名1,字符串2),将字符串2的所有字符一个一个复制到字符数组中,直到遇到结束标志 '\0'为止,并将结束标识符也写入字符数组1中
指定数量的字符串赋值函数:strncpy(字符数组1,字符数组2,要复制的字符个数)
(3)、字符串连接函数:strcat(字符数组1,字符串2),取消第一个字符数组的字符串的结束标志 '\0' ,把第二个字符串拼接至第一个字符串后面,并把拼接的结果存放到第一个字符数组中
(4)、字符串比较函数 :strcmp(字符串1,字符串2),按字典排序进行比较,即从字符串1和字符串2的第一个字符开始从左至右依次按照 ASCII码 进行比较,直到出现不相同的字符或者碰到结束标志 '\0' 为止,以第一个不相等的字符的比较结果作为整个字符串的比较1结果:
字符串1和字符串2相等,即长度相同,对应的字符也相同,返回0
字符串1大于字符串2,则返回一个正整数
字符串1小于字符2.则返回一个负整数
(5)、查找字符2在字符串1中第一次出现的位置:strchr(字符串1,字符2)
(6)、找到字符串2在字符串1中第一次出现的位置:strstr(字符串1,字符串2)
二维数组:
void main() { int i; int a[5][10]; for(i = 0;i < 5;i++) { gets(a[i]); } printf("\n%s",a); // a = a[0] }
1、求200以内的所有的素数
算法分析:
采样筛选法:
(1)、取最小的数2,并声明它是素数,同时筛去它及它的所有倍数
(2)、取未被筛去的数中最小者,声明它是素数,同时筛去它及它的所有倍数
(3)、重复步骤(2),至筛中无数为至,得到所有的素数
本例可使用数组,使数组下标就是200以内的数,让数组元素的值作为筛去与否的标志,这里设数组元素的初值为0,筛去以后就是1
为提高筛选效率:
一个合数n必有一个不大于sqrt(n)的正因子,故一个数若是没有小于sqrt(n)的正因子,则说明它是一个素数
代码:
#include <stdio.h> #include <stdlib.h> #include <math.h> void main() { int prime[201] = {0}; // 已筛去的值为1.未筛去的值为0 int d; int k; int i; for(d = 2;d <= sqrt(200);d++) { if(prime[d] == 0) { for(k = 2*d;k <= 200;k = k + d) { prime[k] = 1; // 筛去d的所有倍数 } } } k = 0; for(i = 2;i <= 200;i++) { if(prime[i] == 0) { printf("%d\t",i); k++; //一行输出5个数 if(k % 5 == 0) { printf("\n"); } } } }
2、将由6个整数组成的序列,将其按从大到小的顺利排列
算法分析:使用冒泡排序法【对于n个数排序,至多进行n-1 遍排序,每遍进行n-i 次比较】
代码:
#include <stdio.h> #include <stdlib.h> const int n = 6; void main() { int a[n]; int i; int j; int temp; //输入 printf("请输入待排序元素:\n"); for(i = 0;i < n;i++) { printf("a[%i]=",i); scanf("%d",&a[i]); } //排序 for(i = 1;i < n;i++) { for(j = 0;j < n-i;j++) { if(a[j] < a[j+1]) { temp = a[j]; a[j] = a[j + 1]; a[j + 1] = temp; } } } //输出 printf("排序后从大到小输出:\n"); for(i = 0;i < n;i++) { printf("%d\t",a[i]); } printf("\n"); }
由于对什么样的数据都会扫描n-1遍,包括已经排好序的也会扫描n-1遍
改进:设置一个变量change 表示一遍扫描中是否会进行交换,在每一遍扫描开始时,将其设置为,表示未交换;在扫描中如果进行了交换,则将变量设置为1,本遍扫描完成后,如果change=0,则表示本遍扫描中未进行交换,即可退出扫描。
代码:
//改进 void main() { int a[n]; int i; int j; int temp; int change; //输入 printf("请输入待排序元素:\n"); for(i = 0;i < n;i++) { printf("a[%i]=",i); scanf("%d",&a[i]); } //排序 for(i = 1;i < n;i++) { change = 0; for(j = 0;j < n-i;j++) { if(a[j] < a[j+1]) { temp = a[j]; a[j] = a[j + 1]; a[j + 1] = temp; change = 1; } } if(change = 0) { break; } } //输出 printf("排序后从大到小输出:\n"); for(i = 0;i < n;i++) { printf("%d\t",a[i]); } printf("\n"); }
直接插入法实现:
//直接插入法实现 void main() { int a[n]; int i; int j; int temp; //输入 printf("请输入待排序元素:\n"); for(i = 0;i < n;i++) { printf("a[%i]=",i); scanf("%d",&a[i]); } //排序 for(i = 1;i < n;i++) { j = i - 1; temp = a[i]; while((a[j] < temp) && (j >= 0)) { a[j + 1] = a[j]; j--; } a[j + 1] = temp; } //输出 for(i = 0;i < n;i++) { printf("%d\t",a[i]); } printf("\n"); }
直接插入法改进:
//直接插入法实现改进 void main() { int a[n]; int i; int j; int change; int temp; //输入 printf("请输入待排序元素:\n"); for(i = 0;i < n;i++) { printf("a[%i]=",i); scanf("%d",&a[i]); } //排序 for(i = 1;i < n;i++) { j = i - 1; temp = a[i]; change = 0; while((a[j] < temp) && (j >= 0)) { a[j + 1] = a[j]; j--; change = 1; } a[j + 1] = temp; if(change = 0) { break; } } //输出 for(i = 0;i < n;i++) { printf("%d\t",a[i]); } printf("\n"); }
3、
算法分析:采样直接插入法进行排序
(1)、用数组a存储待排序元素,n存储待排序元素的个数
(2)、让 i 表示排序的遍数,其值为从2到n
(3)、在每趟排序中,a[1],a[2],a[3]。。。,a[i-1] 已经排好序,以a[0] 为监视哨,将a[i]依次与a[i-1],a[i-2],.............,a[0]比较,即令循环变量j = i -1, i - 2, .... , 0
(4)、如果a[0] < a[j] ,则将a[j] 后移,否则终止此循环
(5)、将a[j + 1]的值赋为a[o]
#include <stdio.h> #include <stdlib.h> void main() { static int a[] = {23,56,234,1,45,34,21,394,3,35}; int i,j,temp; //排序 for(i = 1;i < 10;i++) { j = i - 1; temp = a[i]; //前面i-1个元素已经排好序 while((a[j] > temp) && (j >= 0)) // 把前面i-1个元素中比a[i]大的元素依次后移 { a[j + 1] = a[j]; j--; } a[j + 1] = temp; // 把a[i]插入到正确的位置 } //输出 for(i = 0;i < 10;i++) { printf(" %d",a[i]); } printf("\n"); }
改进:使用a[0] 作为监视哨,免去查找过程中每一步都要检测的数组是否越界的问题
代码:
#include <stdio.h> #include <stdlib.h> const int n = 10; //改进 void main() { int a[n+1]; int i,j; //输入 for(i = 1;i <= n;i++) { printf("请输入待排序数a[%d]:",i); scanf("%d",&a[i]); } //排序 for(i = 2;i <= n;i++) { a[0] = a[i]; for(j = i - 1;a[0] < a[j];j--) { a[j + 1] = a[j]; } a[j + 1] = a[0]; } //输出 for(i = 1;i <= n;i++) { printf("%d\t",a[i]); } }
4、将英语规则名词有单数变为复数,规则如下:
(1)、以字母y结尾,且y前面是一个辅音字母,则将y 变 i ,再加es;
(2)、以s、x、ch、sh结尾,则加es
(3)、以字母o结尾,则加es
(4)、其他情况直接加s
代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> void main() { char word[100]; int len; printf("请输入一个单词:"); scanf("%s",word); len = strlen(word); //求单词长度 // 若以y结尾 if((len > 1) && (word[len - 2] != 'a') && (word[len - 2] != 'e') && (word[len - 2] != 'i') && (word[len - 2] != 'o') && (word[len - 2] != 'u') && (word[len - 1] == 'y')) { word[len - 1] = 'i'; word[len] = 'e'; word[len + 1] = 's'; word[len + 2] = '\0'; } //若以s、x、ch、sh结尾 else if((word[len - 1] == 's') || (word[len - 1] == 'x') || (len > 1 && word[len - 1] == 'h' && (word[len - 2] == 'c' || word[len - 2] == 's'))) { word[len] = 'e'; word[len + 1] = 's'; word[len + 2] = '\0'; } //以o结尾 else if(word[len - 1] == 'o') { word[len] = 'e'; word[len + 1] = 's'; word[len + 2] = '\0'; } //其他方式结尾 else { word[len] = 's'; word[len + 1] = '\0'; } printf("单词的复数形式为:%s\n",word); }
5、明文变密文:
代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> void main() { char str1[200]; //存储明文 char str2[200]; //存储密文 int num; int len = 0; int i; //输入明文 printf("请输入明文:"); gets(str1); //求明文长度 len = strlen(str1); for(i = 0;i < len;i++) { num = -1; //初始化字母序列 //处理小写字母 if(str1[i] <= 'z' && str1[i] >= 'a') { num = str1[i] - 'a' + 1; num = num * 3 % 52; } //处理大写字母 else if(str1[i] <= "Z" && str1[i] >= "A") { num = str1[i] - 'A' + 27; num = num *3 % 52; } //密文为小写字母 if(num > 0 && num <= 26) { str2[i] = num + 'a' - 1; } //密文为大写字母 else if(num >= 27 && num <= 51) { str2[i] = num +'A' - 27; } //密文为Z else if(num == 0) { str2[i] = 'Z'; } //密文为其他字符 else { str2[i] = str1[i]; } } //为密文加上结束标志 str2[i] = '\0'; printf("密文是:%s\n",str2); }
6、【查找】
(1)、从前向后依次查找
代码:
#include <stdio.h> #include <stdlib.h> const int n = 7; void main() { int a[n + 1]; int i,j,x; //输入 for(i = 1;i <= n;i++) { printf("请输入a[%d]:",i); scanf("%d",&a[i]); } printf("请输入待查元素:"); scanf("%d",&x); //查找 for(i = 1;i <= n;i++) { if(a[i] == x) { break; } } if(i <= n) { printf("%d\n",i); } else printf("%d\n",0); }
(2)、从后向前,依次查找,故结束后不必对i的值进行比较
代码:
void main() { int a[n + 1]; int i,j,x; //输入 for(i = 1;i <= n;i++) { printf("请输入a[%d]:",i); scanf("%d",&a[i]); } printf("请输入待查元素:"); scanf("%d",&x); //查找 for(i = n;i >= 1;i--) { if(a[i] == x) { break; } } printf("%d\n",i); }
(3)、使用监视哨 ,免去查找过程中每一步都要检测的数组是否越界的问题
代码:
void main() { int a[n + 1]; int i,j,x; //输入 for(i = 1;i <= n;i++) { printf("请输入a[%d]:",i); scanf("%d",&a[i]); } printf("请输入待查元素:"); scanf("%d",&x); //查找 a[0] = x; //若到i = 0时,退出循环,i = 0 for(i = n;a[i] != x;i--); printf("%d\n",i); }
(4)、折半查找 【必须为有序数组】
算法思想:
代码:
void main() { int a[n + 1]; int i,x,low = 1,high = n,mid; //输入 for(i = 1;i <= n;i++) { printf("请输入有序数字a[%d]:",i); scanf("%d",&a[i]); } printf("请输入待查元素:"); scanf("%d",&x); //查找 while(low <= high) { mid = (low + high) / 2; if(x == a[mid]) break; else if(x < a[mid]) high = mid - 1; else low = mid + 1; } //输出 if(x == a[mid]) { printf("%d\n",mid); } else printf("%d\n",0); }
7、写一个函数,使其能将一个二维数组(5×3)中的数据进行行列互换(参考函数 原型:void tran(int array[5][3]))
代码:
#include <stdio.h> #include <stdlib.h> int b[3][5]; //外部二维数组,可以被全部函数访问 void tran(int array[5][3])//定义转秩函数,无返回值 { int i,j; for(i=0; i<5; i++) for(j=0; j<3; j++) b[j][i]=array[i][j];//交换 } main() { int i,j; int a[5][3]= {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; printf("交换前是:\n"); for(i=0; i<5; i++) { for(j=0; j<3; j++) printf("%4d",a[i][j]); printf("\n"); } tran(a);//调用交换函数实现对数组 a 的转秩 printf("\n 交换后是:\n"); for(i=0; i<3; i++) { for(j=0; j<5; j++) printf("%4d",b[i][j]); printf("\n"); } }
8、写一个函数,使其能统计主调函数通过实参传送来的字符串,对其中的字母、数字和空格分别计数(要求在主函数中输入字符串及输出统计结果)(参考函数原型:void count(char* str))
代码:
#include <stdio.h> #include <stdlib.h> int b[3]; //定义外部变量,用于存储各种字符的个数 void count(char *str)//定义统计函数 { while((*str)!=0) { if(('a'<=*str&&*str<='z')||('A'<=*str&&*str<='Z'))//求字符个数 b[0]++; if('0'<=*str&&*str<='9')//求数字个数 b[1]++; if(*str==' ')//空格个数 b[2]++; str++; } } void main() { char str[100]; printf("请输入字符串:\n"); gets(str); printf("字符串%s 中",str); count(str);//调用统计函数 printf("\n 字母个数:%d",b[0]); printf("\n 数字个数:%d",b[1]); printf("\n 其空格个数:%d",b[2]); }
程序分析:
定义了一个外部数组变量 b[3]用于存储各种字符的个数。
外部变量可以被全部函数共同访问,所以就不需要在统计函数和主函数中分开定义各自的统
计变量,更加方便和节省空间9、写一个函数,使其能处理字符串中除字母(大小写)、数字外的其他 ASCII 字符,对多于一个连在一起的相同字符,将其缩减至仅保留一个。(参考函数原型:void del(char*str))
算法分析:
难点在于处理连在一起的相同字符。首先定 义一个字符数组 str2[ ],用于存储判断处理后的字符串。字符串 str 开始循环后,如果是字母或者数字,就赋给 str2;如果是其他字符,先判断是否为连续,再进行赋值。连续的情况需要特殊处理,循环直到是其他字符后再赋值。
代码:
#include <stdio.h> #include <stdlib.h> char str2[80];//定义一个数组存储字符串 void del(char *str)//定义函数 { int i=0; while((*str)!=0) { if(('a' <= *str && *str <= 'z')||('A' <= *str && *str <= 'Z')||('0' <= *str && *str <= '9'))//判断 ASCII 码 { str2[i]=*str; str++; i++; } else//处理连在一起的相同其他字符 { while(*str==*(str+1)) str++; str2[i]=*str; str++; i++; } } } void main() { char str[80]; printf("请输入字符串:"); gets(str); del(str); printf("\n新字符串:%s\n",str2); }
10、设有一个 3 位数,将它的百、十和个位 3 个单一数,各自求立方,然后加起来,正好等于这个 3 位数,如 153=1+125+27。写一个函数,找出所有满足条件的数。(参考函数原型:int find(int n))
代码:
#include <stdio.h> #include <stdlib.h> int find(int n) { int i,j,k; //i 表示百位,j 表示十位,k 表示个位 int flag; //标志位,是否满足条件 i = n / 100; //求百位 j = n / 10 - i * 10; //求十位 k = n % 10; //求个位 if(n == i * i * i + j * j * j + k * k * k) //判断 flag = 1; else flag = 0; return flag; } void main() { int f,n; printf("符合条件的数有:"); for(n = 100; n < 1000; n++) //循环判断所有的三位数 { f = find(n); if(f) printf("%4d",n); } printf("\n"); }
11、写一个函数,使其能求出一元二次方程的解。(参考函数原型:void s(int a,int b,intc),a、b、c 分别代表一元二次方程的系数)
代码:
#include <stdio.h> #include <stdlib.h> float x1,x2; void s(int a,int b,int c) { int s;12 s = b * b -4 * a * c; //求两个解 x1 = (sqrt(s) - b) / (2 * a); x2 = (-sqrt(s) - b) / (2 * a); } main() { int a,b,c; printf("请输入一元二次方程的系数:"); scanf("%d,%d,%d",&a,&b,&c); if(a == 0)//去掉 a 为 0 的不合法方程 { printf("a 不能为 0!\n"); } else { s(a,b,c); printf("方程的解为:%f 和%f\n",x1,x2); } }
12、写一个程序,从键盘输入 5 个正整数,然后求出它们的最小公倍数,并显示输出(通过调用对两个正整数求最小公倍数的函数实现)(参考函数原型:int find(int i,int j))
代码:
#include <stdio.h> #include <stdlib.h> int find(int i,int j) { int temp,a,b; if(i<j)//保证用较大的数除以较小的数 { temp=i; i=j; j=temp; } a=i; b=j; while(b!=0)//辗转相除 { temp=a%b; a=b; b=temp; } return(i*j/a); } main() { int a[5],b,i; printf("请输入 5 个整数:"); for(i=0; i<5; i++) scanf("%d",&a[i]); b=find(a[0],a[1]);//调用函数对 5 个整数进行处理 b=find(b,a[2]); b=find(b,a[3]); b=find(b,a[4]); printf("5 个整数的最小公倍数是%d\n",b); }
13、如果一个数正好是它的所有约数(除了它本身以外)的和,此数称完备数,如:6,它的约数有 1、2、3,并且 1+2+3=6。求出 30 000 以内所有的完备数,并显示输出(求完备数用函数实现)(参考函数原型:void find(int j),直接在子函数中输出完备数及其所有约数)
算法分析:
对于整数 j,要求出所有的约数,需要对小于 j 的所有数进行循环。在每求
出一个约数的同时,j 减去这个约数,再将结果赋给 j,如果是完备数,最后的结果将是 0。
需要注意是的,j 的值在不断变化,为了保证 j 一直用初值进行求约数操作,所以首先将 j
的值赋给一个中间变量 s,利用 s 来进行减操作,让两步操作不相互影响。代码:
#include <stdio.h> #include <stdlib.h> int k[20]; void find(int j) { int i,n,s;//i 为因子 n = -1; s=j; for(i=1; i<j; i++) { if((j%i)==0) { n++; s = s - i; k[n]=i;//将每个因子赋给数组 k } } if(s==0) { printf("%d 是一个完备数,它的因子是:",j); for(i=0; i <= n; i++) printf("%6d",k[i]);//输出 printf("\n"); } } main() { int n; printf("符合条件的数有:\n"); for(n=1; n<30000; n++) find(n); }
14、如果有两个数,每一个数它的所有约数(除了它本身以外)的和正好等于对方,则称这两个数为互满数,求出 30 000 以内所有的互满数,并显示输出。求一个数它的所有约数(除了它本身以外)的和用函数实现(参考函数原型:int factor(int j))
代码:
#include <stdio.h> #include <stdlib.h> int k[40]; #define N 30000 int factor(int j) { int i,n,s;//i 为因子 n = -1; s=j; for(i=1; i<j; i++) { if((j%i)==0) { n++; s = s - i; k[n]=i;//将每个因子赋给数组 k } } s=1; for (i=1; i<=n; i++)s+=k[i]; // 将每个因子累加 return s; } void main() { int s1,s2,m,n; for (m=2; m<N; m++) { s1=factor(m); for (n=m+1; n<N; n++) { s2=factor(n); if(s1==s2) printf("%d和%d是互满数\n",m,n); } } }
15、函数实现将输入的一组数据逆序输出(参考函数原型:void isort(int a[]))
算法分析:
长度为 n 的数组 a[n]逆序的实现方法就是将 a[i]和 a[n−i−1]交换。
代码:
#include <stdio.h> #include <stdlib.h> #define N 5 void isort(int a[]) { int i,temp; for(i=0; i<N/2; i++) //交换 { temp=a[i]; a[i] = a[N - i - 1]; a[N - i - 1] = temp; } } main() { int a[N],i; printf("请输入%d 个数据:\n",N); for(i=0; i<N; i++) scanf("%d",&a[i]); isort(a); printf("逆序输出的结果是:"); for(i=0; i<N; i++) printf("%d\t",a[i]); printf("\n"); }