C 语言解 常见编程题(下)

简介: C 语言解 常见编程题

C 语言解 常见编程题(上):https://developer.aliyun.com/article/1489149


10 回文数

/* 判断 n 是否为回文数 */
#include <stdio.h>
/* 思路: 倒置数值,判断倒置后是否相等 */
int isPalindromes(int n){
    // m倒置后的, nn复制一份n用于操作, div 倒置所需乘数
    int m = 0, nn = n, div = 1;   
    while (n / div) div *= 10;
    do
    {
        div /= 10;
        m += nn % 10 * div;
    } while (nn /= 10);
    printf("%d----倒置后:%d\n",n,m);
    if (m == n) return 1;
    else return 0;
}
int main(){
    printf("%d", isPalindromes(1234321));
    return 0;
}

测试数据1: 1234321

1234321----倒置后:1234321

1

测试数据1: 12345

12345----倒置后:54321

0

/* 判断 n 是否为回文数 */
#include <stdio.h>
/* 思路: 挨个比较 每个位上的 数字 */
int isPalindromes(int n){
    int div1 = 1,div2 = 1;   //div1 左第一位所需的除数, div2 右第一位所需的除数
    int m1,m2;  //m1 左第一位的值, m2 右第一位的值
    while(n/div1/10) div1 *= 10;;
    while(div1 > div2){    //对比过 中间一个,停止对比
        m1 = n/div1%10;
        m2 = n/div2%10;
        printf("%d----%d\n",m1,m2);   
        if(m1!=m2) return 0;
        div2*=10;
        div1/=10;
    }
    return 1;
}
int main(){
    printf("%d", isPalindromes(1234321)); 
    return 0;
}

测试数据1: 1234321

1----1

2----2

3----3

1

测试数据2: 12354321

1----1

2----2

3----3

5----4

0

测试数据3: 1234

1----4

0


11 进制转换


① N进制转10进制


  • 由于16进制包括有abc等字符, 需使用字符串形式输入
  • 原理:权值相加 , 比如8进制转10进制,如下

/* n进制转10进制 */
#include <stdio.h>
//将字符转为所表示的数值, 比如 'a'或'A' 返回 10
int charToint(char c){
    if(c>='a') return c-87;
    else if(c>='A') return c-55;
    else return c-'0';
}
// n进制数num 转为 10进制数值
int numTodec(char *num, int n){
    int i,dec=0,k=1;   // k 权值
    for(i=0; num[i+1];i++);  //下标指向末位,从最后位开始
    for(;i>=0;i--,k*=n)
        dec+= k*charToint(num[i]);
    return dec;
}
int main(){
    char num[20];   //使用字符串形式,兼容16进制
    gets(num);   
    printf("%d",numTodec(num,8));
    return 0;
}
/* 
  n进制转10进制 -- 排除16进制(不考虑字符情况) 
*/
#include <stdio.h>
// n进制数num 转为 10进制数值
int numTodec(int num, int n){
    int dec=0,k=1;   // k 权值
    for(;num;k*=n,num/=10) dec+=num%10*k;   
    return dec;
}
int main(){
    int num;   
    scanf("%d",&num);
    printf("%d",numTodec( num , 8 ));
    return 0;
}

② 10进制转N进制


  • 原理: 除N取余, 至0为止
  • 比如二进制:

/* 递归 -- 10进制转N进制 */
#include <stdio.h>
//输出 10进制数num 的 n进制形式,只输出,不返回值
void decToany(int num,int n){
    if(num){
        decToany(num/n,n);
        printf("%c", num%n + (num%n>9?55:'0') );  //兼容16进制,以字符形式输出
    }
}

int main(){
    decToany(89,2);
    return 0;
}

12 数组排序


通用函数 – 交换:

//将数组p中的下标分别为a,b的两个数交换
void swap(int a,int b,int p[]){
    int temp = p[a];
    p[a] = p[b];
    p[b] = temp;
}

① 冒泡排序

#include<stdio.h>
int main(){
  int a[10]={3,2,5,8,1,9,7,4,0,6};
  // 外层循环代表循环次数(n-1)
  for (int i = 0; i < 10-1; i++){
    // 内层循环代表第j个与第i个比
    for (int j = i+1; j <= 10; j++){
      if(a[i]>a[j]){
        int t=a[i];
        a[i]=a[j];
        a[j]=t;
      }
    }
 }
// 打印结果
  for (int i = 0; i <= 9; i++) printf("%d",a[i]);
  return 0;
}

