C语言基础编程题和基础算法题
来自于网络和自己的思考,因为来源广泛,仅供自己学习,感谢那些提供代码和提供题目的大佬,博主主要使用这篇文章记录自己的代码,不排除存在错误以及思考不够谨慎的方面;
基本思想:
辗转相除法:
辗转相除法,又叫欧几里得算法。两个正整数a和b(a>b),他们的最大公约数等于a除以b的余数和b之间的最大公约数。
比如10和25,25除以10余5,那么10和25的最大公约数等同于5和10之间的最大公约数。
1)使用递归:
#include<stdio.h>
int gcd(int a, int b)
{
if(a % b == 0)
return b;
else
gcd(b, a%b);
}
2)使用循环:
#include<stdio.h>
int gcd(int a, int b)
{
int temp;
while(a % b != 0)
{
temp = a % b;
a = b;
b = temp;
}
return b;
}
两个正整数a和b(a>b),他们的最大公约数等于a-b的差值c和较小数b的最大公约数。
比如10和25,25-10=15,那么10和25的最大公约数等于10和15的最大公约数。
代码省略,因为我觉得这种方法好麻烦的说,我还不理解;
##基础算法题
-
约瑟夫环
基础编程题
- 求s=a+aa+aaa+aaaa+aa…a的值,其中a是一个数字。例如2+22+222+2222+22222(此时共有5个数相加),几个数相加有键盘控制。
#include<stdio.h>
int main(void)
{
int m, n;
int summer;
while(scanf("%d %d", &m, &n) == 2)
{
summer = sum(m, n);
printf("sum = %d\n", summer);
}
return 0;
}
int sum(int m, int n)
{
int i; // 用来计数的变量;
int number = m; // 用来算第几个数字的变量;
int number1 = 1; //用来算是10的多倍;
int sum = 0; //总数;
for(i = 1; i < n; i++)
{
number1 *= 10;
number += m * number1;
sum += number;
}
if( n == 1)
sum = m;
else
sum += m;
return sum;
}
- 打印出如下图案(菱形)
#include<stdio.h>
#define N1 10
#define N2 9
void Space_pr(int n);
int main(void)
{
int i, j;
for( i = 1; i <= N1; i++)
{
Space_pr(i);
for(j = 1; j <= 2*i-1; j++)
printf("*");
printf("\n");
}
for( i = N2; i >= 1; i--)
{
Space_pr(i);
for(j = 1; j <= i*2-1; j++)
printf("*");
printf("\n");
}
return 0;
}
void Space_pr(int n)
{
int i = 0;
while( i != N1 - n)
{
printf(" ");
i++;
}
return 0;
}
- 求前20项和的结果,即2/1+3/2+5/3+8/5+13/8…,这道题的根据其实是熟知的小兔子问题,又叫斐波那契数列,重点是因为用int会损失精度,所以在设数列求解时也应该用double类型;斐波那契数列的特点是1,1, 2, 3, 5, 8, 13, 21, 37…,即f(n) = f(n - 1) + f( n - 2);
#include<stdio.h>
#define N 21
int main(void)
{
double a[N] = {0.0};
int i;
double sum = 2.0;
a[0] = 1.0;
a[1] = 2.0;
for(i = 2; i < N; i++)
{
a[i] = a[i-1] +a[i-2];
sum += a[i]/a[i-1];
}
printf("%f", sum);
return 0;
}
- 判断6位数是否为回文数?回文数即如122221,123321这种;
(其实我还有一点疑问,在main函数声明的变量,因为是在循环内层发生了变化,实际上也会传出来吗?如果是函数改变了变量的值,最后打印是否仍会变为原来的值还是打印函数发生变化的值?)
#include<stdio.h>
#define N 6
int main(void)
{
int number, temp;
int a[N];
int i, j;
printf("enter a number: ");
while(scanf("%d", &number) == 1)
{
temp = number;
for(int i = 0; i < N; i++)
{
a[i] = temp % 10;
temp /= 10;
}
for(i = 0, j = N - 1; i < j; i++, j--)
{
if( a[i] != a[j] )
{
printf("%d is not huiwenshu.\n", number);
break;
}
}
if( i >= j )
printf("%d is huiwenshu.\n", number);
printf("Please next number: ");
}
return 0;
}
5.删除一个字符串中的指定字母,如:字符串 “aca”,删除其中的 a 字母。
(这个题我有想到三种方法,第一种是在字符串中寻找特定的字母,碰到了就把后面的往前移,但是这种方法会多移删除字母的个数;第二种方法是在字符串中寻找特定的字母,碰到了就计数,最后把字符串整体移动,不过我不知道咋实现,因为需要在不改变顺序的情况下完成,且不增加空间复杂度;还有第三种方法,就是下面我写代码的这个方法,就是找到了特定的字母,就把它往后放,最后统一删除,我只写出了查找的方法, 没写删除,其实最好应该把删除和寻找写成两个函数,然后在放到主函数l里面去。
#include<stdio.h>
#include<strings.h>
#define N 100
int main(void)
{
char a[N];
char ch, temp;
char i = 0, j;
printf("Pleae enter a string of characters: ");
gets(a);
printf("Please enter a letter to delete: ");
ch = getchar();
j = strlen(a) - 1;
while( i < j)
{
if(a[i] != ch)
i++;
else
{
if(a[j] != ch)
{
temp = a[j];
a[j] = a[i];
a[i] = temp;
i++;
j--;
}
else
j--;
}
}
puts(a);
return 0;
}
- 判断输入的数是否为质数;
(艾希,我最开始的时候忘记考虑输入的数字为1的情况了,如果用户输入的不是数字,我不知道这个报错语句加在哪里才可以重新又开始循环判断;)
#include<stdio.h>
int gcd(int n);
int main(void)
{
int number;
printf("Please enter a number: ");
while(scanf("%d", &number) == 1)
{
if( number == 1)
printf("1 is zhishu.");
else
{
if( number == gcd(number))
printf("%d is zhishu.", number);
else
printf("%d is not zhishu.", number);
}
printf("\nPlease enter a next number(enter q to quit): ");
}
return 0;
}
int gcd(int n)
{
int i;
int number;
for( i = 2; i <= n; i++)
{
if( n % i == 0)
break;
}
return i;
}
- 字符串反转,如将字符串“www.runoob.com”反转为“moc.boonur.www”。
#include<stdio.h>
#define N 1000
int main(void)
{
char a[N];
int i, j;
char temp;
printf("Please enter a string of characters: ");
gets(a);
j = strlen(a) - 1;
for(i = 0; i < j; i++, j--)
{
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
puts(a);
return 0;
}
- 求100以内的质数;
(感受到了使用定义字符常量的好处,直接修改字符中的数字,就可以实现求1000,求1000的质数了)
#include<stdio.h>
#define N 100
int main(void)
{
int i;
int number = 1;
while( number < N)
{
for( i = 2; i <= number / 2; i++)
{
if(number % i == 0)
break;
}
if( i >= number / 2 && i * i != number)
printf("%5d", number);
number++;
}
return 0;
}
- 求10个数排序;
(下面是我写的程序,这个程序有两个问题,第一个是当输入超过10个的时候,它会自动舍弃10个后面的数据进行排序,第二个是当输入不是数字的时候,虽然会提示输入错误,然后需要重新输入,如果输入的是一串字符,它就会提示字符串个数个报错,重复n*”Please enter right number“次;我不知道咋解决这个问题;还有就是如果是输入的字符和数字这种不正确的格式,它会保留字符后面的数字,然后提示一次报错,但是其实后面输入的数字并没有什么卵用。这里的排序我用的是简单排序,就是每进行一次排序,至少保证一个数字被排好了);
#include<stdio.h>
#define N 10
void Paixu(int number[], int n);
int main(void)
{
int i;
int number[N];
printf("Please enter 10 numbers: ");
for(i = 0; i < N; i++)
{
while(scanf("%d", &number[i]) != 1)
{
printf("Please enter right number: ");
getchar();
}
}
Paixu(number, N);
for(i = 0; i < N; i++)
{
printf("%5d ", number[i]);
}
return 0;
}
void Paixu(int number[], int n)
{
int i, j;
int temp;
for(i = 0; i < n; i++)
{
for(j = i + 1; j < n; j++)
{
if( number[j] > number[i])
{
temp = number[j];
number[j] = number[i];
number[i] = temp;
}
}
}
return 0;
}
- 求3X3矩阵的对角线和;
#include<stdio.h>
#define VOL 3
#define COL 3
int main(void)
{
int i, j;
int a[VOL][COL];
int sum = 0;
for(i = 0; i < VOL; i++)
{
printf("Please enter the volumn: ");
for(j = 0; j < COL; j++)
{
if(scanf("%d", &a[i][j]) != 1)
{
printf("Please enter the right number.");
getchar();
j--;
}
}
}
for(i = 0; i < VOL; i++)
{
for(j = 0; j < COL; j++)
{
if(i == j)
sum += a[i][j];
}
}
printf("The sum of the main duijiaoxian is %d.", sum);
sum = 0;
sum = a[0][COL-1] + a[1][1] + a[2][0];
printf("The sum of the duijiaoxian is %d.", sum);
return 0;
}
- 插入一个数到 数组中,使其接着按照原来的方法排序;
#include<stdio.h>
#define N 11
void Paixu(int a[], int number, int n);
int main(void)
{
int number;
int n;
int a[N] = {1, 4, 16, 18, 23, 54, 55, 57, 58, 60};
n = sizeof a / sizeof(a[0]);
printf("This is already list like a[] = {1, 4, 16, 18, 23, 54, 55, 57, 58, 60}, ");
printf("\nPlease enter a number: ");
scanf("%d", &number);
Paixu(a, number, n);
printf("The finish list is a[] = {");
for(int i = 0; i < n; i++)
{
printf("%d ", a[i]);
}
printf("}");
return 0;
}
void Paixu(int a[], int number, int n)
{
int i, temp;
a[n-1] = number;
for(i = n-1; i >=0; i--)
{
if(a[i] < a[i-1])
{
temp =a[i-1];
a[i-1] = a[i];
a[i] = temp;
}
}
return 0;
}
- 将一个数组倒序排列;
#include<stdio.h>
#define N 10
void reverse(int a[]);
int main(void)
{
int a[N] = {12, 22, 31, 1, 2, 3, 1, 6, 9, 10};
int i;
printf("Please enter a list a[N] ={12, 22, 31, 1, 2, 3, 1, 6, 9, 10}");
reverse(a);
printf("\nReverse the list is that a[N]={");
for(i = 0; i < N; i++)
{
printf("%d ", a[i]);
}
printf("}");
return 0;
}
void reverse(int a[])
{
int j, k, temp;
for(j = 0, k = N - 1; j < k; j++, k--)
{
temp = a[j];
a[j] = a[k];
a[k] = temp;
}
}
- 计算字符串中子串出现的次数 。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define N 50
#define M 5
int main(void)
{
int i, j, k, cnt = 0, S1length, S2length;
char S1[N], S2[M];
printf("请输入一个字符串: \n");
gets(S1);
printf("请输入一个字符子串: \n");
gets(S2);
S1length = strlen(S1);
S2length = strlen(S2);
for(i = 0; i < S1length; i++)
{
j = 0;
k = i;
while(j < S2length)
{
if(S1[k] == S2[j])
{
k++;
j++;
}
else
break;
}
if(j == S2length)
cnt++;
}
fputs(S1, stdout);
printf("中有%d个", cnt);
fputs(S2, stdout);
return 0;
}
- 两个字符串连接;
#include<stdio.h>
#include<string.h>
#define N 1000 //后面出现的字符串长度不能超过该数值范围;
void strconnect(char *str1, int n, char *str2, int m);
int main(void)
{
int str1length = 0, str2length = 0;
char str1[N];
char str2[N];
puts("请输入第一个字符串: ");
gets(str1);
puts("请输入第二个字符串: ");
gets(str2);
str1length = strlen(str1);
str2length = strlen(str2);
strconnect(str1, str1length, str2, str2length);
puts(str1);
puts(str2);
return 0;
}
void strconnect(char *str1, int n, char *str2, int m)
{
int i, j;
char *ch;
for(i = 0; i < m; i++)
{
str1[n+i] = str2[i];
}
str1[n+m] = '\0';
return 0;
}
- 偶数总能够表示为2个素数相加;
(偶其实也不太喜欢太长的代码,奈何现在处于新手期,不太能缩减代码~)
#include<stdio.h>
int isPrime(int n);
int main(void)
{
int i, j;
int number;
printf("请输入一个偶数: ");
scanf("%d", &number);
for(i = 2; i < number; i++)
{
if(isPrime(i) == 1)
{
if(isPrime(number-i) == 1)
{
printf("%d = %d + %d", number, i, number - i);
break;
}
}
}
return 0;
}
int isPrime(int n)
{
int i = 2;
while(i < n)
{
if(n % i == 0)
break;
i++;
}
if(i == n)
{
return 1;
}
else
return 0;
}
- 给定一串字符串,将其进行排序;
(纪念我第一次用上指针~)
#include<stdio.h>
#include<string.h>
#define N 1000
int main(void)
{
int length;
char str[N];
puts("请输入一串字符串: ");
gets(str);
length = strlen(str);
strorder(str, length);
puts("排序后的字符串为: ");
printf("%s", str);
return 0;
}
void strorder(char *str,int length)
{
int i, j, temp;
for(i = 0; i < length; i++)
{
for(j = i + 1; j < length; j++)
{
if(*(str + i) > *(str + j))
{
temp = *(str + i);
*(str + i) = *(str + j);
*(str + j) = temp;
}
}
}
return 0;
}
- 编写一个函数,输入n为偶数时,调用函数求1/2+1/4+…+1/n,当输入n为奇数时,调用函数1/1+1/3+…+1/n。
#include<stdio.h>
float qiannxianghe(int number);
int main(void)
{
int number;
float sum;
puts("请输入一个数: ");
scanf("%d", &number);
sum = qiannxianghe(number);
if(number % 2 == 0)
printf("1/2+1/4+1/6......+1/n之和%.4f。\n", sum);
else
printf("1/1+1/3+1/5......+1/n之和%.4f。\n", sum);
return 0;
}
float qiannxianghe(int number)
{
int i = 0, k = 0;
float sum = 0;
if( number % 2 == 0)
{
while( k < number)
{
k = (i + 1) * 2;
sum += 1.0 / k;
i++;
}
}
else
{
while( k < number)
{
k = i * 2 + 1;
sum += 1.0 / k;
i++;
}
}
return sum;
}
- 将一个整数反转,并输出;
#include<stdio.h>
#define N 100
int main(void)
{
int number, i, n;
int a[N];
printf("请输入一个10~100000以内的整数: \n");
scanf("%d", &number);
n = number;
printf("反转后的整数位: \n");
for(i = 0; i < N; i++)
{
if( n != 0)
{
a[i] = n % 10;
printf("%d", a[i]);
n /= 10;
}
}
return 0;
}