Qilu Yuan bio photo

Email

Email2

My CV

Csdn

Github

C语言基本语法

0. CLion配置

下载CLion: Other Versions - CLion (jetbrains.com)

下载mingw-w64: Releases · niXman/mingw-builds-binaries · GitHub

1. 数据基本类型

1.1 变量的定义

变量类型 变量名;

1.不能是c语言标识符

2.首字母只能是字母或下划线,组成为数字、字母、下划线

3.区分大小写

1.2 变量类型

int a = 1; //整型变量
printf("%d\n", a);

long long b = 100ll; //长整型
printf("%lld\n", b);

//浮点型
float c = 1.0;
printf("the float is %.1f\n", c);
double c0 = 1000.0;
printf("the float is %.1lf\n", c0);

//字符型:单引号是字符型,双引号是字符串型
char ccc1[] = "h";
char c2[7] = "nihao\n";
printf("%s\n%s", ccc1, c2);

//布尔型
bool boolen = true;
cout << boolen << endl;

1.3 强制类型转换

double a = 10.01;
printf("%lf\n", a);
int b = (int)a;
printf("%d,%d", (int)a, b);

1.4 符号常量与const常量

#define pi 3.14
const double pi = 3.14;

1.5 运算符

1.算数运算符
加(+)减(-)乘(*)除(/)
取模(余数)%
自增++
自减–

2.关系运算符
<, >, ≤, ≥, ==, ≠
3.逻辑运算符 &&, ||, !(与,或,非)
4.条件运算符

max = a > b ? a : b;

if (a > b) {
    max = a;
} else {
    max = b;
}

2. scanf/printf输入和输出 , 顺序结构

2.1赋值表达式

int a = 5;
a = 10;

2.2 scanf/printf和cin/cout

int a;
printf("Please input the value of a:");
scanf("%d", &a);
printf("2*a = %d", 2 * a);

int b;
cin >> b;
cout << "a*b=" << a * b << endl;

2.3 getchar/putchar输入和输出

char c1, c2, c3;
c1 = getchar();
getchar();
c2 = getchar();
c3 = getchar();
c1 = 'a';
putchar(c1);
putchar(c2);
putchar(c3);

2.4 注释

单行注释

// 单行注释

多行注释

/*
多行注释
*/

2.5 typedef

typedef char* PCHAR;
PCHAR pa, pb; //char *pa; char *pb;
pa = "hello";
pb = "hello"; //正常
pb = 'h'; //报错,不能将char类型的值赋给PCHAR类型实体
return 0;
#include <iostream>
using namespace std;
typedef int (*A)(char, char);
int fun0(char a, char b);
int fun1(char a, char b);
int main() {
    A a;
    a = fun0;
    a('a', 'b');
    a = fun1;
    a('a', 'b');
    return 0;
}
int fun0(char a, char b) {
    cout << "fun0" << endl;
    return 0;
}
int fun1(char a, char b) {
    cout << "fun1" << endl;
    return 0;
}

2.6常用math函数

fabs() 绝对值;

floor()向下取整;cell()向上取整

pow(a,b) a的b次方

sqrt()算数平方根

log()自然对数为底对数

sin(); cos(); tan(); asin(); acos(); atan()

round()四舍五入

3. 选择结构

3.1 if语句

if (a > 1) {
    
} else {
    
}

3.2 if 语句的嵌套

if () {
    //...
    if () {
        //...
    } else {
        //...
    }
    //...
}

3.3 switch语句

switch () {
    case :
        ...
        break;
    case :
        ...
        break;
    default:
        ...
}

4. 循环结构

4.1 while循环

while () {
    ....
}

4.2 do…while循环

do {
    ...
} while ();

4.3 for循环

for (表达式A; 表达式B; 表达式C) {
    
}

执行顺序:执行A—>判定B—>成立则执行内部语句—>执行C—>判定B—>不成立退出,成立则继续执行内部语句

4.4 break和continue语句

break: 退出整个当前循环

continue: 退出本次循环,直接进入下一次循环

5. 数组

5.1一维数组

