机试复习笔记

一、基础笔记

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;
}

运行结果:

1e4999b23fdf1d78e02399a6ac7e660a.png

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;
}

运行结果:

7770b7f3409a48d0e8a57d8ee5afe390.png

(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;
}

运行结果:

0ddbc72cf90439116e7e9bf2f07d77cc.png

3.常用函数及其头文件

d62411162e35513ce4fed7d5290f04db.png

二、题目

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. 运行结果:

331639a14553bdba12823255ca079a83.png

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. 运行结果:

092ae95d3d49cb37df3d5d5e6de83589.png

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. 运行结果:

e796245072d509e298e290a0baecd2e5.png

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. 运行结果:

763972902e648f27f17c4a3b5dd89f6b.png

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. 运行结果:

d94b8179a8eedac6ce47cf00f095865a.png

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. 运行结果:

ceaaf2634aa0b18e331809c8d926e850.png

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. 运行结果:65d27edb30714871231b7b53b7cb5ba9.png

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. 运行结果:

36ecf42e2a0a640ccffc7881f524a7eb.png

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. 运行结果:

4c879e57a39d1e4eb7813a15045d3c81.png

10.猴子选大王

1. 思路:

  1. 定义一个数组标识猴子状态,其中下标0的空间被舍弃掉(每个数组值初始为0,表示未被淘汰)。
  2. n只猴子,进行n轮遍历(循环)。
  3. 根据报数大小确定内层循环的次数,每一轮循环将一只猴子状态变为‘1’;在循环体中根据( item = item%n+1 )计算得到下一只猴子编号,并判断其状态是否为0;循环结束可以得到最后一只报数的猴子。
  4. 将最后一只报数的猴子状态置为1(淘汰)。
  5. 根据外层循环次数确定是不是大王(最后剩下的猴子),并输出。

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. 运行结果:

ee3589a498adc04496cf1769346f3fc2.png

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. 运行结果:

a00abbac89c1398bb2ae7d80a97632b9.png

12.大数相加

1. 问题描述:

        在一般语言中对整型数都有个最大限制,现给出两个超出正常范围的十进制数对其进行求和,是带进位的加法。

2. 思路:

  1. 将两个大数以字符串形式保存;
  2. 将两个字符串转置,并确认出较长的字符串;
  3. 开始进行相同位数的相加,需要设置一个进位(初始值为0);
  4. 开始进行剩余字符串与进位的相加;
  5. 判定最后一位是否有进位。

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.运行结果:

d2ec8766bb4e1fcb39e24e57cdc53e6c.png

13.找到加和为 t 的所有组合(回溯法应用)

1. 回溯法(暴力检索方法)三步走:

  1. 确定函数类型(一般为 void 型)与 参数 
  2. 确定递归终止条件 
  3. 确定内层循环递归逻辑 

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 .运行结果: c750fd3dd0ffb7bcd5dc59edea883e11.png

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. 运行结果:

819f781c9373356a383e9228f4bacb09.png

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. 运行结果:

3d6dd4f7fd49c267447bd983dd7eb626.png

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. 运行结果:

4cd099063f117e4b67973de786d74854.png

17.判断平方对称数

1. 问题描述:

  • 判断一个非负整数 n(n<256) 是否是平方对称数,是则输出"yes",否则输出"no";
  • 比如:11的平方是121 ,则是11是平方对称数。

2. 思路:

  1. 将平方数的每一位存放在数组中
  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. 运行结果:

6966e2dfeea37ea79a3ecb4121c3a2e1.png

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.运行结果:

9e2e6664ee483f4bd3cb6c6d57e50da3.png

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. 运行结果:

b64c811769d3ca8f91060f883a346439.png

20.交叉输出

1. 问题描述:

        输入一串整数数组,将其中的偶数从大到小排序,奇数从小到大排序。然后交叉输出(第一个输出奇数)。

2. 思路:

  1. 分别提取偶数和奇数,存放到不同的数组之中;
  2. 使用冒泡排序分别对偶数数组和奇数数组进行降序和升序;
  3. 交叉输出排序后的两个数组。

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. 运行结果:

1b7ceb4c782de7b7f9758a3afe66d3f0.png

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.运行结果:

ae21e5f68291c828017cffe8874368c5.png

22.变换字符串

1. 问题描述:

         一串字符串,每个都是 a~z之间,将每一个字符都变成其对应的下一个,z会变成a,如果遇到连续相同的多个字符,则第二个变换两次,两个以上,则第三个及以后与第一个保持一致。

2. 思路:

  1. 对全部字符加1 
  2. 将相邻且相同的第二个字符再次加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. 运行结果:

e75b7768ac13380a1ad9b2b3c969dc19.png

23.最大和子数组

1. 问题描述:

  • 给定一个整数数组,找到一个具有最大和的连续子数组,返回其最大和。

2. 思路:

  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. 运行结果:

234d83f7eb2badc134dadca140ce9b76.png

24.哈夫曼树(未解决)

1.问题描述:

  • 计算哈夫曼树的带权路径长度。

25.括号匹配问题

1. 问题描述:匹配各种(两种)括号

2. 思路:

  1. 初始创立一个空栈;
  2. 逐个读入括号;
  3. 如果是左括号,那么就压入栈中;
  4. 如果是右括号,则先检查栈是否为空,如果栈为空,则表示无左括号与之匹配,匹配失败。如果栈不为空,则进入下一步;
  5. 从栈顶取出元素,检测此左括号与读入右括号是否匹配,如果不匹配,则返回匹配失败。如果匹配成功,则回到第二步,直至不满足循环条件;
  6. 检测栈是否为空,如果栈为空,则表示匹配完成后还有多余的括号,匹配失败。  若栈为空,则返回匹配成功。

3. 注意:

  1. 定义栈时不要使用指针,将其取地址后传入各个函数;
  2. 在进行字符串输入时,前边不能存在其他输入,不然会缓冲区中的回车符会顶替字符串。(解决方法:使用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. 运行结果:

076cbe7fc9d6a0c0961c42eff8f9ff61.png

26.开灯问题

1. 问题描述:

        有从1到n依次编号的 n 个同学和 n 盏灯。1号同学将所有的灯都关掉;2号同学将编号为 2 的倍数的灯都打开;3号同学则将编号为 3 的倍数的灯作相反处理(该号灯如打开的,则关掉;如关闭的,则打开);以后的同学都将自己编号的倍数的灯,作相反处理。问经n个同学操作后,哪些灯是打开的?

2. 思路:

  1. 定义一个数组表示每个灯的状态,初始为0,表示第一个人将所有的灯关掉;
  2. 从第二个人开始遍历到第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. 运行结果:

33f22871818408e8a3543070fabfa5c8.png

27.求天数

1. 问题描述:

  • 给定一个日期,判定其是这一年的低多少天。

2. 思路:

  1. 判断是不是闰年;
  2. 根据是否是闰年确定每月的天数(主要是二月的天数);
  3. 使用循环进行计算。

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. 运行结果:

37b47e7a77dbe1603a2dd16acb4a4ec7.png

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. 运行结果:

6e864bdc0c863263735ac3a43da6c680.png

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

欧小文呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值