/* 
  冒泡排序法
  将长度为len的数组arr, 以升序排序
*/
void bubbling(int *arr,int len){
    // 外层循环代表循环次数(n-1)
    for(int i=0;i<len-1;i++){
        int var = 1;  //交换标记变量
         // 内层循环代表个数(n-1-i)
        for(int j = 0; j< len - i - 1; j++)
            if(arr[j]>arr[j+1]) { 
                swap(j,j+1,arr); 
                var = 0;
            }
        //print_arr(arr,len);   //查看排序过程
        if(var) break;   //本回合未产生排序,即已排序完成,跳出循环,提高效率(非必须)
    }
}

② 选择排序

#include<stdio.h>
int main(){
  int a[10]={3,2,5,8,1,9,7,4,0,6};
  // 外层循环代表循环次数(n-1)
  for (int i = 0; i < 10-1; i++){
    // 内层循环代表第j个与第i个比
    for (int j = i+1; j <= 10; j++){
      if(a[i]>a[j]){
        int t=a[i];
        a[i]=a[j];
        a[j]=t;
      }
    }
 }
// 打印结果
  for (int i = 0; i <= 9; i++) printf("%d",a[i]);
  return 0;
}

/* 
  选择排序法 升序
  最多产生 len(数组长度) 次交换
*/
void elect_sort(int *arr,int len){
    int i,j,k;
    for(i=0;i<len;i++){
        k=i;  //假设当前下标为最小值
        for(j = i + 1; j < len; j++)  //找最小值下标
            if(arr[j]<arr[k]) k = j;
        if(k!=i) swap(i,k,arr);  //将最小值交换到i的位置
    }
}
//选择排序法1,交换次数较多,但更简洁
void elect_sort_1(int *arr,int len){
    for(int i = 0; i < len; i++)
      for(int j = i + 1; j < len; j++)
            if(arr[i]>arr[j]) swap(i,j,arr);
}

③ 插入排序

//一般插入排序
#include<stdio.h>
int main(){
  int a[10]={3,2,5,8,1,9,7,4,0,6};
  // 循环数组a
  for (int i = 0; i < 10; i++){
    // 循环前面的被插入数组
    for (int j = i; j > 0; j--){
      if (a[j] < a[j - 1])
      {
        int t = a[j];
        a[j] = a[j - 1];
        a[j - 1] = t;
      }
    }
  }
// 打印结果
  for (int i = 0; i <= 9; i++) printf("%d",a[i]);
  return 0;
}

/*
  插入排序法 升序
*/
void insertt_sort(int *r, int len){
    int i, j, k;
    for (i = 1; i < len; i++){
        if (r[i] < r[i - 1]){
            k = r[i];  //存入当前待插入的值,否则定位后移 会覆盖
            for (j = i - 1; r[j] > k && j>=0; j--)  //后移,寻找合适的插入位置
                r[j + 1] = r[j];  
            r[j + 1] = k;  //插入
        }
    }
}

13 数组反转

// 交换a,b所指向的值
void swap(int *a,int *b){
    int temp = *a;
    *a = *b;
    *b = temp;
}
/* 
  数组反转
  传入数组首地址head与长度len
*/
void reverse(int *head,int len){
    int *tail = head+len-1;  //tail 尾指针,指向最后一个元素
    while(head<tail)
        swap(head++,tail--);
}

14 查找


① 折半查找


  • 要求已按 升序 排序好的数组
/* 
  循环 -- 折半查找
  在arr数组 [0,len]之间, 查询num的下标 
  存在 返回其下标,不存在返回 -1
*/
int Halfsearch(int *arr,int len,int num){
    int mid,low = 0, high = len - 1;
    do{
        mid = (low + high)/2;
        printf("\n%d---%d",low,high);
        if(arr[mid]>num) high = mid - 1;
        else if(arr[mid]<num) low = mid + 1;
        else return mid;
    }while(low <= high);
    return -1;
}
/*
  递归 -- 折半查找
  在arr数组的下标为 [low,high] 之间查找 num
  存在 返回其下标,不存在返回 -1
*/
int Halfsearch(int *arr,int low,int high,int num){
    if(low>high) return -1;
    int mid = (low+high)/2;
    if(arr[mid]>num) 
        return Halfsearch(arr,low,mid-1,num);
    else if(arr[mid]<num) 
        return Halfsearch(arr,mid+1,high,num);
    else return mid;
} 

