丙午🐎年

acc8226 的博客

顺序程序设计

  1. 定义声明
  2. 列出表达语句
  3. 输出结果

数据的表现形式机器运算

3 种常见数据类型

  1. 整型(不带小数点的数据类型)
  2. 实型(带小数点的数据类型)
  3. 字符型(仅含一个字符的数据类型)

常量和变量

计算机高级语言中,数据的两种表现形式

[1] 常量
(1)整型常量 + 号可省略,- 号不可省,默认为 int,超出为 long,如果需要手动表示,则后加 L 或者 l(L 更突出),但都是 4 个字节
(2)实型常量,十进制小数形式和指数形式 (float 和 double 型,字面量 3.0 默认为 double 类型,当然可加 F 或 f 表示成 float 类型)
(3)字符常量,由一对单引号引起,其内部存储的对应字符的 ASCII 码,包括普通字符和转义字符

转义字符及其作用

1
2
3
4
5
6
7
8
9
10
11
12
13
\n 换行
\t Tab键
\' 单引号
\" 双引号
\? 问号(直接写也可以的)
\\ 反斜杠
\a 警号
\b 退格(退格键,光标删除前一个字符并左移一位);
\ddd  三位的 d 八进制数字 常用的有 \012 或者 \12 代表换行
\xhh 两位的**十六进制**数字对应的 ASCII 码

\0,\00,\000,
\x0,\x00,\x000 都是指空字符

