C语言基础
上手
- 类型
- 整形
- int 4 2^(4*8-1)
- short 2 2^(2*8-1)
- long 4
- unsigned short 2 2^(2*8)
- 负数补码为正数-1再全部取反
- (int) 类型转换
- 实型
- float 4
- double 8
- long double 16
- 字符型
- char
- unsigned char
- auto 自动推断
- 整形
- 运算符
++ -- + -
+ - * / % = += *=
? :
< <= => > == !=
! && ||
,
取后者~ << >> & | ^
- printf
printf("a = %d",a)
%d %ld %x %c %f %lf
整形 长整形 十六进制整形 字符型 浮点- %m.nf 总宽m,n位小数,左补空格
- %9d,小于9位时左边补空格
- scanf
scanf("%d,%f,%c,%u",&a,&b,&c,&d)
char a[100];scanf("%s",&a)
- putchar 字符输出
- getchar 字符输入
- puts 字符串输出
- gets 字符串输入
流程控制
c
if(a==3)
{
printf("a")
}
else if(a==5) printf("aa")
else printf("aaaa")
c
char op;
scanf("%c",&op);
switch (op)
{
case '1': printf('a');break;
case '2': printf("aa");break;
default: printf("error");
}
c
int i,sum=0;
i=1;
while (i<=100)
{
sum+=i;
i++
}
printf("%d\n",sum);
// while(1)
c
int i,sum=0;
i=1;
do
{
sum+=i;
i++
}while (i<=100);
printf("%d\n",sum);
c
int i,sum=0;
for (i=1;i<=100,i++)
sum+=i;
printf("%d\n",sum);
// for(;;)
c
int i,f=1;
i=1;
loop : if (i<=6)
{
f=f*i;
i++;
goto loop;
}
printf("%d\n",f);
数组
- 数组
int array[]={1,2,3,4,5}
int a [3] [3]={1,2,3,4,5,6,7,8,9}
- 未赋值为0
sizeof(a) / sizeof(a[0])
长度
- 字符串
char str[] = "string"
- 未赋值的自动为'\0'
- 长度后面一项也为"\0"
char c[7]; scanf("%s",c)
printf("%s",c)
<string.h>
gets()
puts()
strcpy()
strncpy()
复制strcat()
合并strcmp()
比较strlen()
长度strchr()
strrchr()
首/尾开始查找strspn()
strcspn()
(不)属于字符集的长度strpbrk()
查指定字符集的任一个字符strstr()
查找\另一个字符串strtok()
分割strcoll()
比较- 其它
函数
- 不能嵌套定义
- 函数名本质是函数的入口地址
- 可变参数
void func(char *a, ...)
va_list arg
va_start(arg, a)
va_end(arg)
c
#include "stdio.h"
#include "math.h"
int main()
{
int m;
int prime(int); // 函数声明
scanf("%d", &m);
if (prime(m))
printf("%d是素数\n", m);
else
printf("不是素数\n");
return 0;
}
int prime(int n)
{
for (int i = 2; i <= sqrt(n); i++)
{
if (n % i == 0)
return 0;
}
return 1;
}
指针
- &为取地址,* 为取指向的变量
int *node=NULL;
防止野指针
c
// 想通过函数改变量值要传指针
// 同理 想改指针指向要传指针的指针
#include "stdio.h"
void swap(int *p1,int *p2)
{
int t ;
t=*p1;
*p1=*p2;
*p2=t;
}
void main()
{
int a=10,b=4;
swap(&a,&b);
printf("%d,%d\n",a,b);
}
指针和数组
- 数组名表示数组首地址
int* p = a
*(a+i)
a[i]
a
&a[0]
p++
*(a+=1)
void func(int (*p)[])
fun(arr)
指针(的)数组
char* p[5]={"xyz","nbplus","hkye","c"};
字符串数组void main(int argc,char* argv[]){}
也可用于函数参数
c
void main()
{
char* c[5]={"xyz","nbplus","hkye","c"};
char** p;
for(p=c;p<c+5;p++)
{
printf("%s\n",*p)
}
}
指针和函数
c
int* min(int* x,int n)
{
int i,*q;
q=x;
for(i=1;i<n;i++)
if(*q>*(x+i)) q=x+i;
return q;
}
void main()
{
int *p,a[5]={4,7,2,6,9};
p=min(a,5);
printf("min:%d\n",*p);
}
c
int max(int x,int y)
{
return x>y?x:y;
}
void main()
{
int a,b,c;
int (*f)(int,int);
f=max;
scanf("%d%d",&a,&b);
c=(*f)(a,b);
printf("%d\n",c);
}
结构体
- 支持嵌套定义
- 默认值数字类型为0或4096 字符为空
c
//
struct Date
{
int year;
int month;
int day;
}birth1={1999,7,21};
struct Date birth2={1998,12,10};
struct Date birth5={
.year=1997,
.month=7,
.day=7
}
struct Date birth3,birth4;
c
struct Stu
{
int num;
char name[10];
int score;
}stu1;
void main()
{
printf("please input records:\n");
scanf("%d%s%d",&stu1.num,&stu1.name,&stu1.score);
printf("%d,%s,%d\n",stu1.num,stu1.name,stu1.score);
}
c
struct Person
{
char name[10];
int count;
}candi[5]={"lucy",0,"bob",0,"kai",0,"tom",0,"bella",0,"tom",0};
c
typedef struct {
int a;
double b;
}emp_i, *pemp_i; //typedef 了两个新的数据类型(结构体),其中一个是指针方式的名字
int main(void)
{
emp_i a1;
pemp_i b1 = &a1;
a1.a++;
b1->a++;
}
链表
c
#include "stdio.h"
#include "string.h"
struct Book
{
char title[20];
int total;
struct Book *next;
};
viod main()
{
struct Book a,b,c,*head,*p;
strcpy(a.title,"c语言");
a.total=105;
strcpy(b.title,"网页设计");
b.total=90;
strcpy(c.title,"数据结构");
c.total=200;
head=&a;
a.next=&b;
c.next=&c;
c.next=NULL;
p=head;
while (p!=NULL)
{
printf("%s,%d\n",(*p).title,(*p).total);
p=(*p).next;
}
}
c
#include "stdio.h"
#include "stdlib.h"
struct Book
{
int num;
char title[20];
int total;
struct Book *next;
};
int n;
struct Book *creat() //创建链表
{
struct Book *head,*p1,*p2;
n=0;
printf("input book information:\n");
p1=p2=(struct Book *)malloc(sizeof(struct Book));
scanf("%d%s%d",&(*p1).num,(*p1).title,&(*p1).total);
while((*p1).num!=0)
{
n=n+1;
if(n==1)
head=p1;
else
(*p2).next=p1;
p2=p1;
p1=(struct Book *)malloc(sizeof(struct Book));
scanf("%d%s%d",&(*p1).num,(*p1).title,&(*p1).total);
}
(*p2).next=NULL;
return head;
};
struct Book *insert(struct Book *head,struct Book *bo)
{
struct Book *p0,*p1,*p3;
p1=head;
p0=bo;
if(head==NULL)
{
head=p0;
(*p0).next=NULL;
}
else
{
while(((*p0).num>(*p1).num)&&((*p1).next!=NULL))
{
p2=p1;
p1=(*p1).next;
}
if((*p0).num<=(*p1).num)
{
if(head==p1)
head=p0;
else
(*p2).next=p0;
(*p0).next=p1;
}
else
{
(*p1).next=p0;
(*p0).next=NULL;
}
}
n+=1;
return head;
};
struct Book *dele(struct Book *head,int num) //删除节点
{
struct Book *p1,*p2;
if(head==NULL)
{
printf("\n the list is empty. \n");
return head;
}
p1=head;
while(num!=(*p1).num&&(*p1).next!=NULL)
{
p2=p1;
p1=(*p1).next;
}
if(num==(*p1).num)
{
if(p1==head)
head=(*p1).next;
else
(*p2).next=(*p1).next;
n=n-1;
}
else
printf("the node could not be found.\n");
return head;
};
void print(struct Book *head) //输出链表
{
struct Book *p;
p=head;
printf("book information: \n");
if(head!=NULL)
while(p!=NULL)
{
printf("%d,%s,%d\n",(*p).num,(*p).title,(*p).total);
p=(*p).next;
}
}
void main()
{
struct Book *head,bo;
int num;
head=create();
printf(head);
printf("please input the insert record:\n");
scanf("%d%s%d",&bo.num,bo.title,&bo.total);
head=insert(head,&bo);
printf(head);
printf("the delete number:\n");
scanf("%d",&num);
head=dele(head,num);
printf(head);
}
共用体
共用体同一时间只有一个成员的值是有效的
c
union data{
int n;
char ch;
double f;
};
union data a, b, c;
枚举类型
可以看成一个宏定义的集合
c
typedef enum
{
MONDAY=1, //如果是从1开始的序列可不写
TUESDAY,
WEDNESDAY
}Week_t;
int main()
{
Week_t week;
week=MONDAY; //week==1
week=TUESDAY; //week==3
week=8; //报错
b=MONDAY; //可以不定义直接用b==1
}
别名
c
typedef float FLA;
typedef char NAME[20];
typedef struct Person
{
int num;
char name[20];
char addr[30];
}PER;
PER a,b;
文件
r | 只读打开文本文件 | w | 只写建立新文本文件 | a | 追加打开文本文件 |
---|---|---|---|---|---|
rb | 只读打开二进制文件 | wb | 只写建立新二进制文件 | ab | 追加打开二进制文件 |
r+ | 读写打开文本文件 | w+ | 读写建立新文本文件 | a+ | 读写追加打开文本文件 |
rb+ | 读写打开二进制文件 | wb+ | 读写建立新二进制文件 | ab+ | 读写追加打开二进制文件 |
常用方法
- fopen() 打开
FILE *f = fopen("file.txt", "w");
- fclose() 关闭
fclose(f);
f=NULL
- fgetc() 读取一个字符
while(c != EOF)
c = fgetc(f)
- fputc() 写入一个字符
do{}while(c != '$')
fputc(getchar(), f)
- fgets() 读取一个字符串
fgets(str, 99, f)
- fputs() 写入一个字符串
fputs(str, f)
- fprintf() 写入格式化数据
- fscanf() 格式化读取数据
- fread() 读取数据
int len = fread(str, size, count, f);
- fwrite() 写入数据
size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
- feof() 文件是否结束
feof(f)
- ferror() 文件读/写是否出错
- clearerr() 清除文件错误标志
clearerr(f)
- ftell() 文件指针的当前位置
ftell(f)
fseek(pf,0,SEEK_END);
long n = ftell(f)
文件大小
- rewind() 把文件指针移到开始处
rewind(f)
- fseek() 重定位文件指针
fseek(f,offset,1/2/0)
- SEEK_CUR 1 当前位置
- SEEK_END 2 末尾
- SEEK_SET 0 开头
- rename() 重命名
rename(old, new)
- remove() 删除
remove(f)
例子
c
#include "stdio.h"
#include "stdlib.h"
void main()
{
FILE *fp;
char ch;
if((fp=fopen("C:\\brgzz.tet","w"))==NULL)
{
printf("cannot open file!");
getchar();
exit(0);
}
printf("input a string:\n");
ch=getchar();
while(ch!='\n')
{
fputc(ch,fp);
ch=getchar();
}
fclose(fp);
}
c
#include "stdio.h"
#include "stdlib.h"
void main()
{
FILE *fp;
char ch;
if((fp=fopen("C:\\brgzz.tet","r"))==NULL)
{
printf("cannot open file!");
getchar();
exit(0);
}
while((ch=fgetc(fp))!=EOF)
putchar(ch);
putcgar('\n');
fclose(fp);
}
c
//将一个文本文献复制到另一个
#include "stdio.h"
#include "stdlib.h"
#define N 80
void main()
{
FILE *in,*out;
char infile[10],outfile[10];
char str[N];
printf("enter the infile name:\n");
scanf("%s",infile);
printf("enter the outfile name:\n");
scanf("%s",outfile);
if((in=fopen(infile,"r"))==NULL)
{
printf("cannot open file!");
getchar();
exit(0);
}
if((out=fopen(outfile,"w"))==NULL)
{
printf("cannot open file!");
getchar();
exit(0);
}
while (fgets(str,N,in)!=NULL)
fputs(str,out):
fclose(in);
fclose(out);
}
c
//追加字符串并全部输出
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#define N 80
void main()
{
FILE *fp;
char str[N];
if((fp=fopen("C:\\brgzz.txt","a+"))==NULL)
{
printf("cannot open file!");
getchar();
exit(0);
}
printf("input a string:\n");
gets(str);
fputs(str,fp);
rewind(fp); //位置标记移到开头
while(fgets(str,N,fp)!=NULL)
puts(str);
fclose(fp);
}
c
#include "stdio.h"
#include "stdlib.h"
#define N 6
struct stu
{
char name[10];
int num;
int age;
char addr[15];
}boya[N],boyb[N],*pp,*qq;
void main()
{
FILE *fp;
int i;
pp=boya;
qq=boyb;
if((fp=fopen("C:\\stu_list.dat","wb+"))==NULL)
{
printf("cannot open file");
getchar();
exit(0);
}
printf("\ninput data\n");
for(i=0;i<N;i++,p++)
scanf("%s%d%d%s",pp->name,&pp->num,&pp->age,pp->addr);
pp=boya;
fwrite(pp,sizeof(struct stu),N,fp);
rewind(fp);
fread(qq,sizeof(struct stu),N,fp);
printf("name \tnumber age addr\n");
for(i=0;i<N;i++,qq++)
printf("%s\t%5d%7d%10s\n",(*qq).name,(*qq).num,(*qq).age,(*qq).addr);
fclose(fp);
}
c
#include "stdio.h"
#include "stdlib.h"
struct stu
{
char name[10];
int num;
int age;
char addr[15];
}boya[6],boyb[6],*pp,*qq;
void main()
{
FILE *fp;
int i;
pp=boya;
qq=boyb;
if((fp=fopen("c:\\stu_list.dat","w+"))==NULL)
{
printf("cannot open file!");
exit(0);
}
printf("\ninput data\n");
for(i=0;i<6;i++,pp++)
scanf("%s%d%d%s",pp->name,&pp->num,&pp->age,pp->addr);
pp=boya;
for(i=0;i<6;i++,pp++)
fprintf(fp,"%s%d%d%s\n",(*pp).name,(*pp).num,(*pp).age,(*pp).addr);
rewind(fp);
for(i=0;i<6;i++,qq++)
fscanf(fp,"%s%d%d%s",(*qq).name,&(*qq).num,&(*qq).age,(*qq).addr);
printf("\n \nname \tnumber age addr \n");
qq=boyb;
for(i=0;i<6;i++,qq++)
printf("%s\t%5d%7d%11s\n",(*qq).name,(*qq).num,(*qq).age,(*qq).addr);
fclose(fp);
}
c
struct _iobuf {
char *_ptr; //指向buffer中第一个未读的字节
int _cnt; //记录剩余的未读字节的个数
char *_base;//文件的缓冲
int _flag;//打开文件的属性
int _file;//获取文件描述
int _charbuf;//单字节的缓冲,即缓冲大小仅为1个字节
int _bufsiz;//记录这个缓冲大小
char *_tmpfname;//临时文件名
};
typedef struct _iobuf FILE;
其它
宏定义
- 习惯上用大写字母表示
- 不要分号,不参与检查
- 可以使用
#undef宏名
来终止宏定义 - 可嵌套使用
#define A 2
#define B (A*10)
- 带参数使用
#define SQ(x) x*x
a=SQ(5);//a=25
- 带逻辑
#define MAX(x,y) (x)>(y)?(x):(y)
- 带函数
#define F1(a,b) printf("%d\n",a>b?a:b);
- 定义格式字符串
#define F2 "%d,%d\n"
模块
- include "文件名"
.h
头文件- 函数声明
- 宏定义
- 结构体定义
.c
程序文件- 主函数实现
.cpp
c++文件
条件编译
c
//如果标识符被#define宏命令过,则编译程序1
#ifdef 标识符
程序1;
#else
程序2;
#endif
//如果标识符未被#define宏命令过,则编译程序1
#ifndef 标识符
程序1;
#else
程序2;
#endif
//如果表达式非0,则编译程序1
#if 表达式
程序1;
#else
程序2;
#endif
关键字
- static
- 局部变量的值保持
- 静态全局变量仅对当前文件可见
- 静态类成员属于整个类
- extern
- 用于跨文件使用变量
- volatile
- 阻止编译器优化
- 运行时不用缓存
cpp
// c语言中的#include 基本等效于把文件内容写进来
// 因此其实.h文件里面东西写进来就不用引入了
// 编译的时候要把用到的文件都写上
// g++ -o demo main.cpp test.cpp
#include <iostream>
using namespace std;
// static int a; // 使用文件自己的a
// extern int a; // 使用全局的a
int print(void);
int main() {
cout << a << endl;
print();
return 0;
}
cpp
#include <iostream>
using namespace std;
int a = 17;
void print() { cout << a << endl; }
内置函数
- exit(0) 退出
- perror(char *string) 报错
- memset()
- bzero(void *s, int n) 将内存块前n个字节清零
string.h
c
#include <stdio.h>
#include <string.h>
int main() {
char str[50] = "Hello, World!";
printf("Before memset: %s", str);
// 将字符串的前 5 个字符设置为 'A'
memset(str, 'A', 5);
printf("After memset: %s", str);
return 0;
}
动态内存分配
使用malloc可以在程序运行时确定数组长度
c
#include <stdio.h>
#include <stdlib.h>
int main() {
int len;
int i, b;
// 注意:这里应先声明指针,然后使用malloc分配内存
int *p = (int *)malloc(4 * sizeof(int)); // 分配内存空间,size为所需字节数
if (p == NULL) { // 检查内存是否成功分配
printf("内存分配失败");
return -1;
}
printf("请输入数组个数:");
scanf("%d", &len);
// 根据用户输入调整内存分配大小
p = (int *)realloc(p, len * sizeof(int));
if (p == NULL) { // 再次检查内存是否成功分配
printf("内存重新分配失败");
return -1;
}
printf("请输入要存储的数字:");
for (i = 0; i < len; i++) {
scanf("%d", &p[i]);
}
for (b = 0; b < len; b++) {
printf("%d", p[b]);
}
// 释放所分配的内存
free(p);
return 0;
}
time.h 时间库
c
#include "stdio.h"
#include "time.h"
time_t ts;
struct tm *date;
char *str;
int main()
{
ts = time(0);
printf("%d\n", ts);
date = gmtime(&ts);
printf("%d\n", date->tm_hour);
date = localtime(&ts);
printf("%d\n", date->tm_hour);
ts = mktime(date);
printf("%d\n", ts);
str = ctime(&ts);
printf("%s\n", str);
str = ctime(date);
printf("%s\n", str);
str = ctime(date);
printf("%s\n", str);
return 0;
}
argc & argv
./argtest 1234 abcd
argc
3argv
["./argtest", "1234", "abcd"]