0
点赞
收藏
分享

微信扫一扫

C语言练习

成义随笔 2022-07-18 阅读 82

title: 初级编程 date: 2022.06.21 top_img: ​​https://s4.ax1x.com/2022/02/26/ben1FU.jpg​​​ cover: ​​​https://s4.ax1x.com/2022/02/26/ben3YF.jpg​​ tags: C categories: 初级编程 description: C语言入门编程,以小见大 keywords: comments: toc: true

交换2个整形数据的值(异或与宏处理) 不建议使用

异或思想

a=10

b=100

a=a^b
b=a^b
a=a^b

将3句合成一句

a^=b^=a^=b

加法思想

x=x+y;

y=x-y;

x=x-y;

无法合并为一句……

#include<stdio.h>
int main( )
{
int a=60;
int b=50;
a^=b^=a^=b;
printf("a=%d,b=%d",a,b);
puts("");
}

也可以用宏去处理

#include<stdio.h>
#define swapt(x,y) ((x^=y^=x^=y))
int main()
{
int a=10;
int b=20;
swapt(a,b);
printf("%d %d",a,b);
return 0;
}

用&运算去判断奇偶

值得注意但是,运算符的优先顺序

这里的()必须还得打上去

#include<stdio.h>

int main( )
{
for(int i=0;i<10;i++)
{
if( (i&1) ==0 )
printf("偶数&1=1,偶数: %d\n",i);
if( (i&1) ==1 )
printf("奇数&1=1,奇数: %d\n",i);
}
}

用参数化宏比较2个数的大小

用宏命令返回2个数较大的那个

#include<stdio.h>
#define max(x,y) ((x)>(y)?(x):(y))
//这里的话,每个都打上括号的话,就会不出错
int main()
{
int x=10;
int y=20;
int z=30;
int q=40;

int result=max(max(x,y),max(q,z));
printf("%d",result);
return 0;
}

用参数化宏计数二次方

#include<stdio.h>

#define sqrt(x) ((x)*(x))

int main()
{
printf("%d",sqrt(20));
return 0;

}

​#define sqrt(x) ((x)*(x))​​必须写括号

如果​​#define sqrt(x) (x*x)​

sqrt(1+2)

就是

(1+2*1+2)!=9

计算二元一次方程

它不是用穷举法,而是给定基本算法的公式,然后PC去带入数值计算

#include<stdio.h>
#include<math.h>

int main()
{
double deta=0;
double a=0;
double b=0;
double c=0;
double x=0,x1=0,x2=0;

puts("请输入A*x^2+B*x+C的A,B,C");

scanf("%lf %lf %lf",&a,&b,&c);

deta=b*b-4*a*c;

//有解
if(a!=0)
{
puts("这是一个一元二次方程");
//有2个解
if(deta>0)
{
x1=(-b+sqrt(deta))/(2*a);
x2=(-b-sqrt(deta))/(2*a);
}
//有2个相同的解
else if(deta==0)
{
x1=x2=(-b)/(2*a);
}
//无解
else
{
puts("deta<0,no value");
return 0;
}
printf("x1=%.5lf\n",x1);
printf("x2=%.5lf\n",x2);
}
//非一元二次方程
else
{
puts("这不是一个一元一次方程");
//无解
if(b==0||c==0)
{
puts("首先a=0,其次b=0或者c=0->no value");
return 0;
}
//有解
else
x=(-c)/b;
printf("%lf\n",x);
}

return 0;

}

用位运算判断正负

int main() {
int input, asm_input;//因为下面使用了>>,所以定义为整型,int 4字节
scanf("%d", &input);
asm_input = input >> 31;

//int 4Byte 32bit >>31取了一个符号位

if (asm_input == 0)
//符号位是0,它是非负
{
if (input == 0)
//输入为0
{
printf("输入的是0");
}
//输入不为0,
else
{
printf("输入的是正数");
}
}
//符号位是1,为负数
else
{
printf("你输入的是负数");
}
return 0;
}

同理可言

int main() {
char input, Asm_input;//因为下面使用了>>,所以定义为字符型,char 1字节
puts("请输入");
scanf("%d", &input);
Asm_input = input >> 7;
//char 1Byte 8bit >>7取了一个符号位

if (Asm_input == 0)
//符号位是0,它是非负
{
if (input == 0)
//输入为0
{
printf("输入的是0");
}
//输入不为0,
else
{
printf("输入的是正数");
}
}
//符号位是1,为负数
else
{
printf("你输入的是负数");
}
return 0;
}

九九乘法表- 为什么要用双重循环

#include<stdio.h>
int main()
{

int x=0;
int y=0;
for(x=1;x<10;x++)
{
y=1;
for(;y<=x;y++)
printf("%-2dx %2d =%-2d ",y,x,x*y);
puts("");
}
return 0;
}

当一个循环建立在在另外一个循环之上的话

循环A

循环B

A循环1次,B才循环n次,

在B循环n次当中,我们要保持A不变

于是我们就要双重循环去制约他们的先后循环顺序

素数判断 -循环时间减少一半

一般的编程

好比20

我们的常规方法是

从2开始​​i++​

用​​20/i​