② 顺序查找


  • 对数组无要求 , 不排序也行
  • 效率极低
/* 顺序查找 */
int sequential(int *arr,int len,int num){
  for(int i = 0; i < len; i++)
        if(arr[i]==num) return i;
     return -1;
}
  • 要求已按 升序 排序好的数组
/* 顺序查找 */
int sequential(int *arr,int len,int num){
  for(int i = 0; i < len; i++)
        if(arr[i]==num) return i;
      else if(arr[i]>num) break;   //找不着
     return -1;
}

15 字符串函数


① 字符串连接

#include <stdio.h>
//将s2连接到s1后面, s2不改变
void strconcat(char *s1,char *s2){
    int i,j;
    for(i = 0;s1[i];i++);  //定位到 s1字符串 中的'\0' 位置
    for(j = 0;s2[j];i++,j++)
        s1[i] = s2[j];
    s1[i] = '\0';       //结束!!!超级重要!!!超级容易忘!!!
}
int main(){
    char a[100],b[100];
    gets(a);
    gets(b);
    strconcat(a,b);
    puts(a);
    return 0;
}

② 比较字符串

#include <stdio.h>
//比较字符串s1,s2 , 相等返回0, 正数s1大,反之.
int strcomp(char *s1,char *s2){
    for(int i=0;s1[i] || s2[i];i++)
        if(s1[i]!=s2[i]) return s1[i]-s2[i];
    return 0;
}

int main(){
    char a[100],b[100];
    gets(a);
    gets(b);
    printf("%d",strcomp(a,b));
    return 0;
}

③ 复制字符串

#include <stdio.h>
//s2字符串 复制 到s1中
void strcopy(char *s1,char *s2){
    int i,j;
    for(i=0;s2[i];i++)
        s1[i] = s2[i];
    s1[i] = '\0';        //结束!!!超级重要!!!超级容易忘!!!
}

int main(){
    char s1[100],s2[100];
    gets(s2);
    strcopy(s1,s2);
    puts(s1);
}

16 链表


① 动态链表创建

#define LEN sizeof(Player)
//类型声明
typedef struct Node{
    int num;
    struct Node *next;
} Player;
//动态链表创建
Player *creat(){
    int temp;  //暂存量--判断是否继续输入
    Player *head, *p1, *p2;
    head = p1 = p2 = (Player *)malloc(LEN);
    printf("请输入你的编号 宝儿:");
    scanf("%d", &temp);
    if (!temp) return NULL;  //第一次输入0,返回空表
    p2->num = temp;  //存入
    do
    {
        scanf("%d", &temp);  // 下一个节点的数据!!!
        if (!temp) break;    //输入0结束输入,不想继续输入=>不用再创建新节点     
        p1 = (Player *)malloc(LEN);  //创建新节点
        p1->num = temp;
        p2->next = p1;    //上个节点next指向新的节点
        p2 = p1;          //p2 也指向新节点
    } while (1);
    p2->next = NULL;    //将本节点的next指向NULL,如改为指向head,形成一个圈,循环链表
    return head;
}

② 链表打印+返回长度

//链表打印+长度
int printLinked(Player *head){
    int len = 0;
    if (!head)
        printf("这个是空表哦 亲");
    else {
        Player *p = head;
      while (p){
          printf("%d ", p->num);
          p = p->next;
            len++;
            if(p==head) break;  //如果是首尾相连的链表
      }
     }
    return len;
}

③ 链表删除节点

//链式链表 删除节点
void del_linked(Player *head,Player *del){
    Player *p = head;
    while(p->next!=del){   //找到待删除节点的上一个节点
        p = p->next;
      if(!p){
            printf("\n找不到你要删除的节点呢 亲");
            return;
        }
    }
    p->next = del->next;  //将其指向下一个节点
}
//循环链表 删除节点
void del_linked(Player *del){
    Player *p = del;
    while(p->next!=del)   //找到待删除节点的上一个节点
        p = p->next;
    p->next = del->next;  //将其指向下一个节点
}
//删除头结点可在主函数中使用以下语句
head = head -> next;

④ 链表插入

//将add插入到head链表的第n个位置之后, n>=1     链式链表
void insert(Player* head,Player *add,int n){
    if(n<1) {printf("非法操作!");return;}  
    if(n>linklegth(head)) n = linklegth(head);  //大于最大长度,插入在最后
    Player * p = head;
  while(--n)
        p=p->next;
    add->next = p->next;
    p->next = add;    
}

