分享我的#C语言学习之路

家人们,这些都是我前几天的学习笔记,现在和大家一起分享,希望我们可以一起进步

#include <math.h>
#include <string.h>
#include <time.h>//调用时间函数时引用;返回的是函数值是time_t类型(长整型)
#include <stdlib.h>//使用rand时需引用的头文件;
#include <stdio.h>

数组的正确创建方式:数组类型+数组名[常量];
eg: int arr[10];---10个元素都是整型的数组;
    char arr3[10];
    float arr4[10];
错误写法:
eg: int count=10; int arr2[count];
//注意:[]中要给常量才可以;

char arr1[5]={'a','b'};放的ab000(程序默认的);
char arr2[5]="ab"; 放的ab和\0(自己放的)和00;
char arr[]="abcdef";
printf("%d\n",sizeof(arr));//7;--求字符串所占的空间大小,由于最后有个字符串结束标志也占用空间,所以为7
printf("%d\n",strlen(arr));//6;---求字符串的长度,求的是'\0'之前字符串的个数;

arr1[]={'a','b'};
printf("%d\n",strlen(arr1));//随机值;
sizeof---计算变量、数组、类型的大小,单位是字节


int main()
{
   char arr[] = "abcdef";//[a][b][c][d][e][f][\0]
   int i=0;
   int sz=sizeof(arr)/sizeof(arr[0])
   for(i=0;i<sz;i++)
       printf("%c ",arr[i]);
   return 0;
}//打印对应的元素

数组在内存中的存放情况:数组在内存中是连续存放的;
int main()
{
    int arr[]={1,2,3,4,5,6,7,8,9,10};
    int i=0;
    int sz=sizeof(arr)/sizeof(arr[0]);
    for(i=0;i<sz;i++)
    {
       printf("&arr[%d]=%p\n",i,&arr[i]);
    }
   return 0;
}//由于每个元素都是整型,每个元素都是四个字节,所以地址存放时,都相差4,所以数组在内存中是连续存放的;


二元数组的创建
int arr[3][4];//3行4列
char ch[5][6];//
初始化:
int arr[3][4]={1,2,3,4,5,6,6,7,8,9,10,11};//自动按顺序对应摆放;
int arr[3][4]={{1,2,3},{2,3,4,5},{3,3,6}};//一个{}对应一行

int arr[][4]={1,2,3,4,5,6,7,8,9,10};//可以省略行下标,但是不能省略列下标;

二元数组的遍历:
int main()
{
    int arr[4][4]={12,2,23,14,5,6,37,23,8,9,32,4,3,26,7,3};
    int i=0;
    int j=0;
    for(i=0;i<4;i++)
        {for(j=0;j<4;j++)
        {printf("%-2d ",arr[i][j]);}
    printf("\n");}
    return 0;
}


二元数组在内存中的存放:二元数组在内存中也是连续存放的,两个地址之间也是相差4
int main()
{
    int arr[4][4]={12,2,23,14,5,6,37,23,8,9,32,4,3,26,7,3};
    int i=0;
    int j=0;
    for(i=0;i<4;i++)
        {for(j=0;j<4;j++)
        {printf("&arr[%d][%d]=%p ",&arr[i][j]);}
    printf("\n");}
    return 0;
}


数组作为函数参数
eg:冒泡排序函数将一个整型数组进行排序(排成一个升序)
void bubble_sort(int brr[],int s)
{
    int i=0;
    int temp;
    for(i=0;i<s-1;i++)//表示一趟,将最大的数排在最右边;
    {
       int falg=1;//假设你输入的数组是有序的; 
       int j=0;
       for(j=0;j<s-1-i;j++)//表示将相邻的两个数比较后,最大数排到最右边要比较几次;
          {if(brr[j]>brr[j+1])
              {temp=brr[j];
              brr[j]=brr[j+1];
              brr[j+1]=temp;
              flag=0;}}
    if(flag==1)
    {break;}//表示美走完一趟,就去判断重新排序的数组是不是有序的,如果是,那么跳出整个循环;
    }
}
int main()
{
    int arr[]={12,2,23,14,5,6,37,23,8,9,32,4,3,26,7,3};
    int sz=sizeof(arr)/sizeof(arr[0]);
    int i=0;
    bubble_sort(arr,sz);//数组传参,穿的是数组的首个元素的地址;
    for(i=0;i<sz;i++)
        printf("%d ",arr[i]);
    return 0;
}