int a[10]; //定义数组
a[5]; //访问数组

5.2 冒泡排序

通过交换,最大值(最小值)移动到数组的一端

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

for (int i = 1; i <= 4; i++) {
    for (int j = 0; j < 5 - i; j++) {
        if (a[j] > a[j + 1]) { //最大值往后移动
            int temp = a[j];
            a[j] = a[j + 1];
            a[j + 1] = temp;
        }
    }
}

5.3二维数组

int a[5][6];
double db[10][10];

5.4 memset——对数组中每一个元素赋予相同的值

int a[10]; 
memset(a, 0, sizeof(a));

5.5 字符数组

初始化


char str[15] = {'G', 'o', 'o', 't', 'o', 'r', 'y', '!'};

输入输出

char str[15];
scanf("%s", &str);
printf("%s", str);

gets(str);
puts(str);

3.字符数组存放方式

字符数组的每一位都是一个char字符。一维字符数组的末尾都有一个空字符\0

5.6 string.h类处理字符数组

strlen(); //字符数组长度
strcmp(a, b); //字符串大小比较
strcpy(a, b); //将b赋予给a
strcat(a, b); //a接到b之后

5.7 sscanf和sprintf

char buff[10] = {0}; //声明字符串
int a = 13; //任意变量
int b = 26;
char str[] = "sc";
sprintf(buff, "%d%d%s", a, b, str); //将a变量按照格式写入buff中
printf("%s", buff);    


char buff[20] = {0}; //用于承接Todayis
char buff2[20] = {0}; //用于承接2015-02-27
char buff3[20] = {0}; //用于承接12:22:30
char strbuf[] = "Todayis 2015-02-27 12:22:30";
sscanf(strbuf, "%s %s %s", buff, buff2, buff3); //注意"%s %s %s"间隔%s有空格
printf("buff:%s\r\n", buff);
printf("buff2:%s\r\n", buff2);
printf("buff3:%s\r\n", buff3);

6. 函数

6.1 函数的定义

/*
返回类型 函数名称(参数类型 参数) {
    函数主体
}
*/
int func(int a) {
    int b;
    b = a;
    return b;
}

6.2 main函数

一个程序只有一个主函数,并且无论主函数在哪个位置,整个程序都是从主函数的第一句开始执行。

6.3 数组作为函数的参数

数组作为参数时,参数中数组第一维不需要填写长度。函数中对数组元素的修改等同于对原数组的修改。

6.4 函数的嵌套调用

即在一个函数中调用另一个函数,与普通调用几乎没区别

6.5 函数的递归调用

一个函数调用其自身

6.6 函数的内部的static变量

普通变量在函数调用完成后被释放,如果需要某个变量在整个程序的运行过程中不被释放加入static关键字

7. 指针

7.1 指针的基本用法

1 指针的概念

内存地址:内存中每个字节单位都有一个编号

指针:指针就是内存地址

指针变量:用于存放地址的变量

2格式

int a = 5;
int* p = &a; //指针变量的定义并赋予a的地址。
int* p2;

3 指针操作符

// & 取地址操作符
// * 取值操作符

4 指针变量的初始化和赋值

//将普通变量的地址赋值给指针p
int a = 10;
int* p = &a;
//将数组的首地址赋值给指针q
int arr[] = {1, 2, 3, 4, 5};
int* q = arr;
//将指针变量p保存的地址赋值给另一个变量
int* r = p;

7.2指针运算

1 算术运算(+,-)

对指针的操作即让指针向前向后移动

char str[32] = "HelloWorld";
char* p = str; //H
p++; //e
p--; //H

2 关系运算 > ≥ < ≤ == ≠

指针之间的关系运算比较的是它指向地址的高低

指向高地址的指针是大于指向低地址的指针

7.3其他

1 指针大小和段错误

1.1 指针的大小

int* p;
sizeof(p);

1.2 使用指针时的段错误

(1) 野指针

(2) 内存泄露

2 指针修饰

const 常量化

(1) 修饰普通变量

const int a = 10;
int const b = 20;
int *p = &a, *q = &b;
//此时a和b只读,不可以修改。但是可以通过指针修改。
*p = 1;
*q = 2;