直到19完毕循环

这样我们最多循环18次

老代码如图

int ispr
ime(int n)
{
int i;
for (i = 2; i < n; i++)
{
if (n % i == 0)
{
return 0;
}
}
return 1;
}

看一下下面这个图

于是我们只需要循环数值的一半

因为​​一半 x 一半​​是一个分界线,如果前一半都没有找到对应的因数,那么后面那一半也就没有了

所以如果检测的数本来就是质数,我们只需要循环原来一半的时间我么就可以实现相同的效果

int isprime(int n)
{
int i;
for (i = 2; i <= n/2; i++)
{
if (n % i == 0)
{
return 0;
}
}
return 1;
}

所以我们学到了啥?

认真观察事物的本质与规律…..

去深入的思考

一个奇怪的方法,没看懂

#include<stdio.h>
#include<math.h>
int is(int);
int main()
{
int n,count=0;
scanf("%d",&n);

for(int i=n;i>3;i--)
if(is(i))
if(is(i-2))
count++;
printf("%d",count);
return 0;
}

int is(int n)
{
for(int i=2;i<sqrt(n)+1;i++)
{
if(n%i==0)
return 0;
}
return 1;
}

判断一个数是不是2个素数的和

#include<stdio.h>
int check(int);
int main()
{
int flag=0;
int input=34;
int i=0;
for(i=2;i<=input/2;i++)
if(check(i)==1)
if(check(input-i)==1)//input-i+i=input
{
printf("%3d=%3d+%3d\n",input,input-i,i);
flag=1;
}
if(flag==0)
puts("sorry");
return 0;
}
int check(int x)
{
int i=0;
for(i=2;i<=x/2;i++)//注意是从2开始,不能是0,1,
if(x%i==0)
return 0;
return 1;
}

16进制u转化为10进制的Bug完善

遇到的bug

  1. Visual_Stdio的编译器没有给我动态内存,导致无法访问???
  2. 递归函数的退出程序要用​​exit(1)​​,而不是return,因为你递归n次,要return n次才可以退出

C-Free版本

#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include <math.h>

//清理屏幕
void clean()
{
system("pause");
system("cls");
}
//进制转化
void Incremental_conversion(char*str)
{
puts("请输入字符串16进制");
if(str==NULL)
return ;
scanf("%s",str);
int len=strlen(str);//输入的长度
int i=0;
int key=0;//退出按钮
int check_Digt=0;//字符数字 ->ASCII的编码
int check_small_word=0;//字符串a,b...e,f ->ASCII的编码
int check_large_word=0;//字符串A,B...E,F ->ASCII的编码
int check1=0;//布尔类型判断是否是字符数字
int check2=0;//布尔类型判断是否是a,b,..,e,f/A,B,...E,F
int output=0;//输出结果

//如果输入带有0x,就把字符串往前移位,好比0x1234,改为1234\0\0
if( str[0]=='0'&& (str[1]=='x'||str[1]=='X') )
{
for(;i<len-2;i++)
str[i]=str[i+2];
str[i]='\0';//后方2位必须置为空,否者0x1234->123400就错了,要1234\0\0
str[i+1]='\0';
len-=2;//长度也会-2
}

for(i=0;i<len;i++)
{
check_Digt=str[i]-48;//字符数字-<数字
check_small_word=str[i]-87;//小写字母-数字
check_large_word=str[i]-55;//大写字母-数字

//布尔类型判断是否是字符数字
check1=check_Digt>=0&&check_Digt<=9;

//布尔类型判断是否是a,b,..,e,f/A,B,...E,F
check2=(check_small_word>=10&&check_small_word<=15)||(check_large_word>=10&&check_large_word<=15);

//把所有情况综合在一起检测 ,注意哪些情况
if((check1&&check2)||check1||check2)
{
str[i]=check_Digt<10?check_Digt:(check_small_word<0?check_large_word:check_small_word);
}
//输入错误 ,并且选择
else
{
flag1: puts("input wrong");
puts("option input 1,continue");
puts("option input 0,just exit");
scanf("%d",&key);
if(key==1)
{
clean();
//递归
Incremental_conversion(str);
}
else if(key==0)
exit(1);
else
{
//输入错误
clean();
goto flag1;
}
}

}
//数字分解再相加
for(i=0;i<len;i++)
{
output+=str[i]*((int)pow(16,len-1-i));
}
printf("转化的结果是 sum=%d\n\n",output);


//是否还要继续输入
flag2: puts("now, do want to continue?");
puts("over input 1,continue");
puts("ovre input 0,just exit");
scanf("%d",&key);
if(key==1)
{
clean();
Incremental_conversion(str);
}

else if(key==0)
exit(1);
else
{
//输入错误
clean();//清屏
goto flag2;
}
}

int main()
{

char *str=(char*)calloc(1024,sizeof(char));
memset(str,'\0',1024);
Incremental_conversion(str);//进制转化函数
free(str);//释放堆区
return 0;
}

Visual_stdio版本

#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include <math.h>

