C语言学习/复习(不包含指针)

配置C语言运行环境,下载code::blocks并运行第一个代码:

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

int main()
{
    printf("hello world!");
    return 0;
}

数据类型

bool类型

非零(true),零(false)

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

int main()
{
    bool a;
    a = 1;

    if(a){
        printf("true, %d\n", a);
    }
    else{
        printf("false, %d\n", a);
    }


    return 0;
}

bool类型只有零与非零的关系,只要是非零值都判定为真。

char类型
类型名称长度(字节byte)值域
char1byte==8bit-128127或0255
signed char1-128~127
unsigned char10~255
原码反码补码

​ 正数的原码反码补码都相同;
​ 负数的反码即原码的除符号位其它位取反,补码就是反码+1

原码-11000 0001
反码1111 1110
补码1111 1111

​ 计算机在内存中存储方式是补码。

​ 使用char数据类型需要的变量需要注意防止超出阈值:

char c1 = 128; //出错,数据越界 -128
char c1 = 129; //出错,数据越界 127
unsigned char c2 = -1; //出错,数据越界 255
					   //1000 0001补码1111 1111
short类型
类型名长度(字节byte)值域
short2-32768~32767
unsigned short20~65535
int类型
类型名长度(byte)值域
int4
unsigned int4

常量

​ 常量指在程序运行时数值不发生改变的数据。

整形常量

​ 整数可以是十进制数,八进制数和十六进制数

浮点常量

​ 浮点常量又被称为实数,一般含有小数部分。

指数常量

​ 指数形式的实数一般由尾数部分、字母e或E和指数部分组成。一般都用来表示特别大或特别小的数。

字符常量

​ 字符常量是一个单一字符,其表示形式是由两个单引号包括的一个字符。

​ 字符常量的值就等于字符的ASCII码值。

//可以把字符常量看作一个字节的正整数。
char a,b,c,d;
a = 'F';	//把70赋值给a
b = 'A'+2;	//b存放的是'C'字符
c = ' '+'B'; //c存放的是'b'字符
d = 'b'-32;	//d存放的是'B'字符
//他们分别相当于下列运算:
a = 70;
b = 65+2;
c = 32+66;
d = 97-32;

示例代码:

#include <stdio.h>

int main()
{
    char c1 ,c2, c3;
    c1 = 'A';
    c2 = 'A'+' ';
    c3 = 'A'+' '+2;

    printf("%c %c %c",c1,c2,c3);
    return 0;
}

字符串常量

​ 字符串常量就是用双引号括起来的一串字符来表示的数据。(字符串以’\0’结尾)

#include <stdio.h>

int main()
{
    char arr[] = {"abc"};
    char arr2[] = {'a','b','c','\0'};

    printf("%d %d \n",sizeof(arr),sizeof(arr2));

    printf("%s %s \n",arr,arr2);
    return 0;
}
标识常量

​ 也叫符号常量,一般用大写英文字母的标识符。在使用之前必须预先定义,说明形式为:宏。

#include <stdio.h>

#define ONE 1
#define TWO ONE+ONE
#define TWOO ((ONE)+(ONE))

int main()
{
    int a=10,b=20,c,c2;

    c=ONE + TWO*b + a;//1+1+1*b+a = 32

    c2=ONE + TWOO*b +a;//1+2*b+a = 51

    printf("%d %d\n",c,c2);

    return 0;
}

​ 这里面的宏定义是企业笔试题经常会挖的坑,在宏定义时必须使用括号来标记优先级。

变量

​ 变量在程序中用变量名表示,变量名由字母、数字、下划线组成,不能以数字开始,不能和C的关键字重名。

​ 程序运行时,变量占据存储空间的大小由其数据组成。变量在内存空间中的首地址,称为变量的地址。

变量的声明

​ 变量在程序中使用时,必须预先说明他们的存储类型和数据类型。

​ 说明的一般形式是:<存储类型><数据类型><变量名>;

​ 存储类型是关键字:auto、register、static和extern

​ 数据类型可以是基本数据类型,也可以是自定义的数值。

变量的存储类型:
auto

说明的变量只能在某个程序范围内使用,通常在函数体内或函数中的复合语句中(默认是随机数)。

