1.输出字符用putchar(ch),输出字符串用printf()。二者功能不可互相替代。
2.目前接触的基本都是静态数组,即声明方式为a[10]之类。与动态数组声明方式不同。静态数组可以修改数组的数据。
3.格式控制字符串说明:
例如:
#include
int main()
{
int x = 5342;
int *p = NULL;
p = &x;
printf("If I know the name of the variable, I can get it's value by name: %d\n",x);
printf("If I know the address of the variable is:%x, then I can also get it's value by address:%d\n",p,*p);
return 0;
}
4.int和long区别
5.静态变量
全局变量都是静态变量。局部变量定义时如果前面加了“static”关键字,则该变量也成为静态变量。
静态变量的存放地址,在整个程序运行期间,都是固定不变的。
非静态变量(一定是局部变量)地址每次函数调用时都可能不同,在函数的一次执行期间不变。
如果未明确初始化,则静态变量会被自动初始化成全0(每个bit都是0,局部非静态变量的值则随机。
注:静态变量不是指值不发生变化。
6.变量名、函数名、类型名统称为“标识符”。一个标识符能够起作用的范围 ,叫做该标识符的作用域。
7.所谓变量的“生存期”,指的是在此期间,变量占有内存空间,其占有的内 存空间只能归它使用,不会被用来存放别的东西。全局变量的生存期,从程序被装入内存开始,到整个程序结束;静态局部变量的生存期,从定义它语句第一次被执行开始,到整个程序结束为止。
8.%3d--可以指定宽度,不足的左边补空格 %-3d--左对齐 %03d---一种左边补0 的等宽格式,比如数字12,%03d出来就是: 012
9.单行注释从“//”开始直到行末为止;多行注释用“/*”和“*/”包围起来。
10.在C99 中,double的输出必须用%f,而输入需要用%lf,但是在C89和C++中都不必如此——输入输出可以都用%lf。
11.想输出\n,可以printf("\\n"),想输出%d,可以printf("%%d")。
12.int型最小值:-2147483648;最大值:2147483647
13.double是浮点数,它的小数点的位置是“浮动”的,所以很难说double类型能精确到小数点后面几位。通常这个关于精度的问题都是通过它能表示的有效数字(十进制)的位数来表示的。遵循IEEE标准的8字节(64位)的double能表示的有效数字的位数是:15 ~ 16
14.函数floor(x)返回不超过x的最大整数。假设在经过大量计算后,由于误差的影响,整数1变成了0.9999999999,floor的结果会是0而不是1。为了减小误差的影响,一般改成四舍五入,即floor(x+0.5)(2)。如果难以理 解,可以想象成在数轴上把一个单位区间往左移动0.5个单位的距离。floor(x)等于1的区间 为[1,2),而floor(x+0.5)等于1的区间为[0.5,1.5)。
15.long long (其范围是-2^63~2^63-1) 在Linux下的输入输出格式符为%lld,但Windows平台中有时 为%I64d。
16.科学计数法用e表示时中间不能加空格,如“1e-6”,而不能是“1e - 6”!
17.x = i ++; //先让x变成i的值,再让i加1; x = ++i; //先让i加1, 再让x变成i的值
18.在C语言中,double型变量输入用%lf,输出用%f。
19.函数的声明可以在main()函数里面,而定义部分可以放在main()函数后面。
20.+-*/%都是双目运算符。双目操作符等号两边操作数类型要相同。
21.区分一下常量与静态变量。5,9这都是常量,静态变量
22.'\\'指的是'\','\/'指的是'/'。
23.
1.常量与变量
2.算术运算、赋值运算、关系运算:
3.软件测试:精心设计一批测试用例 [输入数据,预期输出结果] ,然后分别用这些测试用例运行程序,看程序的实际运行结果与预 期输出结果是否一致。
4.格式化输入:float型:%f;double型:%lf
5.
6.常用数学库函数:
7.
8.分支结构一般分为二分支和多分支两种结构。
9.
10.变量的作用域与生命周期:
10.数据存储:
11.整数的表示三种表现形式:
12.整数后的字母后缀
13.实数的表示
14.转义字符
15.自动类型转换
16.易忽略的优先级:
17.数组
18.字符串数组
19.排序
(1)选择排序法
for(int i = 0; i < n - 1; i++){
int idx = i;
for(int j = i + 1; j < n; j++){
if(a[j] < a[idx]) idx = j;
}
int t = a[i]; a[i] = a[idx]; a[idx] = t;
}
(2)冒泡排序
for(int i = 1; i < N; i++){
for(int j = 0; j < N - i; j++){
if(a[j] > a[j + 1]){
int t = a[j]; a[j] = a[j + 1]; a[j + 1] = t;
}
}
}
(3)冒泡法对二维字符数组排序:
for(int i = 1; i < N; i++){
for(int j = 0; j < N - i; j++){
if(strcmp(a[j], a[j + 1]) > 0){
char* tmp = a[j];
a[j] = a[j + 1];
a[j + 1] = tmp;
}
}
}
20.指针
21.C语言中,在main()函数外声明函数和函数内声明函数有何区别?
22.字符串相关函数:
23.动态存储分配函数malloc()
if ((p = (int *)malloc(n*sizeof(int))) == NULL) {
printf(“Not able to allocate memory. \n”);
exit(1);
}
24.计数动态存储分配函数calloc ()
25.分配调整函数realloc
26.指向函数的指针
27.
1.python是一种解释性语言,C语言是一种编译型语言;python是一种面向对象的语言,C语言是一种面向过程的语言;Python有C语言编写完成,执行效率不如C语言;C语言支持指针直接操作内存,运行效率极高。
2.计算机能够直接识别和接受的二进制代码称机器指令;在汇编语言中,用助记符代替机器指令的操作码,用地址符号或标号代替指令或操作数的地址。
3.汇编语言与机器语言一一对应,每一条机器指令都有与之对应的汇编指令。汇编语言可以通过编译得到机器语言,机器语言可以通过反汇编得到汇编语言。
4.Java吸收了C++的各种优点,放弃了多继承、指针等概念,其最主要的特点是采用平台无关的字节码,实现“一次编译,到处运行”。
5.
编译执行:高级语言的代码经过编译链接后,形成的可执行文件,就可以在机器上反复执行。
解释执行:高级语言的代码不提前进行编译,而是在运行时由解释器一行一行代码翻译成机器代码再执行。
编译执行和解释执行的直观区别:是用编译器翻译后的代码去执行,还是直接拿着源代码去执行。
编译执行的优点是程序执行效率高,可用于操作系统、大型应用程序、数据库系统等开发。
解释执行的优点是跨平台能力强,开发效率高,可用于交互式界面。
6.
结构化程序设计方法采用自顶向下、逐步求精的设计方法,将复杂程序划分为若干个相互独立的模块。模块是子程序,各个模块通过“顺序、选择、循环”的控制结构进行连接。模块只有一个入口、一个出口。
7.
编辑程序后,用该语言的编译程序对其进行编译,以生成二进制代码表示的目标程序(.obj 或 .o),与编程环境提供的库函数进行链接(Link)形成可执行的程序(.exe)。
把源代码翻译成目标代码的过程称为编译 compile
把多个目标文件合并起来,生成可执行文件的过程称为链接 link(就是把你的代码文件,用的库函数中代码所在文件等等合成一个文件,就是.exe文件)。
高级语言是源代码(source code);汇编语言是汇编代码(assemble code);机器语言是目标代码(object code)
8.调试:在程序中查找错误并修改错误的过程。调试的方法:设置断点,单步跟踪。
9.编程环境:主要包括程序的编辑器(Editor)、编译器(Compiler)、调试器(Debuger)。
10.基本数据类型:int, float, float, char
构造数据类型:数组,结构,联合,枚举,指针,空类型。
11.流程控制分为语句级控制(三种基本控制结构)和单位级控制(子程序,如函数)
12.编译程序只能指出语法错误,而不是语义错误(逻辑错误)。语法错误是compile error,链接错误是link error,逻辑错误是bug.
13.codeblocks, visual studio是编辑器,visual C++, gcc是编译器,GDB是调试器。
1.swap三种编写方式
#include
void swap1(int x, int y), swap2(int *px,int *py),swap3(int *px,int *py);
int main()
{
int a=1,b=2;
int *pa=&a, *pb=&b;
swap1(a,b);
printf("After calling swap1:a=%d, b=%d\n",a,b);
a=1;
b=2;
swap2(pa,pb);
printf("After calling swap2:a=%d, b=%d\n",a,b);
a=1;
b=2;
swap3(pa,pb);
printf("After calling swap3:a=%d, b=%d\n",a,b);
return 0;
}
void swap1(int x, int y)
{
int t;
t=x;
x=y;
y=t;
}
void swap2(int *px, int *py)
{
int t;
t=*px;
*px=*py;
*py=t;
}
void swap3(int *px, int *py)
{
int *pt;
pt = px;
px = py;
py = pt;
}
2.计时器
可以使用time.h和clock()函数获得程序运行时间。常数 CLOCKS_PER_SEC和操作系统相关,请不要直接使用clock()的返回值,而应总是除以 CLOCKS_PER_SEC。
阶乘之和
#include
#include
int main()
{
const int MOD = 1000000;
int n, S = 0;
scanf("%d", &n);
for(int i = 1; i <= n; i++)
{
int factorial = 1;
for(int j = 1; j <= i; j++)
factorial = (factorial * j % MOD);
S = (S + factorial) % MOD;
}
printf("%d\n", S);
printf("Time used = %.2f\n", (double)clock() / CLOCKS_PER_SEC);
return 0;
}
3.神奇的程序
#include
int main()
{
int a = 10;
double b = 9.9 + 0.1;
int c = (a == b);
printf("%d",c);
return 0;
}
//输出结果是1.
4.汉诺塔
#include
void hanio(int n,char a,char b,char c);
int main()
{
int n;
printf("input the number of disk:");
scanf("%d",&n);
printf("the steps for %d disk are:\n",n);
hanio(n,'a','b','c');
return 0;
}
void hanio(int n,char a,char b,char c)
{
if(n==1)
printf("%c-->%c\n",a,b);
else{
hanio(n-1,a,c,b);
printf("%c-->%c\n",a,b);
hanio(n-1,c,b,a);
}
}
(1)下列语句可以对指针变量p赋值:
(第二条0即为空指针NULL,第四条p指向地址为1732的int型变量)
p = &i;
p = 0;
p = NULL;
p = (int*)1732
(2)*p = *p+1; ++*p; (*p)++,都是将指针p所指的变量值加1。但表达式*p++等价于*(p++),先取*p的值作为表达式的值,在将指针p的值加1,之后p不在指向变量a。
(3)假设a是一个数组,p是一个指针。
p=a;
p=&a[0];
p=a+1;
p=&a[1]
/*法一*/
sum = 0;
for(p=a; p<=&a[99]; p++)
sum += *p;
/*法二*/
sum = 0;
for(int i=0; i<100; i++)
sum += *(a+i);
/*法三*/
p = a;
sum = 0;
for(int i=0; i<100; i++)
sum += p[i];
(4).用指针定义字符串(以下两语句不完全一样)
char sa[] = "This is a string.";
char *sp = "This is a string.";
(注)char const *ptr:此种写法和const char *等价,大家可以自行实验验证。
scanf("%s", s);
gets(s);
printf("%s", s);
puts(s);
注:gets()是有返回值的,输入成功返回首地址,不成功返回NULL。puts()输出时自动把'\0'转化为'\n',输出成功返回'\n',否则返回EOF。
(1)void * p:可以用任何类型的指针对 void 指针进行赋值或初始化。
(2)因 sizeof(void) 没有定义,所以对于 void * 类型的指针p,*p 无定义,++p, --p, p += n, p+n,p-n 等均无定义。
(1)int *a = (int *)malloc(n * sizeof( int ));
(2)free(a)
指针存的值就是指针所指向的值的地址,因此指针之间相互赋值,并非是让另外一个指针指向该指针,而是让两个指针储存的值是相同的,就是说让一个指针和另外一个指针指向相同的地方。
#include
using namespace std;
int main(){
int a = 10;
int *p1 = &a;
int *p2 = p1;
int **p3 = &p2;
cout << p1 << endl << p2 << endl << p3 << endl << *p3 << endl;
return 0;
}
/*
0x6dfed4
0x6dfed4
0x6dfed0
0x6dfed4
*/
1.void * memset(void * dest,int ch,int n):(头文件string.h)
将从dest开始的n个字节,都设置成ch。返回值是dest。ch只有最低的字节起作用。
char szName[200] = "";
memset( szName,'a',10);
int a[100];
memset(a,0,sizeof(a));
9.void * memcpy(void * dest, void * src, int n) (头文件string.h)
将地址src开始的n个字节,拷贝到地址dest。返回值是dest。
10.字符串处理函数(#include
(1)字符串赋值函数:strcpy(s1, s2)
(2)字符串连接函数:strcat(s1, s2)
(3)字符串比较函数:strcmp(s1, s2), 若str1=str2,则返回零;若str1
(4)字符串长度函数:strlen(s1) (返回 '\0' 之前的字符个数)
11.字符串操作库函数:(#include
(1)char * strchr(const char * str,int c):寻找字符c在字符串str中第一次出现的位置。如果找到,就返回指向该位置的char*指 针;如果str中不包含字符c,则返回NULL。
(2)char * strstr(const char * str, const char * subStr):寻找子串subStr在str中第一次出现的位置。如果找到,就返回指向该位置的指针;如 果str不包含字符串subStr,则返回NULL。
(3)int stricmp(const char * s1,const char * s2):大小写无关的字符串比较。如果s1小于s2则返回负数;如果s1等于s2,返回0;s1大 于s2,返回正数。不同编译器编译出来的程序,执行stricmp的结果就可能不同。
(4)int strncmp(const char * s1,const char * s2,int n):比较s1前n个字符组成的子串和s2前n个字符组成的子串的大小。若长度不足n,则取整个串作为子串。返回值和strcmp类似。
(5)char * strncpy(char * dest, const char * src,int n):拷贝src的前n个字符到dest。如果src长度大于或等于n,该函数不会自动往dest中写 入‘\0’;若src长度不足n,则拷贝src的全部内容以及结尾的‘\0’到dest。
(6)char * strtok(char * str, const char * delim):连续调用该函数若干次,可以做到:从str中逐个抽取出被字符串delim中的字符分隔开的若干个子串。
(7)int atoi(char *s); 将字符串s里的内容转换成一个整型数返回。比如,如果字符串s的内容是“1234”,那 么函数返回值就是1234。如果s格式不是一个整数,比如是"a12",那么返回0。
(8)double atof(char *s); 将字符串s中的内容转换成实数返回。比如,"12.34"就会转换成12.34。如果s的格式 不是一个实数 ,则返回0。
(9)char *itoa(int value, char *string, int radix):将整型值value以radix进制表示法写入 string。
(1)例两个同类型的结构变量,可以互相赋值。但是结构变量之间不能用 “==”、“!=”、“<”、“>”、“<=”、“>=”进行比较运算。
(2)声明一个结构三种形式:
struct point
{
int x;
int y;
};
struct point p1, p2;
struct
{
int x;
int y;
} p1, p2;
struct point
{
int x;
int y;
} p1, p2;
(3)声明在函数内部的结构类型只能在函数内部使用,和局部变量相类似。若想让结构被多个函数使用,就要把结构声明在函数外部。
(4)赋值(代码中的p1, p2展现了两种赋值方式)
#include
struct point
{
int x,y;
};
int main()
{
struct point p1, p2;
p1 = (struct point){1, 2};
p2 = {3, 5};
printf("%d %d %d %d", p1.x, p1.y, p2.x, p2.y);
}
(5)结构指针(以下三个语句等效,s1为结构变量,p为指向s1首地址(第一个成员)的指针)
s1.num=101;
(*p).num=101;
p->num=101;
(6)和数组不同,结构变量名字并不是结构变量的地址,必须使用&运算符。
#include
struct point
{
int x,y;
};
int main()
{
struct point p1, p2;
p1 = {1, 2};
struct point *p = &p1;
printf("%d %d\n", p1.x, p1.y);
printf("%d %d\n", (*p).x, (*p).y);
printf("%d %d\n", p->x, p->y);
return 0;
}
2. 联合(union)
(1)用法和 struct 一模一样
#include
union AnElt {
int i;
char c;
}elt1, elt2;
int main() {
int a = sizeof(union AnElt);
int b = sizeof(AnElt);
int c = sizeof(elt1);
printf("%d %d %d\n", a, b, c);
return 0;
}
/*
Output:
4 4 4
*/
(2)sizeof (union ...) = sizeof( 每个成员 ) 的最大值。
(3)成员变量共享同一内存空间。
(4)英特尔CPU是小端,内部储存是低位在前,高位在后。
#include
typedef union{
int i;
char ch[sizeof(int)];
} CHI;
int main() {
CHI chi;
chi.i = 1234;
for (int i = 0; i < sizeof(int); i++) {
printf("%02hhX", chi.ch[i]);
}
printf("\n");
return 0;
}
/*
1234表示为16进制:
0x000004D2
Output:
D2040000
*/
(1)编译预处理指令
(2)#define
(3)宏
#include
#define PI 3.1415926
#define FORMAT "%f\n"
#define PI2 2 * PI
#define PRT printf("%f ", PI);\
printf("%f\n", PI2)
int main() {
printf(FORMAT, PI2 * 3.0);
PRT;
return 0;
}
/*
Output:
18.849556
3.141593 6.283185
*/
(4)没有值的宏
(5)预定义的宏
#include
int main() {
printf("%s: %d\n", __FILE__, __LINE__);
printf("%s, %s\n", __DATE__, __TIME__);
return 0;
}
/*
Output:
E:\computer\program\2020.04\2020.04.17\源.cpp: 3
Apr 22 2020, 10:20:17
*/
(6)带参数的宏:
(1)先在一个.h(头文件)中放入函数的原型
//max.h
int max(int a, int b);
(2)然后在 max.cpp 中 #include 这个头文件,并定义函数
//max.cpp
#include "max.h"
int max(int a, int b) {
return a > b ? a : b;
}
(3)最后看看 main.cpp 怎么写:
#include
#include "max.h"
int main() {
int a = 5;
int b = 6;
printf("%d", max(a, b));
return 0;
}
(4)#include 有两种形式来指出要插入的文件:
(5)其他注意事项:
(6)头文件
(7)不对外公开的函数
(1)变量的声明
(2)声明是不产生代码的东西,定义是产生代码的东西。常见的声明有:
(3)只有声明可以放在头文件中,否则会造成一个项目中多个编译单元中有重名的实体(不过,某些编译器允许几个编译单元中存在同名的函数,或者用 weak 修饰符来强调这种存在)。
(4)同一个编译单元中,同名的结构不能重复声明。如果多个头文件里有同名的结构声明,很难保证这个结构不被声明多次。这时候需要“标准头文件结构”。
(5)运用条件编译和宏,保证这头文件在一个编译单元中只会被 #include 一次。#pragma once 也能起到相同的作用,但不是所有编译器都支持。
//max.h
#ifndef _gALL_
#define _gALL_
extern int gALL;
#endif
#ifndef _Node_
#define _Node_
struct Node {
int n;
};
#endif
// min.h
#ifndef _Node_
#define _Node_
#include "max.h"
struct Node {
int n;
};
#endif
//max.cpp
int gALL = 10;
//main.cpp
#include
#include "min.h"
int main() {
printf("%d\n", gALL);
return 0;
}
(1)标准头文件结构
(2)#ifndef:
(3)#pragma once:
(1)打开文件标准代码
#include
int main() {
FILE* fp = fopen("12.in", "r");
if (fp) {
int num;
fscanf(fp, "%d", &num);
printf("%d\n", num);
fclose(fp);
}
else {
printf("无法打开文件\n");
}
return 0;
}
(2)fopen
r | 打开只读 |
r+ | 打开读写,从文件头开始 |
w | 打开只写。如果不存在则创建,如果存在则清空 |
w+ | 打开读写,如果不存在则新建,如果存在则清空 |
a | 打开追加。如果不存在则新建,如果存在则从文件尾开始 |
...x | 只新建,如果文件已存在则不能打开 |
(2)文本 vs 二进制
(4)程序为什么要文件:
(5)二进制读写
//student.h
#pragma once
const int STR_LEN = 20;
typedef struct _student {
char name[STR_LEN];
int gender;
int age;
}Student;
//main.cpp
#include
#include "student.h"
void getList(Student aStu[], int number) {
char format[STR_LEN];
sprintf(format, "%%%ds", STR_LEN - 1);
//"%19s"
for (int i = 0; i < number; i++) {
printf("第%d个学生:\n", i);
printf("name, gender, age:\n");
scanf(format, &aStu[i].name);
scanf("%d", &aStu[i].gender);
scanf("%d", &aStu[i].age);
}
}
int save(Student aStu[], int number) {
int ret = -1;
FILE* fp = fopen("student.data", "w");
if (fp) {
ret = fwrite(aStu, sizeof(Student), number, fp);
fclose(fp);
}
return ret == number;
}
int main() {
int number = 0;
printf("输入学生的数量:");
scanf("%d", &number);
Student aStu[20];
getList(aStu, number);
if (save(aStu, number)) {
printf("保存成功\n");
}
else {
printf("保存失败\n");
}
return 0;
}
(6)在文件中定位
//student.h
#pragma once
const int STR_LEN = 20;
typedef struct _student {
char name[STR_LEN];
int gender;
int age;
}Student;
//main.cpp
#include
#include "student.h"
void read(FILE *fp, int index) {
fseek(fp, index * sizeof(Student), SEEK_SET);
Student stu;
if (fread(&stu, sizeof(Student), 1, fp) == 1) {
printf("%s %d %d", stu.name, stu.gender, stu.age);
}
}
int main() {
FILE* fp = fopen("student.data", "r");
if (fp) {
fseek(fp, 0L, SEEK_END);
long size = ftell(fp);
int number = size / sizeof(Student);
int index = 0;
printf("有%d个数据,你要看第几个", number);
scanf("%d", &index);
read(fp, index - 1);
fclose(fp);
return 0;
}
}
(7)二进制文件的可移植性
(1)定义文件类型指针:
(2)文件处理步骤:
(3)打开文件:
r | 以只读方式打开文件,该文件必须存在。 | rb | 打开二进制文件进行只读 |
w | 打开只写文件,若文件存在则长度清为0,即该文件内容消失,若不存在则创建该文件。 | wb | 以只写方式打开或新建一个二进制文件,只允许写数据。 |
a | 以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留(EOF符保留)。 | ab | 打开二进制文件进行写/追加 |
r+ | 以读/写方式打开文件,该文件必须存在。 | rb+ | 以读/写方式打开一个二进制文件,只允许读/写数据。 |
w+ | 打开可读/写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。 | wb+ | 以读/写方式打开或建立一个二进制文件,允许读和写。 |
a+ | 以附加方式打开可读/写的文件。若文件不存在,则会建立该文件,如果文件存在,则写入的数据会被加到文件尾后,即文件原先的内容会被保留(原来的EOF符不保留)。 | ab+ | 以读/写方式打开一个二进制文件,允许读或在文件末追加数据。 |
(4)关闭文件:
if(fclose(fp)){
printf("Can not close the file!\n");
exit(0);
}
(5)字符方式文件读写:
(6)复制文件内容
while(!feof(fp1)){
ch = fgetc(fp1);
if(ch != EOF) fputc(ch, fp2);
}
(7)字符串方式读写函数
(8)格式化方式读写文件:
(9)其他: