一、基础笔记
1.字符串
(1)字符串定义
代码:
#include <stdio.h> #include <string.h> int main () { int i; char *str1 = "Hello"; //指针定义 ,字符串可读不可写 char str2[] = "Hello"; //数组定义 ,字符串可读可写 char str3[10] = "Hello"; //末尾会有0,占用一个数组单位 // printf("%d\n",sizeof(str2)) ; //验证字符数组比字符串多一个单位,末尾为0 for(i=0;i<sizeof(str1);i++){ printf("%c",str1[i]); } // printf("%d",str2[5]); //int变量0对应的字符为空,即不显示 return 0; }
(2)字符串输入与输出
代码:
#include <stdio.h> int main () { char word[8]; // scanf("%s",word); //读到一个单词为止,界限为空格或回车或tab // //不安全,可能会超过数组界限 scanf("%7s",word); //安全输入方法 ,表示最多输入7个 printf("%s",word); }
(3)字符串数组
代码:
#include <stdio.h> int main () { //简单定义 // int i; // char str [][20]={ // "hello", // "nihao", // "wanna" // }; // for(i=0;i<3;i++){ // printf("%s\n",str[i]); // } // return 0; //高阶定义 int i; char *str []={ "hello", "nihao", "wanna" }; for(i=0;i<3;i++){ printf("%s\n",str[i]); } }
(4)字符串函数
代码:
#include <stdio.h> #include <string.h> int main () { /* 1.输入字符串 gets 函数 与输出字符串 puts 函数 */ char str[20]; gets(str); //接受输入的字符串 // printf("%s",str); puts(str); //输出字符串 /* 2.字符串连接 strcat函数 */ char str1[10]="Hello,"; char str2[20]="jiji"; puts(str1); puts(str2); strcat(str1,str2); //将字符串2连接到字符串1后边,结果放到字符数组1中 puts(str1); puts(str2); /* 3.字符串复制 strcpy 函数 与 strncpy 函数 */ char str1[10] ="jiji"; //定义空数组str1 char str2[10] = "yang"; //定义数组str2 char str3[10] = "haofei"; //定义数组str3 strcpy(str1, str2); //全部覆盖 printf("%s\n", str1); strncpy(str1, str3, 3); //只覆盖前三个 printf("%s\n", str1); /* 4.字符串比较函数 strcmp函数 与 strncmp函数 */ int num1; int num2; int num3; int num4; char str1[10]="abc"; char str2[10]="abc"; char str3[10]="bac"; char str4[10]="cab"; num1=strcmp(str1,str2) ; //字符串相等,返回0 num2=strcmp(str1,str3) ; //小于,返回-1 num3=strcmp(str4,str3) ; //大于,返回1 printf("%d, %d, %d",num1,num2,num3); /* 5.测字符串有效值长度函数 strlen函数 */ char str[10]="hello"; int n=strlen(str); //测字符串 int m=strlen("jiji"); //测字符串常量 printf("%d,%d",n,m); /* 6.转换为小写函数 strlwr函数 与转换为大写函数 strupr函数 */ char str[10]="AaBbCcDd"; strlwr(str); //将字符串中的大写字母转换为小写字母 printf("%s\n",str); strupr(str); //将字符串中的小写字母转换为大写字母 printf("%s\n",str); /* 7.查找字符串函数 strstr函数 */ /*附: strchr函数是对应的查找字符函数 */ char a[] = "abcdefg"; char b[] = "bc"; char* ret = strstr(a, b); //判断b是否是a的子串 if (ret == 0){ printf("找不到!\n"); //不是子串,返回 0 / NULL } else{ //是子串,返回地址 printf("%s\n", ret); //输出 bcdefg } return 0; }
(5)字符处理与判断
代码:
#include <stdio.h> #include <ctype.h> int main() { char input; printf("请输入一个字符:"); scanf("%c", &input); if (isalnum(input)) { //1. isalnum 函数判断是不是字母或数字 printf("输入的字符是字母或数字\n"); } else { printf("输入的字符不是字母或数字\n"); } if (isalpha(input)) { //2. isalpha 函数判断是不是字母 printf("输入的字符是字母\n"); } else { printf("输入的字符不是字母\n"); } if (isdigit(input)) { //3. isdigit 函数判断是不是数字 printf("输入的字符是数字\n"); } else { printf("输入的字符不是数字\n"); } if (islower(input)) { //4. islower 函数判断是不是小写字母 printf("输入的字符是小写字母\n"); } else { printf("输入的字符不是小写字母\n"); } if (isupper(input)) { //5.isupper 函数判断是不是大写字母 printf("输入的字符是大写字母\n"); } else { printf("输入的字符不是大写字母\n"); } printf("大写形式的字符是:%c\n", toupper(input)); //6. toupper 函数转换为大写字母 return 0; }
运行结果:
2.结构体
(1)简单定义
代码:
#include <stdio.h> /*1.一般将结构类型的声明放在所有函数的外边*/ struct date{ int year; int mouth; int day; }; //5.简化结构体声明(或者是将结构体改名) typedef struct date{ int year; int mouth; int day; } D; D today_1; //定义变量时不再需要struct int main() { //2.定义结构变量 ,初始化结构变量 struct date today={2024,3,8}; //类似数组初始化 struct date tomorrow={.year=2024,.day=9}; //具体指定初始化 ,未初始化,默认为0 printf("%d %d %d",today.year,today.mouth,today.day) ; printf("%d %d %d",tomorrow.year,tomorrow.mouth,tomorrow.day) ; //3.指向结构的指针 (p为普通指针,q为结构体指针,则*p是一个值,*q指向一个结构体变量) /* ptr->x = 10; <==> (*ptr).x = 10; */ //4.结构数组 return 0; }
(2)链表应用
代码:
#include<stdio.h> #include<stdlib.h> /* 1.定义链表节点 */ typedef struct _node{ int value; struct _node *next; }Node; int main () { int number; Node *head = NULL; /* 头指针与尾指针均指向 NUll */ Node *last ; /* 2.连续读入数据放入链表 */ do { scanf("%d",&number); if(number!=-1){ Node*p=(Node*)malloc(sizeof(Node)); //申请一个节点大小的空间 p->value=number; //赋值 p->next=NULL; //将下一指针赋值为 NULL if(head){ //头指针不为空 ,将该节点链接到链表中 last->next=p; } else{ //头指针为空,确定头指针 head=p; } last=p; //确定尾指针 } } while(number!=-1); /* 3.遍历输出每一个链表节点值 */ Node *p; for(p=head;p;p=p->next){ printf("%d ",p->value); } /* 4.找到某个值 */ int a; int isWhere=0; printf("\n请输出你要查询的值:"); scanf("%d",&a) ; for(p=head;p;p=p->next){ if(p->value==a){ isWhere=1; break; } } if(isWhere){ printf("可以找到!"); }else{ printf("找不到!"); } /* 5.查找删除某个节点 */ int b; int is=0; Node*q; printf("\n请输入你要删除的节点值:"); scanf("%d",&b); for(q=NULL,p=head;p;q=p,p=p->next){ if(p->value==a&&p==head){ //第一个节点就是要删除节点 is=1; head=p->next; free(p); break; }else if(p->value==b&&p==last){ //最后一个节点是被删除节点 q->next=NULL; last=q; free(p); is=1; break; }else if(p->value==b) { //中间节点是被删除节点 q->next=p->next; free(p); is=1; break; } } if(is){ printf("删除后的链表是:"); for(p=head;p;p=p->next){ printf("%d ",p->value); } }else{ printf("链表中无该值!"); } /* 6.清除链表 */ for (p=head;p;p=q){ q=p->next; free(p); } return 0; }
运行结果:
(3)堆栈应用
代码:
#include <stdio.h> #include <stdlib.h> // 定义链表节点 typedef struct Node { int data; struct Node* next; } Node; // 定义堆栈结构 typedef struct { Node* top; // 栈顶指针 } Stack; // 初始化堆栈 void initializeStack(Stack* stack) { stack->top = NULL; } // 判断堆栈是否为空 int isEmpty(Stack* stack) { return stack->top == NULL; } // 压栈操作 void push(Stack* stack, int value) { Node* newNode = (Node*)malloc(sizeof(Node)); if (newNode == NULL) { printf("内存分配失败\n"); exit(EXIT_FAILURE); } newNode->data = value; newNode->next = stack->top; stack->top = newNode; } // 弹栈操作 int pop(Stack* stack) { if (isEmpty(stack)) { printf("堆栈为空\n"); exit(EXIT_FAILURE); } Node* topNode = stack->top; int value = topNode->data; stack->top = topNode->next; free(topNode); return value; } // 获取栈顶元素 int peek(Stack* stack) { if (isEmpty(stack)) { printf("堆栈为空\n"); exit(EXIT_FAILURE); } return stack->top->data; } // 释放堆栈内存 void freeStack(Stack* stack) { while (!isEmpty(stack)) { pop(stack); } } int main() { Stack myStack; initializeStack(&myStack); // 压栈操作 push(&myStack, 10); push(&myStack, 20); push(&myStack, 30); // 获取并打印栈顶元素 printf("栈顶元素: %d\n", peek(&myStack)); // 弹栈操作并打印元素 printf("弹栈元素: %d\n", pop(&myStack)); printf("弹栈元素: %d\n", pop(&myStack)); // 再次获取并打印栈顶元素 printf("栈顶元素: %d\n", peek(&myStack)); // 释放堆栈内存 freeStack(&myStack); return 0; }
运行结果:
3.常用函数及其头文件
二、题目
1.十进制数转十二进制数
1. 思路:除12取余法
2. 代码:
#include<stdio.h> int main() { int num; //十进制数 char str[100]; int cnt=0; printf("请输入十进制数:"); scanf("%d",&num); //1.除 12 取余法依次保存余数到字符数组(字符串)中 do{ if(num%12==10){ str[cnt]='A'; }else if(num%12==11){ str[cnt]='B'; }else{ str[cnt]=num%12+48; } num/=12; cnt++; } while(num!=0); //循环结束条件是商为 0 //2. 逆序输出十二进制数 printf("对应的12进制数是:"); for(cnt-=1;cnt>=0;cnt--){ printf("%c",str[cnt]); } return 0; }
3. 运行结果:
2.十二进制转十进制
1. 思路:乘12加和
2. 代码:
#include <stdio.h> int main() { int num; //每一位十进制数 int sum=0; //十进制数 int cnt; char str[100]; //十二进制数 int isEr=1; //判断是否是合法十二进制数 printf("请输入十二进制数:\n"); scanf("%s",str); //核心方法:从高位到低位,逐位乘 12 相加,转十进制 for(cnt=0;str[cnt];cnt++){ if(str[cnt]>'B'){ isEr=0; break; }else if(str[cnt]=='A'){ num=10; sum=sum*12+num; }else if(str[cnt]=='B'){ num=11; sum=sum*12+num; }else{ num=str[cnt]-48; sum=sum*12+num; } } //输出结果 if(isEr){ printf("对用的十进制数是:%d",sum); }else{ printf("输入有误!"); } return 0; }
3. 运行结果:
3.过滤字符串中重复字符(使用strchr函数)
1. 思路:使用strchr函数判断是不是子串(函数用法见字符串函数)
2. 代码:
#include <stdio.h> #include <string.h> int main(){ int i; int j=0; char str1[100]; char str2[100]=""; printf("请输入一个字符串:\n"); scanf("%s",str1); for(i=0;str1[i];i++){ if(strchr(str2,str1[i])==NULL){ //主要使用查找字符函数 strchr 函数 str2[j] = str1[i]; j++; } } printf("过滤后的字符串为:%s\n",str2); return 0; }
3. 运行结果:
4.求两个字符串最长公共子串
1. 思路:确定公共子串下标与长度
2.代码:
#include <stdio.h> #include <string.h> int main () { int i,j,k; char str1[100]; char str2[100]; char str3[100]; printf("请输入字符串str1:"); scanf("%s",str1); printf("请输入字符串str2:"); scanf("%s",str2); //找到最长公共子串的起始位置与长度() int start = 0; //初始起始位置为0 int len = 0; //设定初始最长公共字串长度是0 for(i=0;i<strlen(str1);i++){ for(j=0;j<strlen(str2);j++){ if(str1[i]==str2[j]){ //遍历找到第一个相同的字符 k=1; while((str1[i+k]==str2[j+k])&&(str1!='\0')){ //尝试一共有几个相同字符 k++; } if(k>len){ //判断是否是最长的子串 len=k; start=i; } } } } if(len){ //根据子串长度判断是否有公共子串 //可以直接将公共子串复制到str3 strncpy(str3,str1+start,len) ; puts(str3); // for(i=start;len>0;i++,len--){ //也可直接输出 // printf("%c",str1[i]); // } }else{ printf("无公共子串!"); } return 0; }
3. 运行结果:
5.N以内的所有素数
1. 思路:判断素数
2. 代码:
#include <stdio.h> #include <math.h> int isSushu(); int main() { int num; int i; printf("请输入一个数:"); scanf("%d",&num) ; printf("%d以内的素数有:\n",num); for(i=0;i<=num;i++){ if(isSushu(i)){ printf("%d ",i); } } } //判断一个数是否是素数 (能否被除过1与数本身的其他数整除) int isSushu(int a) { int cnt=1; int i; if(a<=1){ cnt=0; }else{ for(i=2;i<=sqrt(a);i++){ if(a%i==0){ cnt=0; break; } } } return cnt; }
3. 运行结果:
6.将一个句子中的每个单词转置(字符串转置1)
1. 思路:遍历字符串,找到每一个单词的区间;然后单独将每一个单词转置
2. 代码:
/* 对字符串中的每个单词转置 */ #include <stdio.h> #include <string.h> int main () { int i; int k; int j; char temp; char str[100]; char *p; printf("请输入一个字符串:"); // scanf("%[^\n]",str) ; //输入除回车'\n'外的所有字符 ; gets(str); //也可以使用gets函数 for(i=0;i<strlen(str);i++){ //从头开始遍历字符串 p=&str[i]; for(k=0;str[i]!=' ' && i<strlen(str);k++,i++){ //1. 找到单词区间,i为起始下标 ,k为长度 } //2. 转置每一个单词 for(j=0;j<k/2;j++){ temp=*(p+j); *(p+j)=*(p+k-1-j); *(p+k-1-j)=temp; //p+k-1为最后一个 } } //3. 输出转制后的字符串 printf("%s",str); return 0; }
3. 运行结果:
7.星号排版
1. 思路:先确定最中间的一行,然后分别确定上半部分与下半部分
2. 代码:
/* 13 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include<stdio.h> int main() { int n,m; int i,j; char a[1000][1000]; printf("请输入正奇数n:"); scanf("%d",&n); while(n%2==0||n<=0){ printf("输入有误,请输入一个正奇数:"); scanf("%d",&n); } m=n/2; //1.将矩阵所有值置为' ' for(i=0;i<n;i++){ for(j=0;j<n;j++) a[i][j]=' '; } //2.确定中间一行 for(i=0;i<n;i++){ if(i%2==0){ a[m][i]='*'; } } //3.确定上半部分 for(i=m-1;i>=0;i--){ for(j=0;j<n-2;j++){ if(a[i+1][j]=='*'&&a[i+1][j+2]=='*'){ a[i][j+1]='*'; } } } //4.确定下半部分 for(i=m+1;i<n;i++){ for(j=0;j<n-2;j++){ if(a[i-1][j]=='*'&&a[i-1][j+2]=='*'){ a[i][j+1]='*'; } } } //5.输出整个矩阵 for(i=0;i<n;i++){ for(j=0;j<n;j++){ printf("%c",a[i][j]); if(j==n-1){ printf("\n"); } } } return 0; }
3. 运行结果:
8.计算三角形面积
1. 思路:三角形三边长分别为abc,面积为S,周长为M;则根据公式 S=根号下m*(m-a)*(m-b)*(m-c)计算三角形面积。
2. 代码:
#include<stdio.h> #include<math.h> /* 三角形三边长分别为abc,面积为S,周长为M S=根号下m*(m-a)*(m-b)*(m-c) */ int main () { double a,b,c; double m,s; printf("请输入三角形的三个边长:"); scanf("%lf%lf%lf",&a,&b,&c); //判断是否能够构成三角形 if((a+b<=c)||(a+c<=b)||(b+c<=a)){ printf("输入有误!"); } else{ //可以构成三角形 m=(a+b+c)/2; s= sqrt(m*(m-a)*(m-b)*(m-c)); printf("该三角形的面积是:%f",s); } return 0; }
3. 运行结果:
9.判断完数(一个数等于除其本身外的所有因子之和)
1. 思路:将因子累计加和,判断是否等于它本身。
2. 代码:
/* 问题:输出1000以内的完数 完数:如果一个数恰好等于除它本身外的因子之和,这个数就是完数。 例如6=1+2+3. */ #include <stdio.h> #include <math.h> int main () { int i,j; int sum; printf("1000以内的完数有:"); for(i=2;i<=1000;i++){ sum=0; for(j=1;j<i;j++){ //1. 计算因子和 if(i%j==0){ sum+=j; } } if(sum==i){ //2. 判断是否为完数 printf("%d ",i); } } return 0; }
3. 运行结果:
10.猴子选大王
1. 思路:
- 定义一个数组标识猴子状态,其中下标0的空间被舍弃掉(每个数组值初始为0,表示未被淘汰)。
- n只猴子,进行n轮遍历(循环)。
- 根据报数大小确定内层循环的次数,每一轮循环将一只猴子状态变为‘1’;在循环体中根据( item = item%n+1 )计算得到下一只猴子编号,并判断其状态是否为0;循环结束可以得到最后一只报数的猴子。
- 将最后一只报数的猴子状态置为1(淘汰)。
- 根据外层循环次数确定是不是大王(最后剩下的猴子),并输出。
2. 代码:
/* N个猴子围成一个圈 1、从第一只猴子开始报数,第一只猴子报1 2、每个报2的猴子退出,然后从下一只猴子重新开始报数, 3、要求输出退出的顺序和最后剩下的人 */ #include <stdio.h> int main() { int n; //猴子个数 int item=0; //第一轮从从 item%n+1 开始报数 int i,j; printf("请输入猴子数量N:"); scanf("%d",&n); int num[n]; //猴子编号不是从0开始,而是1 ;默认为 0 (未淘汰) ,1(被淘汰) for(i=1;i<=n;i++) { //1. 一共进行 n 轮报数 for (j=1;j<=2;j++){ //2. 开始每一轮报数,每一轮报2个数 ,并确定最后一只报数猴子的编号 // item = item%n+1; /* 关键语句,下一个报数猴子编号 */ // while(num[item]==1){ //已经被淘汰 ,循环找到未被淘汰的猴子 // item = item%n+1; // } do{ item = item%n+1; /* 关键语句,下一个报数猴子编号 */ } while(num[item]==1); } num[item]=1; //3. 淘汰最后一个报数的猴子 if(i!=n){ printf("第%d个出局的猴子为:%d号;\n",i,item) ; }else{ printf("最后留下的猴子是:%d号。\n",item) ; } } return 0; }
3. 运行结果:
11.约瑟夫环
1. 思路:类似猴子选大王
2. 代码:
/* 约瑟夫环运作如下: 1、一群人围在一起坐成环状(如:M) 2、从某个编号开始报数(如:K) 3、数到某个数(如:N)的时候,此人出列,下一个人重新报数 4、一直循环,直到所有人出列,约瑟夫环结束 */ #include <stdio.h> #include <stdlib.h> int main() { int m,n,k; int i,j; printf("请输入总人数M,报数长度N,开始编号K:"); scanf("%d%d%d",&m,&n,&k); // int num[m]; int *num = (int *)malloc((m+2) * sizeof(int)); //动态分配内存 k--; //确定是第一个报数的人的前一位 for(i=1;i<=m;i++){ //1. 循环报数 m 轮 for(j=1;j<=n;j++){ //2. 开始一轮报数,找到一个出列的人 do{ k=k%m+1; } while(num[k]==1); } num[k]=1; //3. 出列 if(i!=m){ //4. 输出 printf("第%2d个出列的人是:%d号\n",i,k); }else{ printf("最后一个出列的人是:%d号\n",k); } } free(num); // 释放动态分配的内存 return 0; }
3. 运行结果:
12.大数相加
1. 问题描述:
在一般语言中对整型数都有个最大限制,现给出两个超出正常范围的十进制数对其进行求和,是带进位的加法。
2. 思路:
- 将两个大数以字符串形式保存;
- 将两个字符串转置,并确认出较长的字符串;
- 开始进行相同位数的相加,需要设置一个进位(初始值为0);
- 开始进行剩余字符串与进位的相加;
- 判定最后一位是否有进位。
3. 代码:
#include <stdio.h> #include <string.h> int main () { int i; int temp; int len1,len2; char str1[1000]; char str2[1000]; char str3[1000]; printf("请输入第一个数:"); gets(str1); printf("请输入第二个数:"); gets(str2); /* 1.将两个大数转置,方便运算 */ //转置第一个大数 for(i=0;i<strlen(str1)/2;i++){ temp=str1[i]; str1[i]=str1[strlen(str1)-1-i]; str1[strlen(str1)-1-i]=temp; } //转置第二个大数 for(i=0;i<strlen(str2)/2;i++){ temp=str2[i]; str2[i]=str2[strlen(str2)-1-i]; str2[strlen(str2)-1-i]=temp; } /* 2.确定较长的数是str1 */ if(strlen(str1)<strlen(str2)){ strcpy(str3,str1); strcpy(str1,str2); strcpy(str2,str3); } len1=strlen(str1); len2=strlen(str2); /* 3.计算相同位数的值 */ for(i=0,temp=0;i<len2;i++){ str1[i]=str1[i]+str2[i]+temp-96; if(str1[i]>=10){ str1[i]%=10; temp=1; } else{ temp=0; } } /* 4.计算str1多出位数的值 */ for(i=len2;i<len1;i++){ str1[i]=str1[i]+temp-48; if(str1[i]>=10){ str1[i]%=10; temp=1; }else{ temp=0; } } /* 5.判定最后一位是否进位 */ if(temp==1){ str1[i]='1'-48; len1+=1; //有进位,str1长度加 1 } /* 6.倒序输出结果str1 */ printf("大数相加的和是:") ; for(i=len1-1;i>=0;i--){ printf("%d",str1[i]); } return 0; }
4.运行结果:
13.找到加和为 t 的所有组合(回溯法应用)
1. 回溯法(暴力检索方法)三步走:
- 确定函数类型(一般为 void 型)与 参数
- 确定递归终止条件
- 确定内层循环递归逻辑
2.代码:
#include <stdio.h> #include <stdlib.h> /* 回溯法(暴力检索方法)三步走: 1.确定函数类型(一般为 void 型)与 参数 2.确定递归终止条件 3.确定内层循环递归逻辑 */ //递归函数声明 void find(int *a, int index1, int n, int t, int max, int *b, int index2); //主函数 int main() { int t, n, i; printf("请输入t和n(中间用空格隔开):\n"); scanf("%d %d", &t, &n); int *a=(int *)malloc(sizeof(int)*n); //申请存储全部数据的空间 int *b=(int *)malloc(sizeof(int)*n); //申请存储当前组合的数组的空间 printf("请输入n个整数(中间用空格隔开):\n"); for (i = 0; i < n; i++) { scanf("%d", &a[i]); } printf("加和为%d的所有组合为:\n", t); find(a, 0, n, t, 0, b, 0); //调用递归函数 free (a); //释放空间 free (b); return 0; } // 递归函数定义(用于搜索符合条件的组合) void find(int *a, int index1, int n, int t, int max, int *b, int index2) { int i; //1.max 等于 t (返回条件 1 ) if (max == t) { // 找到符合条件的组合,输出 for (i = 0; i < index2; i++) { if(i<index2-1){ printf("%d+", b[i]); } else{ printf("%d", b[i]); } } printf("\n"); return; } //2.max 大于 t(返回条件 2 ) if (index1 == n || max > t) { // 递归结束条件:超出数组范围或者当前和已经大于目标值 return; } //3.max 小于 t (内层循环递归逻辑) for (i = index1; i < n; i++) { b[index2] = a[i]; // 选择当前元素加入组合 find(a, i + 1, n, t, max + a[i], b, index2 + 1); // 进行下一个数值遍历 } }
3 .运行结果:
14.删除子串
1. 问题描述:
输入两个字符串S1,S2,在字符串S1中删除含有字符串S2的子串, 输出删除子串的个数num以及最后剩下的字符串S3。
2. 思路:
- 方法一:判断从每一个字符开始的连续字符串是不是子串;是的话,则略过该子串;不是的话,将该字符加入到新的字符串中。
- 方法二:利用strstr函数循环一个字符串中是否还存在给定子串;若存在,将相关字符置为' '(空格);不存在,则输出值不是' '的字符。
3. 代码:
#include <stdio.h> #include <string.h> int main() { char str1[100]; char str2[100]; char str3[100]; int i,j,k; int num=0; //法二中使用,表示被删除字串个数 int num1=0; //用于判定子串个数 int num2=0; //用于判定str3字符串长度 printf("请输入字符串str1:"); gets(str1); printf("请输入字符串str2:"); gets(str2); // //方法一:从一个字符开始判定连续字符串是不是子串 // for(i=0;i<strlen(str1);i++){ // // j=0; // k=i; // while(str1[k]==str2[j]&&j<strlen(str2)){ //计算连续相同的字符个数 // k++; // j++; // } // if(j==strlen(str2)){ //是子串 // num1++; // i=k-1; //移到匹配子串末尾 // }else { //不是子串 // str3[num2] =str1[i] ; // num2++; // } // // } // // //输出 // if(num1==0){ // printf("无子串可删除!"); // }else if(strlen(str3)==0){ // printf("删除字串的个数是%d;\n剩余字符串str3为空!",num1); // }else{ // printf("删除字串的个数是%d;\n剩下的字符串str3为:",num1); // puts(str3); // } //方法二:循环利用strchr函数判断是否还存在该字串,如果存在,则继续删除 while(strstr(str1,str2)){ num++; char *str4=strstr(str1,str2); //1. 确定子串下标 for(i=0;i<strlen(str2);i++){ *(str4+i)=' '; //2. 将对应子串位置的值置为 ' '(空格) } } //3. 判断输出字符串str1 printf("删除字串的个数是:%d,删除子串后的字符串为:",num); for(i=0;i<strlen(str1);i++){ if(str1[i]!=' '){ printf("%c",str1[i]); } } return 0; }
4. 运行结果:
15.字符串压缩
1. 问题描述:
- 输入一个字符串S1,对输入的字符进行压缩,如果不能压缩则原封不动。
- S1:aaabbcddddde 输出:S2:3a2bc5de
2. 思路:类似删除子串,遍历每一个字符,判断从该字符开始是否有连续相同的多个字符。
3. 代码:
#include <stdio.h> #include <string.h> int main () { int num; int i,j; char str[100]; printf("请输入需要压缩的字符串:"); gets(str); printf("压缩后的字符串为:"); //遍历每一个字符,判断是否有多个连续相同的字符 for(i=0;i<strlen(str);i++){ num=0; j=i+1; while(str[i]==str[j]&&j<strlen(str)){ j++; num++; } i+=num; //转到相同字符的最后一个下标 if(num!=0){ //有相同字符,需输出相同个数 printf("%d",num+1); } printf("%c",str[i]); //输出字符 } return 0; }
4. 运行结果:
16.身份证合法性判断
1. 问题描述:
我国身份证号为18位,前17位必为数字,最后一位可为数字或者字母X:其中前六位为地址码,即对象常住户口所在县(市,旗,区),第七至第十位为出生年份,第十一、十二位为出生月份,第十三、十四位为出生日期。那么问题来了,我们知道年份分为平年和闰年,所谓闰年就是:那些能被4整除但不能被100整除或者能被400整除的年份,我们谓之"闰年", 闰年的2月份有29天,而平年则有28天。设计一个程序,判断一个身份证号的合法性。
2. 思路:
- 如果一个人的身份证合法,则返回0;
- 如果一个人的身份证号长度不合法,则返回1;
- 如果一个人身份证号前17位出现非数字字符,则返回2;
- 如果一个人身份证号第18位既不是数字也不是X,则返回3;
- 如果一个人出生年份在(1900-2017)之外,则返回4;
- 如果一个人出生月份不合法,则返回5;
- 如果一个人出生日期不合法,则返回6;
3. 代码:
#include <stdio.h> #include <string.h> static int year,mouth,day; //定义静态变量 int main () { int isHefa=0; //身份证号合法 char str[100]; printf("请输入身份证号:"); gets (str); if(strlen(str)!=18){ isHefa=1; }else if(isShuzi(str)){ //前17位有非数字字符 isHefa=2; }else if(str[17]!='X'&&(str[17]<'0'||str[17]>'9')) { //第18位字符不合法 isHefa=3; }else if(isYear(str)){ //出生年份不在规定范围内 isHefa=4; }else if(isMouth(str)) { //出生月份不合法 isHefa=5; }else if(isDay(str)){ //出生日期不合法 isHefa=6; } printf("%d",isHefa); return 0; } //判断是否有非数字字符 int isShuzi(char*p) { int is=0; //合法 int i; for(i=0;i<strlen(p)-1;i++){ if(p[i]<'0'||p[i]>'9'){ is=1; //不合法 } } return is; } //判断年份 int isYear(char*p) { int is=0; //合法 int i; year=0; for(i=6;i<10;i++){ //计算年份 p[i]-=48; year=year*10+p[i]; } if(year<1900||year>2017) { is=1; //不合法 } return is; } //判断月份 int isMouth(char*p) { int is=0; //合法 int i; mouth=0; for(i=10;i<12;i++){ //计算月份 p[i]-=48; mouth=mouth*10+p[i]; } if(mouth<1||mouth>12){ is=1; //不合法 } return is; } //判断日期 int isDay(char*p) { int is=0; //合法 int i; day=0; //计算日期 for(i=12;i<14;i++){ p[i]-=48; day=day*10+p[i]; } if(mouth==1||mouth==3||mouth==5||mouth==7||mouth==8||mouth==10||mouth==12){ if(day<0||day>31){ is=1; //长月不合法 } }else if(mouth==4||mouth==6||mouth==9||mouth==11){ if(day<0||day>30) { is=1; //短月不合法 } }else if((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)&&(day<0||day>28)){ is=1; //闰年2月不合法 }else if(day<0||day>29){ is=1; //平年2月不合法 } return is; }
4. 运行结果:
17.判断平方对称数
1. 问题描述:
- 判断一个非负整数 n(n<256) 是否是平方对称数,是则输出"yes",否则输出"no";
- 比如:11的平方是121 ,则是11是平方对称数。
2. 思路:
- 将平方数的每一位存放在数组中
- 比较数组的数据是否满足对称的性质
3. 代码:
#include <stdio.h> #include <stdlib.h> int isP(int m); //判断函数声明 int main() { int n; int i; printf("请输入一个非负整数n(n<=256):") ; scanf("%d",&n); //输出n以内的所有平方对称数 for(i=0;i<=n;i++){ if(isP(i*i)){ printf("%.3d是平方对称数,其平方为:%5d;\n",i,i*i); } } return 0; } int isP(int m) { int is=1; //是平方对称数 int k=m; int cnt=0; int i; //确定位数 do{ cnt++; m/=10; }while(m); //将每一位复制到数组中 int *num=(int*)malloc(cnt*sizeof(int)); //申请内存 for(i=cnt-1;i>=0;i--){ num[i]= k%10; k/=10; } //判定数组是否对称 for (i=0;i<cnt;i++){ if(num[i]!=num[cnt-1-i]){ is=0; //不是平方对称数 break; } } free(num); //释放内存 return is; }
4. 运行结果:
18.表达式计算
1.问题描述:
计算多个中缀表达式的值,每行一个表达式,输入0表示结束。
2.思路:
- 1. 使用两个栈,一个用来存放操作数,另一个用来存放运算符。
- 2. 从左到右扫描表达式,遇到操作数时直接入操作数栈,遇到运算符时则需要考虑它与栈顶运算符的优先级关系:
- 如果栈为空,或者当前运算符的优先级高于栈顶运算符,则直接入栈。
- 否则,从运算符栈中弹出运算符,与操作数栈中弹出的两个操作数进行计算,将结果压入操作数栈,直到当前运算符可以入栈为止。
- 3. 继续扫描表达式,重复步骤 2。
- 4. 当扫描结束后,依次从运算符栈中弹出运算符,与操作数栈中的操作数进行计算,直到运算符栈为空。
- 3. 最终,操作数栈中剩下的唯一一个操作数就是中缀表达式的计算结果。
3.代码:
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <ctype.h> #include <string.h> /* 第一部分:声明定义栈 */ //定义栈节点 typedef struct Node{ char chr; struct Node *next; }Node; //定义数字栈 typedef struct { Node * top; }Stack; //初始化栈 void chushihua(Stack *stack){ stack->top=NULL; } //判断栈是否为空 bool isEmpty(Stack * stack){ return stack->top==NULL; } //入栈 void ruzhan(Stack *stack,char c){ Node* p=(Node*)malloc(sizeof(Node)); p->chr =c; p->next=stack->top; stack->top=p; } //出栈 char chuzhan (Stack *stack){ char c=stack->top->chr; Node*p=stack->top; stack->top=p->next; free(p); return c; } //获取栈顶元素 char topzhan (Stack *stack){ return stack->top->chr; } /* 第二部分:运算符优先级、字符转数字、二值计算 */ //获取每个运算符的优先级 int yxj(char op){ switch (op){ case '+': case '-': return 1; case '*': case '/': return 2; default: return -1; } } //二值计算 int cate(Stack *stack,char op) { //栈是数字栈 int num1 = chuzhan(stack)-'0'; int num2 =chuzhan(stack)-'0'; switch(op){ case '+': return num2+num1; case '-': return num2-num1; case '*': return num2*num1; case '/': return num2/num1; } } /* 第三部分:表达式求值 */ //表达式求值函数 int qiuzhi (char *str){ int number; //返回值 int i; int num; //标识二值计算结果 char op; //标识弹出的运算符 int n=strlen(str); //表达式长度 Stack mystack1; //数字栈 chushihua(&mystack1); Stack mystack2; //运算符栈 chushihua(&mystack2); // 开始计算 for(i=0;i<n;i++){ if(isdigit(str[i])) { //1. 数字直接入栈 int sum=0; while(isdigit(str[i])){ //多个连续数字 sum=sum*10+str[i]-'0'; i++; } i--; ruzhan(&mystack1,sum+'0'); }else{ //2. 运算符 //2.1 运算符不能入栈 while(!(isEmpty(&mystack2)) && yxj(str[i]) <= yxj(topzhan(&mystack2))){ //取2值进行计算 op=chuzhan(&mystack2) ; num=cate(&mystack1,op) ; ruzhan(&mystack1,num+'0'); } ruzhan(&mystack2,str[i]); //2.2运算符可以入栈 } } //3. 表达式遍历结束,开始剩余运算符计算 while(!isEmpty(&mystack2)) { //取2值进行计算 op=chuzhan(&mystack2) ; num=cate(&mystack1,op) ; ruzhan(&mystack1,num+'0'); } number=chuzhan(&mystack1)-'0'; //数字栈中剩余的数值为计算结果 return number; } /* 第四部分:主函数 */ int main() { int i=0; char str[1000]; printf("请输入需要计算的表达式:\n"); char strstr[100][100]; //字符串数组 //表达式输入 while(1){ gets(strstr[i]); if(strstr[i][0]=='0'){ break; } i++; } int n=i; //表示表达式个数 int result[n] ; //结果数组 //计算并输出结果 printf("计算结果是:\n") ; for(i=0;i<n;i++){ result[i]=qiuzhi(strstr[i]); printf("%s=%d\n",strstr[i],result[i]); } return 0; }
4.运行结果:
19.判断出栈序列是否合法
1. 问题描述:
- 1. 对于一个栈,已知元素的进栈序列,判断一个由栈中所有元素组成的排列是否是可能的出栈序列。比如,进栈序列为1 2 3 4,则可能的出栈序列有4 3 2 1,1 4 3 2等。而1 4 2 3就不是。
- 2. 输入形式:从标准输入读取第一行是一个整数N(3≤N≤10),代表有N个元素,其进栈序列是1 2 3 …… N;第二行是空格分隔的1~N的数字的一个排列。
- 3. 输出形式:向标准输出打印结果。如果该排列是可能的出栈序列,则打印"YES",否则打印"NO"。
2. 思路:
- 出栈序列中,元素 i 之后所有比 i 小的元素间必须是降序排列的。(也就是判断元素 i 之后有没有比 i 小但却比它前边的某个元素大的元素)
3. 代码:
#include<stdio.h> #include<stdlib.h> int main() { int n; int i,j; int min; int flag=1; //出栈序列合法 printf("请输入N:"); scanf("%d",&n); int *p=(int *)malloc(n*sizeof(int)); printf("请输入出栈序列:"); for(i=0;i<n;i++){ scanf("%d",&p[i]); } for(i=0;i<n;i++){ //判断每一个元素i之后所有比i小的元素是否是降序排列 for(j=i+1,min=p[i];j<n;j++){ if(p[j]<min){ min=p[j]; }else if(p[j]<p[i]){ //不成立的条件:大于前边的值,但却比 p[i]小 ,即不是降序排列 flag=0; break; } } if(flag==0){ break; } } if(flag){ printf("出栈序列合法!"); }else{ printf("出栈序列不合法!"); } free(p); return 0; }
4. 运行结果:
20.交叉输出
1. 问题描述:
输入一串整数数组,将其中的偶数从大到小排序,奇数从小到大排序。然后交叉输出(第一个输出奇数)。
2. 思路:
- 分别提取偶数和奇数,存放到不同的数组之中;
- 使用冒泡排序分别对偶数数组和奇数数组进行降序和升序;
- 交叉输出排序后的两个数组。
3. 代码:
#include <stdio.h> int main() { int i,j,k; int n; //排序交换用 int cnt1=0; int cnt2=0; int a[10] = {2, 3, 14, 6, 2, 15, 12, 14, 4, 11}; // for(i=0;i<10;i++){ //输出原始数组 // printf("%d ",a[i]); // } // printf("\n"); //计数 for(i=0;i<sizeof(a)/4;i++){ if(a[i]%2!=0){ cnt1++; //奇数 }else{ cnt2++; //偶数 } } int num1[cnt1]; //奇数函数 int num2[cnt2]; //偶数函数 //插入 for(i=0,j=0,k=0;i<sizeof(a)/4;i++){ if(a[i]%2!=0){ //奇数 num1[j]=a[i]; j++; }else{ //偶数 num2[k]=a[i]; k++; } } // for(i=0;i<sizeof(num1)/4;i++){ //输出num1 // printf("%d ",num1[i]); // } // printf("\n"); // for(i=0;i<sizeof(num2)/4;i++){ //输出num2 // printf("%d ",num2[i]); // } // printf("\n"); //升序 for(i=0;i<sizeof(num1)/4;i++){ for(j=0;j<sizeof(num1)/4-1;j++){ if(num1[j]>num1[j+1]){ n=num1[j]; num1[j]=num1[j+1]; num1[j+1]=n; } } } // for(i=0;i<sizeof(num1)/4;i++){ //输出升序后的num1 // printf("%d ",num1[i]); // } // printf("\n"); //降序 for(i=0;i<sizeof(num2)/4;i++){ for(j=0;j<sizeof(num2)/4-1;j++){ if(num2[j]<num2[j+1]){ n=num2[j]; num2[j]=num2[j+1]; num2[j+1]=n; } } } // for(i=0;i<sizeof(num2)/4;i++){ //输出降序后的num2 // printf("%d ",num2[i]); // } // printf("\n"); //交叉输出 printf("排序后的数组为:") ; for(i=0;i<sizeof(num1)/4||i<sizeof(num2)/4;i++){ if(i<sizeof(num1)/4&&i<sizeof(num2)/4){ //2个数组均未越界 printf("%d ",num1[i]); printf("%d ",num2[i]); }else if(i>=sizeof(num1)/4){ //num1越界 printf("%d ",num2[i]) ; }else{ //num2越界 printf("%d ",num1[i]); } } return 0; }
4. 运行结果:
21.英文语句转置(字符串转置2)
1.问题描述:
- 输入:student. a am I
- 输出:I am a student.
2.思路:先将整个句子转置,然后使用将句子中的每个单词转置。
3.代码:
#include<stdio.h> #include<string.h> int main() { int i,j,k; int temp; int cnt; char str[100]; char *p; printf("请数组需要转置的句子:"); gets(str); //1.转置整个句子 for (i=0;i<strlen(str)/2;i++){ temp=str[i]; str[i]=str[strlen(str)-1-i]; str[strlen(str)-1-i]=temp; } // puts(str); //2.再次转置句子中的每个单词 for(i=0;i<strlen(str);i++){ p=&str[i]; for(cnt=0;i<strlen(str)&&str[i]!=' ';i++){ //确定单词 cnt++; } for(k=0;k<cnt/2;k++) { //转置单词 temp=*(p+k); *(p+k)=*(p+cnt-1-k); *(p+cnt-1-k)=temp; } } //3.输出 printf("转置后的句子是:"); puts(str); return 0; }
4.运行结果:
22.变换字符串
1. 问题描述:
一串字符串,每个都是 a~z之间,将每一个字符都变成其对应的下一个,z会变成a,如果遇到连续相同的多个字符,则第二个变换两次,两个以上,则第三个及以后与第一个保持一致。
2. 思路:
- 对全部字符加1
- 将相邻且相同的第二个字符再次加1
3. 代码:
#include <stdio.h> #include <string.h> int main() { int i; char str[100]; gets(str); //1. 对全部字符加一 for(i=0;i<strlen(str);i++){ if(str[i]==' '){ continue; }else if(str[i]!='z'){ str[i]=str[i]+1; }else{ str[i]='a'; } } //2. 将相邻且相同字符再次加一 for(i=1;i<strlen(str);i++){ if(str[i]==' '){ continue; }else if(str[i]==str[i-1]){ if(str[i]=='z'){ str[i]='a'; }else{ str[i]=str[i]+1; } } } puts(str); //输出字符串 return 0; }
4. 运行结果:
23.最大和子数组
1. 问题描述:
- 给定一个整数数组,找到一个具有最大和的连续子数组,返回其最大和。
2. 思路:
- 遍历数组,找到每一个数开头的连续最大加和数组,确定其开头元素与数组长度;
- 输出最大加和最大的数组。
3. 代码:
#include <stdio.h> #include <stdlib.h> int main() { int n,i,j ; int sum; int max; int index; printf("请输入数组长度n:"); scanf("%d",&n); int *a=(int *)malloc(sizeof(int)*n); //动态申请空间 int *b=(int *)malloc(sizeof(int)*n); //记录和值 int *c=(int *)malloc(sizeof(int)*n); //记录数组长度 printf("请输入数组的各个值:"); for(i=0;i<n;i++){ scanf("%d",&a[i]); } //找到每一个下标 i 开始的对应的最大连续数组 for(i=0;i<n;i++){ sum=0; b[i]=a[i]; //默认数组长度为 1 c[i]=1; for(j=i;j<n;j++){ sum+=a[j]; if(sum>b[i]){ //如果加上该值大于原来的和,则更新 “和 ”与 “数组长度 ” b[i]=sum; c[i]=j-i+1; } } } //判定哪一个连续数组和最大 ,并确定其下标 max=b[0]; for(i=0;i<n;i++){ if(b[i]>=max) { max=b[i]; index=i; } } //根据下标与数组长度,进行输出 printf("符合要求的子数组为{"); for(i=index;i<index+c[index];i++){ printf(" %d ",a[i]); } printf("},最大和是%d。",b[index]); return 0; }
4. 运行结果:
24.哈夫曼树(未解决)
1.问题描述:
- 计算哈夫曼树的带权路径长度。
25.括号匹配问题
1. 问题描述:匹配各种(两种)括号
2. 思路:
- 初始创立一个空栈;
- 逐个读入括号;
- 如果是左括号,那么就压入栈中;
- 如果是右括号,则先检查栈是否为空,如果栈为空,则表示无左括号与之匹配,匹配失败。如果栈不为空,则进入下一步;
- 从栈顶取出元素,检测此左括号与读入右括号是否匹配,如果不匹配,则返回匹配失败。如果匹配成功,则回到第二步,直至不满足循环条件;
- 检测栈是否为空,如果栈为空,则表示匹配完成后还有多余的括号,匹配失败。 若栈为空,则返回匹配成功。
3. 注意:
- 定义栈时不要使用指针,将其取地址后传入各个函数;
- 在进行字符串输入时,前边不能存在其他输入,不然会缓冲区中的回车符会顶替字符串。(解决方法:使用getchar()函数消耗掉)
4. 代码:
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> //定义栈节点 typedef struct Node{ char c; struct Node *next; }Node; //定义栈 typedef struct { Node *top; }Stack; //初始化栈 void chushihua(Stack *stack){ stack->top=NULL; } //判断栈是否为空 bool isEmpty(Stack*stack){ return stack->top==NULL; //空则返回 true,非空则返回 false } //入栈 void ruzhan(Stack *stack,char a){ Node *node=(Node*)malloc(sizeof(Node)); node->c=a; node->next=stack->top; stack->top=node; } //出栈 char chuzhan(Stack *stack){ char chr; Node *p=stack->top; chr=p->c; stack->top=p->next; free (p); return chr; } //获取栈顶元素 char topzhan(Stack *stack){ char chr; chr=stack->top->c; return chr; } int main () { char temp; //暂存出栈 括号 int is=1; //默认匹配成功 int i,n; //n 标识括号序列长度 Stack mystack; //建栈 chushihua(&mystack) ; //初始化 printf("请输入括号个数:"); scanf("%d",&n) ; getchar(); // 消耗掉换行符,不然会留在缓冲区,顶替括号序列 char*str=(char*)malloc(sizeof(char)*(n)); //括号数组 printf("请输入括号序列:") ; gets(str); //第一步:开始遍历括号序列 for(i=0;i<n;i++){ //情形一:左括号,入栈 if(str[i]=='('||str[i]=='['){ ruzhan (&mystack,str[i]) ; } //情形二:右括号 if(str[i]==')'||str[i]==']'){ if (isEmpty(&mystack)) { //1.栈为空,匹配失败 is=0; break; }else{ //2.栈不空,比较栈顶括号 与 读入括号是否匹配 temp=chuzhan(&mystack); //(匹配的话也还是要出栈) if((temp=='(' && str[i]==']') || (temp=='[' && str[i]==')')){ //不匹配 is=0; break; } } } } //第二步:判断最后的栈是否为空 if(!isEmpty(&mystack)) { //栈不为空 is=0; } //第三步:根据 is 输出 if(is==1){ printf("括号序列匹配成功!"); } else{ printf("括号序列不匹配!"); } return 0; }
5. 运行结果:
26.开灯问题
1. 问题描述:
有从1到n依次编号的 n 个同学和 n 盏灯。1号同学将所有的灯都关掉;2号同学将编号为 2 的倍数的灯都打开;3号同学则将编号为 3 的倍数的灯作相反处理(该号灯如打开的,则关掉;如关闭的,则打开);以后的同学都将自己编号的倍数的灯,作相反处理。问经n个同学操作后,哪些灯是打开的?
2. 思路:
- 定义一个数组表示每个灯的状态,初始为0,表示第一个人将所有的灯关掉;
- 从第二个人开始遍历到第n个人,每个循环中都进行找灯(遍历n盏灯),然后进行关灯或开灯(根据之前的状态决定)。
3. 代码:
#include <stdio.h> #include <stdlib.h> int main() { int i,j; int n; printf("请输入n的个数:"); scanf("%d",&n); int *a=(int *)malloc(sizeof(int)*n); for(i=0;i<n;i++){ //第一个人将所有灯关掉 a[i]=0; } for(i=2;i<=n;i++){ //n-1个人 for(j=0;j<n;j++){ //n盏灯 if((j+1)%i==0){ //找灯 if(a[j]==0) { a[j]=1; //开灯 }else{ a[j]=0; //关灯 } } } } //输出开着的灯 printf("最后开着的灯有:"); for(i=0;i<n;i++){ if(a[i]==1){ printf("%d号灯 ",i+1); } } return 0; }
4. 运行结果:
27.求天数
1. 问题描述:
- 给定一个日期,判定其是这一年的低多少天。
2. 思路:
- 判断是不是闰年;
- 根据是否是闰年确定每月的天数(主要是二月的天数);
- 使用循环进行计算。
3. 代码:
#include <stdio.h> #include <string.h> #include <stdbool.h> //判断闰年 bool isR(int a){ return (a % 4 == 0 && a % 100 != 0) || (a % 400 == 0); } int main () { int a,b,c; int number,i; printf("请输入需要判定的日期(年/月/日):"); scanf("%d/%d/%d",&a,&b,&c ) ; number=c; int mouth[12]={31,28,31,30,31,30,31,31,30,31,30,31}; if(isR(a)){ //是闰年,修改二月的天数 mouth[1]=29; } //计算结果 for(i=0;i<b-1;i++){ number+=mouth[i]; } //输出结果 printf("%d/%d/%d是这一年的第%d天!",a,b,c,number); return 0; }
4. 运行结果:
28.排序
1.问题描述:
- 输入一串数字,用逗号隔开,然后排序,但是如果一串连着的数字,只要输出最大和最小的就行了
- 输入:1,90,2,4,110,3
- 输出:1 4 90 110
2.思路:字符串读入,分割得到数字数组,然后排序,然后判断输出
3.代码:
#include <stdio.h> #include <string.h> #include <ctype.h> int main() { int i,j,k; int first; char str[100]; int num[100]; printf("请输入一串数字,中间用逗号隔开:"); gets(str); //1.分割字符串 for(i=0,j=0;i<strlen(str);i++){ first=0; if(isdigit(str[i])){ //找到开头 while(isdigit(str[i])&&i<strlen(str)){ //确定长度 first=first*10+(str[i]-'0'); i++; } i--; num[j]=first; j++; } } //2.冒泡排序(升序) for(i=0;i<j;i++){ for(k=0;k<j-1;k++){ if (num[k]>num[k+1]){ first=num[k+1]; num[k+1]=num[k]; num[k]=first; } } } //3.输出 for(i=0;i<j;i++){ k=i; while((num[i+1]==num[i]+1)&&(i!=j-1)){ //确定连续长度 i++; } if(i==k){ printf("%d ",num[i]); } else{ printf("%d %d ",num[k],num[i]); } } return 0; }
29.求原数组
1. 问题描述:
- 给定一个数组,该数组中的数值是原数组中两相邻元素的差值,求原数组;
- 如给定 { 1 ,2 ,0 ,2 ,-1 },原数组为 { 1 ,3 ,3 ,5 ,4 }。
2. 思路:
- 根据对应计算方法求解原数组。
3. 代码:
#include <stdio.h> #include <stdlib.h> int main() { int n; int i; int temp; printf("请输入数组长度n:"); scanf("%d",&n); int *a=(int *)malloc(sizeof(int)*n); //动态申请空间 int *b=(int *)malloc(sizeof(int)*n); printf("请输入数组的各个值:"); for(i=0,temp=0;i<n;i++){ scanf("%d",&a[i]); } //计算并输出原数组的各个值 printf("原数组为:"); for(i=0;i<n;i++){ b[i]=a[i]+temp; temp=b[i]; printf("%d ",b[i]); } return 0; }
4. 运行结果: