#include
#include
#include
#include
#include
#include
int main(int argc,char **argv){
int a[5] = {10, 2, 33, 4, 15}; // 定义数组
int *p = a; // 定义指向数组元素的指针
int (*f)[5] =&a; // 定义指向数组指针的指针
printf("%d\n",**f); //10
printf("%d\n",*(*f+1)); //2
int d[2][5]={{1,2,3,4,5},{22,45}}; //不能用指针定义二维数组,int (*h)[5]={{},{}};会报错
int (*h)[5]=d; //二维数组指针
printf("%d\n",**h); //1
printf("%d\n",*(*h+1)); //2
printf("%d\n",*(*(h+1)+1)); //4
//数组的初始化,只有字符串可以用指针形式定义,其余的必须用标准格式定义arr[]={....}
//int *q={1,2,4}; //是错误的
int q[]={1,2,4}; //标准格式定义,正确
char *s="123344"; //字符串可以用指针定义
// char *n={1,2,3}; 错误
// int *m[3]={{1,2,3},{}}; 这样表示是错误的,只能用标准格式
char *x[3]={"123","asd","dd"}; //*x[3]=*(x[3]) 与(*x)[3]是有区别的 后者可以代表二维指针或者指针的指针
printf("%s\n",*x); //123
printf("%s\n",*(x+1)); //asd
printf("%c\n",(*(x+1))[2]);//d
char ff[3][10]={"1213","qwwq","zzzzcxc"};
char (*v)[10]=ff;
printf("%c\n",(*(v+1))[2]);
printf("%c\n",*(*(v+1)+3)); //可以这样理解:p为指针,也是“1213”的首地址,p+1 代表第二个字符串的地址,也是它的首地址,
//*(v+1) 单独表示是取p+1指针的字符串,如在运算中,代表第二字符串的地址指针,也是它的第一个字符的地址
//*(v+1)+3 这是指针运算,表示第二个字符串的读3+1个字符的指针
//*(*(v+1)+3) //取指针指向的字符
//所以,如表示单个元素 v[m][n]==*(*(v+m)+n) 左边为数组符号,右边为指针符号
int *e; //一维指针
e=(int [3]){12,234,100}; //符合语句,其值为指针
printf("%d\n",*(e+1)); //234
int (*r)[3]; //二维数组指针
r=(int [][3]){{1,2,3},{10,20,30},{11,22,33}};
printf("%d\n",r[1][2]); //30
printf("%d\n",*(*(r+1)+2)); //30
return 0;
}
特别注意:除了字符串,包括一维和多维,都不能用指针变量初始化数组,必须用a[m]={.. }
a[m ][n]={ ...} 格式定义 。 m可留空。而且,一维指针为: void *p 二维指针维
void (*p)[n] n不能省,如是多维字符串初始化,必须是 void *p[n] n不能省,不能写成
(*p)[n] 格式
函数声明中,多维数组中最左边方括号可以为空,其于右边的括号内必须指定具体数值,象int. **t. 是指针数据的指针
#include
#include
#include
#include
#include
#include
int main(int argc,char **argv,char *envp[]){
char *p[]={"121","asd","12w"}; //不能用(*p)[3]这种形式,可能是它代表二维指针吧
while(*envp){ //这个是读取命令参数的方法,只有这种情况可以用,读取其他数组报错
printf("%s\n",*(envp++));
}
puts("----------------------------");
for(int t=0;t<3;t++){ //读取数组的标准方法
printf("%s\n",*(p+t));
}
return 0;
}
数组的指针
在c中,几乎所以使用数组名的表达式中,数组名的值是一个指针常量,也就是数组 第 一个元素的地址。注意这个值是指针常量,不是变量。
int a[10]={ ….....};
int *q;
q=&a[0] ; <=> q=a; //这两句是等价的。
但是,a=q 是非法的,因为a是常量。
a[5]=*(q+5) //数组下标等价于数组的指针间接寻址。
int a[10]={….....};
int *p=a; //一定要理解,非常重要。
注意 int *p 是定义的p为整型指针变量,如初始化必须是指针类型值。
如:
char c='a';
char *q= &c;
特别要理解字符串常量这个特殊情况:
char *q="hello world."; //"hello world" 的值为存储这个字符串常量的地址指针。
到现在就可以很好理解scanf输入什麽时候加&符号了
如:
char c[10];
int t;
scanf("%d",&t); //注意t前面必须加& 地址符号。
scanf("%s",c); //因为c就是指针类型。同样。printf("%s",a) a也是指针类型。
c语言中,任何字符串常量的值的类型都是指针类型。
所以,只有见到函数参数是 char * 或者const char * 就是要输入字符串。
如:c中打开文件的函数
FILE * fopen(const char *restrict, const char *restrict)
此函数的意思就是函数返回值为FILE类型的存储指针,如打开成功,返回打开文件运行代码的内存地址指针,失败,返回NULL。 参数1为文件路径名加文件名,用字符串常量表示,如"/home/wjs/2.c", 参数2 为字符串常量,如" r" , "w","a","r+","w+","a+",表示读写方式。
c语言中规定:关于函数参数,在函数原型或函数定义的场合中(并且也只有在这两种场合中),可以用 int *p 代替 int p[ ]
fun( int *p) <==> fun (int p[ ]) 等价
#include
#include
#define A "hello world."
int test(int *p);
int main(void){
int t[10]={1,2,3,4,5,6};
test(t);
return 0;
}
int test(int *p){
printf("%d\n",p[3]); //4
printf("%d\n",*(p+3)); //4
return 0;
}
2. #define A B 把b自定义 A
如定义字符串: #define HELLO "hello world"
定义数值 #define LEN 10
3. const 修饰,表示不可变
const int t[10] 不可变数组
const int t=10 不可变变量
4. c 语言的字符串就是以\0结尾的char数组。
字符串常量或者叫字符串文字是指用一对双括号包围的任何字符,系统自动加\0.
<1> c语言的字符串定义:
先定义字符串 c : char c [ 20]={.......... ,'\0'};
程序中可以直接用c 代表字符串了
<2> 字符串常量的定义
a: #define A ”hello world."
b: char c[20]="hello world."
c: char *p="hello world" //特别要理解,这里赋值是字符串常量的地址指针。可以参看下面的代码理解
printf("%c\n", *"hello"); // 输出 h,"hello" 的值为字符串hello内存存储地址的指针。
char *p="hello world.";
for(int n=0;n
p++;
}
输出为 h e l l o
scanf 输入时系统自动加如\0 空白符。printf 函数可以直接输出 字符串数组。如不加空白符,那是字符数组 .printf() 也能直接输出 字符数组。这和java 输出数组就有区别。
char c[20];
scanf("%s",c);
printf("%s\n",c); //直接输出。
5 键盘输入:
a. char c=getchar() //一个字符的输入
b. char c[20]; gets(c); //一个字符串的输入,可以包括空格等,不推荐使用。
c. char c[20]; char *p; p=fgets(c,20,stdin); //输入一个字符串,推荐用。
d. char c[20]; scanf("%s",c) //可以输入字符串。整数。浮点数,字符等
6. 屏幕输出
a. putchar('a'); //输出一个字符
b. puts(&); //& 表示输出字符串的地址指针
如: puts("hello");
char *p="hello"; puts(p+1); //ello
c. char c[20]="hello"; fputs(c,stdout);
d. printf( )
========================================================
c 服务器与客户端 for deepin
服务器:
#include
#include
#include
#include
#include
#include
void error_handling(char *message);
int main(int argc,char *argv[]){
int serv_sock;
int clnt_sock;
struct sockaddr_in serv_addr; //定义服务器strust
struct sockaddr_in clnt_addr; //定义存储客户端ip ,port 的struct
socklen_t clnt_addr_size;
char message[]="hello nanning";
if(argc!=2){
printf("Usage:%s \n",argv[0]);
exit(1);
}
serv_sock=socket(PF_INET,SOCK_STREAM,0);
if(serv_sock==-1)
error_handing("socket() error");
memset(&serv_addr,0,sizeof(serv_addr)); //把struct serv_addr 全部位置0
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
serv_addr.sin_port=htons(atoi(argv[1]));
struct sockaddr *myaddr=&serv_addr;
if(bind(serv_sock,myaddr,sizeof(serv_addr))==-1) //注意长度类型:socklen_t
error_handing("bind() error|port binding");
if(listen(serv_sock,5)==-1)
error_handing("listen() error");
printf("%s\n","listening port");
clnt_addr_size=sizeof(clnt_addr);
struct sockaddr *myclnt=&clnt_addr;
clnt_sock=accept(serv_sock,myclnt,&clnt_addr_size);// 把连接的客户端的ip,port存储在struct clnt_addr中
if(clnt_sock==-1) // 注意长度类型是存储值的指针地址
error_handing("accept() error");
write(clnt_sock,message,sizeof(message));
char *c=inet_ntoa(clnt_addr.sin_addr); //客户端的ip 网址
printf("%s\n",c); //127.0.0.1
close(clnt_sock);
close(serv_sock);
return 0;
}
void error_handing(char *message){
fputs(message,stderr);
fputc('\n',stderr);
exit(1);
}
客户端
#include
#include
#include
#include
#include
#include
void error_handing(char *message);
int main(int argc,char *argv[]){
int sock;
struct sockaddr_in serv_addr;
char message[30];
int str_len;
if(argc!=3){
printf("Usage:%s \n",argv[0]);
exit(1);
}
sock=socket(PF_INET,SOCK_STREAM,0);
if(sock==-1)
error_handing("socket() error");
memset(&serv_addr,0,sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=inet_addr(argv[1]);
serv_addr.sin_port=htons(atoi(argv[2]));
struct sockaddr *myaddr=&serv_addr;
if(connect(sock,myaddr,sizeof(serv_addr))==-1)
error_handing("connect() error");
str_len=read(sock,message,sizeof(message)-1);
if(str_len==-1)
error_handing("read() error");
printf("message from server:%s\n",message);
close(sock);
return 0;
}
void error_handing(char *message){
fputs(message,stderr);
fputc('\n',stderr);
exit(1);
}
服务器:./ s 3000
客户端: ./c 127.0.0.1 3000
---------------------------------------------------------
c 中,数组使用前必须定义,也就是必须定义存储空间大小,而且使用数组的标准定义定义。
如:char c[30]; int t[10]
不能用指针来定义数组的空间大小
如: char *p;
scanf("%s",p);
printf("%s\n",p);
这样写是错误的,因为没有定义字符串存储空间大小。第一条应改位 char p[20]; 定义存储20个字符的存储空间。
时间
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char** argv){
time_t ptm=0;
time( &ptm); //取当前时间,是long 类型
printf("%s\n",ctime(&ptm)); //把long类型时间转换为年月日的时间格式
struct tm *t = localtime( &ptm ); // 把当前时间转存在时间tm结构中
printf("当前的本地时间和日期:%s", asctime(t)); //把tm 时间转换为年月日格式时间
printf("%d:%d:%d:%d:%d\n",(*t).tm_sec,(*t).tm_min,(*t).tm_hour,(*t).tm_mday,(*t).tm_mon);//把tm 结构中的当前时间数据分别输出
//t为指针,*t 为tm结构值
return(0);
}
socket 结构类型:struct sockaddr
struct sockaddr{
unsigned short sa_family // AF_INET
char sa_data[14] //14字节的ip地址,0-1:port 2-5:ip
printf (%#x\n",3000); 3000=0xbb8;
所以可以用sockaddr 代替sockaddr_in
struct sockaddr s_addr;
memset(&s_addr,0,sizeof(s_addr));
s_addr.sa_family=AF_INET;
s_addr.sa_data[0]=0x0b;
s_addr.sa_data[1]=0xb8;
s_addr.sa_data[2]=0;
s_addr.sa_data[3]=0;
s_addr.sa_data[4]=0;
s_addr.sa_data[5]=0;
inet_addr("127.0.0.1") 相当于 htonl(127*2^24+0*2^16+0*2^8+1),一定要用htonl()转换为网络传输的字节格式。
当然,c 中没有2^24这种运算符号。
对socket 的读写 read() ,write():标准函数是
int len =read(sk,&dd,len_dd)
sk 为socket ,dd为读取socket内容后存储在本机数值,可以是char ,short,int,数组。
len_dd为dd的字节长度。
如,读取char为 1, short 为2, int 4, 字符串数组为数组长度-1.
---------------------------------------------------------------------------------------------------------------
//读取文本文件到字符数组中。先测量文件长度,再根据文件长度设置数组长度。网络传输文件可以用此法把文件读入数组中,再把数组一次性传输到socket中
//当然,可以先向socket接收方传输数组长度,让接收方知道接收多少字符,设置号接收数组长度,再传输数组内容。
#include
#include
#include
#include
#include
#include
int main(void){
FILE *f=fopen("/home/wjs/c/1.txt","r+");
if(f==NULL){
puts("file error\n");
exit(0);
}
int t=0;
while(!feof(f)){ //测量文件长度,feof(f)到文件末尾等于非0,不到末尾等于0
fgetc(f); //利用fgetc()移动文件指针
t++;
}
rewind(f); //把文件指针重置为0,非常重要,如不重置,fgetc(f)就会继续从上次读文件长度时读
char c[t];
for(int n=0;n
c 的socket read() write() send() recv() 都是按字节发送,接收的。所以可以发送接收任意数据:如int char 数组,字符串,数据结构struct
下面代码就是发送接收struct
发送:
#include
#include
#include
#include
#include
#include
struct school{ //声明数据结构school
char name[4];
int age;
};
int main(void){
struct sockaddr_in s_addr;
memset(&s_addr,0,sizeof(s_addr));
s_addr.sin_family=AF_INET;
s_addr.sin_addr.s_addr=htonl(INADDR_ANY);
s_addr.sin_port=htons(3000);
int s=socket(PF_INET,SOCK_STREAM,0);
if(s==-1){
puts("socket error\n");
}
if(bind(s,(struct sockaddr *)&s_addr,sizeof(s_addr))==-1){
puts("bind error\n");
}
if(listen(s,10)==-1){
puts("listen error\n");
}
puts("listening port\n");
int c=accept(s,NULL,NULL);
if(c==-1){
puts("accept() error\n");
}
//------------------------------------------------------------------
struct school my={ //初始化数据结构my
"wh",
20
};
write(c,&my,sizeof(my)); //发送my
return 0;
}
接收
/*#include
#include
#include
#include
#include
#include
struct school{ //说明要接收的数据结构类型
char name[4];
int age;
};
int main(void){
struct sockaddr_in c_addr;
memset(&c_addr,0,sizeof(c_addr));
c_addr.sin_family=AF_INET;
c_addr.sin_port=htons(3000);
c_addr.sin_addr.s_addr=inet_addr("127.0.0.1");
int sk=socket(PF_INET,SOCK_STREAM,0);
if(sk==-1)
puts("socket error\n");
if(connect(sk,(struct sockaddr *)&c_addr,sizeof(c_addr))==-1)
puts("connect error\n");
//-------------------------------------------------------------------
struct school my;
int r=read(sk,&my,sizeof(my)); //接收数据结构
if(r==-1)
puts("read error\n");
printf("%s\n",my.name);
close(sk);
return 0;
}*/
这就是java 的objectOutputStream.writeObject("hello");
objectInputStream.readObject(); 的功能
同理,也可以把struct顺序写入文件
//把数据结构struct写入文件保存
#include
#include
#include
#include
#include
#include
struct school{
char name[4];
int age;
};
int main(void){
struct school me={
"wz",
18
};
FILE *f=fopen("/home/wzpc/c/1.txt","w");
if(f==NULL){
puts("file error\n");
exit(0);
}
int sk=fileno(f); //FILE *转 socket 流类型,利用socket 的write ,read函数
write(sk,&me,sizeof(me));
fclose(f);
FILE *h=fopen("/home/wzpc/c/1.txt","r");
int ff=fileno(h); //FILE * 转 socket类型
struct school ww;
read(sk,&ww,sizeof(ww));
printf("%s %d\n",ww.name,ww.age); //wz
//18
return 0;
}
FILE * f 与int socket()类型可以互转,可以利用它们各自的函数
fdopen() socket类型转文件
fileno() 文件转socket
数据类型
char //1字节 char既可以表示字符,也可以表示一字节整数
short //short int 2字节
int 4字节
long //long int 8字节
float 4字节
double 8字节
unsigned
signed
void
组合:如 long long, unsigned int, signed int=int,
特别注意,如用char可 表示一字节整数,前面可加修饰符 ubsigned,signed
unsigned char //0-255
signed char=char //-128~127
c 测量任意格式文件长度
#include
#include
#include
#include
#include
#include
int main(void){
FILE *f=fopen("/home/wjs/c/1.txt","r");
if(f==NULL){
puts("file error\n");
exit(0);
}
long int t;
while(!feof(f)){ //不到文件末尾
fgetc(f);//读一字节,相对与移到文件指针
t++;
}
printf("%d\n",t);
return 0;
}
c 对字符串赋值
以下是转载:
学了这么多年的C语言,突然发现连字符串赋值都出错,真的很伤心。
char a[10];
怎么给这个数组赋值呢?
1、定义的时候直接用字符串赋值
char a[10]="hello";
注意:不能先定义再给它赋值,如char a[10]; a[10]="hello";这样是错误的!
2、对数组中字符逐个赋值
char a[10]={'h','e','l','l','o'};
3、利用strcpy
char a[10]; strcpy(a, "hello");
c中struct 的 a->b : a为struct 的指针,b为struct中的结构成员名, a->b 代表struct中的b成员,可以为b赋值,也可以取值。
-----------------------------------------------------------------------------------------------------------------------
c 对文件存储数据的理解:1.可以存储字符,字符串
2.可以存储int ,float ,double,数组,struct,或者其他非单字节数据。对于第一种,字符,字符串存储,可以用标准函数读写`,如:fgetc,fputc,fgets,fputs。
对于第二种情况:就必须把FILE *文件转换位 int socket类型,利用write ,read函数来操作。
或者用系统调用 int open()函数来打开文件,再用write ,read来完成
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(void){
int f=open("/home/wzpc/c/1.txt",O_RDWR);
if(f==-1){
puts("file orror\n");
exit(1);
}
// char t='q';
// int t=100;
char t[]="hello world";
write(f,&t,sizeof(t));
close(f);
return 0;
}
fopen() 参数:
r 文件必须存在,读文件
w 文件如不存在,则创建,再写文件
文件如存在,则使文件成为0长,再写
a 文件如不存在,则创建,再写。
如文件存在,则追加文件
r+ 文件必须存在,可读可写
w+ 文件如不存在,创建,可读可写
文件存在,从0字节可读可写
a+ 打开或创建,在文件尾读或写,从0字节开始读。
利用fwrite fread 也可以按二进制方式读写 数组。struct 等
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(void){
FILE *q=fopen("/home/wzpc/c/1.txt","w+b");
if(q==NULL){
puts("file error\n");
exit(1);
}
int t=888;
fwrite(&t,4,1,q);
rewind(q); //文件指针归0,这句非常重要
int c;
fread(&c,4,1,q);
printf("%d\n",c);
return 0;
}
#include
#include
#include
#include
#include
#include
int main(void){ //unsigned char 可以代表0-255的单字节整数,char=signed char //-128~127
unsigned char c[2][3][5]={{{18,3,23,0,22 },{100,34,5,23,8 },{66,44,9,200,205 }},{{1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7}}};
unsigned char (*p)[3][5]=c; //获取三维数组指针
printf("%d\n",*(*(*(p+1)+2)+2)); //=p[1][2][2]
printf("%d\n",p[1][2][2]); //数组中,可以用指针代表数组名
printf("%d\n",c[1][2][2]);
return 0;
}
注意多维指针的定义:必须是(*p)[n] 的形式。
fopen()打开文件后,文件指针等于0.不管是用何种方式打开,那怕是用追加的方式打开,如不进行读写操作,文件指针还是为0
int *(p1[5]); //指针数组,可以去掉括号直接写作 int *p1[5]; int (*p2)[5]; //二维数组指针,不能去掉括号
c 中,* 优先级大于+,-
二维数组里 **p 的值绝对不会是指针,引申一下,含两个**符号的值绝对不是指针值
=====================================
基于文件的数据库
用
用
注意,中文一个字符占3个字节,如名字是3个字,必须分配9个字节,但实践验证,这样还会出玩乱码,必须多分配一个中文所占字节数,那就是12个字节。这样当输入3个字的中文名字时,就不会出现乱码了
自动生成c 编程程序模板
// 自动生成编程模板
#include
#include
#include
int main(int argc,char **argv){
char path[100]="/home/wjs/c/";
strcat(path,argv[1]);
strcat(path,".c");
FILE *f=fopen(path,"w+");
if(f==NULL){
puts("path error");
exit(1);
}
fputs("#include \n",f);
fputs("#include \n",f);
fputs("#include \n",f);
fputs("#include \n",f);
fputs("#include \n",f);
fputs("#include \n",f); //可以增加头文件
fputs("int main(int argc,char **argv){\n",f);
fputs("\n",f);
fputs(" return 0;\n",f);
fputs("}\n",f);
return 0;
}
#include
#include
using namespace std;
int main()
{
// 执行/bin目录下的ls, 第一参数为程序名ls, 第二个参数为"-al", 第三个参数为"/etc/passwd"
if(execl("/bin/ls", "ls", "-al", "/etc/passwd", (char *) 0) < 0)
{
cout<<"execl error"<
else
{
cout<<"success"<
return 0;
}
#include
#include
#include
#include
#include
#include
int main(int argc,char **argv,char *envp[]){
if(execl("/usr/bin/gcc","gcc","1.c","-o","1",NULL)<0)
puts("error");
return 0;
}