注意啦:通常数组名就是收元素地址;
eg:
int main()
{
    int arr[]={2,3,4,5,6,7};
    printf("%p\n",arr);
    printf("%p\n",arr[0]);
    printf("%d\n",*arr);//如果打印出来是2,那么说明数组名就是首元素地址;
   return 0;
}//两个打印的结果是一样的;


特殊情况:数组名就不是首元素地址;
eg:
int arr[]={1,2,3,4,5,6};
int sz=sizeof(arr)/sizeof(arr[0]);
//1.sizeof(数组名)----数组名表示整个数组,sizeof(数组名)计算的是整个数组的大小,单位是字节;
//2.  &数组名,数组名代表整个数组;&数组名,取出的是整个数组的地址;
printf("%p\n",&arr);//得到的是整个数组的地址,也可以说是说明这个数组地址从这个地址开始;


//求总数为m个球选择k个的组合的可能性
#include <stdio.h>
int fac(int z)
{
    int i=1;
    int sum=1;
    for(i=1;i<=z;i++)
      {    sum=sum*i;}
    return sum;
}
int main()
{
   int temp=0;
   int m,k;
   int ret=0; 
   printf("请输入两个数:>");
   scanf("%d %d",&m,&k);
   //随意输入两个数,判断大小,并将较大的值给m,小的给k;
   if(m<k)
   { temp=k;
     k=m;
     m=temp;}
//函数调用来求三个的阶乘;
  ret=fac(m)/(fac(k)*fac(m-k));
  printf("ret= %d\n",ret);
   return 0;
}

//求阶乘时,阶乘数小的时候 可以使用int、long int
//但是阶乘数大的时候,上面的存储范围不够,所以可以使用long long、unsigned long long
//long long 输出时为:%lld; unsigned longlong为:%llu;

操作符详解
1.算数操作符:+(加) -(减) *(乘) /(除) %(取)
注:%--对于左操作数和右操作数必须都是整数
eg: a=5 % 2;
其他操作符都可以作用于整数和浮点数;


2.移位操作符(只能作用于整数)
<<---左移
直接丢弃左边,右边补0;

>>---右移:移动的是二进制位;
一: 
算术移位:右边丢弃,左边补上原符号位;
//0代表正,1代表负;
二:
逻辑右移:右边直接丢弃,左边补0,没有补1的规则;
eg:
int a=-1;
//10000000000000000000000000000001(32位)--原码
//11111111111111111111111111111110(32位)--反码
//11111111111111111111111111111111(32位)--补码
移动的是补码,显示的是原码;
int b=a>>1 //二进制位向右移动1位;由于此时a是个负数,所以右移一位后左边补1;
printf("%d\n",b);//输出为-1,说明是算术移位;
//Ctrl+Alt+M---查看内存
//整数的二进制有三种表现形式:原码、反码、补码
//存到内存中的是:补码
//对于正整数的原码和补码和反码是相同的;

3.位操作符
& --按二进制位与
eg:
int a=3;//00000000000000000000000000000011
int b=5;//00000000000000000000000000000101
int c=a&b;//00000000000000000000000000000001;
printf("%d\n",c);//c=1;
如果a,b是负数的话,就要变成补码然后按位与;

| --按二进制位或
int a=3;//00000000000000000000000000000011
int b=5;//00000000000000000000000000000101
int c=a|b;//00000000000000000000000000000111
printf("%d\n",c);//c=7

^ --按二进制位异或(对应的二进制位相同则为0,不同则为1)
int a=3;//00000000000000000000000000000011
int b=5;//00000000000000000000000000000101
int c=a^b;//00000000000000000000000000000110
printf("%d\n",c);//c=6

变态面试题:
不能创建临时变量(第三个变量),实现两个数的交换;
方法1:加减法---可能会溢出,数据丢失;
int a=3,b=5;
a=a+b;//a=8,b=5;
b=a-b;//a=8,b=3;
a=a-b;//a=5,b=3;
printf("%d%d",a,b);

