c

1 基础知识

字节:计算机主存被划分的编号单元,字节可以保存8位二进制 数字位(0、1)
地址:字节的编号

指令

指令:计算机CPU执行某种操作的命令编码
程序:计算机能识别和执行的指令集合
机器指令:计算机能直接识别和接受的二进制代码(只含0、1)

编程语言分类

低级语言、高级语言

低级语言:机器语言、符号语言
机器语言:机器指令的集合
符号语言 = 汇编语言:
ADD加、SUB减、LD传送

高级语言:
FORTRAN(fortran)、ALGOL(数值计算)、
BASIC、QBASIC、
上面是非结构化语言(符合语法规则即可,规范不严格,可读性差)
下面是结构化语言(顺序 分支 循环,结构清晰、便于编写 阅读 维护)
COBOL(商业管理)、C
下面是面向对象语言
C++、Visual Basic、Java

编辑,预编译,编译,链接,调试运行

源程序:高级语言写的程序
目标程序:机器指令的程序(二进制0 1,文件后缀.obj)

c、c++程序设计步骤:
编辑,预编译,编译,链接,调试运行

编辑程序:程序代码的输入
预编译程序:代码文本的替换,是整个编译过程的最先做的工作
编译程序:把源程序转换为目标程序,
用到了预处理器(= 预处理程序、预编译器)
作用:对源程序进行检查,有无语法错误
过程:预编译+正式编译

预编译执行:define、include
编译执行:typedef

链接处理:
计算机不能直接执行目标文件,只能执行 可执行程序(后缀是.exe)
编译针对一个源程序,链接的是多个源程序文件,即使只有1个源程序文件,也要连接,因为要与函数库连接(scanf)

标准程序:

#include<。。。>
int main()
{
   ...
   return 0;
}

2 编程知识

除法 - 整数与浮点数

5/9=0
5.0/9=5/9.0=5.0/9.0 != 0

大小写转换

a+32:小写转大写
x*=y+8 等价与 x=x*(y+8)
x%=y+8 等价与 x=x%(y+8)

函数声明:

#include<。。。>
int main()
{
   void max(int,int),min(int,int);
	等价于
   void max(int x, int y),min(int x, int y);
   ...
   return 0;
}
void max(int a, int b)
{}
void min(int a, int b)
{}

变量存储方式:

静态存储、动态存储

内存:运行时用
存储空间:不参与运行,就是放数据的
存储空间:
程序区、静态存储区、动态存储区

静态存储区:
全局变量、
静态局部变量(用static)、静态外部变量(用static的全局)、
外部变量(无static,可在别文件用extern引用的)

动态存储区:
函数形参、无static的自动变量、
函数调用的现场保护和返回地址

局部变量存储类别:
auto自动(动态存储)
static静态(静态存储,分局部和全部静态)
register寄存器(该变量会放在CPU寄存器中,速度变快)

全局变量存储类别:

extern外部的
其它文件在声明该外部函数时不能初始化定义

#include<。。。>
int main()
{
   extern int a;
   void max(int,int),min(int,int);
等价与
   void max(int x, int y),min(int x, int y);
   ...
   return 0;
}
int a;  
// 该行以下是a的作用域,以上不是,
在上面某行加入extern int a;可以解决!
void max(int a, int b)
{}
void min(int a, int b)
{}

我直接在所有函数前声明全局变量就好了!就不必去用extern了
在不同文件用同一全局变量就要用extern了
该文件的全局变量不希望别的文件使用,就可以 static int a;

static局部变量:
在静态存储区,程序运行期间不释放
static全局变量:
对于外文件不可见

内存的4个区:

全局数据区(全局变量,静态变量,字符串常量)
代码区(函数 代码)
栈区(运行函数而分配的形参,局部变量,返回地址)
堆区(动态内存分配new, malloc, calloc)

函数:

用户使用角度:库函数、自定义的函数
形式上:无参函数、有参函数

定义函数时,其参数是形参
主函数调用子函数,其括号的参数是实参
实参的值传给形参,形参的改变不影响实参!
数据类型 char和int可以相互兼容

数组名作实参,传递的是第一个元素的地址
一般int变量的实参和形参,互不影响是因为实参和形参它俩地址不同,自然互不影响
但数组名做地址 作为实参,形参的接收的就是地址,它俩地址相同,会相互影响

int swap1(int *x, int *y)传值
{
   int p;//不能是int *p;指针为初始化,在下面用*p,*p是不可预见的
   p=*x;*x=*y;*y=p;//交换功能,不加*,在主函数就会交换失败
}

int swap2(int &x, int &y)传址
{
   int p;
   p=x;x=y;y=p;
}

int main()
{
   ...
   int *p1, *p2;
   p1=&a;
   p2=&b;
   swap1(p1, p2);
   swap2(a, b);
}

内部函数:

static int max(int a, int b){}
不能被其它文件调用

外部函数:
调用其它文件的函数
extern int max(int a, int b);声明一下

数组

数组:有序数据的集合
int a[10]={0}:全部元素为0
int a[10]={1,2}:其它元素默认为0
int a[]={1,2} 等价与 int a[2]={1,2}

字符数组默认’\0’
指针数字默认NULL
int a[3][4]={1,2,3,4}
等价于
int a[][4]={1,2,3,4}

字符串在字符数组中

字符串存在字符数组中,以 ‘\0’ 结束
char s[]="sdd";
等价与
char s[]={"sdd"};
此时:字符串长度+1 = 字符数组字节数 = 4
其末尾是’\0’
char s[]={'s', 'd', 'd'};
则字节数为3

字符数组输入

多个%s时,空格区隔相邻字符串

数据类型 a[常量n]
数组名a就是其数组起始地址,不用加&
strlen(字符数组)=字符串长度,不含末尾’\0’
strlwr(字符串):转小写
strupr(字符串):转大写

一维数组形参 其大小说明可省略
void max(int a[]){}
多维数组形参 其第一维大小说明可省略
void max(int a[][5]){}
void max(int a[][6][5]){}

引用和指针:

引用:
是对象别名,用来传输较大的数据变量
不占用新的地址,节省内存开销
间接访问更安全

所以引用&只能声明,不存在定义
1 声明时必须初始化,即引用b是谁的别名
初始化后不能改变为别的对象的别名
2 数组元素不能是引用
int a[3]; int (&t)[3] = a;
int & ref[3] = { 2, 3, 5}; ×
注意到引用是别名
数组元素是引用,
引用又是别的对象别名,一系列别的对象恰好物理地址连续?
3 不能对引用进行引用(引用不能嵌套引用,没有引用的引用)

常引用:

引用本就不能改变=常const
常引用是 不能通过引用修改对象值
对象依然修改

指针和数组:

int *p=&a;

p=&a; *p=a;
指针赋值用变量,别直接用整数100
指针已经和变量a赋过值 这时可以用100给指针赋值,此时a也为100了

一维数组:
a[0]=*a=*(a+0)
a[i]=*(a+i)

二维数组:
&a[1]=(a+1) (第1行首地址)
&a[i]=(a+i) (第i行首地址)

a[0]=*(a+0)=*a (a[0][0]地址)
a[1]=*(a+1) (a[1][0]地址=第1行首地址)
a[i]=*(a+i) (a[i][0]地址=第i行首地址)

a[0]+1=*(a+0)+1 (a[0][1]地址)
a[1]+1=*(a+1)+1 (a[1][1]地址)
a[i]+j=*(a+i)+j (a[i][j]地址)

&a[0][0]=a[0]+0
a[0][0]=*(a[0]+0)
a[0][1]=*(a[0]+1)=*(*(a+0)+1)=*(*a+1)= a[i][j]=*(a[i]+j)=*(*(a+i)+j)

a+1是第1行首地址
*(a+1)a[1][0]的地址
两者等价!

char *a="sdfg";char *a;
a="sdfg";char a[14];
a="sdf";   ×

char a[14]="sdf";
int *p[4];指针数组,暗含二维的意思
int (*p)[4];一维普通整数数组
int *p[4] 等价与 int *(p[4])
数组p的每个元素是指针

作用于数组a的函数:
int *p = min_element(a, a+6);
a[0]至a[5]最小元素的指针给指针p
注意是a[5]!

int *p = msx_element(a, a+7);
a[0]至a[6]最大元素的指针给指针p

注意是a[6]!

random_shuffle(a, a+7);
a[0]至a[6]随机打乱

int *p = find(a, a+8, key);
a[0]至a[7]中元素值为key的元素的指针给指针p

指针和字符串

char *p=“sfgs”;
cout<< p;是输出字符串
(void *)p是字符串地址

字符串 清空与free()?

typedef struct // 变长 
{
	char *ch;
	int length;
}Str;

free(str.ch) 程序会崩溃
直接 str.ch = NULL; 即可

free(链表节点指针) 而不是 字符指针

字符串赋值

字符串指针直接赋值即可

#include<bits/stdc++.h>
#define num 100
using namespace std;

int main()
{
	//1
	char *p, b = 's';
	p = &b;
	cout << "1" << endl;
	cout << *p << endl << endl;

	//2
	char *a ="abcdefg";
	cout << "2" << endl;
    cout << "输出字符: " << *a << endl;
    cout << "第二次输出字符: " << *(a + 1) << endl;
    cout << "输出字符串: " << a << endl << endl;
    
    //3
    char q[num] = "asd" ;
    cout << "3" << endl;
    cout << *q << endl;
    cout << q << endl << endl;
    
    //4
    char q1[num] = {'s','d','f','\0'}; // <=>  char q1[num] = "sdf";
    cout << "4" << endl;
    cout << *q1 << endl;
    cout << q1 << endl << endl;
	
	//5
	char q2[num];
	strcpy(q2, "asd");
	cout << "5" << endl;
	cout << *q2 << endl;
	cout << q2 << endl << endl;

	return 0;
}