void clean()
{
system("pause");
system("cls");
}
void Incremental_conversion(char*str)
{
puts("请输入字符串16进制");
scanf_s("%s",str,1024);
int len=strlen(str);
int i=0;
int key=0;
int check_Digt=0;
int check_small_word=0;
int check_large_word=0;
int check1=0;
int check2=0;
int output=0;

if( str[0]=='0'&& (str[1]=='x'||str[1]=='X') )
{
for(;i<len-2;i++)
str[i]=str[i+2];
str[i]='\0';
str[i+1]='\0';
len-=2;
}

for(i=0;i<len;i++)
{
check_Digt=str[i]-48;
check_small_word=str[i]-87;//小写-数字
check_large_word=str[i]-55;//大写-数字

check1=check_Digt>=0&&check_Digt<=9;
//小写的ascii大,大写的ASCII小
//
check2=(check_small_word>=10&&check_small_word<=15)||(check_large_word>=10&&check_large_word<=15);
if((check1&&check2)||check1||check2)
{
str[i]=check_Digt<10?check_Digt:(check_small_word<0?check_large_word:check_small_word);
//printf("%d\n",str[i]);
}
else
{
flag1: puts("input wrong");
puts("option input 1,continue");
puts("option input 0,just exit");
scanf_s("%d",&key);
if(key==1)
{
clean();
Incremental_conversion(str);
}

else if(key==0)
exit(1);
else
{
goto flag1;
}
}

}
for(i=0;i<len;i++)
{
output+=str[i]*((int)pow(16,len-1-i));
}
printf("转化的结果是 sum=%d\n\n",output);


flag2: puts("now, do want to continue?");
puts("over input 1,continue");
puts("ovre input 0,just exit");
scanf_s("%d",&key);
if(key==1)
{
clean();
Incremental_conversion(str);
}

else if(key==0)
exit(1);
else
{
clean();
goto flag2;
}
}

int main()
{
int i=0;
char *str=(char*)calloc(1024,sizeof(char));
if (str == NULL)
{
return 0;
}
else
Incremental_conversion(str);
free(str);
return 0;
}

斐波那契数列

就是后一个数是前2个数的和

#include<stdio.h>
int main()
{
int q1=0;
int q2=1;
int sum=0;

int i=0;
int max=0;
puts("请问你要输出几个数?");
scanf("%d",&max);
for(;i<max;i++)
{
printf("%d ",q1);
sum=q1+q2;
q1=q2;
q2=sum;
}
}

最大公约数

方法一 穷举法

公约数从小->大

他们同时除一个数,如果都能除尽,说明是公约数

#include <stdio.h>

int main()
{
int n1, n2, i, output,min;

printf("输入两个正整数,以空格分隔: ");
scanf("%d %d", &n1, &n2);
min=n1<n2?n1:n2;
for(i=1; i <=min; i++)
{
// 判断 i 是否为最大公约数
if(n1%i==0 && n2%i==0)//i从1开始,一直遍历到最大值,如果满足同时被2个数整除就记录一下
output = i;
}
printf("%d 和 %d 的最大公约数是 %d", n1, n2, output);
return 0;
}

它的另外一个模板是

原理一模一样,从大的公约数到小

#include <stdio.h>

int main(void)
{
int x, y, gcd;
printf("请输入两个正整数:");
scanf("%d%d", &x, &y);
gcd=x<y?x:y;
while(x % gcd ||y % gcd)//当余数同时为0就退出
gcd--;
printf("gcd = %d\n", gcd);
return 0;
}

方法二 未知

公约数从大->小

#include <stdio.h>
int main()
{
int n1, n2;

printf("输入两个数,以空格分隔: ");
scanf("%d %d",&n1,&n2);

while(n1!=n2)
{
if(n1 > n2)
n1 -= n2;
else
n2 -= n1;
//大小的ifelse保证结果为正
}
printf("GCD = %d",n1);//组后n1与n2都是一样的

return 0;
}

辗转相除法

#include<stdio.h>

int main()
{

int x=21;
int y=49;

int buff;

//这下面这个代码的顺序很重要
while(y!=0)
{
buff=x%y;
x=y;
y=buff;
}
printf("%d",x);

return 0;
}

辗转相除法-函数递归

#include<stdio.h>
int func(int,int);
int main()
{
printf("%d",func(21,49));
return 0;
}
int func(int x,int y)
{
if(y!=0)
return func(y,x%y);
else
return x;
}

另外一种写法,可能它的步骤更加前进些

#include <stdio.h>

int func(int m, int n);
int main()
{
printf("%d",func(21,49));
return 0;
}
int func(int m, int n)
{
if(m % n != 0) //直接运算后判断,返回那个商,而那个商是以前的余数
return func(n, m%n);
else
return n;
}

最大公约数

穷举法

#include <stdio.h>

int main()
{
int n1, n2, max;
printf("输入两个正整数: ");
scanf("%d %d", &n1, &n2);

max=n1>n2?n1:n2;
while(1)
{
if(max%n1==0&&max%n2==0)
{
printf("%d",max);
break;
}
max++;
}


return 0;
}

难以琢磨

#include <stdio.h>
int main()
{
int n1,n2,buff,gcd;
n1=72;
n2=120;
gcd=n1<n2?n1:n2;
while(n1%gcd||n2%gcd)
gcd--;
printf("%d",(n1*n2)/gcd);
return 0;
}