(4)字符串常量
(5)符号常量(例如 #define PI 3.1415)

[2]  变量:变量必须先定义后使用
[3]  常变量 const int a = 3;
[4]  标识符:对变量名,符号常量名,函数,数组,类型等命名的有效字符序列

数据类型

[int]整型  vc 中四个字节,在存储单元中的存储方式是整数的补码, 范围是 -2(31) 到 2(31)-1 即 -2147483648 到 2147483647,无符号为 0-4294967295
 [short]短整型

  • 有符号为 -2(15)到 2(15)-1 即 -32768 到 32767
  • 无符号为 0-65535

[long]长整型 在 vc 中与 int 一样在 C 语言中,有 [signed] long [int],即在有些条件下括号内的是可以省略的。

[char]字符型  -128-127 无符号为 0-255 以整数形式(字符的 ASCII 码)存在内存

[float]单精度浮点型 字节数 4 有效数字 6(指小数部分) 也就是 float 能得到 6 位小数,数值范围 0 以及正负 1.2*10(-38 次方)3.4*10(38 次方)

[double]双精度浮点型 字节数 8 有效数字 15 数值范围 0 及 2.3*10(-308次方)1.7*10(308)

这样确定常量的类型

对于字符型,只要有单撇号扩起来的的单个字符或转义字符,对于数值常量按以下规律
整型 不带小数点的数值,在一个整数的末尾加大写字母 L 或小写字母 l,表示是长整型都分配四个字节,因此没有必要用 long int 型。
浮点型常量 凡小数形式或指数形式出现的实数,如 10.0 是浮点型常量。可以在常量的末尾加专用字符,强制指定常量的类型加 F/f 表示 float 型,分配四个字节。如果在实型常量后面加 L/l,则表示指定此常量为 long double

运算符和表达式

(1)基本的运算符
(2)自增自减运算符
(3)表达式和运算符的优先级与结合性
(4)不同类型数据间的混合运算
(5)强制类型 转换运算符
(double)a;
(int)(x+y);
(float)(5%3)
其基本形式为(类型名)(表达式)
(6)C 运算符

C 语句

C 语句及其作用及其分类 声明部分不是语句,它不产生机器指令,只是对有关数据的声明。

一个函数由数据声明部分和执行语句执行.

C 语言分为以下 5 类

(1)控制语句
(2)函数调用语句 由一个函数调用加一个分号组成
(3)表达式语句
(4)空语句
(5)复合语句:复合语句常用在 if 语句或循环中,此时程序需要连续执行一组语句。而且在复合语句中最后一句的分号不能省略不写。

数据的输入与输出

1
2
3
4
5
6
7
8
9
10
11
printf 函数中常用格式字符
c    输出一个字符,若一个整数在 0~127 之间,作为 ASCII 码转换为相应字符
d,i  输出带符号的十进制数(正数没 +,负数有 -),也可以在d前面加数字
ld   输出长整型
s    输出字符串 如下("%s%s\n","c",",p");
f    输出实数,包括 float, double, long double,其中 (%m.nf) 制定数据宽度和小数位数,m 可以省略, m 为正代表右对齐,为负代表左对齐
e,E  输出指数形式,vc 下默认 1.6e4 位,共 13 位数,大写 E 则结果有 E,否则为 e
g,G  输出浮点数,系统自动选取 f 或 e 格式中长度较短的格式,不输出无意义的 0
o    输出不带符号的八进制
x,X  输出十六进制
u    输出无符号整数

对于 float 和 double 型, 请分别用 scanf("%f", &inch)scanf("%lf", &inch) 进行输入

字符数据的输入与输出

getchar() 这里无参数
putchar(c1)

puts(字符数组); // 会在字符串最后自动加上 ‘\0’ 最终转换为 ‘\n’ 作为换行的意思,所以 putchar() 也有一样的作用
gets(字符数组)

以上都是一些非格式化的输入/输出

使用数学公式

1
2
3
4
5
6
7
#include <stdio.h>  
#include <math.h>

// 求一个公式
int main() {
pow(3, 2);
}

恶心的语法

i+j 指的是 i()+j

参考

谭浩强著《C 程序设计》

c 语言的八进制以 0 开头

& 和 && 左边是非短路与, 右边是短路与.

while(!e) 表示 !e != 0 则 与 e == 0 等价

什么时候使用 while, for while, for 循环

如果有固定的循环次数用 for
如果必须执行一次, 用 do while
否则用 while

include <stdbool.h> 后可以使用 bool, true 和 false 了

定义数组

1
2
3
int arr[100]; // 此时还没有初始化
int arr[100] = {0} // 且初始化
int arr[] = {3, 5, 1, 3, 2} // 可以不给大小

数组的特点

  1. 所有的元素具有相同的类型
  2. 一旦创建, 不能改变大小。
  3. 数组中的元素在内存中是连续依次排列的。

二维数组

可以理解为数组的数组, 数组的每个元素仍然是一个数组.
遍历用两重循环

数组的长度

sizeof 给出整个数组占据的内容大小, 单位是字节.
size(a) / size(a[0]) // 占据大小 / 单个元素的大小, 相除就得到了数组的单元个数

注意: 数组作为函数参数时, 往往还需再传一个参数来表示数组的长度

函数

函数: 是一块代码, 做一件事.

函数的先后关系:

函数原型

函数头, 已分号结尾就构成了函数原型。
函数原型的目的告诉这个函数长什么样。

  • 名称
  • 参数(数量及类型)
  • 返回类型

建议函数原型声明的时候写全, 例如这样 void swap(void),而非void swap(), 否则会引起编译器的误解.

本地变量:
函数的每次运行, 产生一个独立的变量空间,在这个空间中的变量, 是函数的这次运行所独有的,称作本地变量.

取址运算符 &

  • scanf(“%d”, &i)里面的 &
  • 获得变量的地址后, 它的操作数必须是变量
    • int i; printf(“%x”, &i) //16进制输出
  • 地址的大小是否与 int 相同类型 sizeof(int) 取决于编译器
    • int i; printf(“%p”, &i);
1
2
3
4
// 无符号浮点型
printf("%lu\n", sizeof(int));
// 地址的大小是否与int相同类型取决于编译器
printf("%lu\n", sizeof(&i));
  • 变量的值是内存的地址。
    • 普通变量的值是实际的地址。
    • 指针变量的值是具有实际值的变量的地址。

错误写法

1
2
3
int i;
// 编译没报错, 但是此时应该取地址
scanf("%d", i);

指针

它的值是变量的地址.
int *p, q; // 表示p是一个int型指针变量, q是普通int型.

数组变量是特殊的指针

函数参数表中的数组实际上就是指针
所以以下四种函数原型是等价的

  • int sum(int *arr, int n);
  • int sum(int *, int);
  • int sum(int arr[], int n);
  • int sum(int [], int n);
1
2
3
4
int a[] = {5, 15, 34, 54, 14, 2, 52, 72};
int *p = &a[1];

则 p[2] 的值是 34, p[-1] 的值是 5

练习

/*
GPS数据处理
题目内容:

NMEA-0183 协议是为了在不同的 GPS(全球定位系统)导航设备中建立统一的BTCM(海事无线电技术委员会)标准,由美国国家海洋电子协会(NMEA-The National Marine Electronics Associa-tion)制定的一套通讯协议。GPS接收机根据NMEA-0183协议的标准规范,将位置、速度等信息通过串口传送到PC机、PDA等设备。

NMEA-0183 协议是 GPS 接收机应当遵守的标准协议,也是目前GPS接收机上使用最广泛的协议,大多数常见的GPS接收机、GPS数据处理软件、导航软件都遵守或者至少兼容这个协议。

NMEA-0183 协议定义的语句非常多,但是常用的或者说兼容性最广的语句只有GPGGAGPGGA、GPGSA、GPGSVGPGSV、GPRMC、GPVTGGPVTG、GPGLL 等。

其中$GPRMC语句的格式如下: $GPRMC,024813.640,A,3158.4608,N,11848.3737,E,10.05,324.27,150706,A*50

这里整条语句是一个文本行,行中以逗号“,”隔开各个字段,每个字段的大小(长度)不一,这里的示例只是一种可能,并不能认为字段的大小就如上述例句一样。
字段0:$GPRMC,语句ID,表明该语句为Recommended Minimum Specific GPS/TRANSIT Data(RMC)推荐最小定位信息
字段1:UTC时间,hhmmss.sss格式
字段2:状态,A=定位,V=未定位
字段3:纬度ddmm.mmmm,度分格式(前导位数不足则补0)
字段4:纬度N(北纬)或S(南纬)
字段5:经度dddmm.mmmm,度分格式(前导位数不足则补0)
字段6:经度E(东经)或W(西经)
字段7:速度,节,Knots
字段8:方位角,度
字段9:UTC日期,DDMMYY格式
字段10:磁偏角,(000 - 180)度(前导位数不足则补0)
字段11:磁偏角方向,E=东W=西
字段16:校验值

这里,“”为校验和识别符,其后面的两位数为校验和,代表了“$”和“”之间所有字符(不包括这两个字符)的异或值的十六进制值。上面这条例句的校验和是十六进制的50,也就是十进制的80。

提示:^ 运算符的作用是异或。将 $和之间所有的字符做^运算(第一个字符和第二个字符异或,结果再和第三个字符异或,依此类推)之后的值对65536取余后的结果,应该和后面的两个十六进制数字的值相等,否则的话说明这条语句在传输中发生了错误。注意这个十六进制值中是会出现A-F的大写字母的。

现在,你的程序要读入一系列 GPS 输出,其中包含 $GPRMC,也包含其他语句。在数据的最后,有一行单独的
END
表示数据的结束。

你的程序要从中找出 GPRMC语句,计算校验和,找出其中校验正确,并且字段2表示已定位的语句,从中计算出时间,换算成北京时间。一次数据中会包含多条GPRMC 语句,计算校验和,找出其中校验正确,并且字段2表示已定位的语句,从中计算出时间,换算成北京时间。一次数据中会包含多条GPRMC语句,以最后一条语句得到的北京时间作为结果输出。

你的程序一定会读到一条有效的 $GPRMC 语句。

输入格式:
多条 GPS 语句,每条均以回车换行结束。最后一行是END三个大写字母。

输出格式:
6位数时间,表达为:
hh:mm:ss
其中,hh是两位数的小时,不足两位时前面补0;mm是两位数的分钟,不足两位时前面补0;ss是两位数的秒,不足两位时前面补0。

输入样例:

$GPRMC,024813.640,A,3158.4608,N,11848.3737,E,10.05,324.27,150706,A*50

END
输出样例:

10:48:13
*/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include<stdio.h>
#include<string.h>


int char2Int (char c) {
int ret;
if (c >= '0' && c <= '9') {
ret = c - '0' + 0;
} else if (c >= 'A' && c <= 'F') {
ret = c - 'A' + 10;
} else if (c >= 'a' && c <= 'f') {
ret = c - 'a' + 10;
}
return ret;
}

// 两位字符转成数字并+8北京时间
int trans2Integer(char c1, char c2) {
int i = 10 * char2Int(c1) + char2Int(c2);
return i;
}


// 两位字符转成数字并+8北京时间
int trans2IntegerPlus8(char c1, char c2) {
int i = trans2Integer(c1, c2);
if (i <= 15) {
i += 8;
} else {
i -= 16;
}
return i;
}

// 两位字符转成十六进制
int trans2IntegerHex(char c1, char c2) {
int i = 16 * char2Int(c1) + char2Int(c2);
return i;
}

// 两位数字转成字符形式
void printNum(int i) {
char ret[2];
if (i<10) {
ret[0] = '0';
} else {
ret[0] = i / 10 + '0' + 0;
}
ret[1] = i % 10 + '0' + 0;
printf("%s", ret);
}

int main() {
char str[88];
char strFinal[88] = "";
char *strEnd = "END";
int condition = 0;
do {
scanf("%88s", str);
if (strcmp(str, strEnd) != 0) {
// 是否正确的开头
if (str[0] == '$' && str[1] == 'G' && str[2] == 'P' && str[3] == 'R' && str[4] == 'M' && str[5] == 'C') {

// 判断校验和是否达标

// 取出$ 和 * 之间的每一位
int len = strlen(str);
int checkRet = 'G';

char wantA;
char wantB;
for (int i = 2; i<len; i ++) {
if (str[i] != '*') {
checkRet ^= str[i];
} else {
wantA = str[i + 1];
wantB = str[i + 2];
break;
}
}
// 取出校验和的int类型
checkRet %= 65536;
// 16进制值中是会出现A-F的大写字母的。
if (checkRet == trans2IntegerHex(wantA, wantB)) {
condition = 1;
strcpy(strFinal, str);
}
}
} else {
break;
}
} while(1);

if (condition) {
char hour1 = strFinal[7];
char hour2 = strFinal[8];
printNum(trans2IntegerPlus8(hour1, hour2));
printf(":");

char min1 = strFinal[9];
char min2 = strFinal[10];
printNum(trans2Integer(min1, min2));
printf(":");

char second1 = strFinal[11];
char sencod2 = strFinal[12];
printNum(trans2Integer(second1, sencod2));
}
return 0;
}

char 是一种整数, 也是一种特殊的类型: 字符

  • 用单引号表示的是字符的字面量: ‘a’, ‘1’
  • ‘’ 也是一个字符
  • printf 和 scanf 里用%c来输入输出字符。

大小写转换

  • 字母在 ASCII 表中是顺序排列的。
  • 大写字母和小写字母是分开排列的,并不在一起。
  • ‘a’ - ‘A’ 可以得到两段之间的距离,于是,
    • a + 'a' - 'A' 可以把一个大写字母变成小写字母。
    • a + 'A' - 'a' 可以把一个小写字母变成大写字母。

C语言的字符串是以字符数组的形态存在的

  • 不能用运算符对字符串做运算
  • 通过数组的方式可以遍历字符串

字符串(其实还是一个字符数组, 但是以’\0’结尾)

image.png

  • 0 标志字符串的结束, 但它不是字符串的一部分
  • 字符串以数组的形式存在, 以数组或指针的形式访问.

用指针还是数组

  • char* str = “Hello”;
  • char str[] = “Hello”;

用数组: 当这个字符串在这里, 作为了本地变量控件会被自动回收
用指针: 当这个字符串不知道在哪里, 用于只读, 用于处理参数 和 动态分配空间
看上去明显用指针更通用。

总而言之如果要构造字符串用数组, 否则用指针。

#include<string.h>的一些方法

strlen 返回 s 的字符串长度(不包含结尾的 0)
int strcmp(const char *s1, const char * s2) 比较两个字符串, 返回:

int putchar(int c)
向标准输出写一个字符
返回写了几个字符, EOF(-1)表示写失败

getchar
从标准输入读入一个字符
返回类型是 int, 是为了返回 EOF(-1)

  • windows–> Ctrl + Z
  • Unix–> Ctrl + D
1
2
3
4
5
6
7
8
int main(int argc, char const *argv[]) {

int ch ;
while((ch = getchar()) != -1) {
putchar(ch);
}
return 0;
}

标准 ASCII 编码表

ASCII 码(十进制)控制字符 ASCII 码(十进制) 控制字符
0 NUT 32 (space)
1 SOH 33 !
2 STX 34 ”
3 ETX 35 #
4 EOT 36 $
5 ENQ 37 %
6 ACK 38 &
7 BEL 39 ’
8 BS 40 (
9 HT 41 )
10 LF 42 *
11 VT 43 +
12 FF 44 ,
13 CR 45 -
14 SO 46 .
15 SI 47 /
16 DLE 48 0
17 DCI 49 1
18 DC2 50 2
19 DC3 51 3
20 DC4 52 4
21 NAK 53 5
22 SYN 54 6
23 TB 55 7
24 CAN 56 8
25 EM 57 9
26 SUB 58 :
27 ESC 59 ;
28 FS 60 <
29 GS 61 =
30 RS 62 >
31 US 63 ?

64 @ 96 `
65 A 97 a
66 B 98 b
67 C 99 c
68 D 100 d
69 E 101 e
70 F 102 f
71 G 103 g
72 H 104 h
73 I 105 i
74 J 106 j
75 K 107 k
76 L 108 l
77 M 109 m
78 N 110 n
79 O 111 o
80 P 112 p
81 Q 113 q
82 R 114 r
83 S 115 s
84 T 116 t
85 U 117 u
86 V 118 v
87 W 119 w
88 X 120 x
89 Y 121 y
90 Z 122 z
91 [ 123 {
92 \ 124 |
93 ] 125 }
94 ^ 126 ~
95 _ 127 DEL

特殊控制字符说明
NUL 空
VT 垂直制表
SYN 空转同步
SOH 标题开始
FF 走纸控制
ETB 信息组传送结束
STX 正文开始
CR 回车
CAN 作废
ETX 正文结束
SO 移位输出
EM 纸尽
EOY 传输结束
SI 移位输入
SUB 换置
ENQ 询问字符
DLE 空格
ESC 换码
ACK 承认
DC1 设备控制 1
FS 文字分隔符
BEL 报警
DC2 设备控制 2
GS 组分隔符
BS 退一格
DC3 设备控制 3
RS 记录分隔符
HT 横向列表
DC4 设备控制 4
US 单元分隔符
LF 换行
NAK 否定
DEL 删除

字符串中存在 ASCLL 为 160 的空格,并且该空格不能通过 input.replaceAll("\\s+", " ");
以及 trim 的方法去除。

需要通过下面的代码可以去除 replaceAll("[\\u00A0]+", "")

0%