错误操作:

	char *q3;
	strcpy(q3, "asd");
	strcpy(*q3, "asd");
	cout << "5.2" << endl;
	cout << *q3 << endl;
	cout << q3 << endl << endl;

函数指针 指针函数:

函数指针:
函数代码有被分配存储空间,其起始地址为这个函数的指针
int (*p)(int,int)
是指针,是指向函数的指针,
函数有两个int参数,函数返回int数据(函数代码首地址)

函数指针的作用:
函数指针可用作形参,在不同函数的不同组合时可以用

指针函数:
int *p(int a, intb){}
返回一个指针,即数组
一般函数返回一个值,可能不够用,我希望返回一系列值,用指针函数!

#include<stdio.h>
void main()
{
	float score[][4]={{60,70,80,90},{56,89,67,88},{34,78,90,66}};
	float *search(float (*point)[4],int n);
	float *p;
	int i,n;
	printf("输入学生学号n:(0=<n<=2)");
	scanf("%d",&n);
	printf("the score of No.%d are:\n",n);
	p=search(score,n);
	for(i=0;i<4;i++)
		printf("%5.2f ",*(p+i));
	putchar('\n');
}

float *search(float (*point)[4],int n)
{
	float *pt;
	pt=*(point+n);
	return pt;
}

指针常量 常量指针

指针常量 指针变量:

指针常量:
指针类型的常量,该指针不能变,
即指针是常量 不能变
指针指向的对象值可以变
int b=5;
int * const p=&b;
p不能变,即 p只能指向b了
然后*p=6; √
b=9; √

指针变量:就是一般的指针

常量指针:
指向常量的指针
即:指向常量的指针变量

const int b;  
int const b; (等价)
const int *p=&b;
int const *p=&b;(等价)
p可以更改指向别的对象c
非常量指针q=常量指针p  ×
常量指针p=非常量指针q  √

常指针常量:
指向常量的 指针常量

const int b;
const int * const p=b;
int const * const p=b;

左值 右值

左值表达式代表对象本身,
右值表达式代表对象的值

左值:在赋值运算符左侧,其值可以改变,永久对象,可被取地址,如:有名称的变量、函数形参(栈中的对象)
右值:在赋值运算符右侧,其值可以改变,临时对象(即将销毁),不可取地址,如:字面常量(1、2…等)、匿名对象(临时对象)以及函数的返回值
std::move(str) 显式将一个左值str转换为右值

*与&

&跟左值,不能式变量表达式(a+1)
&(a+1) ×
&a √

typedef

typedef int b;
int新名字是b
b h;就是int h;

3 冷知识

C语言exe文件闪退

main函数末尾的return前加上:
system("pause");getchar();

这样生成的exe文件就不会闪退了

0和’\0’

在dev c++中0='\0'

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int p = (0 == '\0');
	cout << " 0 == '\\0'  = " << p << endl;
}

未满的整型数组,求真实元素个数?

1 手动记录
2 需要约定一个数字作为结束标记

原因:
数组的未满部分,对于计算机来说,全部存0或随机数,

手动初始化、calloc数组,未满部分就是0
malloc,未满部分就是随机数

sizeof

char str[] = “abcdef”; → sizeof(str) = = 7,因为str的类型是char[7],
也有sizeof(“abcdef”) == 7,因为"abcdef"的类型是const char[7]。

char ptr = “abcdef”; → sizeof(ptr) == 4,因为ptr的类型是char

char str2[10] = “abcdef”; → sizeof(str2) = = 10,因为str2的类型是char[10]。

void func(char sa[100], int ia[20], char * p);
→ sizeof(sa) == sizeof(ia) == sizeof( p) == 4,
因为sa的类型是char*, ia的类型是int*,p的类型是char*

时间函数

均用到库函数:#include<time.h>

程序用时

参考于:https://blog.csdn.net/homewm/article/details/80302534

2个方法:
clock() / CLOCKS_PER_SEC 精确到毫秒
time(NULL) start, end ; difftime(end, start) 精确到

法1 clock() / CLOCKS_PER_SEC
精确到毫秒
clock():CPU运行的时钟周期数
CLOCKS_PER_SEC:1秒CPU运行的时钟周期数

clock_t start, end;
start = clock();
end = clock();
(double)(end - start) / CLOCKS_PER_SEC
#include<bits/stdc++.h> 
using namespace std;