阶乘

这里要注意一下数据的范围,其思想还是很重要的

#include<stdio.h>
int func(int);
int main()
{
int a=4;
int sum=func(a);
printf("%d",sum);
return 0;
}
int func(int x)
{
if(x>1)
return x*func(x-1);
else
return x;
}

几位数的判断

关于里面数据初始化的问题是一个关键

#include<stdio.h>

int main()
{
int input=0,base=1,count=0;
scanf("%d",&input);
//input=9;
for(;input/base>0;count++)//因为base=1,所以这里的coutn肯定是可以++
base*=10;
printf("%d",count);
return 0;
}

#include<stdio.h>
int main()
{

int input=0,count=0;
scanf("%d",&input);
while(input!=0)
{
input/=10;
count++;
}
printf("%d",count);
return 0;
}

#include<stdio.h>
int main()
{

int input=0,count=1,n=1;
scanf("%d",&input);
while(input/10>0)
{
input/=10;
count++;
}
printf("%d",count);
return 0;
}

x的y次方

一般形式

#include <stdio.h>

int main()
{
int x,y,output=1;
scanf("%d %d",&x,&y);
for(;y>0;y--)
output*=x;
printf("%d",output);
return 0;
}
/*
for(i=1;i<=b;i++)
{
c *= a;
}
上面这种写法的思路也差不多


*/

函数递归

#include<stdio.h>
int func(int,int);
int main()
{
int x,y,output=1;
scanf("%d %d",&x,&y);
printf("%d",output*func(x,y));
return 0;
}
int func(int x,int y)
{
if(y>0)
{
return x*func(x,y-1);
}
else
return 1;
}

回文数-把数值逆序

好比把1234变为4321

#include <stdio.h>

int main()
{
int input=0,y,z=0;
//canf("%d",&input);
input=123456;
while(input!=0)
{
y=input%10;//获取最后一位
z=z*10+y;//把数据向高进制前移
input/=10; //数据斩断
}
printf("%d",z);
return 0;
}

转化为字符串的比较

#include <stdio.h>
#include<string.h>
#include<stdlib.h>

int main()
{
int a=1234,len,i;
char str1[10];
char str2[10];
memset(str1,'\0',10);
memset(str2,'\0',10);
sprintf(str1,"%d",a);
len=strlen(str1);
for(i=0;i<len;i++)
str2[len-1-i]=str1[i];
//然后用strcmp比较
return 0;
}

阿姆斯壮数-临时变量的运用与初始化

#include <stdio.h>
#include <math.h>

int main()
{
int low,high,n,i,temp,buff,sum,check;
low=100;
high=1000;
for(;low<high;low++)
{
temp=low;//这里这个temp很重要... low不能发生变化, 最后的low会++的
check=low;//最后判断那个结果是不是和它一样
n=0;//计数,有几位
buff=temp;
sum=0; //记录它的和
while(buff!=0)
{
buff/=10;
n++;
}//判断它是几位数
buff=0;
for(i=n;i>0;i--)//数分解再处理
{
buff=temp%10;
sum+=pow(buff,n);
temp/=10;
}
if(check==sum)//如果2个数相等就输出
printf("%d ",sum);

}
return 0;
}

函数版

#include<stdio.h>

char func(long long);//它只是算一下某个数有几位,然后去调用其它的函数
long long mi(long long,char);//这个函数只是代替了你的math.h的pow(x,y)
char check(long long,char );//它的作用是算它每个位的某个次方,会调用到mi函数
int main()
{
long long high=1000;
long long low=100;//在数据(low,high) 中寻找符合条件的数
char flag=0;
for(;low<high;low++)
{
flag=func(low);
if(flag==1)
printf("%lld ",low);
}
return 0;
}

char func(long long low)
{
long long temp=low;
char ret=0;//返回值的抓取
char n=0;
while(temp!=0)
{
temp/=10;
n++;//记录那个数有几位
}
temp=low;
ret=check(temp,n);
return ret;
}
char check(long long low,char n)
{
char flag=0;
char i=0;
long long x=0,y=0,z=0;
z=low;
for(i=n;i>0;i--)
{
x=low%10;
y+=mi(x,n);
low/=10;
}
if(y==z)
return 1;
else
return 0;
}
long long mi(long long x,char n)
{
long s=1;
while(n!=0)
{
s*=x;//不断的乘
n--;
}
return s;
}

三角形输出-规律查找

输出

1
2 3 2
3 4 5 4 3
4 5 6 7 6 5 4
5 6 7 8 9 8 7 6 5

#include<stdio.h> 

int main()
{
int i,k;
for(i=0;i<5;i++)
{
//空格打印,这里可能要记录一些数值
for(k=0;k<5-1-i;k++)
printf(" ");
for(k=i+1;k<=(2*(i)+1);k++)
printf("%d ",k);
for(k=k-2;k>i;k--)
printf("%d ",k);
puts("");
}
}

杨辉三角形

最简单的思路,最安全的思路

#include <stdio.h>