17 求方程近似解


① 二分法

#include <stdio.h>
#include <math.h>
double func(double n){
    return 2 * pow(n, 3) - 4 * pow(n, 2) + 3 * n - 6;   //待求解函数
}

double Solution(double low, double high){
    double mid, fm;
    mid = (low + high) / 2;
    fm = func(mid);      
    //printf("%f--%f   -->  %f\n", low, high, mid);   //二分过程
    if (fm == 0 || (high - low) < 1e-5)//两种情况停止,一是fm刚好等于0(应该不可能),二是精度小于1e-5时,直接返回mid为近似解
        return mid;
    else if (fm < 0)
        return Solution(mid, high);
    else if (fm > 0)
        return Solution(low, mid);
}
int main(){
    printf("%.2f", Solution(-10, 10));
    return 0;
}

② 牛顿迭代法

#include<stdio.h>
#include<math.h>
double func(double x){ //举例函数
    return 2*x*x*x-4*x*x+3*x-6.0;
}
double func1(double x){ //导函数
    return 6*x*x-8*x+3;
}
int Newton(double *x,double precision,int maxcyc){      //maxcyc 迭代次数
    double x1,x0;
    int k;
    x0=*x;
    for(k=0;k<maxcyc;k++){
        if(func1(x0)==0.0){//若通过初值,函数返回值为0
            printf("迭代过程中导数为0!\n");
            return 0;
        }
        x1=x0-func(x0)/func1(x0);//进行牛顿迭代计算
        if(fabs(x1-x0)<precision || fabs(func(x1))<precision){//达到结束条件
            *x=x1; //返回结果
            printf("该值附近的根为:%lf\n",*x);
            return 1;
        }
        else //未达到结束条件
            x0=x1; //准备下一次迭代
    }
    printf("迭代次数超过预期!\n"); //迭代次数达到,仍没有达到精度
    return 0;
}
 
int main(){
    double x,precision;
    int maxcyc;
    printf("输入初始迭代值x0:");
    scanf("%lf",&x);
    printf("输入最大迭代次数:");
    scanf("%d",&maxcyc);
    printf("迭代要求的精度:");
    scanf("%lf",&precision);
    if(Newton(&x,precision,maxcyc)==1) //若函数返回值为1
    ;
    else //若函数返回值为0
        printf("迭代失败!\n");
    return 0;
}

18 求最大值


① 输入三个数abc,输出其中最大值

#include <stdio.h>
int main()
{
  int a, b, c;
  scanf("%d,%d,%d", &a, &b, &c);
  if (a >= b && a >= c)
    printf("max=%d", a);
  else if (b >= a && b >= c)
    printf("max=%d", b);
  else if (c >= a && c >= b)
    printf("max=%d", c);
  return 0;
}

②求出n个数字的最大值

#include<stdio.h>
 
int main()
{
  int x,max,n;
  scanf("%d",&n);
  scanf("%d",&x);
  max=x;
  for(int i=0;i<n-1;i++)
  {
    scanf("%d",&x);
    if(max<x)
      max=x;
  }
  printf("%d",max); 
  return 0; 
} 

19 打印图形


①打印菱形

#include<stdio.h>
 
int main()
{
  int m=3,n=1;
  for (int i = 0; i < 7; i++)
  {
    for (int i = 0; i < m; i++)
    {
      printf(" ");//前面空格数
    }
    i<3?m--:m++;
    for (int j = 0; j < n; j++)
    {
      printf("%c",'*');
    }
    n=i<3?n+2:n-2; 
    printf("\n"); 
  }
  return 0; 
} 


测试相关函数


/* 循环 */
#include <stdio.h>
int main(){
    
    return 0;
}

随机生成数组

#include <time.h>
//函数声明: 防止编译系统警告
void srand(unsigned seed);
int rand(void);
//随机数组 a数组首地址,l数组长度
void getArr(int *a,int l){
    int i=0;
    srand(time(NULL));  //以当前系统时间作为种子
    printf("\n你生成的数组为:");
    while (i < l) printf("%d,",a[i++] = rand()%(2*l+1));  //限制范围[0,2*l]
}

打印数组

void print_arr(int *a,int len){
    printf("\n数组为:");
    while(len--)  printf("%d,",*a++);
}

折半查找 测试案例