int main()
{
	clock_t start, end;
	start = clock();
	int i; 
	
	for(i = 0; i < 100000000; i++)
		rand();
	
	end = clock();
	cout << "程序用时 " << (double)(end - start)/CLOCKS_PER_SEC << "s" << endl << endl;
	
	system("pause");
	return 0;
}

法2 time(NULL) start, end ; difftime(end, start)
精确到

time(NULL):得到当前日历时间或者设置日历时间

start = time(NULL);
end = time(NULL);
difftime(end, start)
#include<bits/stdc++.h> 
using namespace std;

int main()
{
	clock_t start, end;
	start = time(NULL);
	srand(time(NULL));
	int i, b = 0;
	
	for(i = 0; i < 100000000; i++)
		rand();
	
	end = time(NULL);
	cout << "程序用时 " << difftime(end, start) << "s" << endl << endl;
	
	system("pause");
	return 0;
}

时间

小时、tm结构体、现在时间 localtime、gmtime、asctime

小时:

time_t seconds;
seconds = time(NULL);
seconds/3600 :自 1970-01-01 起的小时数

下面的结构体tm不用手动定义:

struct tm 
{
   int tm_sec;         /* 秒,范围从 0 ~ 59      */
   int tm_min;         /* 分,范围从 0 ~ 59      */
   int tm_hour;        /* 小时,范围从 0 ~ 23     */
   int tm_mday;        /* 一月中的第几天,范围从 1 ~ 31    */
   int tm_mon;         /* 月,范围从 0 ~ 11(注意)  */
   int tm_year;        /* 自 1900 年起的年数      */
   int tm_wday;        /* 一周中的第几天,范围从 0 到 6 */
   int tm_yday;        /* 一年中的第几天,范围从 0 到 365   */
   int tm_isdst;       /* 夏令时               */
};

tm_year是1900年后的年数,真实年数 = tm_year +1900

夏令时:
夏季天亮早的,人为将时间调快一小时,早起早睡,减少照明量,充分利用光照资源,节约照明用电

得到现在时间:
2个办法:

法1

	time_t t;
	time(&t);   获取当前时间
	cout << ctime(&t) <<endl;

法2:

最简代码!:
	time_t t;
	time(&t);  获取当前时间
	
	struct tm *lt;
	lt=localtime(&t);  等价于 lt=gmtime(&t); 转换为时间结构
	
	cout << asctime(lt) <<endl;

strftime
size_t strftime( char *strDest, size_t maxsize, const char *format, const struct tm *timeptr);

其中format

	%a 星期几的简写 
    %A 星期几的全称 
    %b 月分的简写 
    %B 月份的全称 
    %c 标准的日期的时间串 
    %C 年份的后两位数字 
    %d 十进制表示的每月的第几天 
    %D 月//%e 在两字符域中,十进制表示的每月的第几天 
    %F 年--%g 年份的后两位数字,使用基于周的年 
    %G 年分,使用基于周的年 
    %h 简写的月份名 
    %H 24小时制的小时 
    %I 12小时制的小时 
    %j 十进制表示的每年的第几天 
    %m 十进制表示的月份 
    %M 十时制表示的分钟数 
    %n 新行符 
    %p 本地的AM或PM的等价显示 
    %r 12小时的时间 
    %R 显示小时和分钟:hh:mm 
    %S 十进制的秒数 
    %t 水平制表符 
    %T 显示时分秒:hh:mm:ss 
    %u 每周的第几天,星期一为第一天 (值从06,星期一为0%U 第年的第几周,把星期日做为第一天(值从053%V 每年的第几周,使用基于周的年 
    %w 十进制表示的星期几(值从06,星期天为0%W 每年的第几周,把星期一做为第一天(值从053%x 标准的日期串 
    %X 标准的时间串 
    %y 不带世纪的十进制年份(值从099%Y 带世纪部分的十进制年份 
    %z,%Z 时区名称,如果不能得到时区名称则返回空字符。 
    %% 百分号 
	time_t a;
	time( &a);
	
	struct tm *b;
	b= localtime( &a);
	
	char buffer[80]; sizeof(buffer) = 80
	以年月日_时分秒的形式表示当前时间:
	strftime(buffer, 80, "%Y%m%e_%H%M%S", b); 80 对应 buffer[80]

mktime
mktime(struct tm *timeptr)
timeptr转为time_t类型,若失败则返回 -1

	int ret;
	struct tm a;
	
	a.tm_year = 2001 - 1900;
	a.tm_mon = 7 - 1;
	a.tm_mday = 4;
	a.tm_hour = 0;
	a.tm_min = 0;
	a.tm_sec = 1;
	a.tm_isdst = -1;
	
	ret = mktime(&a);
	if( ret == -1 )
	{
	    printf("错误:不能使用 mktime 转换时间。\n");
	}
	else
	{
		char buffer[80];
		strftime(buffer, sizeof(buffer), "%c", &a);
		print(buffer);
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_1403034144

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值