int main()
{
int arr[10][10]={0};
int j,i,z;
//z为行数
z=7;

//初始化每个数的的第一位与最后一位为1,
for(i=0;i<z;i++)
{
arr[i][0]=1;
arr[i][i]=1;
}
for(i=1;i<z;i++)//因为第一位与最后一位已经被我们初始化了,所以就不用再从0开始
{
for(j=1;j<i;j++)//为什么是小于i?而不是<=i,因为最后一位已经被我们初始化了
arr[i][j]=arr[i-1][j]+arr[i-1][j-1];//实现了是上面2位的相加
}
for(i=0;i<z;i++)
{
for(j=0;j<z-i-1;j++)
printf(" ");//为了效果的实现就打印了空格
for(j=0;j<=i;j++)
printf("%4d",arr[i][j]);//为什么是j<=i?通过观察得来的 ,%4d是为了更好的对齐
puts("");
}
}

他这样做有一定的风险

#include <stdio.h>

int main()
{
int i,j,n=0,a[17][17]={0,1};
n=7;//行数
for(i=1;i<=n;i++)
{
for(j=1;j<=i;j++)
{
a[i][j]=a[i-1][j-1]+a[i-1][j]; /*每个数是上面两数之和*/
printf("%5d",a[i][j]); /*输出杨辉三角*/
}
printf("\n");
}
}

用2个一位数组

思想还好

#include <stdio.h>

int main()
{
int i,j,n=0,S[17]={1},D[17];
n=7;
for(i=0;i<n;i++)
{
D[0]=S[0];//把顶位给初始化位1
for(j=1;j<=i;j++)
D[j]=S[j-1]+S[j];
for(j=0;j<=i;j++)
{
S[j]=D[j]; /*把算得的新行赋给a,用于打印和下一次计算*/
printf("%5d",S[j]);
}
printf("\n");
}
}

写简单点

#include <stdio.h>

int main()
{
int i,j,n=7,S[20]={1},D[20]={0};
for(i=0;i<n;i++)
{
D[0]=S[0];//初始化开头部分为1
for(j=1;j<=i;j++)//每一行有几个就算几个
D[j]=S[j]+S[j-1];//S就像上一级,D就像是下一级
for(j=0;j<=i;j++)
printf("%4d",S[j]=D[j]);//实现一个主客的变化
puts("");
}
}

最节约内存的写法,用到了零时保存的思想

这个写法还是蛮新器的

#include <stdio.h>
int main()
{
int i,j,x,y,z;
int arr[20]={1,0};
for(i=0;i<7;i++)
{
y=0;
for(j=0;j<=i;j++)
{
x=arr[j];
arr[j]=y+x;//初始话操作
y=x;
printf("%4d",arr[j]);
}//当我们每每完成一次初始化数组与打印他还会保留原始的信息
puts("");
}
}
/*好比上一次循环
我们得到数组
1,2,3,4,5
于是这一段代码
x=arr[j];//数据访问
arr[j]=y+x;//当前数据初始化
y=x;//数据的一个备份.其位置只能在这里
中的x=arr[i],就是访问上一次数组留下的信息

*/

没搞懂的杨辉三角形公式

#include <stdio.h>
int main()
{
int rows, coef = 1, space, i, j;

printf("行数: ");
scanf("%d",&rows);

for(i=0; i<rows; i++)
{
for(space=1; space <= rows-i; space++)
printf(" ");

for(j=0; j <= i; j++)
{
if (j==0 || i==0)
coef = 1;
else
coef = coef*(i-j+1)/j;

printf("%4d", coef);
}
printf("\n");
}

return 0;
}

进制转化

更多的是一种进制转化的思想….

Binary->Dec

#include<stdio.h>
#include<math.h>
double func(double);
int main()
{
double x=110110111;
printf("%.0lf",func(x));

return 0;
}
double func(double x)
{

int n=0;
double ret=0;
double buff =0;
while(x!=0)
{
buff=(int)x%10;//double类型的不可以去%10
ret+=buff*pow(2,n);//某一位*2的某次放
x/=10;
n++;
}
return ret;
}

另外写一种

大同小异,没有用到pow,而是自己写这个函数

#include<stdio.h>

int pow_(int ,int );
int main()
{
int n=110110111;
int x,y,z;
y=0;
z=0;
while(n!=0)
{
x=n%10;
y+=x*pow_(2,z);
n/=10;
z++;
}
printf("%d\n",y);


return 0;
}
int pow_(int base,int n)
{

int ret=1;
while(n!=0)
{
ret*=base;
n--;
}
return ret;
}

Dec->Binary

#include <stdio.h>
#include <math.h>

long long convertDecimalToBinary(int n);

int main()
{
int n;
n=100;
printf("十进制数 %d 转换为二进制位 %lld", n, convertDecimalToBinary(n));
return 0;
}

long long convertDecimalToBinary(int n)
{
long long ret=0;
long long x,y,z;
long long base=1;
while(n!=0)
{
x=n%2;
ret+=base*x;
base*=10;
n/=2;
}
return ret;
}

Dec->Oct

思路还是一样的,不过他最后那种写法比较好,使得变量更少的使用

#include <stdio.h>


int func(int );
int main()
{
int x=78;
printf("%d\n",func(x));
return 0;
}

