若干C的练习题 (不定期更新)
扎实基本功
- 整数转二进制
- 用筛选法求100之内的素数
- 判断素数
- 水仙花数
- 输出完数
- 两数最大公约数以及最小公倍数
- 斐波那契数列
- 小球10m落下,每次回弹高度一半,静止后的距离
- 两队比赛,求名单 a不和d, c不和d , f
- 三字符求最大
- 统计字符
- 鞍点,行最大,列最小
- 第i个字母变成第(26-i+1)个字母
- 两字符串生接在一起
- 两字符串复制起来
- 将数组里的负数排在最靠前
- 两数组比较,统计对应元素比大小的个数
- 输入字符串,并反序
- 求和 a+aa+aaa+aaaa+aaaaa+aaaaaa+...+a.......a
- static用法
- 一年中的第几天
- 字符串长度
- 数组往后移动n位,循环移动
- 截取字符串从m位,包含m位的后面的全部
- 分数列前20项1/2,2/3,3/5,5/8.....之和
- 十行杨辉三角形
- 递归法求n阶勒让德多项式的值
- 字符串中的偶数下标提出来
- 5个字符串排排序
- 结构体相关操作
- n个人围成圈,1 2 3循环数,数到3就出局,下面的人继续,直到最后一个
- 100 到 999 的数,数里面的数字是互不相同的,而且能开根号
- 字符串s中删除字串t,t可能出现多次
整数转二进制
用递归,思想就是找下这个整数和2的几次方最接近,而且这个2的几次方还不能大于整数,找到后,减去再重复,知道剩下1或者0为止。看代码吧
char *zhuanerjinzhi(int n, char *a, int ci){
//要是n被减的到负数了,那就此为止吧
if(n <= 0) return a;
//记一下这个是2的第几次方
int j = 0;
//这个就是2
int z = 2;
//如果n-z大于等于0,那么n里面还有东西,还得加大z的值
while ((n-z) >= 0) {
//z往大一走就是两倍的走
z*=2;
//顺便记下这个z,现在是j+1次方
j++;
}
//OK出来了,说明已经碰见比n还要大的z了,那就说明n应该就在2的j次方
//赋值
a[j] = '1';
//要是第一次的话那就紧接着在后面家上结束符,要不输出不好看
if(ci == 0){
a[++j] = '\0';
}
//如果减去之后得到剩下的数等于一的话,那就是2的0次方赋值为一
if(n-z/2 == 1){
a[0] = '1';
}else{
//不是的话就进入递归就好了
zhuanerjinzhi(n - z/2, a, ++ci);
}
//最后返回a
return a;
}
//逆转
char nizhi(char* a){
int Strlen = strlen(a);
char temp;
for (int i = 0; i < Strlen/2; i++) {
temp = *(a + Strlen - i - 1);
*(a + Strlen - i - 1) = *(a+i);
*(a+i) = temp;
}
}
void main (){
//最大到2的20次方,肯定超不过就行
char b[20] = {'0','0','0','0','0','0','0','0','0','0','0','0','0',
'0','0','0','0','0','0','0'};
char *a = b;
//给个10
a = zhuanerjinzhi(10, a, 0);
nizhi(a);
printf("%s\n" ,a);
}
用筛选法求100之内的素数
int a[100] = {};
int b = 2;
for (int i = 0; i < 100; ++i) {
a[i] = i;
}
a[1] = 0;
//到此为止有了一个初步的数组
//下面开始除以除数,除数最大就是sqrt(100)
while (b < sqrt(100)){
//遍历数组中的有效值
for (int i = 0; i < 100; ++i) {
//数组中的数字不为零,而且可以整除除数且不等于除数
if(a[i] != 0 && a[i] % b ==0 && a[i] != b)
{
//置零
a[i] = 0;
}
}
//除数累加
b++;
}
//输出
for (int i = 0; i < 100; ++i) {
if(a[i] != 0)
{
printf("%5d", a[i]);
}
}
2 3 5 7 11 13 17 19 23 29 31 37
41 43 47 53 59 61 67 71 73 79 83 89
97
判断素数
#define OK 1
#define ERR 0
typedef int Status;
Status isSu(int n){
int i;
for (i = 2; i < n; i++) {
if(n%i == 0){
return ERR;
}
}
return OK;
}
水仙花数
//1-20000的水仙花数
void outputShuixianhua(int s, int e){
int i;
int shuixianhua(int);
for (i = s; i <= e; i++) {
if(i == shuixianhua(i)){
printf("%6d", i);
}
}
}
//求出水仙花数
int shuixianhua(int n){
int weishu(int);
int w = weishu(n);
int i, k, j, sum = 0;
for (i = 0; i < w; i++) {
k = 1;
for (j = 0; j < w; j++) {
k *= n%10;
}
n = n/10;
sum += k;
}
return sum;
}
//求该数有几位
int weishu(int n){
int i = 0;
while (n) {
n = n/10;
i++;
}
return i;
}
输出完数
void outputFineDig(int s, int e){
int i;
int gongyinshuSum(int);
for (i = s; i <= e; i++) {
if(i == gongyinshuSum(i)){
printf("%6d", i);
}
}
}
//公因数之和
int gongyinshuSum(int n){
int sum = 0, i;
for (i = 1; i < n; i++) {
if(n%i==0){
sum+=i;
}
}
return sum;
}
两数最大公约数以及最小公倍数
//最大公约数
int zuidagongyue(int n, int m){
int k = 0;
//初始顺序
if(n > m){
k = n;
n = m;
m = k;
}
//辗转横跳逼出结果
while (m%n != 0) {
k = m;
m = n;
n = k%n;
}
return n;
}
//最小公倍数
int zuixiaoGongbei(int n, int m){
return m*n/zuidagongyue(n, m);
}
斐波那契数列
//递归
int feibolaqie(int n){
if(n == 1){
return 1;
}
if(n == 2){
return 1;
}
return feibolaqie(n-1)+feibolaqie(n-2);
}
小球10m落下,每次回弹高度一半,静止后的距离
//也就是求极限
float ziyouxialuo(float n){
float sum = 0,temp = n;
n = 2 * n;
while (n != 0) {
sum += n;
n = n/2;
}
return sum - temp;
}
两队比赛,求名单 a不和d, c不和d , f
char A[3] = {'a', 'b', 'c'};
char B[3] = {'d', 'e', 'f'};
int i, j;
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
if((*(A+i) == 'a' && *(B+j)=='d') ||( A[i] == 'c' && (B[j] == 'd' || B[j] == 'f')))
continue;
printf("%c vs %c\n", A[i], B[j]);
}
}
三字符求最大
//三字符求最大
char * zuidazifu(char *a, char *b, char *c, char *t){
//strcmp
//如果返回值 < 0,则表示 str1 小于 str2。
//如果返回值 > 0,则表示 str2 小于 str1。
//如果返回值 = 0,则表示 str1 等于 str2。
strcpy(t, a);
if (strcmp(b, t) > 0) {
strcpy(t, b);
}
if(strcmp(c, t) > 0)
{
strcpy(t, c);
}
return t;
}
统计字符
//三行,分别统计每行大小写空格数字空格及其他
char sum[100] = "aS #1w\nasdas\n234Sx\n";
int up,low,dig,spac,other,hang,index;
hang = 1;
up = low = dig = spac = other = index = 0;
while (*(sum+index) != '\0') {
printf("%c", *(sum+index));
if (*(sum+index) != '\n') {
if(*(sum+index) == ' ')
spac++;
else if(*(sum+index) >= 'A' && *(sum+index) <= 'Z')
up++;
else if (*(sum+index) >= 'a' && *(sum+index) <= 'z')
low++;
else if (*(sum+index) >= '0' && *(sum+index) <= '9')
dig++;
else
other++;
}else{
printf("第%d行 数字:%d 大写:%d 小写:%d 空格:%d 其他:%d", hang, dig, up, low, spac, other);
printf("\n");
up = low = dig = spac = other = 0;
hang++;
}
index++;
}
鞍点,行最大,列最小
//二维数组鞍点 行最大列最小
int andian(int p[][3]){
int i, j;
int mincol,maxrow,row = 0,col = 0,biaoji = 0;
maxrow = 0;
mincol = INT32_MAX;
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
printf("%3d ", p[i][j]);
}
printf("\n");
}
for (i = 0; i < 3; i++) {
//找到每行最大的坐标出来
for (j = 0; j < 3; j++) {
//在具体的一行找到此行最大值
//并记录最大值的两个下标
if(p[i][j] > maxrow){
maxrow = p[i][j];
col = j;
biaoji = i;
}
}
//在找到行最大值的的列中,看看它是不是列里面最小的值
for (j = 0; j < 3; j++) {
//列下标不动,只需要动前面行下标即可
//找到最小的也记录下它的坐标
if(p[j][col] <= mincol){
mincol = p[j][col];
row = j;
}
}
//要是行的坐标一样大,看来是同一个值,就意味着找到了
if(biaoji == row){
printf("%d\n", p[row][col]);
return p[row][col];
}
//每次找完都要重置最大最小值
mincol = INT32_MAX;
maxrow = 0;
}
//-1啥也没找到,当然返回值待议
return -1;
}
第i个字母变成第(26-i+1)个字母
//电文加密,第i个变成第(26-i+1)个
char sum[100] = "abcdefghijklmnopqistuvwxyz\nABCDEFGHIJKLMNOPQISTUVWXYZ";
char *p = sum;
int index = 0;
//循环的时候也可以用 p++; 代替index
while (*(p+index) != '\0') {
printf("%c", *(p+index));
//小写字母
//先看看该字母是第几位与第一位‘a’做差加一
//第2位的话那就对应倒数第2个也就是第25个
//从‘a’开始算那就是后面的25-1个
if(*(p+index) <= 'z' && *(p+index) >= 'a'){
*(p+index) = 'a'+26 - (*(p+index)-'a' + 1);
}
//大写字母
if(*(p+index) <= 'Z' && *(p+index) >= 'A'){
*(p+index) = 'A'+26 - (*(p+index)-'A' + 1);
}
index++;
}
printf("\n");
index = 0;
while (*(p+index) != '\0') {
printf("%c", *(p+index));
index++;
}
printf("\n");
两字符串生接在一起
char a[40] = "asdasd";
char b[20] = "iuiwer";
char *p1 = a;
char *p2 = b;
//把p1指向a的末尾的'\0'
while (*p1 != '\0') {
p1++;
}
//把p2的最开始的字符送给p1末尾的'\0'
while (*p2 != '\0') {
*p1++ = *p2++;
}
//最后p1指向了整个结尾,就是缺了个'\0',补上
*p1 = '\0';
printf("%s", a);
两字符串复制起来
//字符串复制
char a[100];
char b[100];
char *p1 = a;
char *p2 = b;
gets(a);
while ((*p2++ = *p1++) != '\0');
printf("%s", b);
将数组里的负数排在最靠前
//将负数排在最前面
int a[10] = {2,3,123,232,1,-3,-1,-02,-10,0};
int i = 0;
int j = 9;
int temp;
//两个没有见面就一直找下去
while (j > i) {
//此时从当前位置往后找到第一个大于零的数字
while (a[i] < 0 && i <= 9) {
i++;
}
//从当前位置往前找第一个小于零的数字
while (a[j] > 0 && j >= 0) {
j--;
}
//然后两者互换位置
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
for (temp = 0; temp < 10; temp++) {
printf("%d ", a[temp]);
}
两数组比较,统计对应元素比大小的个数
//两数组比较,统计对应元素比大小的个数
int a[10] = {1,23,3,33,34,9,2,34,54,4};
int b[10] = {12,45,23,75,34,23,46,34,1,56};
int i, comp1 = 0,comp2 = 0;
for (i = 0; i < 10; i++) {
if(a[i]>b[i])
{
comp1++;
}
else if (a[i]<b[i])
{
comp2++;
}
printf("%d,%d\n",a[i],b[i]);
}
printf("%d %d", comp1, comp2);
输入字符串,并反序
//输入字符串,并反序
void reverseStr(char * a){
int i, Strlen = (int)strlen(a);
char temp = ' ';
for (i = 0; i < Strlen/2; i++) {
temp = *(a + Strlen - i - 1);
*(a + Strlen - i - 1) = *(a+i);
*(a+i) = temp;
}
}
求和 a+aa+aaa+aaaa+aaaaa+aaaaaa+…+a…a
//求和
int sum(int a, int n){
int sum = 0, i = 1;
//个位相加,十位相加,百位相加
while (n) {
sum += a*i*n;
i *= 10;
n--;
}
return sum;
}
static用法
//static变量的用法
int process(int a, int b){
//就跟单例模式一样,初始化只走一次
static int i = 0;
//在函数中,i是一个静态的局部变量,但是随着外面对函数的调用,值是不会被抹去的
i++;
if(i == 1)
return a>b?a:b;
if(i == 2)
return a<b?a:b;
if(i == 3)
return a+b;
return i;
}
一年中的第几天
//第几天
int Howmanydays(int y, int m, int d){
int days = 0, i;
int M[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
//判断闰年加一天
if( y%400 == 0 || ( y%100 != 0 && y%4 == 0 ) ){
M[2]+=1;
}
//将前面的整月天数算上
for (i = 0; i < m; i++) {
days+=M[i];
}
//再加上这个月的日子
days+=d;
//就酱
return days;
}
字符串长度
char s[100];
gets(s);
char *p1 = s;
//循环完毕后p1指向了'\0',最后一个的后一个
while (*++p1 != '\0');
//s指向了第一个,他们中间相差恰巧就是char的长度
printf("%ld",p1-s);
数组往后移动n位,循环移动
//往后排
int arra[10] = {1,2,3,4,5,6,7,8,9,10};
int i, j, m, temp;
scanf("%d", &m);
//每次移动一位,移动m次
for (i = 0; i < m; i++) {
temp = arra[9];
for (j = 8; j >= 0; j--) {
arra[j+1] = arra[j];
}
arra[0] = temp;
}
//输出
for (i = 0; i < 10; i++) {
printf("%3d", arra[i]);
}
截取字符串从m位,包含m位的后面的全部
//截取字符串从m位以后的全部
char a[100] = "abcdefjhijklmn";
char b[100];
char *p1, *p2;
p1 = a;
p2 = b;
int m, len = (int)strlen(a);
scanf("%d", &m);
if(m > len && m < 0){
printf("Noooo!");
}else
{
//直接找到第m位的字符,包含第m个字符,后面全都要
while (*(p1+m-1) != '\0') {
*p2++ = *(p1+m-1);
p1++;
}
*p2 = '\0';
}
printf("%s", b);
分数列前20项1/2,2/3,3/5,5/8…之和
//分数列前20项1/2,2/3,3/5,5/8.....
int i;
float sum = 0, fenzi, fenmu, temp;
fenzi = 1;
fenmu = 2;
//迭代20次
for (i = 0; i < 20; i++) {
//加加加加
sum += fenzi/fenmu;
//产出下一个分子分母
temp = fenzi;
fenzi = fenmu;
fenmu += temp;
}
//输出咯
printf("%.2f", sum);
十行杨辉三角形
//杨辉三角形,就是个二维数组
int i, j;
int yang[10][10] = {{1,},{}};
for (i = 0; i < 10; i++) {
//第i行就输出i个数字
for (j = 0; j <= i; j++) {
printf("%d ", yang[i][j]);
//趁这个机会就可以填存下一个数组的前i个数
//有点奇怪的是yang[0][-1]我的编译器没报错并且还等于0
//应该是个野值才对,严格的写的话,这里得判断一下
if(i != 9)
yang[i+1][j] = yang[i][j]+yang[i][j-1];
}
//下一行比上一行多一个,那就加上
if(i != 9)
yang[i+1][j] = yang[i][j]+yang[i][j-1];
printf("\n");
}
/*
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
*/
递归法求n阶勒让德多项式的值
double duoxiang(int n, double x){
if(n == 0)
return 1;
if(n == 1)
return x;
else
return ((2*(n-1)+1)*x*duoxiang(n-1,x) - (n-1)*duoxiang(n-2, x))/n;
}
字符串中的偶数下标提出来
char str1[100] = "acacacacacadasasawafasafas";
char str2[100];
//初始下表为1
int index = 1;
char *p1, *p2;
p1 = str1;
p2 = str2;
//边走边赋值
while (*(p1+index) != '\0' || *(p1+index-1) != '\0') {
*p2++ = *(p1 + index);
index += 2;//一次跳两个
}
printf("%s", str2);
5个字符串排排序
char str[5][100];
char temp[100];
printf("输入第1个字符串");
gets(str[0]);
printf("输入第2个字符串");
gets(str[1]);
printf("输入第3个字符串");
gets(str[2]);
printf("输入第4个字符串");
gets(str[3]);
printf("输入第5个字符串");
gets(str[4]);
//遍历快排
int i, j, tempindex;
for (i = 0; i < 5; i++) {
tempindex = i;
strcpy(temp, str[i]);
//从后面的几个元素挑出来最小的
for (j = i; j < 5; j++) {
if(strcmp(temp, str[j]) > 0)
{
strcpy(temp, str[j]);
tempindex = j;
}
}
//标记的换一下
if (tempindex != i) {
strcpy(temp, str[i]);
strcpy(str[i], str[tempindex]);
strcpy(str[tempindex], temp);
}
}
//输出一下
for (i = 0; i < 5; i++) {
printf("%s\n", str[i]);
}
结构体相关操作
//八个同学
int i, j, temp;
CoursesScore tempCourseSoure;
CouersesScoreRecords courseScoreRecors = {{98,90,86,"王小明"},{76,87,90,"刘晓华"},{75,69,86,"张晓霞"},{79,86,90,"李晓玲"},
{92,78,75,"赵小安"},{87,83,86,"卢小荣"},{76,72,86,"周晓鸥"},{91,84,86,"戴小伟"}
};
float average[8];
int sum[8];
int classsum[3];
//输入也行的
for (i = 0; i < 8; i++) {
// printf("姓名:");
// gets(courseScoreRecors[i].StudentName);
// printf("语文:");
// scanf("%d", &courseScoreRecors[i].ChineseScore);
// printf("数学:");
// scanf("%d", &courseScoreRecors[i].MathScore);
// printf("英语:");
// scanf("%d", &courseScoreRecors[i].EnglishScore);
sum[i] = courseScoreRecors[i].ChineseScore + courseScoreRecors[i].MathScore + courseScoreRecors[i].EnglishScore;
average[i] = sum[i]/3.0;
classsum[0] += courseScoreRecors[i].ChineseScore;
classsum[1] += courseScoreRecors[i].MathScore;
classsum[2] += courseScoreRecors[i].EnglishScore;
}
for (i = 0; i < 8; i++) {
printf("姓名:%s,语文:%d,数学:%d,英语:%d,平均分:%.2f,总分:%d\n", courseScoreRecors[i].StudentName, courseScoreRecors[i].ChineseScore, courseScoreRecors[i].MathScore, courseScoreRecors[i].EnglishScore,average[i],sum[i]);
}
printf("语文总分,数学总分,英语总分");
for (i = 0; i < 3; i++) {
printf(", %d",classsum[i]);
}
printf("\n");
//冒泡泡
for (i = 0; i < 8; i++) {
for (j = 0; j < 7 - i; j++) {
if(sum[j] < sum[j+1]){
//在总分里排排序
temp = sum[j];
sum[j] = sum[j+1];
sum[j+1] = temp;
//相应的在结构体里排排序
tempCourseSoure = courseScoreRecors[j];
courseScoreRecors[j] = courseScoreRecors[j+1];
courseScoreRecors[j+1] = tempCourseSoure;
}
}
}
//输入这个排名呢
for (i = 0; i < 8; i++) {
printf("姓名:%s,语文:%d,数学:%d,英语:%d,总分:%d\n", courseScoreRecors[i].StudentName, courseScoreRecors[i].ChineseScore, courseScoreRecors[i].MathScore, courseScoreRecors[i].EnglishScore,sum[i]);
}
n个人围成圈,1 2 3循环数,数到3就出局,下面的人继续,直到最后一个
//n个人,3个3个走,可以用循环列表做,那样会特别简单,我用了数组试了一下
int n, i, k = 1, temp, flag = 1;
scanf("%d", &n);
temp = n;
int arra[n];
//赋值,给它弄成自然数
for (i = 0; i < n; i++) {
arra[i] = i+1;
}
//打印一下
for (i = 0; i < n; i++) {
printf("%3d", arra[i]);
}
printf("\n");
//处理开始,从第一号人开始
i = 0;
//理论上循环所以永远为真,
while (flag) {
//这里判断数组里面是不是0,是0就说面已经出去了,不是的话则还是游戏中呢
if(arra[i] != 0){
//是不是输了三次,特别注意,第一个人应该数的数字是1,k的初始值就为1
while (k == 3) {
//第i个人喊出了他的编号
printf("%3d",arra[i]);
//这个值记录当前还剩多少人,剩到一个人时,那就出来吧
if(temp == 1){
printf("\n******** ");
printf("%d",arra[i]);
printf(" ********");
flag = 0;
}
//数完之后总人数减一,并在他的位置上给标记的0,而且还要重新数数
temp--;
arra[i] = 0;
//k应该为1,但是下面会执行k++,所以这里为了统一就给0
k = 0;
}
//k的发动机开始启动,每次报数的人都算一次
k++;
}
//这里就是循环走,下一个下一个,到最后的时候,再排到前面
i++;
if(i == n){
i = 0;
}
}
// 给了30个数字的测试结果
// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
// 3 6 9 12 15 18 21 24 27 30 4 8 13 17 22 26 1 7 14 20 28 5 16 25 10 23 11 2 19 29
// ******** 29 ********
100 到 999 的数,数里面的数字是互不相同的,而且能开根号
void putout(){
int i, j, k, temp;
//寻找数
for (i = 1; i < 10; i++) {
for (j = 0; j < 10; j++) {
for (k = 0; k < 10; k++) {
//看条件1是否符合
if(i == j || j == k || i == k)
continue;
temp = i * 100 + j * 10 + k;
//条件2是否符合
if((sqrtf(temp) - (int)sqrt(temp)) == 0){
printf("%d, %f\n", temp, sqrt(temp));
}
}
}
}
}
字符串s中删除字串t,t可能出现多次
void delsubStr(char *s, char *t){
char *p1 = s, *p2 = t, *temp = s;
//母串永远有东西就永远不停留
while (*temp != '\0') {
//找一个字串
while (*p1 == *p2 && *p1) {
p1++;
p2++;
}
//如果没找到,母串从下一个找,在初始化所有的字串
if(*p2){
temp++;
p1 = temp;
p2 = t;
}
//如果找到了,就删除
else
{
//p2临时记录母串的位置
p2 = temp;
//往后走,就是把p1后面的提前
while (*p1) {
*temp++ = *p1++;
}
//删除结束善尾工作
*temp = '\0';
//整体结束后,再往后走
temp = p2;
temp++;
}
}
}
本文来自博客园,作者:赫凯,转载请注明原文链接:https://www.cnblogs.com/heKaiii/p/15491266.html