c高级笔记及代码整理

预习检查:
1.linux下的文件描述符

2.二进制文件与文本文件的区别

3.如何从标准输入得到一行但如果避免使用gets()
 
**********************************************
1.文件的分类:
从用户观点:
特殊文件(标准输入输出文件或标准设备文件)
普通文件(磁盘文件)
从操作系统的角度看,每一个与主机相连的输入输出设备看做是一个文件。
2.文件:存储在外部介质上数据的集合,是操作系统管理的单位。
系统调度的最小单位--线程
分配资源的最小单位--进程
管理数据的单位------文件
3.文件概念
C把文件看做是一个字符的序,计由一个一个字符组成的字符流。
二进制文件就是内存的镜像文件

文本文件特点:存储量大,转换为二进制速度慢,直观易记。ASCII形式
二进制文件特点:存储量小,无需转换。但因一个字节不对应一个字符,故不能
直接输出其字符形式。二进制形式
4.文件系统
缓冲文件系统(高级文件系统):系统自动为正在使用的文件开辟内存缓冲区
非缓冲文件系统(低级文件系统):由用户在程序中为每个文件设定缓冲区。


 ------------------------------------------------------------------------------

句的格式以换行表示,ASCII值为10,十六进制表示为0A
结束标志EOF看不到
**********************************************************************
字符串输入 fgets

函数首部:

char  *fgets(char  *str,int length,FILE  *fp);

功能:从fp所指向的文件中,至多读length-1个字符,送入字符数组str中,
如果在读入length-1个字符结束前遇换行符或EOF,读入即结束,字符串读入
后在最后加一个‘\0’字符。

返值:正常,返str指针;出错,返空指针NULL。
字符串输出 fputs

函数首部:
int  *fputs(char  *str,FILE  *fp);

功能:把str指向的字符串写入fp指向的文件。

返值:正常,返0;出错返EOF。
######################################################################
字段输入fread /输出fwrite

函数首部:

int  fread(void  *buffer,int num_bytes, int  count,FILE   *fp);

int  fwrite(void  *buffer,int  num_bytes, int  count,FILE   *fp);

功能:读/写数据块。

返值:成功,返回读/写的字段数;出错或文件结束,返回0。

说明:

buffer:  指向要输入/输出数据存储区的首地址的指针

num_bytes:  每个要读/写的字段的字节数

count:   要读/写的字段的个数

fp:    要读/写的文件指针

fread与fwrite 一般用于二进制文件的输入/输出。
***********************************************************************
#include<stdio.h>
#include<stdlib.h>
int main()
{
        FILE *fp = fopen("xxx","r");
        if(fp == NULL)
        {
                printf("open error!!");
                exit(0);
        }
        FILE *fw = fopen("zzz","w");

        if(fw == NULL)
        {
                printf("open error!!");
                exit(0);
        }
        char str[10];
        while((fgets(str,10,fp)!=NULL)) 
        {
                printf("%s",str);
                fputs(str,fw);
        }
        close(fp);
        close(fw);
        return 0;
}
运行结果:
123456789012345
123456789
cc
d
***********************************************************************
#include<stdio.h>
#include<stdlib.h>
int main()
{
        FILE *fp = fopen("xxx","r");
        if(fp == NULL)
        {
                printf("open error!!");
                exit(0);
        }
        char str[10];
        while(fgets(str,10,fp)!=NULL)
        {
                printf("%s",str);
        }
        close(fp);
        return 0;
}
运行结果:
123456789012345
123456789
cc
d

***********************************************************************
#include<stdio.h>
#include<stdlib.h>

int main()
{
  int a[10]={65,66,67,68,69,70,71,72,73,74};
  FILE *fp = fopen("xxx","w+");//注意要用w+
  if(NULL == fp)               //防止少写一个=导致报错
  {
   printf("open xxx error\n");
   exit(0);
  }
  fwrite(a,sizeof(int),10,fp);
  rewind(fp);
  int b[10]={0};
  fread(b,4,10,fp);
  int i;
  for(i=0;i<10;i++)
  {
   printf("%d ",b[i]);
  }
  fclose(fp);
   return 0;
}
运行结果:
65 66 67 68 69 70 71 72 73 74
*************************************************************
rewind函数

函数首部:  void  rewind(FILE  *fp);

功能:使fp所指文件的位置指针重置到文件开头。

返值:无
*************************************************************
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
  char a[]="china is great";
  FILE *fp = fopen("xxx","w+");
  if(NULL == fp)      //防止少写一个=导致报错
  {
   printf("open xxx error\n");
   exit(0);
  }
  fwrite(a,sizeof(char),strlen(a),fp);
  rewind(fp);      //使fp所指文件的位置指针重置到文件开头
  char b[20];
  fread(b,1,strlen(a),fp);
  puts(b);
  fclose(fp);
   return 0;
}
运行结果:
china is great
****************************************************************
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct Stu
{
  char name[30];
  int num;
  char sex;
  float score;
};
int main()
{
   struct Stu stu[3]=
   {
    "bob",2001,'f',56,
    "smith",2002,'m',45.0,
    "calos",2003,'f',78
   };
   FILE *fp = fopen("studata","w+");
   if(NULL == fp)       //防止少写一个=导致报错
   {
    printf("open studate !");
    exit(0);
   }
   fwrite(stu,sizeof(struct Stu),3,fp);
   struct Stu x[3];
   rewind(fp);      //使fp所指文件的位置指针重置到文件开头
   fread(x,sizeof(struct Stu),3,fp);
   int i;
   for(i=0;i<3;i++)
   {
    printf("%s %d %c %f\n",
                  x[i].name,x[i].num,x[i].sex,x[i].score);
   }
   fclose(fp);
   return 0;
}
运行结果:
bob 2001 f 56.000000
smith 2002 m 45.000000
calos 2003 f 78.000000
*********************************************************************
stdin和stdout
例:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
/*
 * fgets(char*,len,FILE*);
 * fgets(char*,FILE*);
 *
 * 系统默认打开两个文件,分别对应的指针是:stdin(键盘),stdout(显示器)
 */
int main()
{
 char *p = "china";
 FILE *fp = fopen("mm","w");
 fputs(p,stdout);
 fputs(p,fp);
   return 0;
}
运行结果:
china
同时将china写入文件mm中了
*************************************************************************
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
/*
 * fgets(char*,len,FILE*);
 * fgets(char*,FILE*);
 *
 * 系统默认打开两个文件,分别对应的指针是:stdin(键盘),stdout(显示器)
 */
int main()
{
  setvbuf(stdout,NULL,_IONBF,0);
  char q[10];
  FILE *fp = fopen("mm","r+");
  fgets(q,10,fp);
  printf("%s",q);
  fclose(fp);
  fgets(q,10,stdin);//只读入9+\0
                //gets(q);    //若写入20个数据,可能将q后的内存覆盖
  printf("%s",q);
   return 0;
}
运行结果:
who am i   //打印结果
who am i   //输入
who am i   //输出
*********************************************************************
fseek函数
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main()
{
  FILE *fp = fopen("mm","r+");
  if(NULL == fp)
  {
     printf("open error !");
     exit(0);
  }
  int size;
  fseek(fp,-1,SEEK_END);
  size = ftell(fp);
  printf("%d",size);

   return 0;
}
**********************************************************************
#include<stdio.h>
#include<stdlib.h>
struct Node
{
 int num;
 char name[20];
};
typedef struct Node STU;
int main()
{
 FILE *fp;
 fp = fopen("data.txt","w+");
 if(fp == NULL)
 {
  printf("open error\n");
  exit(0);
 }
 STU stu[5]={{10,"aaa"},{11,"bbb"},{12,"ccc"},{13,"ddd"},{14,"eee"}};
 STU student2;
 fwrite(stu,sizeof(STU),5,fp);
 rewind(fp);      //文件指针指向文件首部,读取第一个学生的信息
 fread(&student2,sizeof(STU),1,fp);
 printf("%d %s\n",student2.num,student2.name);
 fseek(fp,2*sizeof(STU),SEEK_SET);   //定位到第三个学生的位置,读取出信息
 fread(&student2,sizeof(STU),1,fp);
 printf("%d %s\n",student2.num,student2.name);
 fclose(fp);
 return 0;
}
运行结果:
10 aaa
12 ccc