int func(int n)
{
int ret=0;
int base=1;
while(n!=0)
{
ret+=(n%8)*base;//这种写法减少了参数的使用
base*=10;
n/=8;
}
return ret;

}

Oct->Dec

#include <stdio.h>
#include <math.h>

long long func(int);
int main()
{
int n=116;
printf("八进制数 %d 转换为十进制为 %lld", n, func(n));
return 0;
}

long long func(int x)
{
long long ret=0;
int n=0;
while(x!=0)
{
ret+=(x%10)*pow(8,n);
x/=10;
n++;
}
return ret;
}

用递归实现字符串的逆序

#include<stdio.h>
void func();
int main()
{
func();
}
void func()
{
char input=8;//随便初始化为8
scanf("%c",&input);//最后一次接收你输入的换行,
if(input!='\n')//判断到你是换行就不再递归,返回并且输出
{
func();//只有这个函数return后,你才可能输出当时函数scanf的字符
printf("%c",input);
}
return;
}

另外一种的递归.可能会比较简洁

#include<stdio.h>
void Re(char*);
int main()
{
char str[20]={0};
fgets(str,20,stdin);
Re(str);
return 0;
}
void Re(char* str)
{
if(*str=='\0')
return ;
Re(str+1);
printf("%c",*str)
}

对半逆序字符串

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char* Re(char* );
int main()
{

char str[20]={0};
scanf("%s",str);
printf("%s",Re(str));
}
void swapt(char& x,char& y)
{
char z=0;
z=x;
x=y;
y=z;
}
char* Re(char* str)
{
char temp=0;
int i=0;
int j=0;
int len=strlen(str);
j=len-1;
while(i<len/2)//用i<j也是一样的意思,因为i=j的时候就已经折半来
{
swapt(str[j],str[i]);
i++;
j--;
}

return str;
}

求平均数

#include<stdio.h>
int main()
{
double avg=0,sum=0;
double input=0;
int count=0;
bool flag=1;
while(flag==1)
{
sum+=input;
flag=scanf("%lf",&input);//scanf()的返回值就是参数的个数
count++;
}
count-=1;
avg=sum/count;
printf("%.2lf",avg);
return 0;
}

错误的写法

如果你输入n=‘q’,他也会sum+=n.那么会加入一个未知的值

while(flag==1)
{

flag=scanf("%lf",&n);//scanf()的返回值就是参数的个数
sum+=n;
n++;
}

数组求和,酷毙了

define

free与calloc

static局部静态

递归

scanf(“%d%c”)奇怪的输入

#include<stdio.h>
#include<stdlib.h>
#define SAFE_FREE(p) \
free(ptr); \
p = NULL;

int len=0;
int* ptr=NULL;
int* func();
int main()
{

int i=0;
int sum=0;
ptr=func();//接收传递过来的指针
for(i=0;i<len;i++)
{
sum+=ptr[i];//p指向那个堆区
}
printf("sum %d\n",sum);//输出和
SAFE_FREE(ptr);//释放堆区
return 0;
}

int* func()
{
static int count1=0,count2=0; //静态局部变量
int Digit=0;
char ascii=0;
scanf("%d%c",&Digit,&ascii);
count1++;
if(ascii!='\n')//空格代表结束
func();
else
ptr=(int*)calloc(count1,sizeof(int));
count2++;
ptr[count1-count2]=Digit;//为什么count1-count2刚好就是index?因为前面的count2先++了
if(count1==count2)//此刻的index=0;说明遍历完毕
{
printf("len is %d\n",count1);
len=count1;
}
return ptr;
}

去除字符串中非字母成分

函数的功能就是一个字符串中字符部分掩盖非字符成分,数据前移的一个过程

我写的这个思路还是比较简单的,还不知道bug

#include<stdio.h>
#include <ctype.h>
#include<string.h>
int main()
{
char str[10]="dqx123";
int len=strlen(str);
int i=0,j=0;
for(i=0;i<len;i++)//如果你不用len的话,用str[i]!='\0'是无法退出的
if(!isalpha(str[i])) //如果str[i]遇到空格怎么办???
{
for(j=i;j<len;j++)
str[j]=str[j+1];
len--;//因为数据前移,所以就长度减一
i--;//你把数据前移,可是移过去后,它是不是字母呢?你还是要对移过去后的字母进行检测
}
puts(str);
return 0;
}

这个思路关于那个逻辑判断有点难以设计

还真不是一眼就能看出来

#include<stdio.h>
#include <ctype.h>

int main()
{
char str[10]="dqx123dqx";
int i,j;
for(i=0;str[i]!='\0';i++)
while(!(isalpha(str[i])||(str[i]=='\0')))
{
for(j=i;str[j]!='\0';j++)
str[j]=str[j+1];
str[j]='\0';
}
puts(str);
return 0;
}

/*
while (!(isalpha(line[i])||(line[i] == '\0')) )

什么时候可以进入循环?????
!(0||0)
非字母||是空字符
什么时候i退出循环
!(1||1)//不可能成立,是字母 就不可能是空字符
!(0||1)//不是字母是空格
!(1||0)//是字母不是空字符

*/

