数据类型
- 占位符:
数据类型 | 占位符 | 字节数 |
---|---|---|
%f | float | |
%d | int,short | 4 |
%ld | long | |
%lf | double | |
%c | char | 1 |
%x | 十六进制 | |
%o | 八进制 | |
%s | 字符串 |
sizeof(int)查看数据类型占用字节数
2.getchar()等待输入,类似system(“pause")
C的标准写法
不同平台的c语言写法不一样,需要标准写法:
#include <stdio.h>
// 标准写法:
int main(int argc,char* argv){
int i = 0;
for(;i < 5 ;i++){
printf("%d\n",i);
}
}
#include <stdio.h>
// 一般window下c的习惯写法
int main(){
for(int i = 0; i < 5; i++){
printf("%d\n",i);
}
}
输入输出函数:
#define _CRT_SECURE_NO_WARNINGS// 宏定义,不会做安全检查
#include <stdio.h>
#include <stdlib.h>
void main(){
int i;
// 赋值,&i代表取i的地址
scanf("%d",&i);
// 打印
printf("输入的值为%d",i)
}
指针
指针存储的是变量的内存地址;
void main(){
int i = 0;
int* p = &i; // p的值就是i这个变量的内存地址
printf("%#x\n",p); // 地址值都是十六进制的。#x为输出格式
i = 200; // 间接赋值
*p = 400; // 对p存的变量进行操作
system("pause");
}
- 指针必须赋值,如int *p = NULL;地址值为0;不能取空指针的值。不能给指针直接赋值为p=1,10,100等,操作系统不允许访问。
- 指针的运算:
一般在数组遍历时才有意义,数组呈线性排列。
int *p = xxx;
p++表示向前移动sizeof(数据类型)个字节;如:
void main(){
int arr[] = {1,2,3,4,5,80};
int *p = arr; // arr = &arr = p三者一样
printf("%d",*p); // 结果为1,因为数组的地址值为数组第一个元素的地址值,当执行p++,则结果为2,
}
函数指针
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
void msg(char* msg,char* title){
MessageBox(0, msg,title,0);
}
int main(int argc, const char * argv[]){
//msg()
// 函数指针
void(*fun_p)(char* msg,char* title) = msg;
// 调用函数指针
fun_p("111","222");
return 0;
}
int add (int a, int b){
return a + b;
}
int sub (int a, int b){
return a - b;
}
typedef int(*fun_p)(int a, int b);
void msg(int (*fun_p)(int a, int b),int m, int n){
// 类似于java的回调函数
int r = fun_p(m, n);
printf("%d\n", r);
}
void main(){
// int(*fun_p)(int a,int b) = add;
msg(add,10,20);
msg(sub,60,50);
}
int* getMinPointer(int ids[], int len){
int i = 0;
int* p = &ids[0]
for(; i < len; i++){
if(ids[i] < *p){
p = &ids[i];
}
}
return p;
}
动态内存分配
内存泄漏:当指针赋值之后再free,并没有真正释放内存
void main(){
// 40m
int* p1 = malloc(1024 * 1024 * 10 * sizeof(int);
// 这里要对p1进行释放,不释放则造成内存泄漏
free(p1);
p1 = NULL;
p1 = malloc(1024 * 1024 * 10 * 2);
if(p1 != NULL){
free(p1);
p1 = NULL;
}
getchar()
}
字符串
- 使用字符数组存储字符串,可以修改(类似java的StringBuffer),几种写法:
char str[] = {'c','h','\0'};
char str[2] = {'c','h'};
char str[10] = "ch";
str[0] = 's'; - 字符指针,不可修改(类似java的String): char *str = "how are you?";
- 字符串api学习网址
- 字符数组赋值,只能在声明时:
char a[10] = "happy" // 可以,不能又a="sad"
但是字符数字可以修改内容,比如a[0] = 'H';
重新赋值只能用strcpy;
字符指针可以不在声明时赋值,但是不能修改内容,同上第一条。 - demo:查找一个字符在字符串中的索引值
void main(void) {
char *str = "I am a coder!";
printf("字符串首地址为%#x\n",str);
// 也是0元素的指针
// strchr在一个串中查找给定字符第一个匹配之处
char* p = strchr(str, 'a');
if(p){
printf("索引位置%d\n",p - str);
}else {
printf("没有找到")
}
system("pause");
// 结果为2
}
结构体
结构体的几种写法
struct Man{
char name[20];
char* sex;
int age;
}m1,m2 = {"jian","m",26}; // m1是结构体变量名。
typedef int Age; // 别名
void main(){
Age a = 9;
m1.sex = f;
strcpy(m1.name,"jack");
m1.age = 10;
m2.age = 20;
}
**匿名结构体 **
主要是控制结构体个数。
struct{
char name[20];
int age;
}m1,m2;
联合体(共用体)
- 联合体是不同类型的变量共用同一段内存,相互覆盖,联合变量任何时刻只有一个成员变量,节省内存。联合体的带下=最大成员所占的子节数。
union MyValue{
int x;
int y;
double z;
}
void main{
union MyValue d1;
d1.x = 1;
d1.y = 2;
d1.z = 2.3;
// 最后一次赋值的有效
}
枚举
枚举是一种数据类型,默认递增
enum Day{
Monday,
Tuesday,
Sunday
};
相当于
enum Day{
Monday = 0,
Tuesday = 1,
Sunday = 2
};
这是默认情况,也可以自己写固定的数。
enum Day d = Monday;
enum Day *p = &d;
int i = 0;
for(; i < 3; i++){
printf(%d\n,*p);
p++;
}
// 输出结果看不懂,说明枚举的变量在内存上不是连续的。
I/O
- I:
// 读取文本文件
void main{
char path[] = "E:\\xxx\\xxx\\xxx.txt";
// 1.打开
FILE *fp = fopen(path,"r"); //rb,wb(binary)代表操作二进制文件
if(fp == NULL){
printf("文件不存在");
return;
}
// 2.读取
char buff[50]; // 缓冲区域
while(fgets(buff,50,fp)){
printf("%s",buff);
}
// 3.关闭
fclose(fp);
getchar;
}
- O:
char path[] = "E:\\xxx\\xxx\\xxx.txt";
// 1.打开
FILE *fp = fopen(path,"w");
char* text = "学java\r\n真是太好啦";
if(fp == NULL){
printf("文件不存在");
return;
}
// 2.写入
fput(text,fp);
// 3.关闭
fclose(fp);
- I/O:
char* r_path = "E:\\xxx\\xxx\\read.txt";
char* w_path = "E:\\xxx\\xxx\\write.txt";
FILE *r_fp = fopen(r_path,"rb");
FILE *w_fp = fopen(w_path,"wb");
// 复制
int buff[50]; // 缓冲区域
int len = 0;
while((len = fread(buff,sizeof(int),50,r_fp)) != 0){
fwrite(buff,sizeof(int),len,w_fp);
}
// 关闭流
fclose(r_fp);
fclose(w_fp);
- 获取文件大小
// 0代表偏移量,seek_end代表文件末尾
fseek(fp,0,SEEK_END);
// 返回当前文件指针,相当雨文件开头的位移量
long filesize = ftell(fp)
宏定义define
宏替换,为了使用更方便。