****************************************************

#include<stdio.h>
int main(int argc,char *argv[])
{
        printf("%d\n",argc);
        return 0;
}
运行结果:
1
***********************************
[root@localhost 6.1]# ./a.out
1
[root@localhost 6.1]# ./a.out a
2
[root@localhost 6.1]# ./a.out a b
3
[root@localhost 6.1]# ./a.out a b c
4
[root@localhost 6.1]# ./a.out a b c d
5
***********************************
#include<stdio.h>
int main(int argc,char *argv[])
{
        printf("%d\n",argc);
        int i;
        for(i=0;i<argc;i++)
        {
                printf("%s\n",argv[i]);
        }
        return 0;
}
运行结果:
[root@localhost 6.1]# ./a.out abc def ghi
4
./a.out
abc
def
ghi
分析:  argc=4
 argv[0]->./a.out
 argv[1]->abc
 argv[2]->def
 argv[3]->ghi

*********************************************
atoi(将字符串转换成整型数) 
相关函数  atof,atol,atrtod,strtol,strtoul
 
表头文件  #include<stdlib.h>
 
定义函数  int atoi(const char *nptr);
 
函数说明  atoi()会扫描参数nptr字符串,跳过前面的空格字符,直到遇上数字或正负符号才
开始做转换,而再遇到非数字或字符串结束时('\0')才结束转换,并将结果返回。
 
返回值  返回转换后的整型数。
 
附加说明  atoi()与使用strtol(nptr,(char**)NULL,10);结果相同。
 
范例  /* 将字符串a 与字符串b转换成数字后相加*/
#include<stdlib.h>
mian()
{
char a[]=”-100”;
char b[]=”456”;
int c;
c=atoi(a)+atoi(b);
printf(c=%d\n”,c);
}
 
执行  c=356
 
*****************************************
#include<stdio.h>
#include<stdlib.h>
int main(int argc,char *argv[])
{
        if(argc != 2)
        {
                printf("Please input like ./a.out argment\n");
                exit(0);
        }
        int num,i;
        num = atoi(argv[1]);//将字符串转化为对应的整型数
        for(i=0;i<num;i++)
        {
                printf("xxx\n");
        }

        return 0;
}
运行结果:
[root@localhost 6.1]# ./a.out 2
xxx
xxx
[root@localhost 6.1]# ./a.out 3
xxx
xxx
xxx
**************************************
数组指针:(本质是指针,指向的是数组)
void func(int (*p)[4],int n)
其中,n为长度,即跳的次数
代码举例:
#include<stdio.h>
#include<stdlib.h>
void func(int (*p)[4],int n);
int main()
{
 int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
 func(a,3);
 return 0;
}
void func(int (*p)[4],int n)
{
 int i,j;
 for(i=0;i<n;i++)
 {
  for(j=0;j<4;j++)
  {
   printf("%3d",p[i][j]);
  }
  printf("\n");
 }
}

运行结果:
  1  2  3  4
  5  6  7  8
  9 10 11 12
********************************************************
预习检查:
1.预编译是什么?
答:在进行第一遍扫描(词法分析和语法分析)之前所作的工作
2.如何得到只经过编译后的文件?
答:gcc -E 文件名.c -o 文件名.i
3.#include<stdio.h>


********************************************************
宏定义:不带参数的:
一般形式:#define 宏名 [宏体]
以#开头的都发生在预处理阶段
#include<stdio.h>
#define YES 1
#define OUT printf("xxxxx\n");
int main()
{
        int a=YES;
        if(a==YES)
        {
                OUT;
        }
        return 0;
}
*****************************************************************
#include<stdio.h>
#define NUM 5+4             //没加括号结果为21,加上括号结果为36
#define OUT printf("xxxxx\n");
int main()
{
        int a=NUM*4;
        printf("%d\n",a);
        return 0;
}
运行结果:
21
****************************************************
带参宏定义:
#define S(a,b)  a*b     注意:S和(a,b)之间不能有空格
     ……
area = S(3,2)    //area=3*2
****************************************************
取消宏定义:
#undef A
*********************************************
条件编译:
#if条件   //当条件为假(0)的时候,注释下面语句
#else     //与#if相反,#if注释是这里不注释
#endif
*********************************************
#define BZ

#ifdef  BZ
……
#else
……  //注释掉
#endif
****************
没有#define BZ

#ifdef  BZ
……  //注释掉
#else
…… 
#endif
******************************************
#define M 8086    //谁与此不同,则被注释掉

#if M==8086
……
#if M==51
……       //注释掉
#if M==2000
……       //注释掉
#endif
******************************************
#include<stdio.h>
#include<stdlib.h>
void why_me();
int main()
{
 printf("The file is%s.\n",__FILE__);
 printf("The file is%s.\n",__DATE__);
 printf("The file is%s.\n",__TIME__);
 printf("The file is%d.\n",__LINE__);
 printf("The file is%s.\n",__func__);
 why_me();
 return 0;
}
void why_me()
{
 printf("This function is%s\n",__func__);
 printf("This function is%s\n",__FILE__);
 printf("This function is%d\n",__LINE__);
}
运行结果:
The file is../src/hello.c.
The file isJun  1 2012.
The file is21:02:35.
The file is9.
The file ismain.
This function iswhy_me
This function is../src/hello.c
This function is18
***************************************************
文件包含:
被包含文件的内容:
@源文件(*.c)
@头文件(*.h):宏定义,数据结构定义,函数说明等

$例$

文件a.c:
#include"agou.h"
aaaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbb
cccccccccccccc
ddddddddddd
eeeeeeee
fffff
ggg
h


文件agou.h
x
yyy
zzzzzzzzzzz
xxxxxxxxxxxxx
vvvvvvvvvvvvvvvvvv
qqqqqqqqqqqqqqqqqqqqqqqq

预处理一下a.c:
gcc -E a.c -o a.i
打开预处理后的文件a.i,内容如下:
# 1 "a.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "a.c"
# 1 "agou.h" 1
x
yyy
zzzzzzzzzzz
xxxxxxxxxxxxx
vvvvvvvvvvvvvvvvvv
qqqqqqqqqqqqqqqqqqqqqqqq
# 2 "a.c" 2
aaaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbb
cccccccccccccc
ddddddddddd
eeeeeeee
fffff
ggg
h

***************************************
避免头文件重复包含:
#ifndef _XXX_H_     //若未定义,则定义
#define _XXX_H_

   文件内容

#endif
***************************************

   位运算:           逻辑运算符

按位与运算    &       逻辑与 &&
按位或运算    |       逻辑或 ||     
按位求反运算  ~       非运算 !
按位异或运算  ^
左移运算     a<<4
右移运算     b>>3
********************************
输出二进制数据:
#include<stdio.h>
#include<stdlib.h>

void bindisp(int a)
{
 int i=32;
 while(i--)
 {
  if(a&(1<<i))
   printf("1");
  else
   printf("0");
  if(i%8==0)
   printf(" ");
 }
 putchar(10);
}
int main()
{
 setvbuf(stdout,NULL,_IONBF,0);
 bindisp(3);
 bindisp(11);
 bindisp(3&11);
 return 0;
}