遍历字符串数组的长度

不用strlen()

// 计算字符串 s1 长度
for(i = 0; s1[i] != '\0'; ++i);

可以看到,这个循环体除了++i以外啥也没干

而++i就是一个长度的遍历

字符串衔接-多变的指针

#include <stdio.h>

int main()
{
char str1[100], str2[100];
char *p = str1;
char n = 0;

printf("请输入第一个字符串:");
scanf("%s", str1);

printf("请输入第二个字符串:");
scanf("%s", str2);

while (*p++ != '\0');//把指针指向末尾的空字符 ,但是这里又++了,本来我们就在空字符那里接着填写
--p;//把指针再次指向以前那个空字符
while (str2[n] != '\0')
{
*p++ = str2[n];//将str2接到str1末
++n;
}
*p = '\0';//设置一个结束的标志

puts(str1);
return 0;
}

我自己写的一个简单的版本

#include<stdio.h>

int main()
{
char str1[100]="dqx";
char str2[100]="123";
char n=0;
char *ptr=str1;
//ptr指向空字符的下一位
while(*(ptr++)!='\0');
ptr--;
while(str2[n]!='\0')
*(ptr++)=str2[n++];
*ptr='\0';
puts(str1);
return 0;
}

字母在字符串当中出现的次数

这种写法很巧妙….利用里每个字母的偏移未知从而确定数组的index

#include<stdio.h>
#include<string.h>
#include <ctype.h>
int main()
{
char str[]="dqx is a good boy";
char ascii[26];
int len=strlen(str);
int i;
memset(ascii,0,26);//初始化为0,好为了后面的++操作

for(i=0;i<len;i++)
if(isalpha(str[i]))//只对小写字母处理,防止未知内存的访问
ascii[str[i]-'a']++;//对于的数组元素++

for(i=0;i<26;i++)
if(ascii[i]!=0)//只是输出次数不为0的
printf("%c:%d\n",'a'+i,ascii[i]); //输出字母对于的次数
return 0;
}

单词排序 strcmp

#include<stdio.h>
#include<string.h>
void swapt(char*,char*);
int main()
{

int i,j;
char str[10][50],temp[50];

puts("请输入5个单词");

for(i=0;i<5;i++)
scanf("%s[^\n]",str[i]);

for(i=0;i<5-1;i++)//冒泡排序
for(j=0;j<5-1-i;j++)
if(strcmp(str[j],str[j+1])>0)
swapt(str[j],str[j+1]); //二维数组的一维名字就是地址

printf("\n排序后: \n");
for(i=0; i<5; ++i)
puts(str[i]);
return 0;

}
void swapt(char* s1,char* s2)
{
char temp[50];//与以前不同,他这里用strcmp来实现那个传值的过程
strcpy(temp,s1);
strcpy(s1,s2);
strcpy(s2,temp);
}

文件简单的写入操作

fgets fpritnf

#include<stdio.h>
#include<stdlib.h>

int main()
{
char s[1000]={0};
FILE *ptr=NULL;
ptr=fopen("D:/dqx.txt","w");
if(ptr==NULL)
exit(1);
puts("请输入字符串");
fgets(s,100,stdin);//从stdin流获取数据到s
fprintf(ptr,"%s",s);//从s写入到ptr

//貌似这个桥梁不可或缺,你得搭建起来...要然不写不到文件里面去
fclose(ptr);
return 0;
}

用fputc逐个字符的写入文件

#include<stdio.h>

int main()
{
FILE* ptr=NULL;
int i=0;
char str[100]="20010927";
ptr=fopen("D:/dqx.txt","w");
while(str[i]!='\0')
fputc(str[i++],ptr);
fclose(ptr);


return 0;
}

用gets

只能读取一行

#include<stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char buff[1024];
FILE* ptr;
memset(buff,0,1024);
int len=0;
ptr=fopen("D:/dqx.txt","r");
fgets(buff,1024,ptr);
puts(buff);
fclose(ptr);
return 0;
}

文件的读取

fscanf

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
char str[1024];
FILE* ptr=NULL;
memset(str,0,1024);
ptr=fopen("D:/dqx.txt","r");
fscanf(ptr,"%[^\n]", str);
puts(str)
return 0;
}

文件从一个文件复制到另外一个文件

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{

FILE* S=fopen("D:/in.txt","r");
FILE* D=fopen("D:/out.txt","w");
char buff[1024];
memset(buff,0,1024);

if((S!=NULL)&&(D!=NULL))//保证2个文件同时打开
{
puts("are you ready");
fread(buff,1024,1,S);//我们这里用数组的形式
fputs(buff,D);
}
fclose(D);
fclose(S);
return 0;
}

输出当前源文件的源代码

#include <stdio.h>
int main()
{
FILE *ptr;
char output;
ptr = fopen(__FILE__,"r");//以read模式打开当前的源文件
do
{
output = getc(ptr);//逐个读取源文件的ASCII
putchar(output);//然后输出
}
while(output != EOF);//EOF最后也被输出
fclose(ptr);
return 0;
}

约瑟夫生者死者小游戏

游戏规则…有30个人