方法2:异或法;(可读性不太高)
int a=3,b=5;
//a--011,b--101
a=a^b;//110(6)
b=a^b;//011(3)
a=a^b;//101(5)
printf("%d%d\n",a,b);

练习:编写一个代码,求一个整数存储在内存中的二进制中的1的个数。
#include <stdio.h>
int main()
   {
       int n=0,count=0,i;
       scanf("%d",&n);//统计n的补码中1的个数
   32bit位存储
       for(i=0;i<32;i++)
       {
    //将n右移i位,判断n在内存中存储时第i位是否为1;
    //注意:负数在内存中存储的是补码
           if(((n >> i) & 1)==1)
           {
               count++;
           }
       }
       printf("%d\n",count);
       return 0;
   }


4.赋值操作符: =
创建变量时的赋值叫初始化,当变量有了之后你改变变量的值叫赋值
eg:
int a=3;//初始化

int a=3;
a=4;//赋值

连续赋值:a=x=y+1;//将y+1赋给x,然后将x赋给a;
//注意赋值操作符是1个等号(=),而判断操作符是两个等号(==)

复合操作符:+=(加等),-=(减等),*=(乘等),/=(除等),%=(取余等),>>=(右移等),<<=(左移等),&=(与等),|=(或等),^=(异或等)
eg:
a=a+2等同于a+=2;
a=a>>2---a>>=;

5.单目操作符:(只有一个操作数) 
!(逻辑反)
-(负值) +(正值) &(取地址) 
sizeof(计算以字节为单位的操作数的类型长度) 
~(对一个数的二进制按位取反) 
--(前置、后置--) 
++(前置、后置++)
*(间接访问操作符或者说解引用操作符)
(类型)---强制类型转换

!--逻辑反操作符;(假变真,真变假)
eg:
if(a)
{
    printf("haha\n")//表示如果a为真,就打印haha;
}
if(!a)
{
    printf("hehe\n");//表示a为假,就打印hehe;
}

&(取地址),*(解引用)
int main()
{
    int a=10;
    int* p=&a;//指针p中放a的地址;
    *p;//*p--指p指向地址a中的数据;
}