运行结果:
00000000 00000000 00000000 00000011 //3
00000000 00000000 00000000 00001011 //11
00000000 00000000 00000000 00000011 //3&11

*******************************************
按位与:
格式:x&y
规则:对应位均为1时才为1,否则为0
如: 3&11     0011
             &1011
              ——
              0011    =3(十进制)
故 3&11=3
特点:和1与运算都为本身,和0与运算则为0
通常用法:将某些位清零。如与255(二进制为00000000 11111111)按位与,即把数据的低八位保留,
其余高位全清零
*******************************************
按位或:
格式: x|y
规则:对应位均为0时才为0,否则为1
如: 3|9     0011
            |1001
            ------
             1011    =11(十进制)
故 3|9=11
特点:和0或运算,不变;和1或,置1
通常用法:将某些位置1 。如:将0x50(二进制为0101 0000)与0x0f(0000 1111)或运算,
          结果为0x5f(0101 1111)
*******************************************
按位取反:
格式: ~x
规则:1取反变为0,0取反变为1
如: ~3     ~0011=1100
*******************************************
异或:
格式:x^y
规则:相异者(即0,1)或,为1;相同者为0
如:  3^9       0011
               ^1001
              -------
                1010      =10(十进制)
故 3^9=10
特点:与全1异或,相当于取反;与全0异或,不变
如:将低4位取反,高4位保持不变,与0x0f异或
********************************************
左移:
格式:x<<n
规则:将x左移n位
特点:左移一位相当于乘2
********************************************
右移:
格式:x>>n
规则:将x右移n位
特点:左移一位相当于除2
********************************************
综合题:
1.将一int型数据8~11位(0位起),清零
 int val = 0xffff;   //1111 1111 1111 1111
 val = val & (~(0xf<<8));//和1111 0000 1111 1111做与运算
 bindisp(val);       //结果为1111 0000 1111 1111
2.将一int型数据8~11位(0位起),置1
 int val = 0x0000;
 val = val | (0xf<<8);
 bindisp(val);
3.将一int型数据8~11位(0位起),取出
法一:  int val = 0xf5ff;
 val &= (0xf<<8);
 val >>= 8;  //val = val>>8;
 bindisp(val);
 printf("%d",val);
 结果为:00000000 00000000 00000000 00000101
  5
法二:  int val = 0xf5ff;
 val >>= 8;  //val = val>>8;
 val &=0xf;
 bindisp(val);
 printf("%d",val);
 结果为:00000000 00000000 00000000 00000101
  5
*****************************************
位域(位段):
含义:位域是以位为单位定义长度的结构体类型中德成员
位段的构成:
例如:声明一个位段结构,并定义一个变量data
 struct pack
 {
     unsigned a:1;
     unsigned b:2;
     unsigned c:3;
 }data;
-----------------------------------------
#include<stdio.h>
#include<stdlib.h>

struct pack
{
 unsigned int a:1;
 unsigned int b:2;
 unsigned int c:3;
};
int main()
{
 struct pack a={1,3,7};
 printf("%d\n",a.a);
 printf("%d\n",a.b);
 printf("%d\n",a.c);
 return 0;
}
运行结果:
1
3
7
----------------------------------------
#include<stdio.h>
#include<stdlib.h>


int main()
{
 struct pack
 {
  unsigned  a:1;
  unsigned  b:2;
  unsigned  c:3;
 }bit,*pbit;
 bit.a=1;
 bit.b=7;
 bit.c=15;
 printf("%d,%d,%d\n",bit.a,bit.b,bit.c);

 pbit=&bit;
 pbit->a=0;
 pbit->b&=3;
 pbit->c|=1;
 printf("%d,%d,%d\n",pbit->a,pbit->b,pbit->c);
 return 0;
}
运行结果:
1,3,7
0,3,7
********************************************
函数指针:
程序举例:
#include<stdio.h>
#include<stdlib.h>
int max(int a,int b)
{
 return a>b?a:b;
}

int main(void)
{

 int (*p)(int,int);  //注意*p要加括号
 int a = 5;
 int b = 6;
 p = &max;    //p指向函数max
 printf("%d\n",(*p)(a,b));

 return 0;
}
运行结果:
6
--------------------------------------------

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char *func(char *p1,char *p2)
{
 int i=0;
 i=strcmp(p1,p2);
 if(i==0)
  return p1;
 else
  return p2;
}

int main()
{
 char* (*pf) (char*,char*);//函数指针
 pf=&func;
 printf("%s",(*pf)("aa","bb"));
 return 0;
}
运行结果:
bb
********************************************
const--只读
如const int a;
  a = 12;  //报错,a为只读
一旦定义,其值不可改变,所以必须要赋初值

int main()
{
 int a=12;
 int b =34;
// int const *p = &a;
// *p = 12;
// p = &b;
// int * const q = &a;
// *q = 12;
// q = &b;
 int const *const q =&a;
 q = &b;
 *q = 12;
 return 0;
}

******************************************************

数组及动态申请
数组三要素:类型,长度,首地址
动态申请的空间在堆内
程序举例:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
 char *p;
 p = malloc(sizeof(char)*10);//动态申请了10个字符空间
 strcpy(p,"china\n");
 printf("%s",p);
 free(p);   //用完要释放
 return 0;
}
Malloc申请的空间处于受保护状态,若不及时释放,其他程序无法使用此段空间。
********************************
typedef给变量起别名
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#if 0
typedef int GS;   //typerename
typedef int INT32;
typedef short INT16;
typedef char INT8;
#endif

#define INT32 int
#define INT16 short
#define INT8  char

int main()
{
 INT32 a;
 INT16 b;
 INT8  c;
 printf("%d\n",sizeof(a));
 printf("%d\n",sizeof(b));
 printf("%d\n",sizeof(c));
 return 0;
}
--------------------------------------
typedef与宏定义的区别:

typedef int INT32;
#define INT32 int
1.首先,书写顺序不同
2.typedef后面必须有分号;
3.执行的时间段不同,宏定义在预处理的时候执行,而typedef和一般C语句一样
4.typedef相当于新定义了一个类型,若typedef char* INT8p;则执行INT8p p,q;相当于char *P,*q;
  p和q都是char*型
  而宏定义只是单纯的文本替换,如#define INT8p  char*,则执行INT8p p,q; 时,只是把INT8p替换为char*,也就是char *P,q;
  p为指针变量,q为字符变量
---------------------------------------
typedef举例:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef char INT8;
typedef char* INT8p;

int main()
{
 INT8  a;
 INT8p p,q;   //等价于char *p,*q;
 printf("%d\n",sizeof(a));
 printf("%d\n",sizeof(p));
 printf("%d\n",sizeof(q));
 return 0;
}
运行结果:
1
4
4
-----------------------------------------
宏定义举例:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define INT8  char
#define INT8p  char*

int main()
{
 INT8  a;
 INT8p p,q;    //等价于char *p,q;
 printf("%d\n",sizeof(a));
 printf("%d\n",sizeof(p));
 printf("%d\n",sizeof(q));
 return 0;
}
运行结果:
1
4
1
------------------------------------------
typedef定义技巧:
1.若想定义形如char a,*p;
只需在前面加上typedef,在将a改为别名INT8,将p改为INT8p
即写为:typedef char INT8,*INT8p;
2.定义数组
typedef int T[10];
引用时用:T m;   //相当于int m[10]
3.结构体
typedef struct Stu

 

*******************************************
enum(属于构造类型)
用enum关键字说明枚举常量有三点好处:
1.用enum关键字说明的常量由编译程序自动生成,程序员不需要手工对常量一一赋值
2.用enum关键字说明常量使程序更清晰易读,因为在定义enum常量的同时也定义了一个枚举类型标示符
3.在调试程序时通常可以检查枚举常量,这一点非常有用,不用手工检查头文件中的常量值
enum与define相比,有以下好处:
1.
2.
3.