需要15人跳船…..船上装不下那么多人了

每个船员都有编号

依次站好

他们从头报数,数到9的就跳下海..跳下去一个就少一个人..那个人的编号也就消失了.

后面的人接着数字​​1​​再报数….报到9

一直报数一直跳…直到到船上还有15人就结束

思路一:就像把30张扑克牌叠在一起,抽到了,就丢掉。难点在于如何将收尾衔接好

#include<stdio.h>


int top=0;
int index=1;
int nine=0;
int check[30]={0};

int main()
{
while(index<=31)//编号从1开始
{
if(index==31)
index=1;//数人到最后又从头再来
else if(top==15)
break;//走了15人下船 ,就退出程序
else//一般在这里开始
{
if(check[index]==1)//下一次数到那个缺失位置就步过
{
index++;//数到这里时, nine不会++,直接过
continue; //我们得记住编号是不会改变的 ,那个人跳进海里后,它的编号不会给别人....
}
else
{
nine++;//报数++
if(nine!=9) //记录他是否数到9
{
index++;
continue;
}
else//但数到9后
{
check[index]=1;//1像是标志位,如果没人在那个位置就是0,有人就退出 //这是为了下一次更好的遍历
nine=0;//恢复为0,重新开始数到9
printf("Num.%02d \n",index);
index++;//遍历++
top++;//已经下船的人数++
}
}
}
}
return 0;
}

自己写的,之前有很多的bug

#include<stdio.h>
int main()
{
int index=1;
int flag=1;
int top=0;//max=15
int check[40]={0};
while(1)
{
if(top==15)
break;
if(check[index]==1)
{
index++;
continue;
}
if(flag==9)
{
check[index]=1;
flag=1;
printf("Num.%d\n",index);
top++;
if(index==31)
{
index=1;
continue;
}
index++;
continue;
}
if(index==31)//31为就是1位 的思想
index=1;//在131:flag时,进行判断,判断时本来131++,flag++ ,但是变为了1++,flag++,所以很正常
index++;
flag++;
}
}

最简洁容易理解的方法

#include<stdio.h>
int main()
{
int
flag=0,//报数的标志
people=0,//下船的人数
index=0,//index
check[30]={0};//下船记录表
while(1)
{
if(check[index]!=1)//0表示没有下船,1表示下船了
flag++;//只有船上的人才可以报数
if(people==15)
break;//15人就退出
if(flag==9)
{
flag=0;//从头再来报数
check[index]=1;//记录那个位置的人已经跳下海了
people++;//下海人数++
printf("%d\n",index+1); //从0开始的报数,所以要+1
}
index++;
if(index==30)//消除出现30的机会,30就是循环头部的1
index=0;
}
return 0;
}

用链表实现

相反很简单,就是不好处理

#include<stdio.h>
#include<stdlib.h>
int main()
{
struct people
{
int index;
people* next;
};
people* ahead=NULL;
people* behind=NULL;
people* Qian=NULL;
people* Hou=NULL;
int count=0;
int flag=0;

//初始化的操作 初始化每个人的编号
for(count=1;count<31;count++)
{
struct people *buff=(struct people*)calloc(1,sizeof(struct people));//这里很需要这个堆区的开辟
buff->index=count;//初始化堆区的参数
if(count==1)//关于头指针
{
ahead=buff;
ahead->next=NULL;//后面的话,他会连上链表的尾部
behind=buff;
}
else
{
behind->next=buff;//让上一个指针指向我们新开辟的堆区
behind=buff;//behind更新一下
}
}
behind->next=ahead;//这里是尾巴被蛇头咬住.而不是头部主动咬尾巴.还是有区别的 ..组后形成一个闭环
Qian=Hou=ahead;
for(count=30;coun>15;)//只有数到9才会有count-- 16-30才是15个
{
for(flag=1;flag<=9;flag++)
{
if(flag==9)
{
count--;
printf("%d\n",Hou->index);
Qian->next=Hou->next;
free(Hou);//去掉那个被剔除的人
Hou=Qian->next;//
}
else//链表的遍历
{
Qian=Hou;//Qian是一个地址的备份
Hou=Hou->next;//Hou不断的更新数据
}
}
}
return 0;
}

#include <stdio.h>
#include <stdlib.h>
int main()
{
int check[30]={0};
int index = -1;
int i = 0;
char count = 0;
for(i = 0;i < 30;i++)//对人数进行编号
check[i] = i + 1;
for(count = 0;count < 15;count++)//循环sw次
{
for(char flag = 0; flag < 9;flag ++)//循环gz次
{
if(index < 29) //令其循环报数
index++; //为什么是ss-1
else //因为k < ss会在k = 30时将k复位为0,而数组只有29
index = 0; //所以 k < ss - 1才会在k = 29时将k复位为0
if(check[index] > 300) //如果当前编号已经被标志,
flag --; //那么我们接着下一个编号报数
}
printf("%d号下船\n",check[index]);
check[index] += 300;//标志已经下船的编号
}
}

举报

相关推荐

C语言 练习

C语言,练习6

C语言习题练习

C语言循环练习

C语言,练习5

C语言-作业练习

C语言,练习2

0 条评论