/*折半查找 */
#include <stdio.h>
#include <time.h>
//函数声明: 防止编译系统警告
void srand(unsigned seed);
int rand(void);
//随机数组 a数组首地址,l数组长度
void getArr(int *a,int l){
    int i=0;
    srand(time(NULL));  //以当前系统时间作为种子
    printf("你生成的数组为:");
    while (i < l) printf("%d,",a[i++] = rand()%(2*l+1));  //限制范围[0,2*l]
}
//将数组p中的下标分别为a,b的两个数交换
void swap(int a,int b,int p[]){
    int temp = p[a];
    p[a] = p[b];
    p[b] = temp;
}
/*
  插入排序法 升序
*/
void insertt_sort(int *r, int len){
    int i, j, k;
    for (i = 1; i < len; i++){
        if (r[i] < r[i - 1]){
            k = r[i];  //存入当前待插入的值,否则定位后移 会覆盖
            for (j = i - 1; r[j] > k && j>=0; j--)  //后移,寻找合适的插入位置
                r[j + 1] = r[j];  
            r[j + 1] = k;  //插入
        }
    }
}
/* 
  在长度为len的arr数组中, 查询num的下标 
  存在 返回其下标,不存在返回 -1
*/
int Halfsearch(int *arr,int len,int num){
    int mid,low = 0, high = len - 1;
    do{
        mid = (low + high)/2;
        printf("\n%d---%d",low,high);
        if(arr[mid]>num) high = mid - 1;
        else if(arr[mid]<num) low = mid + 1;
        else return mid;
    }while(low <= high);
    return -1;
}
void print(int *a,int len){
    printf("\n数组为:");
    while(len--)  printf("%4d",*a++);
}
int main(){
    int arr[10];
    getArr(arr,10);
    insertt_sort(arr,10);
    print(arr,10);
    printf("\n%d",Halfsearch(arr,10,8));
    return 0;
}

数组反转 测试

#include <stdio.h>
#include <time.h>
//函数声明: 防止编译系统警告
void srand(unsigned seed);
int rand(void);
//随机数组 a数组首地址,l数组长度
void getArr(int *a,int l){
    int i=0;
    srand(time(NULL));  //以当前系统时间作为种子
    printf("\n你生成的数组为:");
    while (i < l) printf("%d,",a[i++] = rand()%(2*l+1));  //限制范围[0,2*l]
}
// 交换a,b所指向的值
void swap(int *a,int *b){
    int temp = *a;
    *a = *b;
    *b = temp;
}
/* 数组反转 */
void reverse(int *head,int len){
    int *tail = head+len-1;
    while(head<tail)
        swap(head++,tail--);
}
//打印
void print_arr(int *a,int len){
    printf("\n数组为:");
    while(len--)  printf("%d,",*a++);
}
int main(){
    int arr[10];
    getArr(arr,10);
    reverse(arr,10);
    print_arr(arr,10);
    return 0;
}

你生成的数组为:18,12,0,7,1,19,11,3,13,0,

数组为:0,13,3,11,19,1,7,0,12,18,

相关文章
|
8天前
|
网络协议 程序员 编译器
C语言:编程世界的基础与魅力
C语言:编程世界的基础与魅力
|
2月前
|
监控 网络协议 API
C语言系统编程
C语言系统编程
|
2月前
|
Linux C语言 开发者
Linux系统下C语言的高阶编程
Linux系统下C语言的高阶编程
15 0
|
2月前
|
存储 C语言 索引
掌握多维数组,让你的C语言编程技能暴涨!
掌握多维数组,让你的C语言编程技能暴涨!
|
2月前
|
存储 编译器 程序员
汽车电子行业的 C 语言编程标准
汽车电子行业的 C 语言编程标准
65 0
汽车电子行业的 C 语言编程标准
|
2月前
|
存储 人工智能 安全
C语言:选择+编程(每日一练Day15)
C语言:选择+编程(每日一练Day15)
54 2
|
8天前
|
编译器 C语言 C++
C语言,C++编程软件比较(推荐的编程软件)
C语言,C++编程软件比较(推荐的编程软件)
|
2月前
|
C语言
C语言:选择+编程(每日一练Day13)
C语言:选择+编程(每日一练Day13)
35 0
|
11天前
|
C语言
C 语言解 常见编程题(上)
C 语言解 常见编程题
45 0
|
23天前
|
存储 Java C语言
从C语言的面向过程编程过渡理解面向对象编程风格
从C语言的面向过程编程过渡理解面向对象编程风格
9 0