(2) 修饰指针指向的内容

const int *p;
int const *q;
//指向的内容不能改变,但指向可以改变,即*p不能改变
int a = 10;
int b = 20;
p = &a;
q = &b;

(3) 修饰指针指向

int a = 100;
//指针指向不能更改,指向的内容可以更改
int *const p = &a;

8. 结构体

8.1 结构体的定义

struct Stu {
    char name[10];
    int age;
    double height;
} yuanql = {"yuanql1", 20, 1.77}; //定义时赋值
strcpy(yuanql.name, "yuanql");
yuanql.age = 22;
yuanql.height = 1.75;

8.2 访问结构体元素

“.”操作和“- >”操作

8.3 结构体初始化

1.先定义再赋值

2.构造函数

struct Stu {
    char gender;
    int age;
    double height;
    Stu() {}; //默认生成的构造函数
    //自定义的构造函数
    Stu(char _gender, int _age, double _height) : gender(_gender), age(_age), height(_height) {}
};

int main() {
    Stu xiaoming('M', 15, 1.75); //定义时赋值
    //先定义再赋值
    xiaoming.gender = 'M';
    xiaoming.age = 12;
    xiaoming.height = 1.75;
    //构造函数
    xiaoming = Stu('M', 22, 1.75);
    printf("%c,%d,%.2lf", xiaoming.gender, xiaoming.age, xiaoming.height);
    // cout << xiaoming.name << " " << xiaoming.age << " " << xiaoming.height << endl;
}

9. 补充

9.1复杂度

时间复杂度

即算法需要执行基本运算的次数所处的等级,其中基本运算就是类似加减乘除这种计算机直接实现的运算。时间复杂度是评判算法时间效率的有效标准。在时间复杂度中,高等级幂次会覆盖低等级幂次。

空间复杂度

与时间复杂度类似,空间复杂度表示算法需要消耗的最大数据空间。

编码复杂度

编码复杂度是一个定性的概念,并没有什么量化的标准。对于一个问题来说,如果使用了冗长的算法思想,那么代码量会非常巨大,其编码复杂度会非常大。

10. 黑盒测试

10.1 单点测试

对单点测试来说,系统会判断每组数据的输出结果是否正确。如果输出正确,那么对该组数据来说就通过了测试,并获得了这组数据的分值。在这种情况下,题目的总得分等于通过的数据的分值之和。PAT就是采用了单点测试,并且对每组数据都会给出相应的测评结果。l

10.2 多点测试

多点测试要求程序能一次运行所有数据,所有数据完全正确才算通过 (1)while…EOF型

C语言中使用EOF(即End Of File)来代表-1

while (scanf("%d", &n) != EOF) {
    .....
}

(2)while….break型

这种类型是while.… EOF 型的延伸,题目要求当输入的数据满足某个条件时停止输入。这种类型是while.… EOF 型的延伸,题目要求当输入的数据满足某个条件时停止输入。

(3)while(T–)型

在这种类型中,题目会给出测试数据的组数,然后才给出相应数量组数的输入数据。

#include <stdio.h>
int main() {
    int T, a, b;
    scanf("%d", &T);
    while (T--) {
        scanf("%d%d", &a, &b);
        printf("%d\n", a + b);
    }
    return 0;
}

以上就是多点测试的三种输入类型。下面讲解三种常见的输出类型。

(1)正常输出

这种输出类型要求需要每两组输出数据中间没有额外的空行,即输出数据是连续的多行。

(2)每组数据输出之后都额外加一个空行

这个要求非常容易实现,只需要在每组输出结束之后额外输出一个换行符n即可。

(3)两组输出数据之间有一个空行,最后一组数据后面没有空行

这一般是在第三种输入类型 while(T–)的情况下,只需要通过判断T是否已经减小到0来判断是否应当输出额外的换行。

最后需要指出,在多点测试中,每一次循环都要重置一下变量和数组,否则在下一组数据来临的时候变量和数组的状态就不是初始状态了,而重置数组一般使用memset函数或f函数。