程序举例:
#include<stdio.h>
enum color {red,yellow,blue=7,white,black};

int main()
{
 enum color pri;
 for(pri=red;pri<=black;pri++)
 {
  switch(pri)
  {
  case red: printf("red->%d\n",red);
  break;
  case yellow: printf("yellow->%d\n",yellow);
  break;
  case blue: printf("blue->%d\n",blue);
  break;
  case white: printf("white->%d\n",white);
  break;
  case black: printf("red->%d\n",black);
  break;
  default:;
  }
 }
 return 0;
}
运行结果:
red->0
yellow->1
blue->7
white->8
red->9
********************************************
static
static修饰的函数只适用于它所定义的文件中
---------------------
文件static.c如下
---------------------
#include<stdio.h>
void display();
void haha();
int main()
{
        display();
        haha();  //这里调用被拒绝
        return 0;
}
----------------------
文件fun.c如下
----------------------
#include<stdio.h>
static void haha();
void display()
{
        haha();
}

static void haha()
{
        printf("haha\n");
}
-----------------------
由于在static.c的main函数中调用了display()和haha(),而函数haha()被static修饰,所以,当在main函数中调用haha时,系统会提示undefined reference to `haha',而main函数中调用的display()没有被static修饰,可以被调用,而且display()又调用了haha(),此时由于函数display()和函数haha()在同一文件内,故可以成功调用,最终main函数中调用的两个函数只有display()调用成功,直接调用haha()不成功
******************************************
各种变量在内存中的位置
#include<stdio.h>
int a;                                   //data segment,bss aera, initialized with 0 by system
static int a;                            //data segment,bss aera, initialized with 0 by system

int c[10]={1,2,3,4};                     //data segment,initialize rw aera
char *p = "china";                       //p data initialize,rw
                                         //"china"data initialize read-only
int main()
{
 int i,j;                         //stack
 static int m;                    //data segment,bss aera, initialized with 0 by system
 static int n = 6;                //data initialize rw
 
 int x[5] = {1,2,3,4,5};          //x[] stack 
                                  //{1,2,3,4,5} data initialize read-only
 char y[] = "i love xxx";         //y[] stack
                                  //"i love xxx" data initialize read-only
 char *q = "who i am";            //q stack
                                         //"who i am" data initialize read-only
 char *k = malloc(sizeof(int)*10);//k stack
                    //malloc heap
 return 0;
}
*******************************************
******
*排序*
******
-------------------------------------------
1.选择排序法

基本思想:
每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法。

代码举例:
#include<stdio.h>
void SelectSort(int *a,int N);

int main()
{
 int a[5]={5,4,3,2,1};
 int i;
 for(i=0;i<5;i++)
 {
  printf("%d",a[i]);
 }
 printf("\n");
 SelectSort(a,5);
 for(i=0;i<5;i++)
 {
  printf("%d",a[i]);
 }
 return 0;
}
void SelectSort(int *a,int N)
{
 int i,j,tmp;
 for(i=0;i<N-1;i++)   //控制比较趟数
 {
  for(j=i+1;j<N;j++)
  {
   if(a[i]>a[j])
   {
    tmp=a[i];
    a[i]=a[j];
    a[j]=tmp;
   }
  }
 }
}

运行结果:
54321
12345
--------------------------------------------
2.冒泡排序:

基本思想:
冒泡排序是经过n-1趟子排序完成的,第i趟子排序从第1个数至第n-i个数,若第i个数比后一个数大(则升序,小则降序)则交换两数

代码举例:
#include<stdio.h>
void PopSort(int *p,int N);

int main()
{
 int a[5]={5,4,3,2,1};
 int i;
 for(i=0;i<5;i++)
 {
  printf("%d",a[i]);
 }
 printf("\n");
 PopSort(a,5);
 for(i=0;i<5;i++)
 {
  printf("%d",a[i]);
 }
 return 0;
}

void PopSort(int *p,int N)
{
 int i,j,tmp;
 for(i=0;i<N-1;i++)
 {
  for(j=0;j<N-i-1;j++)
  {
   if(p[j]>p[j+1])
   {
    tmp=p[j];
    p[j]=p[j+1];
    p[j+1]=tmp;
   }
  }
 }

}
运行结果:
54321
12345
---------------------------------------------------
3.shell排序:

基本思想:
先取一个正整数d1<n,把所有序号相隔d1的数组元素放一组,组内进行直接插入排序;然后取d2<d1,重复上述分组和排序操作;直至di=1,即所有记录放进一个组中排序为止

代码举例:
#include<stdio.h>
void ShellSort(int *p,int N);

int main()
{
 int a[5]={5,4,3,2,1};
 int i;
 for(i=0;i<5;i++)
 {
  printf("%d",a[i]);
 }
 printf("\n");
 ShellSort(a,5);
 for(i=0;i<5;i++)
 {
  printf("%d",a[i]);
 }
 return 0;
}

void ShellSort(int *p,int N)
{
 int i,tmp,d=N;
 while(d>1)
 {
  d=(d+1)/2;
  for(i=0;i<N-d;i++)
  {
   if(p[i]>p[i+d])
   {
    tmp   = p[i];
    p[i]  = p[i+d];
    p[i+d]= tmp;
   }
  }
 }
}
运行结果:
54321
12345
-------------------------------------------------
4.插入排序法

基本思想:
    输入一个元素,检查数组列表中的每个元素,将其插入到一个已经排好序的数列中的适当位置,使数列依然有序,当最后一个元素放入合适位置时,该数组排序完毕。
例:输入一个数,插入一个各元素已经按照升序排列的数组中,插入后使数组中元素仍然是按照升序排列的。思想:把欲插入的数与数组中各数逐个比较, 当找到第一个比插入数大的元素i时,该元素之前即为插入位置。然后从数组最后一个元素开始到该元素为止,逐个后移一个单元。最后把插入数赋予元素a[i]即可。如果被插入数比所有的元素值都小则插入最前位置。

代码举例:
#include<stdio.h>
void InsertSort(int *p,int N);

int main()
{
 int a[5]={5,4,3,2,1};
 int i;
 for(i=0;i<5;i++)
 {
  printf("%d",a[i]);
 }
 printf("\n");
 InsertSort(a,5);
 for(i=0;i<5;i++)
 {
  printf("%d",a[i]);
 }
 return 0;
}

void InsertSort(int *p,int N)
{
 int i,tmp,j;
 for(i=1;i<N;i++)
 {
  tmp = p[i];
  for(j=i;j>0;j--)
  {
   if(tmp>p[j-1])
   {
    break;
   }
   else
   {
    p[j]=p[j-1];
   }
  }
  p[j]=tmp;
 }
}
运行结果:
54321
12345
---------------------------------------------
5.快速排序法

基本思想:
快速排序(Quicksort)是对冒泡排序的一种改进。由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
一趟快速排序的算法是:   
1)设置两个变量I、J,排序开始的时候:I=0,J=N-1;   
2)以第一个数组元素作为关键数据,赋值给key,即 key=A[0];   
3)从J开始向前搜索,即由后开始向前搜索(J=J-1即J--),找到第一个小于key的值A[j],A[j]与A[i]交换; 4)从I开始向后搜索,即由前开始向后搜索(I=I+1即I++),找到第一个大于key的A[i],A[i]与A[j]交换; 5)重复第3、4、5步,直到 I=J; (3,4步是在程序中没找到时候j=j-1,i=i+1,直至找到为止。找到并交换的时候i, j指针位置不变。另外当i=j这过程一定正好是i+或j-完成的最后另循环结束。)

举例:
初始状态:
  位置: a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] tmp
  数值: 7 3 1 8 12 10 6 4
光标位置: low       high
-----------------------------------------------------------------------------------
第一趟排序的具体过程:
1)将7拿出来(先放在tmp中),a[0]空;
2)将光标low指向的值4与7比较,4小,将4赋给a[0],a[7]空,则光标low移到a[1];
  位置: a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] tmp
  数值: 4 3 1 8 12 10 6  7
光标位置:  low      high 
3)3和7比,3小,low移到a[2];
  位置: a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] tmp
  数值: 4 3 1 8 12 10 6  7
光标位置:   low     high  
4)1和7比,1小,low移到a[3];
  位置: a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] tmp
  数值: 4 3 1 8 12 10 6  7
光标位置:    low    high 
5)p[low]即8和7比,8大,将8赋给p[high]即a[7],a[3]空;
  位置: a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] tmp
  数值: 4 3 1  12 10 6 8 7
光标位置:    low    high 
6)p[low]空,将p[high]即a[7]的内容8与7比较,8大,故high移到a[6];
  位置: a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] tmp
  数值: 4 3 1  12 10 6 8 7
光标位置:    low   high 
7)将p[high]内容6于7比,6小,故把6赋给p[low]即a[3],a[6]空;
  位置: a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] tmp
  数值: 4 3 1 6 12 10  8 7
光标位置:    low   high 
8)p[high]空,则比较p[low]和7,7大,则low移到a[4];
  位置: a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] tmp
  数值: 4 3 1 6 12 10  8 7
光标位置:     low  high 
9)p[low]和7比,p[low]大,则将p[low]赋给a[6],a[4]空;
  位置: a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] tmp
  数值: 4 3 1 6  10 12 8 7
光标位置:     low  high 
10)p[low]空,则比较p[high]和7,7小,则将high移到a[5];
  位置: a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] tmp
  数值: 4 3 1 6  10 12 8 7
光标位置:     low high
11)将p[high]与7比较,7小,则将high移到a[4];
  位置: a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] tmp
  数值: 4 3 1 6  10 12 8 7
光标位置:     low(high)
12)此时,low和high同时指向a[4],则把7赋给a[4].
13)最后,第一趟排序结束
  位置: a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] tmp
  数值: 4 3 1 6 7 10 12 8 7
光标位置:     low(high)
第一趟排序效果:7前面的都比7小,7后面的都比7大;
在一直这样继续下去,直至排序结束
------------------------------------------------------------------------------------
代码举例:

#include<stdio.h>

int FindPos(int *p,int low,int high)
{
 int tmp = p[low];
 while(low<high)
 {
  while(p[high]>tmp && (high>low))
   high--;
  p[low] = p[high];
  while(p[low]<tmp && (high>low))
   low++;
  p[high] = p[low];
 }
 p[low] = tmp;
 return high;
}

void QuickSort(int *p,int low,int high)
{
 int pos;
 if(low<high)
 {
  pos = FindPos(p,low,high);
  QuickSort(p,low,pos-1);
  QuickSort(p,low+1,high);
 }
}
int main()
{
 int a[5]={5,12,3,9,1};
 int i;
 for(i=0;i<5;i++)
 {
  printf("%d  ",a[i]);
 }
 printf("\n");
 QuickSort(a,0,4);
 for(i=0;i<5;i++)
 {
  printf("%d  ",a[i]);
 }
 return 0;
}

运行结果:
5  12  3  9  1 
1  3  5  9  12 
------------------------------------------------

链表:
链表中的最基本单元称为节点,包括两部分信息:存放数据元素信息的称为数据域,存放其后继地址的成为指针域。
结构:
(以4个节点为例)
-----------------------------------------------------------------------------------
节点:头指针p--> a(头节点)  b(首节点) c  d(尾节点)
data:  1(通常不放数据)  2  3  4
next:  b首地址   c首地址  d首地址  NULL
-----------------------------------------------------------------------------------
插入新节点示意图:
-----------------
初始状态:
 head-->【 | NULL】 cur-->【5|】
(1) cur-->next = head-->next;
 head-->【 | 】  cur-->【5|NULL】
(2) head-->next = cur;
 head-->【 | 】-->【5|NULL】
------------------------------------------------------
初始状态:

 head-->【 | 】-->【5|NULL】 cur-->【4|】

(1) cur-->next = head-->next;

 head-->【 | 】-->【5|】  cur-->【4|NULL】

(2) head-->next = cur;
 
 head-->【 | 】-->【5|】 -->【4|NULL】
------------------------------------------------------
记住两句话:
(1)让新来的结点先有所指向
(2)箭头指向谁就是存放着人家的地址
------------------------------------------------------
静态链表举例:
#include <stdio.h>
struct node
{
 int data;
 struct node *next;
};

int main()
{
 struct node a;
 struct node b;
 struct node c;
 struct node d;
 a.data = 1;
 b.data = 2;
 c.data = 3;
 d.data = 4;

 a.next = &b;
 b.next = &c;
 c.next = &d;
 d.next = NULL;  //不能忘记
 struct node *p;
 p = &a;
 while(p!=NULL)
 {
  printf("%d ",p->data);
  p = p->next;
 }
 return 0;
}
运行结果:
1 2 3 4
-----------------------------------------
上面程序改进:
#include <stdio.h>
typedef struct node      //改进的地方
{
 int data;
 struct node *next;
}Node,*PNode;            //改进的地方

int main()
{
 Node a;          //改进应用
 Node b;
 Node c;
 Node d;
 a.data = 1;
 b.data = 2;
 c.data = 3;
 d.data = 4;

 a.next = &b;
 b.next = &c;
 c.next = &d;
 d.next = NULL;
 PNode p;         //改进应用
 p = &a;
 while(p!=NULL)
 {
  printf("%d ",p->data);
  p = p->next;
 }
 return 0;
}
运行结果:
1 2 3 4
----------------------------------
动态链表
动态链表的创建,打印,求长度,插入,数据搜索
程序举例:
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
 int data;
 struct node *next;
}Node,*PNode;

PNode CreatLink()       //头插法
{
 PNode head,cur;     //定义头指针和要插入节点的指针
 head = (PNode)malloc(sizeof(Node));   //malloc()返回void*型指针
 head->next = NULL;//将头节点的指针域置为空
 int tmp;
 printf("Please input node:");
 scanf("%d",&tmp);
 while(tmp)
 {
  cur = (PNode)malloc(sizeof(Node));//申请空间
  cur->data = tmp;     //给数据域填充数值
  cur->next = head->next;//将新插入节点的指针指向要插入位置的下一个节点
  head->next = cur;  //将要插入位置的上一节点的指针指向要插入节点
  scanf("%d",&tmp);
 }
 return head;
}
void PrintLink(PNode head)
{
 head = head->next;     //将指针指向首节点
 while(head != NULL)
 {
  printf("%d ",head->data);//打印节点数据
  head = head->next; //将指针指向下一节点
 }
 printf("\n");
}
int LenLink(PNode head)  //求链表的长度
{
 int len = 0;
 head = head->next;   //将指针指向首节点
 while(head != NULL)  //若指针不为NULL,则len++,并将指针指向下一节点
 {
  len++;
  head = head->next;
 }
 return len;    //返回len
}
void InsertLink(PNode head)
{
 int tmp;
 PNode cur;
 printf("Please input new node:\n");
 scanf("%d",&tmp);
 cur = (PNode)malloc(sizeof(Node));
 cur->data = tmp;
 cur->next = head->next;
 head->next = cur;

}
PNode SearchLink(PNode head,int find)
{
 head = head->next;
 while(head != NULL)
 {
  if(head->data == find)
  {
   return head;   //返回调用此函数的地方
  }
  head = head->next;
 }
 return NULL;
}
int main()
{
 int len,find;
 PNode head,pfind;
 head = CreatLink();
 PrintLink(head); //调用PrintLink()函数,打印链表数据
 len = LenLink(head);
 printf("The length of Link is %d\n",len);
 InsertLink(head);//插入链表
 PrintLink(head);
 printf("Please input find:\n");
 scanf("%d",&find);
 SearchLink(head,find);
 pfind = SearchLink(head,find);
 if(pfind == NULL)
 {
  printf("your find is none\n");
 }
 else
 {
  printf("your find is %d\n",pfind->data);
 }
 return 0;
}


运行结果:
Please input node:1 2 3 4 5 0
5 4 3 2 1
The length of Link is 5
Please input new node:
99
99 5 4 3 2 1
Please input find:
2
your find is 2
-----------------------------------

结点的删除:
(1)使要删除的节点脱链
q->next = p->next;
(2)释放节点资源
free(p);
p = NULL;
节点删除函数:
void DeleteLink(PNode head,PNode pfind)
{
 while(head->next != pfind && head != NULL)
  head = head->next;
 head->next = pfind->next;
 free(pfind);
}
---------------------------------------------------
排序:(冒泡排序法)
(1)交换数据域:
图形示意:

 

函数如下:
void PopSortLink(PNode head,int len)
{
 int i,j,tmp;
 PNode p,q;
 if(head->next == NULL || head->next->next == NULL)//除了头节点,至少还要有两个节点
  return ;
 for(i=0; i<len-1; i++)
 {
  p = head->next;  //冒泡每次从头开始
  q = p->next;
  for(j=0; j<len-i-1; j++)
  {
   if(p->data>q->data)
   {
    tmp = p->data;
    p->data = q->data;
    q->data = tmp;
   }
   p = p->next;
   q = q->next;
  }
 }
}
(2)交换指针域:
图形示意:

 

void PopSortLink(PNode head,int len)
{
 int i,j;
 PNode p,q,list,tmp;
 if(head->next == NULL || head->next->next == NULL)
  return ;
 for(i=0; i<len-1; i++)
 {
  list = head;   //保存头指针
  p = list->next;//确定初始p,q指向
  q = p->next;
  for(j=0; j<len-1-i; j++)
  {
   if(p->data > q->data)
   {
    list->next = p->next; //交换p->next,q->next指向
    p->next = q->next;
    q->next = p;

    tmp = p;     //交换指针p和q
    p = q;
    q = tmp;
   }
   list = list->next;//重新确定p,q指向,即从头开始,以便下一趟比较
   p = p->next;
   q = q->next;
  }
 }
}
-------------------------------------------
将单链表倒置:
图形示意:

 


void ReverseLink(PNode head)
{
 PNode p,q;
 p = head->next;
 head->next = NULL;
 q = p;
 while(q != NULL)
 {
  q = q->next;
  p->next = head->next;
  head->next = p;
  p = q;
 }
}
---------------------------------------------
链表总程序代码:
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
 int data;
 struct node *next;
}Node,*PNode;

PNode CreatLink()
{
 PNode head,cur;     //定义头指针和要插入节点的指针
 head = (PNode)malloc(sizeof(Node));   //malloc()返回void*型指针
 head->next = NULL;//将头节点的指针域置为空
 int tmp;
 printf("Please input node:");
 scanf("%d",&tmp);
 while(tmp)
 {
  cur = (PNode)malloc(sizeof(Node));//申请空间
  cur->data = tmp;     //给数据域填充数值
  cur->next = head->next;//将新插入节点的指针指向要插入位置的下一个节点
  head->next = cur;  //将要插入位置的上一节点的指针指向要插入节点
  scanf("%d",&tmp);
 }
 return head;
}
void PrintLink(PNode head)
{
 head = head->next;     //将指针指向首节点
 while(head != NULL)
 {
  printf("%d ",head->data);//打印节点数据
  head = head->next; //将指针指向下一节点
 }
 printf("\n");
}
int LenLink(PNode head)  //求链表的长度
{
 int len = 0;
 head = head->next;   //将指针指向首节点
 while(head != NULL)  //若指针不为NULL,则len++,并将指针指向下一节点
 {
  len++;
  head = head->next;
 }
 return len;    //返回len
}
void InsertLink(PNode head)
{
 int tmp;
 PNode cur;
 printf("Please input new node:\n");
 scanf("%d",&tmp);
 cur = (PNode)malloc(sizeof(Node));
 cur->data = tmp;
 cur->next = head->next;
 head->next = cur;

}
PNode SearchLink(PNode head,int find)
{
 head = head->next;
 while(head != NULL)
 {
  if(head->data == find)
  {
   return head;   //返回调用此函数的地方
  }
  head = head->next;
 }
 return NULL;
}
void DeleteLink(PNode head,PNode pfind)
{
 while(head->next != pfind && head != NULL)
  head = head->next;
 head->next = pfind->next;
 free(pfind);
}
#if 0
void PopSortLink(PNode head,int len)
{
 int i,j,tmp;
 PNode p,q;
 if(head->next == NULL || head->next->next == NULL)
  return ;
 for(i=0; i<len-1; i++)
 {
  p = head->next;  //冒泡每次从头开始
  q = p->next;
  for(j=0; j<len-i-1; j++)
  {
   if(p->data>q->data)
   {
    tmp = p->data;
    p->data = q->data;
    q->data = tmp;
   }
   p = p->next;
   q = q->next;
  }
 }
}
#endif
void PopSortLink(PNode head,int len)
{
 int i,j;
 PNode p,q,list,tmp;
 if(head->next == NULL || head->next->next == NULL)
  return ;
 for(i=0; i<len-1; i++)
 {
  list = head;   //保存头指针
  p = list->next;//确定初始p,q指向
  q = p->next;
  for(j=0; j<len-1-i; j++)
  {
   if(p->data > q->data)
   {
    list->next = p->next; //交换p->next,q->next指向
    p->next = q->next;
    q->next = p;

    tmp = p;     //交换指针p和q
    p = q;
    q = tmp;
   }
   list = list->next;//重新确定p,q指向,即从头开始,以便下一趟比较
   p = p->next;
   q = q->next;
  }
 }
}
void ReverseLink(PNode head)
{
 PNode p,q;
 p = head->next;  //p指向第一个数据节点
 head->next = NULL; //将原链表置为空表
 q = p;
 while(q != NULL)
 {
  q = q->next;
  p->next = head->next;
  head->next = p;
  p = q;
 }
}
void DestroyLink(PNode head)
{
 PNode p = head;
 while(p != NULL)
 {
  head = head->next;
  free(p);
  p = head;
 }
}
int main()
{
 int len,find;
 PNode head,pfind;
 head = CreatLink();
 PrintLink(head); //调用PrintLink()函数,打印链表数据
 len = LenLink(head);
 printf("The length of Link is %d\n",len);
 InsertLink(head);//插入链表
 PrintLink(head);
 printf("Please input find:\n");
 scanf("%d",&find);
 SearchLink(head,find);
 pfind = SearchLink(head,find);
 if(pfind == NULL)
 {
  printf("your find is none\n");
 }
 else
 {
  printf("your find is %d\n",pfind->data);
  DeleteLink(head,pfind);
  printf("after delete:\n");
  PrintLink(head);
 }
 len = LenLink(head);
 printf("After sort\n");
 PopSortLink(head,len);
 PrintLink(head);
 ReverseLink(head);
 printf("After reverse\n");
 PrintLink(head);
 DestroyLink(head);
 printf("Link has been destroyed!\n");
 return 0;
}
运行结果:
Please input node:1 2 3 4 5 0
5 4 3 2 1
The length of Link is 5
Please input new node:
33
33 5 4 3 2 1
Please input find:
4
your find is 4
after delete:
33 5 3 2 1
After sort
1 2 3 5 33
After reverse
33 5 3 2 1
Link has been destroyed!
---------------------------------------------------
双向链表:
创建,打印,插入,删除,排序,销毁

#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
 int data;
 struct node *pre;
 struct node *next;
}Node,*PNode;

PNode CreatLink()
{
 int input;
 PNode head,cur,list;
 head = (PNode)malloc(sizeof(Node));
 head->pre = head->next = NULL;
 list = head;
 printf("Please input new node:\n");
 scanf("%d",&input);
 while(input)
 {
  cur = (PNode)malloc(sizeof(Node));
  cur->data = input;
  list->next = cur;
  cur->pre = list;

  list = cur;
  scanf("%d",&input);
 }
 list->next = head;
 head->pre = list;

 return head;
}

void PrintLink(PNode head)//正序打印
{
 PNode list = head;
 list = list->next;
 while(list != head)
 {
  printf("%d ",list->data);
  list = list->next;
 }
 puts("");
}
#if 0
void PrintLink(PNode head)//倒序打印
{
 PNode list = head;
 list = list->pre;
 while(list != head)
 {
  printf("%d ",list->data);
  list = list->pre;
 }
 puts("");
}
#endif
int LenLink(PNode head)
{
 PNode list = head;
 int len = 0;
 list = list->next;
 while(list != head)
 {
  len++;
  list = list->next;
 }
 return len;
}
void DestroyLink(PNode head)
{
 head->pre->next = NULL;
 PNode list = head;
 while(list != head)
 {
  head = list->next;
  free(list);
  list = head;
 }
}
void InsertLink(PNode head,int input)
{
 PNode cur;
 cur = (PNode)malloc(sizeof(PNode));
 cur->data = input;

 cur->next = head->next;
 cur->pre = head;
 head->next = cur;
 cur->next->pre = cur;
}
PNode SearchLink(PNode head,int find)
{
 PNode list = head;
 list = list->next;
 while(list != head)
 {
  if(list->data == find)
   return list;
  list = list->next;
 }
 return NULL;
}
void DeleteLink(PNode pfind)
{
 pfind->pre->next = pfind->next;
 pfind->next->pre = pfind->pre;
 free(pfind);
 pfind = NULL;
}
void PopsortLink(PNode head,int len)
{
 int i,j;
 PNode p,q,tmp;
 for(i=0; i<len-1; i++)
 {
  p = head->next;
  q = p->next;
  for(j=0; j<len-1-i; j++)
  {
   if(p->data > q->data)
   {
    p->pre->next = q;
    q->pre = p->pre;
    p->pre = q;
    p->next = q->next;
    q->next = p;
    p->next->pre = p;

    tmp = p;
    p = q;
    q = tmp;
   }
   p = p->next;
   q = q->next;
  }
 }
}
int main()
{
 PNode head,pfind;
 int len,input,find;
 head = CreatLink();
 PrintLink(head);
 len = LenLink(head);
 printf("The len of List is %d\n",len);
 printf("Please input new node:\n");
 scanf("%d",&input);
 InsertLink(head,input);
 printf("After insert:\n");
 PrintLink(head);
 printf("Please input your find:\n");
 scanf("%d",&find);
 pfind = SearchLink(head,find);
  if(pfind == NULL)
  {
   printf("find none\n");
  }
  else
  {
   printf("Your find is %d\n",pfind->data);
   DeleteLink(pfind);
   printf("After delete:\n");
   PrintLink(head);
  }
 len = LenLink(head);
 PopsortLink(head,len);
 printf("After sort:\n");
 PrintLink(head);
 DestroyLink(head);
 return 0;
}
运行结果:
Please input new node:
1 2 3 4 5 6 0
1 2 3 4 5 6
The len of List is 6
Please input new node:
99
After insert:
99 1 2 3 4 5 6
Please input your find:
5
Your find is 5
After delete:
99 1 2 3 4 6
After sort:
1 2 3 4 6 99

******************************

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
 char name[50];
 char inputname[50];
 char passwd[50];
 char inputpasswd[50];
 char tmp[50];
 FILE *fp;
 fp = fopen("data","r");
 if(fp == NULL)
 {
  printf("fopen error");
 }
 fgets(tmp,50,fp);
 while(!feof(fp))
 {
  if(*tmp == '#')
  {
   fgets(tmp,50,fp);
   continue;
  }
  else if(*tmp == '[')
  {
   switch(*(tmp+1))
   {
      case 'n':
     fgets(tmp,50,fp);
     strcpy(name,tmp);
     break;
      case 'p':
     fgets(tmp,50,fp);
     strcpy(passwd,tmp);
     break;
   }
   fgets(tmp,50,fp);
  }
 }
 fclose(fp);
 name[strlen(name)-1] = '\0';
 passwd[strlen(passwd)-1] = '\0';


 printf("please input name:");
 scanf("%s",inputname);
 printf("please input passwd:");
 scanf("%s",inputpasswd);
 while(1)
 {
  if(strcmp(name,inputname)==0&& strcmp(passwd,inputpasswd)==0)
  {
   break;
  }
  printf("please input name:");
  scanf("%s",inputname);
  printf("please input passwd:");
  scanf("%s",inputpasswd);
 }

 printf("Welcome !!!\n");
 return 0;
}


 

 

《C语言高级编程与实例剖析》随书源码 第1章 内存管理 1. 1.1 预备知识 1 1.1.1 PC存储器结构 1 1.1.2 CPU地址线宽度 3 1.1.3 内存管理方式 5 1.1.4 内存编译模式 6 1.1.5 堆概念和结构 9 1.1.6 堆管理函数 10 1.2 高速分配内存技巧 15 1.2.1 类型声明及变量定义 15 1.2.2 函数剖析 16 1.2.3 归纳总结 18 1.3 学生信息数据库实例 18 1.3.1 需求分析 19 1.3.2 源代码解析 19 1.3.3 运行结果 23 1.3.4 归纳总结 23 1.4 巧用内存管理创建通信录 25 1.4.1 需求分析 25 1.4.2 源代码解析 25 .1.4.3 程序运行结果 31 1.4.4 归纳总结 32 1.5 小结 32 第2章 文本屏幕界面设计 33 2.1 文本方式的控制 33 2.1.1 文本方式控制函数 33 2.1.2 文本方式颜色控制函数 34 2.1.3 字符显示亮度控制函数 36 2.1.4 实例解析 36 2.2 窗口设置和文本输出函数 38 2.2.1 窗口设置函数 38 2.2.2 控制台文本输出函数 38 2.2.3 实例解析 38 2.3 清屏和光标操作函数 40 2.3.1 清屏函数 40 2.3.2 光标操作函数 41 2.3.3 实例解析 41 2.4 屏幕文本移动与存取函数 43 2.4.1 屏幕文本移动函数 43 2.4.2 屏幕文本存取函数 43 2.4.3 实例解析 44 2.5 状态查询函数 46 2.5.1 状态查询函数 46 2.5.2 实例解析 47 2.6 创建弹出式菜单实例 48 2.6.1 需求分析 48 2.6.2 源代码解析 49 2.6.3 运行结果 55 2.6.4 归纳总结 55 2.7 文本方式下创建下拉式菜单 56 2.7.1 需求分析 56 2.7.2 源代码解析 56 2.7.3 运行结果 61 2.7.4 归纳总结 62 2.8 综合应用 62 2.8.1 需求分析 62 2.8.2 源代码解析 63 2.8.3 运行结果 66 2.8.4 归纳总结 66 2.9 小结 67 第3章 文件高级操作 68 3.1 文件的基本概念 68 3.2 标准文件的输入输出操作 68 3.2.1 标准文件输入输出 70 3.2.2 标准文件打开函数fopen() 71 3.2.3 标准文件关闭函数fclose() 74 3.2.4 标准文件的读写 75 3.2.5 文件的随机读写函数 78 3.2.6 实例解析 82 3.3 文件的加密与解密 83 3.3.1 移位加密法 83 3.3.2 伪随机数加密法 84 3.3.3 命令加密法 86 3.3.4 逐字节异或加密法 88 3.4 文件分割程序 91 3.4.1 操作方法 91 3.4.2 源代码解析 91 3.4.3 运行结果 94 3.4.4 归纳总结 94 3.5 文件合并程序 94 3.5.1 操作方法 94 3.5.2 源代码解析 95 3.5.3 运行结果 97 3.5.4 归纳总结 97 3.6 小结 97 第4章 图形图像 98 4.1 图形显示基本概念 98 4.1.1 图形显示的坐标 98 4.1.2 像素 99 4.2 图形函数 99 4.2.1 图形系统的初始化 99 4.2.2 恢复显示方式和清屏函数 102 4.2.3 基本图形函数 102 4.3 颜色控制函数 107 4.3.1 颜色设置函数 108 4.3.2 调色板颜色设置 110 4.4 画线的线型函数 114 4.4.1 设定线型函数 115 4.4.2 得到当前画线信息的函数 117 4.5 填色函数及相关作图函数 118 4.5.1 填色函数 118 4.5.2 用户自定义填充函数 119 4.5.3 得到填充模式和颜色的函数 121 4.5.4 与填充函数有关的作图函数 121 4.5.5 可对任意封闭图形填充的函数 124 4.6 屏幕操作函数 125 4.6.1 屏幕图像存储和显示函数 125 4.6.2 设置显示页函数 127 4.7 图形方式下的文本输出函数 130 4.7.1 文本输出函数 131 4.7.2 文本输出字符串函数 133 4.7.3 定义文本字型函数 135 4.8 动画技术 137 4.8.1 动态开辟图视口的方法 137 4.8.2 利用显示页和编辑页交替变化 138 4.8.3 利用画面存储再重放的方法 139 4.8.4 直接对图像动态存储器进行操作 141 4.9 菜单生成技术 141 4.10 图形程序使用环境 142 4.10.1 BGI使用 143.. 4.10.2 图形方式下字符输出的条件 144 4.10.3 BGI图形驱动 145 4.11 直接存储存取 145 4.11.1 BIOS中断在显示中的应用 147 4.11.2 VGA寄存器 149 4.11.3 屏幕图形与VRAM地址的关系 151 4.11.4 VRAM的位面结构 151 4.11.5 将VRAM位面信息存入文件 152 4.11.6 将文件图像信息写入VRAM位面 153 4.11.7 VGA标准图形模式12H编程 154 4.11.8 VGA标准图形模式13H编程 157 4.12 SVGA编程 157 4.12.1 SVGA显卡的检测 158 4.12.2 SVGA模式信息的获取与模式操作 160 4.12.3 SVGA的直接存储器显示与内存控制 162 4.13 综合应用实例 163 4.13.1 用户自定义图模填充长方框图像 163 4.13.2 画圆饼图程序 165 4.13.3 画条形图程序 167 4.13.4 画函数曲线 169 4.14 图形图像综合应用——用动画演示排序算法 171 4.14.1 程序介绍 171 4.14.2 源代码解析 172 4.14.3 运行结果 183 4.14.4 归纳总结 184 4.15 小结 184 第5章 中断 185 5.1 中断的基本概念 185 5.1.1 BIOS 185 5.1.2 中断和异常 186 5.1.3 BIOS功能调用 189 5.2 鼠标中断编程的应用实例 191 5.2.1 鼠标中断的基本概念 191 5.2.2 程序功能分析 198 5.2.3 源代码解析 199 5.2.4 归纳总结 202 5.3 键盘中断编程的应用实例 203 5.3.1 键盘中断的基本概念 203 5.3.2 键盘操作函数bioskey() 207 5.4 鼠标与键盘的综合应用实例 208 5.4.1 需求分析 208 5.4.2 源代码解析 208 5.4.3 运行结果 212 5.4.4 归纳总结 213 5.5 中断应用——菜单制作程序剖析 213 5.5.1 需求分析 213 5.5.2 源代码解析 214 5.5.3 运行结果 227 5.5.4 归纳总结 227 5.6 小结 228 第6章 通信技术 229 6.1 概述 229 6.2 Winsock编程基础 230 6.2.1 Winsock基本概念 230 6.2.2 Winsock基本API 230 6.2.3 关于Winsock的异步模式 234 6.3 Cscoket编程技术 238 6.4 串口编程 238 6.4.1 概念 239 6.4.2 串行接口 239 6.4.3 串行通信方式及异步通信协议 240 6.4.4 串口针脚功能 243 6.5 并口编程 244 6.5.1 概念 244 6.5.2 并行接口 244 6.5.3 并口针脚功能 245 6.6 串并口操作的输入/输出函数 246 6.6.1 输入函数 246 6.6.2 输出函数 246 6.7 双机连接的方法 247 6.8 双机并口通信实例 248 6.8.1 源代码解析 249 6.8.2 归纳总结 280 6.9 网络通信编程——聊天室实例 281 6.9.1 需求分析 281 6.9.2 聊天室服务器端程序分析 282 6.9.3 聊天室客户端程序分析 290 6.10 小结 297 第7章 基本总线接口编程 298 7.1 ISA总线 298 7.1.1 ISA总线简介 298 7.1.2 ISA引脚介绍 299 7.2 PCI总线 302 7.2.1 PCI总线简介 302 7.2.2 PCI引脚介绍 303 7.3 中断控制操作 306 7.3.1 软件中断 307 7.3.2 硬件中断 307 7.4 PCI总线配置 308 7.4.1 PCI总线配置空间及配置机制 308 7.4.2 用I/O命令访问PCI总线配置空间 309 7.5 采用中断方式的信号采集程序 311 7.5.1 功能分析 311 7.5.2 源代码解析 311 7.6 小结 316 第8章 游戏开发 317 8.1 游戏开发概述 317 8.2 BMP图像格式 318 8.3 TC环境下的256色显示 324 8.3.1 VGA的DAC色彩寄存器知识 324 8.3.2 置256色图形模式 324 8.3.3 访问显存 325 8.3.4 显示卡换页 326 8.3.5 硬件无关屏幕初始化 327 8.4 魔方游戏开发程序剖析 329 8.4.1 功能分析 330 8.4.2 鼠标驱动程序 330 8.4.3 主函数模块 344 8.4.4 初始化图形to_graphic_mode模块 347 8.4.5 初始化鼠标initialize模块 347 8.4.6 显示程序的作者word模块 348 8.4.7 显示游戏标题title模块 350 8.4.8 绘制游戏主窗口的draw_win模块 352 8.4.9 建立魔方游戏界面body模块 353 8.4.10 显示魔方游戏showcube模块 362 8.4.11 清除键盘缓冲区clr_kb_buff模块 363 8.4.12 返回鼠标按下操作键值getmousech模块 363 8.4.13 处理用户对功能热键的操作handle模块 364 8.5 小结 377 第9章 综合开发实例——信息管理系统 378 9.1 问题定义 378 9.2 算法设计 378 9.2.1 主函数算法 379 9.2.2 各模块算法 379 9.3 流程图设计 381 9.3.1 主函数模块的流程图 381 9.3.2 其他各模块的流程图 382 9.4 编写程序代码 392 9.4.1 基本介绍 392 9.4.2 信息管理系统程序代码 392 9.5 测试与调试 410 9.5.1 基本介绍 410 9.5.2 信息管理系统测试与调试 411 9.6 整理文档 412 9.7 系统维护 412 9.8 归纳总结 412...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值