sizeof--求大小
//求变量大小时,后面括号可以省略;求类型大小时后面的括号不能省掉
eg:
int main()
{
    int a=10;
    char c='r';
    char* p=&c;
    int arr[10]={0};
    //计算变量所占空间的大小;
    printf("%d\n",sizeof(a));//4
    printf("%d\n",sizeof(int));//a的类型大小--4

    printf("%d\n",sizeof(c));//1字符
    printf("%d\n",sizeof(char);//c的类型--1

    printf("%d\n",sizeof(p));//4(32位),8(64位);
    printf("%d\n",sizeof(char*));//p的类型--4(32位),8(64位);

    printf("%d\n",sizeof(arr));//10*4=40字节
    printf("%d\n",sizeof(int [10]));//数组类型大小--40

    return 0;
}

int main()
   {
       int n=10;
       short s=0;
       printf("%d\n",sizeof(s=n+5));
       printf("%d\n",s);
       return 0;
   }//2,0
//short--2个字符长度;s=n+5--只是一个摆设,实际没有改变s的值

~--按二进制位取反
eg:
int main()
{
    int a=0;
    //00000000000000000000000000000000
    printf("%d\n",~a);
    //11111111111111111111111111111111--补码
    //打印出来原码
    //原码--10000000000000000000000000000001--(-1)
    return 0;
}

(类型)--强制类型转换;
eg:
int a=(int)3.14;

练习:
#include <stdio.h>
void test1(int arr[])
{
    printf("%d\n",sizeof(arr));//4
}
void test2(char ch[])//本质上ch是指针,所以是4/8,当前平台(32位)默认是4
{
    printf("%d\n",sizeof(ch));//4
}
int main()
{
    int arr[10]={0};
    char ch[10]={0};
    printf("%d\n",sizeof(arr));//40
    printf("%d\n",sizeof(ch));//10
    test1(arr);//传参传过去的是首数组的首元素的地址
    test2(ch);
    return 0;
}

6.关系操作符: >, >=, <, <=, !=,==;

7.逻辑操作符:&&(与) ||(或) ---关注的这个数是真是假
//区分&和&&,|和||
eg:
二进制位与: 1&2---->0
数本身与:  1&&2---->1
二进制位或:1|2----->3
数本身或:  1||2---->1

练习:
#include <stdio.h>
int main()
{
    int i=0,a=0,b=2,c=3,d=4;
    i=a++ && ++b && d++;
    //i=a++||++b||d++;
    printf("a=%d\n b=%d\n c=%d\n d=%d\n",a,b,c,d);
    return 0;
}1,2,3,4;
//由于是&&,所以要判断到前面有一个为0,后面就不用算了

#include <stdio.h>
int main()
{
    int i=0,a=0,b=2,c=3,d=4;
    i=a++||++b||d++;
    printf("a=%d\n b=%d\n c=%d\n d=%d\n",a,b,c,d);
    return 0;
}1,3,3,4
//由于是||,所以要判断到有一个非零的数后,后面就可以不用算了

8.条件操作符(三目操作符)
exp1 ? exp2 : exp3
//表示如果表达式1为真,那么表达式2的结果为整个表达式的结果,否则就是表达式3的结果为整个表达式的结果
eg:
max=(a>b? a : b);
相当于
    if(a>b)
        max=a;
    else
        max=b;

9.逗号表达式:就是用逗号隔开的多个表达式,从左向右依次执行,整个表达式的结果是最后一个表达式的结果。
exp1,exp2,exp3,exp4,.....expn;
eg1:
int main()
{
    int a=1;
    int b=2;
    int c=(a>b,a=b+10,a,b=a+1);//逗号表达式;
    printf("%d\n",c);//13
    return 0;
}
//第一个表达式和第三个表达式执行,但是都不产生结果,而第二个表达式中a=2+10=12,所以最后b=12+1=13;

eg2:
if(a=b+1,c=a/2,d>0)//只要判断d是不是大于0就可以

eg3:
a=get_val();
count_val(a);
while(a>0)
{
    a=get_val();
    count_val(a);
}
改用逗号表达式:
while(a=get_val(),count_val(a),a>0)//不便理解,建议熟练后再使用;
{
    a=get_val();
    count_val(a);
}


10.下标引用、函数调用和结构成员
一、[]--下标引用操作符
操作数: 一个数组名+一个索引值
eg:
int arr[10];//创建数组;
arr[9]=10;//实用下标引用操作符;[]的两个操作数是arr+9

二、函数调用操作符
操作数:函数名+()里面的参数
eg:
int a=10,b=20;
int c=max(a,b);
//此处调用函数的时候的()就是函数调用操作符;

三、访问一个结构的成员
.---结构体.成员名
->--结构体->成员名
eg:
//学生类型--描述学生的相关属性
//创建一个结构体类型--struct stu
struct stu
{
    char name[20];//名字
    int age;//年龄
    char id[20];//学号
};//类似图纸
int main()
{
    int a=10;
    //使用struct stu这个类型创建了一个学生对象s1,并初始化;
    struct stu s1={"张三",20,"2019010803"};//实际建房子,占用内存;
    printf("%s\n",s1.name);
    printf("%s\n",s1->name);
    printf("%d\n",s1.age);
    printf("%d\n",s1->age);
    printf("%s\n",s1.id);
    printf("%s\n",s1->id);
    //结构体变量.成员名
    return 0;
}

//->(指针指向)
struct stu
{
    char name[20];//名字
    int age;//年龄
    char id[20];//学号
};//类似图纸
int main()
{
    int a=10;
    //使用struct stu这个类型创建了一个学生对象s1,并初始化;
    struct stu s1={"张三",20,"2019010803"};//实际建房子,占用内存;
    struct stu* p=&s1;
    printf("%s\n",p->name);
    printf("%d\n",p->age);
    printf("%s\n",p->id);
    //结构体变量->成员名
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

fighting787

一起加油,一起成功!

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

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

打赏作者

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

抵扣说明:

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

余额充值