变量和常量
变量名:字母数字下划线,数字不开头
强制类型转换
#include <stdio.h> //include<cstdio>c++中的写法
//(新类型名)变量名
void main() {
double r = 12.56;
int a = 3, b = 5;
printf("%d\n", (int)r);
printf("%d\n", a / b);
printf("%.1f", (double)a / (double)b);
}
------------------------
12
0
0.6
常量和宏
宏是原封不动的将对应部分替换
#define pi 3.14
#define ADD(a,b) ((a)+(b))
void main(){
const r = 777;
}
运算符
注意使用位运算符<<
,>>
时一定要使用括号,因为位运算符的优先级低
const int INF = (1 << 30) - 1;
输入输出
scanf
除了数组外都需要使用地址符&
数据类型 | 格式符 | 举例 |
---|---|---|
int | %d | scanf("%d",&n); |
long long | %lld | scanf("%lld",&n); |
float | %f | scanf("%f",&fl); |
double | %lf | scanf("%lf",&dbl); |
char | %c | scanf("%c",&c); |
string | %s | scanf("%s",str); |
注意
- double的格式符是
%lf
- %c是可以接收空格,回车等空白符的
- 除了%c以外的都以空白符为结束
#include <stdio.h>
void main() {
int a;
char c, str[10];
scanf("%d%c%s", &a, &c, str);
printf("a=%d,c=%c,str=%s", a, c, str);
}
-------------------
input:1 a bcd
output:a=1,c= ,str=a
printf
数据类型 | 格式符 | 举例 |
---|---|---|
int | %d | scanf("%d",&n); |
long long | %lld | scanf("%lld",&n); |
float | %f | scanf("%f",&fl); |
double | %f | scanf("%f",&dbl); |
char | %c | scanf("%c",&c); |
string | %s | scanf("%s",str); |
注意
-
double的格式符是%f
-
%md
共m位,右对齐,不够m位的用
空格 填充,大于m位的不用管
void main() { int a = 123; int b = 12345; printf("%5d\n", a); printf("%3d", b); } ------------------ 123 12345
-
%0md
共m位,右对齐,不够m位的用
0
填充,大于m位的不用管void main() { int a = 123; int b = 12345; printf("%05d\n", a); printf("%03d", b); } ------------------ 00123 12345
-
%.mf
void main() { double dbl = 12.3456; printf("%.0f\n", dbl); printf("%.1f\n", dbl); printf("%.2f\n", dbl); printf("%.3f\n", dbl); printf("%.4f\n", dbl); } --------------- 12 12.3 12.35 12.346 12.3456
getchar和putchar
输入单个字符
int main() {
char c1, c2, c3;
c1 = getchar();
getchar();
c2 = getchar();
c3 = getchar();
putchar(c1);
putchar(c2);
putchar(c3);
}
--------------------
input: abcd
output: acd
b被getchar接收但是没有赋给变量名
c1,c2,c3分别对应acd
gets和puts
gets识别\n
作为输入结束
void main() {
char str1[10];
char str2[5][10];
gets_s(str1);//vs2019认为gets不安全,用gets_s代替
for (int i = 0; i < 3; i++) {
gets_s(str2[i]);
}
puts(str1);
for (int i = 0; i < 3; i++) {
puts(str2[i]);
}
}
特别注意
- 使用scanf和gets时末尾会自动添加
\0
,所以a[10]
实际可用只有9位 - 使用getchar来输入字符串的时候末尾一定要手动添加
\0
- 只有char型字符串需要添加
\0
,数值型数组不需要 - puts自带回车
sscanf和sprintf
void main() {
//字符串转数字,从字符串中扫出来
int n;
char str[100] = "123";
sscanf(str, "%d", &n);
printf("%d\n", n);
//数字转字符串,打印到字符串中去
int m = 233;
char str2[100];
sprintf(str2, "%d", m);
printf("%s\n", str2);
}
--------------------------
123
233
进阶
void main() {
int n;
double db;
char str[100] = "2048:3.14,hello", str2[100];
sscanf(str, "%d:%lf,%s", &n, &db, str2);
printf("n=%d,db=%.2f,str2=%s\n", n, db, str2);
}
------------------------
n=2048,db=3.14,str2=hello
========================
void main() {
int n = 2048;
double db = 3.14;
char str[100] = "hello", str2[100];
sprintf(str2, "%d:%f,%s", n, db, str);
printf("%s\n", str2);
}
-------------------------
2048:3.140000,hello
cin和cout
C++中的输入输出函数,在头文件#include<iostream>
和using namespace std;
才可以使用
#include<iostream>
using namespace std;
void main() {
int n;
double db;
char c;
char str[5];
cin >> n >> db >> c >> str;
printf("%d\n", n);
printf("%f\n", db);
printf("%c\n", c);
printf("%s\n", str);
cout << n <<"haha" << db << "haha" << c << "haha" << str;
}
--------------------------------
1 2 z abcd
1
2.000000
z
abcd
1haha2hahazhahaabcd
常用math函数
#include<math.h> //include<cmath>
double fabs(double x)
#include<math.h>
void main() {
double n = -12.34;
printf("%.2f", fabs(n));
}
-----------
12.34
double floor(double x)和double ceil(double x)
向下取整floor,向上取整ceil,
按照数轴看向下和向上
void main() {
double db1 = -5.2, db2 = 5.2;
printf("%.0f, %.0f\n", floor(db1), ceil(db1));
printf("%.0f, %.0f\n", floor(db2), ceil(db2));
}
---------------------
-6, -5
5, 6
double pow(double r,double p)
r 的 p次方
void main() {
double db = pow(2.0, 3.0);
printf("%f", db);
}
----------
8.000000
sqrt(double x)
void main() {
double db = sqrt(9.0);
printf("%f", db);
}
---------------
3.000000
double log(double x)
计算以e为底的对数
其他底数需要使用换底公式 l o g a b = l o g e b l o g e a log_{a}{b}=\frac{log_{e}{b}}{log_{e}{a}} logab=logealogeb
void main() {
double db = log(1);
printf("%f", db);
}
-------------------
0.000000
sin(double x),cos(double x),tan(double x)
返回值是double型,x使用弧度表示
asin(double x),acos(double x),atan(double x)
返回值是double型,x使用弧度表示
double round(double x)
round四舍五入
不使用round时的舍入规则是:四舍六入五成双,即保证进位后的最后一位是偶数
#include<stdio.h>
#include<math.h>
int main() {
double db1 = round(3.1);
double db2 = round(3.5);
double db3 = round(3.7);
printf("%d %d %d ", (int)db1, (int)db2, (int)db3);
return 0;
}
分支和循环
switch
不写break就会执行case n及其下面所有语句
void main() {
int a = 1, b = 2;
switch (a + b) { //表达式
case 2:
printf("%d", a);
break;
case 3:
printf("%d", b);
break;
case 4:
printf("%d", a+b);
break;
default:
printf("nothing new");
}
}
数组
初始化数组
int a[10] = {5,4,3,2,1};
未被赋值的数据根据编译器不同会赋予不同的默认值,一般情况默认是0
所有数据置0
//这两种方法都可以
int a[10] = {0};
int a[10] = {};
//memset
#include<string.h>
void main() {
int a[5] = { 1,2,3,4,5 };
memset(a, 0, sizeof(a));
for (int i = 0; i < 5; i++) {
printf("%d ", a[i]);
}
printf("\n");
}
----------------
0 0 0 0 0
string.h头文件
包含了对字符数组操作的函数
int strlen(str)
返回字符数组第一个\0
前的字符数
void main() {
char str[10];
gets_s(str);
int len = strlen(str);
printf("%d", len);
}
--------------------
agsol
5
int strcmp(str1,str2)
从前到后依次比较大小,
1<2,返回一个负整数
1==2,返回0
1>2,返回一个正整数
strcpy(str1,str2)
把str2复制给str1,包括\0
strcat(str1,str2)
把str2接到str1后面
指针
什么是指针
指针是一个unsigned类型整数
&
用来取地址
*
用来取指针对应的值
*
是变量类型的一部分
//c程序员习惯
int *p;
//c++程序员习惯
int* p;
//多个同种类型指针
int *p1,p2;//p1是int*,p2是int
//多个同种应该这样定义
int *p1, *p2, *p3;
指针变量
void main() {
int a;
int* p = &a;
a = 233;
printf("%d\n", *p);
printf("%d\n", a);
}
-----------------------
233
233
基类型
指针只能指向自己基类型的变量
int*
的基类型是int
,int*
所指向的数据只能是int
型
指针和数组
指针变量是可以加减法的,常用于数组中,相当于i++
.
void main() {
int a[10] = { 1,2,3,4,5,6,7,8,9,10 };
for (int i = 0; i < 10; i++) {
printf("%d,", a[i]);
}
printf("\n");
for (int* p = a; p < a + 10; p++) {
printf("%d,", *p);
}
}
----------------------------------------
1,2,3,4,5,6,7,8,9,10,
1,2,3,4,5,6,7,8,9,10,
等价写法
*(p+i)==a[i]
指针变量作为函数参数
交换俩个数,不变版本
void swap(int a, int b) {
int temp;
temp = a;
a = b;
b = temp;
}
void main() {
int a = 1, b = 2;
swap(a, b);
printf("a=%d,b=%d\n", a, b);
}
----------------------------
a=1,b=2
指针版本
void swap(int* a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
}
void main() {
int a = 1, b = 2;
int* p1 = &a, * p2 = &b;
swap(p1, p2);
printf("a=%d,b=%d\n", *p1, *p2);
}
-----------------------------------
a=2,b=1
注意
void swap(int* a, int* b) {
int* temp = a;
a = b;
b = temp;
}
这样的写法是错误的,不可以直接交换两个数据的地址
因为地址本质上是一个无符号数.对地址本身进行修改与传入普通的变量没有区别,都是副本
引用
c++中的语法,在函数参数中加&
,表示引用
void change(int& n) {
n = 1;
}
void main() {
int a = 10;
printf("%d\n", a);
change(a);
printf("%d\n", a);
}
-----------------------
10
1
指针的引用
将a和b的地址调换了
void swap(int*& p1, int*& p2) {
int* temp = p1;
p1 = p2;
p2 = temp;
}
void main() {
int a = 1, b = 2;
int* p1 = &a, * p2 = &b;
printf("p1=%d,p2=%d\n", p1, p2);
printf("a=%d,b=%d\n", *p1, *p2);
swap(p1, p2);
printf("p1=%d,p2=%d\n", p1, p2);
printf("a=%d,b=%d\n", *p1, *p2);
}
---------------------------------
p1=13629800,p2=13629788
a=1,b=2
p1=13629788,p2=13629800
a=2,b=1
结构体
typedef struct studentInfo {
int id;
char name[10];
studentInfo* next;
}str,*p;
访问结构体
stu.id;
stu->id;
(*p).id;
(*p)->id;
p->id;//通过指针简介的写法
结构体初始化
普通的结构体内部会生成一个默认的构造函数
也可以自定义初始化函数,但是如果自定义了初始化函数,则不能不经初始化就定义结构体变量
struct studentInfo {
int id;
char gender;
//默认生成的构造函数
studentInfo(){}
//只初始化gender
studentInfo(char _gender) {
gender = _gender;
}
//两个都初始化
studentInfo(int _id, char _gender) {
//赋值
id = _id;
gender = _gender;
}
};
studentInfo stu1 = studentInfo(007, 'M');
studentInfo stu2 = studentInfo('F');
误差
在编译后解决误差的问题
#include<math.h>
const double eps = 1e-8;
//==
#define Equ(a,b) ((fabs((a)-(b)))<(eps))
//>
#define More(a,b) (((a)-(b))>(eps))
//<
#define Less(a,b) (((a)-(b))<(-eps))
//>=
#define MoreEqu(a,b) (((a)-(b))>(-eps))
//<=
#define LessEqu(a,b) (((a)-(b))<(eps))
//pai
const double Pi = acos(-1.0);