#include <stdio.h>
int main()
{
	if(1){
		auto int a;
		printf("a=%d",a);
	}
	printf("a=%d",a);
	return 0;
}
//例如这段代码编译会报错,auto定义的变量是一个局部变量,只能在if(1)的范围内使用,范围外则不能再使用auto定义的变量。
register

称为寄存器型,register变量想将变量放入CPU的寄存器中,这样可以加快程序的运行速度。如果申请不到就使用一般内存,同auto

​ register变量必须是能被CPU所接收的类型。这通常意味着register变量必须是一个单个的值,并且长度应该小于或等于int的长度。

不能用“&”获取register变量的地址。由于寄存器的数量有限,真正起作用的register修饰符的数目都依赖于运行程序的机器。

​ 在某些情况下,把变量保存在寄存器中反而会降低程序运行速度。因为被占用的寄存器不能用于其他目的,或者变量被使用的次数不够多,不足以装入和存储变量所带来的额外开销。

#include <stdio.h>

int main()
{
    register int a;

    printf ("%d %p \n",a,a);//%p就是打出地址

    return 0;
}
//这段程序会乱码,类型不匹配
static

​ static变量称为静态存储类型的变量,既可以在函数体内,也可以在函数体外说明(默认为0)。

​ 局部变量使用static修饰有一下特点:

​ 1.内存中以固定地址存放,而不是以堆栈形式存放;
​ 2.只要程序没有结束,就不会随着说明他的程序段的约束而消失,它下次再调用该函数,该存储类型的变量不会重新说明,而且还保留上次调用存储。

#include <stdio.h>

int main()
{
    int i=1;
    while(i<5){
        static int a=0;
        a++;
        printf("a=%d \n",a);
        i++;
    }

    return 0;
}

static修饰的全局变量或者函数,意味着只能在本文件内使用。

extern

当变量在一个文件中的函数体外说明,所有其他文件中的函数或程序段都可以引用这个变量。

extern称为外部参照引用型,使用extern说明的变量是想引用在其他文件中的函数体外声明的变量。

static修饰的全局变量,其他文件无法使用。

//main.c
#include <stdio.h>

extern int a;
int main()
{
    printf("a=%d\n",a);

    return 0;
}
//extern.c
int c = 20;

​ 上面extern则是告诉编译器这个变量a是来自外部文件的。

运算符

算数运算符

​ C语言提供的算数运算符:+、-、*、/、%、++、–。(float、double不能取余)

关系运算符

​ >、>=、<、<=、==、!=

逻辑运算符

​ !、&&、||

位运算
运算符功能说明举例
~按位取反
&按位与
|按位或
^按位异或
>>位右移
<<位左移
#include <stdio.h>
int main()
{
    unsigned char x = 0126, y= 0xac, z;
    z= x&y;
    printf("%#x \n",z);
    return 0;
}
//out:0x4
赋值运算符

+=、-=、*=、/=、%=、&=、|=、^=、>>=、<<=

#include <stdio.h>
int main()
{
    int count = 0,sum = 0;
    while(count++ < 100)
    {
        sum+=count;
    }
    printf("sum=%d\n",sum);

    return 0;
}
//从1加到100。
特殊运算符
条件运算符

“?:”是个三目运算符

#include <stdio.h>
int main()
{
    int x=70,y=25;

    y=x++>70?100:0;

    printf("x=%d y=%d \n",x,y);

    return 0;
}
逗号运算符:
#include <stdio.h>
int main()
{
    float x = 10.5, y=0.8, z=0;

    z = (x+=5, y=x+0.8, z=x+y);

    printf("x=%f y=%f z=%f \n",x,y,z);
    return 0;
}
//逗号运算符的结果是由最后一个表达式所决定的。
//out x=15.5 y=16.3 z=31.8
sizeof运算符:

它只针对数据类型,而不针对变量

如:sizeof(double)、sizeof(long)

运算符优先级
优先级运算符
1()、[]
2+、-
3++、–、!
4*、/、%
5+、-
6<<、>>
7>、>=、<、<=
8==、!=
9&
10^
11|
12&&
13||
14?:
15=、+=、-=、*=、/=、%=
16&=、|=、<<=等位赋值运算

例如:

int x=1,y=0,z=0;
x++ && y++ || ++z; //结果为1

