写在开头:题源来自于凌云、吴海燕、谢满德老师们编著的《C语言程序设计与实践》第六章C语言结构的课后练习题。
编译器:Dev C++
代码是根据自己的逻辑来实现的,部分题目的算法思想写在了程序代码的注释中。有些解法仅仅是能够实现最终结果,但不一定是最优算法,比如有许多两个for循环甚至三个或更多的for循环暴力实现的算法,这些算法是一定可以优化的。希望我的解法能够给大家有所帮助,如果读者大大们有更好的思路和算法,也希望能在评论区留下更宝贵的智慧。
- 输入一个字符串,输出其中所出现过的大写英文字母
/*输入一个字符串,输出其中所出现过的大写英文字母*/
/*定义s1[]接受输入的字符串,s2为存放筛选之后的字符串*/
#include<stdio.h>
#define MAX 100
int main(){
char s1[MAX]="\0";
char s2[MAX]="\0";
int i,j;
j=0;
printf("请输入一个字符串:\n");
gets(s1);
for(i=0;i<strlen(s1);i++){
if(s1[i]>='A'&&s1[i]<='Z')
s2[j++]=s1[i];
}
printf("字符串s1中出现过的大写字母为:\n");
puts(s2);
return 0;
}
效果图如下:
- 输入10个整数,找出最小的数和他的下标,然后把它和数组中最前面的元素对换
/*输入10个整数,找出最小的数和他的下标,然后把它和数组中最前面的元素对换*/
#include<stdio.h>
int main(){
int n[10],i,j,min;
scanf("请输入10个整数:\n");
for(i=0;i<10;i++){
scanf("%d",&n[i]);
}
printf("输入的数组为:\n");
for(i=0;i<10;i++){
printf("%d ",n[i]);
}
min = 0;
for(i=1;i<9;i++){
if(n[i]<n[min]){
min=i;
}
}
printf("\n数组中最小的数为%d,下标为:%d\n",n[min],min);
int temp=n[0];
n[0]=n[min];
n[min]=temp;
printf("交换后的数组为:");
for(i=0;i<10;i++){
printf("%d ",n[i]);
}
return 0;
}
效果图如下:
- 编写一个程序,将用户输入的十进制整数转换成任意进制的整数
/*编写一个程序,将用户输入的十进制整数转换成任意进制的整数*/
#include<stdio.h>
int main() {
int n,m;
int a[32];
int i;
int result=-1;
int mod=-1;
for(i=0; i<32; i++) {
a[i]=0; //初始化
}
printf("请输入一个十进制整数:\n");
scanf("%d",&n);
while(1) {
printf("请输入要转换成几进制(输入0结束程序):"); //input
scanf("%d",&m);
mod=n%m; //转换逻辑
result = n/m;
for(i=0; mod!=0||result!=0; i++) {
a[i]=mod;
mod = result%m;
result /= m;
}
printf("转换后的结果为:\n");
for(i=31; i>=0; i--) { //output
printf("%d ",a[i]);
a[i]=0;
}
printf("\n");
if(m=0) {
break;
}
}
return 0;
}
效果图如下:
#include<stdio.h>
int main(){
int a[4][4]={4,3,2,1,5,6,7,8,9,31,13,22,21,14,55,43};
int i,j;
int min_row,min_list,max_row,max_list; //row为行,list为列
int max,min;
min=max=a[0][0];
for(i=0;i<4;i++){
for(j=0;j<4;j++){
printf("%-4d ",a[i][j]); //打印数组
}
printf("\n");
}
//找出其中的最大值和最小值,并打印所在的行号和列号
for(i=0;i<4;i++){
for(j=0;j<4;j++){
if(a[i][j]<min){
min_row=i+1;
min_list=j+1;
min = a[i][j];
}
if(a[i][j]>max){
max_row=i+1;
max_list=j+1;
max = a[i][j];
}
}
}
printf("最小值为%d,所在行为:%d,所在列为:%d\n",min,min_row,min_list);
printf("最大值为%d,所在行为:%d,所在列为:%d\n",max,max_row,max_list);
printf("\n");
//求对角线元素之和
int sum_opp=0;
for(i=0;i<4;i++){
sum_opp += a[i][i];
}
printf("对角线之和为:%d\n",sum_opp);
printf("\n");
//求所有的一行之和和一列之和
int sum_row; //行和
int sum_list; //列和
for(i=0;i<4;i++){
sum_row = 0;
for(j=0;j<4;j++){
sum_row += a[i][j];
}
printf("第%d行和为:%d\n",i+1,sum_row);
}
for(i=0;i<4;i++){
sum_row = 0;
for(j=0;j<4;j++){
sum_list += a[j][i];
}
printf("第%d列和为:%d\n",i+1,sum_list);
}
printf("\n");
//求此矩阵的转置矩阵
int temp;
for(i=0;i<4;i++){
for(j=i;j<4;j++){
temp=a[i][j];
a[i][j]=a[j][i];
a[j][i]=temp;
}
}
printf("此矩阵的转置矩阵为:\n");
for(i=0;i<4;i++){
for(j=0;j<4;j++){
printf("%-4d ",a[i][j]); //打印数组
}
printf("\n");
}
printf("\n");
//求此矩阵最外围所有数的和
int sum_round=0;
for(i=0;i<4;i++){
for(j=0;j<4;j++){
if(i==0||i==3||j==0||j==3){
sum_round += a[i][j];
}
}
}
printf("此矩阵最外围所有数的和为:%d\n",sum_round);
return 0;
}
效果图如下:
- 统计单词数。有三行文字,找出其中有多少个空格,多少个单词。规定:一个单词以一个或多个空格相间隔,每行结束都要有空格,标点符号后面也有空格。
#include<stdio.h>
int main(){
char s1[3][100],c;
int i,j;
int word=0; //word用来判别是否是单词的标志。若word=0,表示未出现单词;若出现单词,则word=1.
int count=0; //统计单词数
int space=0; //统计空格数
for(i=0;i<3;i++){
gets(s1[i]);
}
for(i=0;i<3;i++){
for(j=0;s1[i][j]!='\0';j++){
c=s1[i][j];
if(c==' ') {
word=0; //若出现空格,使word=0,count不累加。
space++;
}
else if(word==0){
word=1;
count++;
}
printf("%c",s1[i][j]);
}
}
printf("\n有%d个词\n",count);
printf("有%d个空格\n",space);
return 0;
}
效果图如下:
- 打印十行杨辉三角
/*打印杨辉三角*/
#include<stdio.h>
int main(){
int a[10][10];
int i,j;
for(i=0;i<10;i++){
for(j=0;j<i+1;j++){
if(i==0||i==1||j==0||j==i){
a[i][j]=1;
}
else{
a[i][j]=a[i-1][j]+a[i-1][j-1];
}
printf("%-4d",a[i][j]);
}
printf("\n");
}
return 0;
}
效果图如下:
- 找出一个整数矩阵中的鞍点。定义:其值在其行中最大,在其列上最小。(矩阵中可能没有鞍点)
/*找出一个整数矩阵中的鞍点。定义:其值在其行中最大,在其列上最小。(矩阵中可能没有鞍点)*/
#include<stdio.h>
#define M 3
#define N 4
int main(){
int a[M][N];
int i,j,k;
int max_row,max_list;
int min_row,min_list;
int isPoint=0; //判别是否为鞍点的标志,不是为0,是为1
for(i=0;i<M;i++){
for(j=0;j<N;j++){
scanf("%d",&a[i][j]); //输入数据
}
}
for(i=0;i<M;i++){
for(j=0;j<N;j++){
printf("%-4d",a[i][j]); //输出数据
}
printf("\n");
}
int max=a[0][0];
int min=a[0][0];
//逻辑判断
for(i=0;i<M;i++){
for(j=0;j<N;j++){ //行遍历
if(a[i][j]>max){
max=a[i][j]; //找到改行最大值的下标
max_row=i;
max_list=j; //鞍点的列标
}
}
min=max; //判断该行最大值是否为该列最小值
for(k=0;k<M;k++){
if(a[k][max_list]<min){
min = a[k][max_list];
}
}
if(max==min){ //若找到鞍点,改变鞍点判别标志
isPoint=1;
printf("%d是鞍点\n",a[max_row][max_list]);
}
}
if(!isPoint){
printf("这个矩阵没有鞍点。\n"); //遍历结束后,若没发现鞍点,则输出提示
}
return 0;
}
效果图如下:
- 前m个与后n个元素交换位置的操作。设有十个元素,m=8; n=2
算法思想:进行三次就地逆置。第一次是全部元素进行逆置,第二次是前m个元素进行逆置,第三次是后面n个元素进行就地逆置。就能实现前m个元素与后n个元素交换位置的操作。
/*前m个与后n个元素交换位置的操作*/
/*进行三次就地逆置操作*/
#include<stdio.h>
int main() {
int a[10]= {1,2,3,4,5,6,7,8,9,0};
int i,temp;
int m=8;
int n=2;
for(i=0; i<10; i++) {
printf("%d ",a[i]);
}
for(i=0; i<10/2; i++) { //第一次就地逆置,全部元素进行逆置
temp=a[i];
a[i]=a[10-i-1];
a[10-i-1]=temp;
}
for(i=0; i<n/2; i++) { //第二次就地逆置,局部逆置
temp=a[i];
a[i]=a[n-1-i];
a[n-1-i]=temp;
}
for(i=0; i<m/2; i++) { //第三次就地逆置,局部逆置
temp=a[10-m+i];
a[10-m+i]=a[10-1-i];
a[10-1-i]=temp;
}
printf("\n");
for(i=0; i<10; i++) {
printf("%d ",a[i]);
}
}
效果图如下:
到此为止,又解决了8道C语言程序题。C语言是一门面向过程的语言。这8道数组题涉及到了数组的基本理论知识的同时,也更能体现出面向过程的特点。在解题和编程的过程中,越来越注重逻辑和算法思想。例如进制转换那道题,就需要很完整的进制转换的算法逻辑。这一章的题,也为下面一章“函数”的学习起到了一个引导作用。经过一周的对数组的学习,我对数组的理解也似乎达到了一个瓶颈。这部分的课后习题,相信细心的读者也能发现,我贴的图片中,有一道题是没有解出来的,一开始不是有没有逻辑的问题,而是能不能看懂题目的问题,细读了好几遍题目才发现是找比给出的数中大的最小数和小的最大数的排列,等懂了题目之后,制约我这个题解不出的因素就是算法逻辑问题,我尝试过几种方法进行过组合排列,但发现都是由局限性,而不能写出一个统一规范来解决这一类题。我再把题目贴在下面,希望有强大逻辑的读者大大们,如果对这个题的解法有自己理解或者是最优解的话,可以满足我的求知欲。