!(x+1>0) && y++ || ++z;//结果为1

x+=y==z,y=x+2,z=x+y+z>0;//x为2,y为4

输入输出

数据输出

C语言无I/O语句,I/O操作由函数实现

​ #include <stdio.h>

字符输出函数

​ putchar©

​ 参数:c为字符常量,变量或表达式

​ 功能:把字符c输出到显示器中

​ 返回值:正常,为现实的代码值

#include <stdio.h>
int main()
{
	int c;
	char a;
	c=65;a='B';
	putchar(c);putchar('\n');putchar(a);
}
//out: 
A
B
格式输出函数 printf
#include <stdio.h>

int main()
{
    int a = 245;
    char b = 'A';
    char hello[] = "hello world";
    float c =3.14;

    printf("%d - %x - %o \n",a,a,a);//十进制、十六进制、八进制
    printf("%c - %d \n",b,b);		//字符、ASCII码
    printf("%s \n",hello);			//字符串
    printf("%f - %e - %g \n",c,c,c);//浮点数、指数型、带小数点后有效数

    return 0;
}
#include <stdio.h>

int main()
{
    int a = 1234;
    float f =123.456;
    char ch='a';
    char a[]="hello world";
    
    printf("%8d, %2d \n",a,a);
    printf("%f - %8f - %8.1f - %.2f\n",f,f,f,f);
    printf("%3c \n",c);
    printf("%s - %15s - %10.5s",a,a)
    
    return 0;
}

字符输入函数 getchar
格式输入函数 scanf

​ 语法:scanf(“格式控制串”, 地址表);

#include <stdio.h>

int main()
{
    int a,b,c;
    scanf("%4d%2d%2d",&a,&b,&c);

    printf("%d-%d-%d\n",a,b,c);
    return 0;
}
//若输入20210388则a为2021,b为03,c为88
	int a,b;
    scanf("%2d %*3d %2d",&a,&b);
    //*为抑制符号,代表中间3位不要了。
    //若输入1234567,则a为12,b为78。
输入函数垃圾清理
//使用输入函数可以会留下垃圾:
int x;
char ch;
scanf("%d",&x);
scanf("%c",&ch);
printf("x=%d ch=%c\n",x,ch);
//这段代码会有bug,只输入x,按下回车后会跳过ch的输入

方法1:用getchar清除回车符

方法2:用格式串中空格或"%*c"吃掉回车

字符串输入输出函数
字符串输入函数gets

char * gets(char *s)

​ 功能:从键盘输入一回车结束的字符串放入字符数组中,并自动加’\0’

​ 说明:输入串长度应小于字符数组维数;与scanf函数不同,gets函数不以空格作为字符串输入结束的标志

字符串输出函数puts

int puts(const char *s)

说明:字符数组必须以’\0’结束。

控制语句

if-else语句
switch语句
#include <stdio.h>

int main()
{
    float score = 0;
    printf("please input your score:");
    scanf("%f",&score);

    if(score<0 || score>100){
        printf("input error\n");
        return 0;
    }else{
        switch((int)score/10)
        {
        case 9:
            printf("A");
            break;
        case 8:
            printf("B");
            break;
        case 7:
            printf("C");
            break;
        case 6:
            printf("D");
            break;
        default:
            printf("E");

        }
    }

    return 0;
}
循环语句
goto
//如何使用goto 完成1-100求和
int main()
{
	int i=1,sum=0;

loop:
	if(i<=100){
		sum=sum+i;
		i++;
		goto loop;
	}
	
	printf("sum=%d",sum);
	return 0;
}

当程序有多个出口,使用goto集中到一处很方便。

理由:无条件跳转易于理解;可以减少嵌套;可以避免那些忘记更新某一个出口的问题

while
do-while
for

题目:九九乘法表

#include <stdio.h>

int main()
{
    int i,j;

    for(i=1;i<=9;i++)
    {
        for(j=1;j<=i;j++)
        {
            printf("%d*%d=%d \t",i,j,i*j);
        }
        printf("\n");
    }
    return 0;
}
辅助控制语句
break

用于从循环体内跳出循环体,即提前结束循环。

break只能在循环语句中和switch语句中。

for(r=1;r<=10;r++)
{
	area=pi*r*r;
	if(area>100)break;
	printf("%f\n",area);
}
continue

结束本次循环,接着判定下一次是否执行循环。

for(n=100;n<=200;n++)
{
	if(n%3 == 0){
		continue;
	}
	printf("%d\n",n);
}
return

数组

一维数组

​ 具有一定顺序关系的若干个变量的集合,组成数组的各个变量称为元素。数组中各元素的数据类型要求相同,用数组名和下标确定。

1.所谓一维数组是指只有一个下标的数组,它在计算机内存中是连续存储的。

2.C语言中,一维数组说明一般形式如下:

​ <存储类型> <数据类型> <数组名>[<表达式>]

数组名表示内存首地址,是地址常量。sizeof(数组名)表示数组占用的总内存空间。

编译时分配连续的内存,内存字节数=数组维数*sizeof(元素数据类型)

注意事项:

C语言对数组不做越界检查,使用时要注意

int a[5];
a[5]=10;//这么写是错的

关于用变量定义数组维数

int i=15;
int a[i];

一维数组的引用

数组必须先定义,再使用。
只能逐个引用数组元素,不能一次引用整个数组。
数组元素表示形式:数组名[下标]

int a[10];
printf("%d",a);//错误写法

for(i=0;i<10;i++)
printf("%d",a[i]);//正确写法

一维数组的初始化

1.在定义数组时,位数组元素赋值

int a[5] = {1,2,3,4,5};

2.说明

​ 1.数组不初始化,其元素值为随机数

​ 2.对static数组元素不赋初值,系统会自动赋以0

​ 3.只给部分数组元素赋初值

static int a[5];等价于a[0]=0;a[1]=0…a[4]=0
int a[5]={6,2};等价于a[0]=6,a[1]=2,a[2]=0,a[3]=0,a[4]=0
int a[]={1,2,4,4};编译系统根据初值个数确定数组维数。
#include <stdio.h>

int main()
{
    int a[]={1,2,3,4,5,6},i,n;

    n = sizeof(a) / sizeof(int);//确定数组大小

    for(i=0;i<n;i++){
        printf("%d\n",a[i]);
    }
    printf("%d\n",sizeof(a));
    return 0;
}

//最后out:24。说明数组a的内存大小是24个字节。

冒泡排序:

#include <stdio.h>
int main()
{
    int a[]={1,2,14,16,8},i,j,n;
    int t=0;
    n=sizeof(a)/sizeof(int);
    for(i=0;i<n;i++){
        printf("%d ",a[i]);
    }
    printf("\n");
    
    for(i=0;i<n-1;i++)
    {
        for(j=0;j<n-i-1;j++)
        {
            if(a[j]<a[j+1])
            {
                t=a[j];
                a[j]=a[j+1];
                a[j+1]=t;
            }
        }
    }
    for(i=0;i<n;i++){
        printf("%d ",a[i]);
    }
}
二维数组

二维数组的存放顺序:内存是一维的,按行序优先。

二维数组的引用:

​ 数组名[下标][下标]

二维数组元素的初始化:分行初始化 / 按元素排列顺序初始化

例如:int a[2][3]={{1,2,3},{4,5,6}};

​ 可以省略行数定义:int a[][3]={{1,2},{3,4,5}};

#include <stdio.h>

int main()
{
    int a[2][3];
    int i,j;

    for(i=0;i<2;i++)
    {
        for(j=0;j<3;j++){
            printf("%p ",&a[i][j]);
        }
        printf("\n");
    }

    printf("%p %d \n",a,sizeof(a));
    printf("%p %d \n",a[0],sizeof(a[0]));
    printf("%p %d \n",a[1],sizeof(a[1]));
    return 0;
}
/*out:
000000000061FE00 000000000061FE04 000000000061FE08
000000000061FE0C 000000000061FE10 000000000061FE14
000000000061FE00 24
000000000061FE00 12
000000000061FE0C 12
*/

字符数组和字符串

字符数组

字符数组初始化,以下形式均可:

​ char ch[5] = {‘H’,‘e’,‘l’,‘l’,‘o’};

​ char ch[6]={“hello”};

​ char ch[6]=“hello”;

​ char ch[]=“hello”;

#include <stdio.h>

int main()
{
    char str1[]={'a','b','c','\0'};
    char str2[5]={'a','b','c'};
    int i,n;

    n=sizeof(str1)/sizeof(char);
    for(i=0;i<n;i++)
    {
        putchar(str1[i]);
    }
    putchar('\n');
    n=sizeof(str2)/sizeof(char);
    for(i=0;i<n;i++)
    {
        putchar(str2[i]);
    }
    putchar('\n');

    printf("%s \n",str1);//使用%s输出字符串必须以'\0'结束
    printf("%s \n",str2);

    return 0;
}
字符串数组

C语言中没有字符串常量,用字符数组处理字符串,字符串结束表示:‘\0’

char fruit[][7]={"apple","grape","pear","orange","peach"};

上面代码相当于5个1维数组。

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

int main()
{
    char fruit[][7]={"apple","grape","pear","orange","peach"};

    int n,m,i,j;
    n=sizeof(fruit)/sizeof(fruit[0]);//行数,总内存/1行的内存
    m=sizeof(fruit[0])/sizeof(char);//列数
    /*
    for(i=0;i<n;i++){
        for(j=0;j<m;j++)
        {
            putchar(fruit[i][j]);
        }
        putchar('\n');
    }
    */
    for(i=0;i<n;i++){
        printf("%s \n",fruit[i]);
    }
    return 0;
}

倒序输出字符串:

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

#define N 20
int main()
{
    char str[N]={0};
    int n,i;

    printf("please input str:");
    gets(str);
    //n=sizeof(str)/sizeof(char);
    n = strlen(str);

    for(i=n-1;i>=0;i--){
        putchar(str[i]);
    }

    return 0;
}

另一种思路:交换

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

#define N 20
int main()
{
    char str[N]={0};
    int n,i,j;
    
    printf("please input strL");
    gets(str);
    
    n=strlen(str);
        
    i=0;
    j=n-1;
    while(i<j)
    {
        t=str[i];
        str[i]=str[j];
        str[j]=t;
        
        i++;j--;
    }
    puts(str);
    
    return 0;
}

字符串函数

​ C语言库中实现了很多字符串处理的函数:#include <string.h>

几个常见的字符串处理函数:

1.strlen,求字符串长度
2.strcpy,字符串拷贝
3.strcat,字符串连接
4.strcmp,字符串比较

strlen函数

计算字符串长度,返回值字符串实际长度,不包含’\0’在内。

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

#define N 20
int main()
{
    char s[10]={'a','0','b','\0','c'};
    char s1[] = "\tab\v\\c";

    printf("%d %d\n",strlen(s),sizeof(s));
	printf("%d %d\n",strlen(s1),sizeof(s1));
    return 0;
}
//这一例子中:out: 
//3 10
//6 7
//原因,strlen当遇到'\0'则不再计算,只计算'\0'前面的字符数。

面试题:strlen和sizeof的区别:
1.strlen是一个函数,sizeof是一个运算符。而且strlen只计算’\0’前面的字符,而sizeof是计算整个的内存大小。

strcpy函数

格式:strcpy(字符串1,字符串2);

功能:将字符串2拷贝到字符串1。

返回值:返回字符串1的首地址

说明:字符数组1必须足够大;拷贝时’\0’一同拷贝。

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

#define N 30
int main()
{
    char str[] = "hello";

    char des[N];

    int i,n;
    n=strlen(str);
    //strcpy(des,str);
    //等价于↓
    while(i<=n)
    {
        des[i]=str[i];
        i++;
    }

    puts(str);
    puts(des);

    return 0;
}
strcat

格式:strcat(字符数组1,字符数组2);

功能:把字符数组2连接到字符素组1后面

返回值:返回字符数组1首地址

说明:字符数组1必须足够大;连接前,两串均以’\0’结束,连接后,串1的’\0’取消,新船最后加’\0’。

strcmp

格式:strcat(字符串1,字符串2);

功能:比较两个字符串

比较规则:对两串从左向右逐个字符比较ASCII码值,直到遇到不同字符或’\0’为止。

返回值:返回int型整数

​ 若字符串1<字符串2,返回负整数

​ 若字符串1=字符串2,返回0

字符串拓展用法

strncpy(str1,str2,n);复制指定长度字符串

strncat(str1,str2,n);指定长度附加

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值