c语言难点综合

怼烎@ 2023-07-18 03:30 18阅读 0赞

上学期c语言后半期老师没怎么教,自己又不大学,学得比较菜。但基于打基础考虑和后续的与数据结构相关的链表、数据库相关的指针、c++里的类似于结构体的类与对象等都有着一衣带水的关系,所以只好看了一遍遍的课本,把一些重要的知识点综合总结出来。高能预警!!!

一、函数部分

  1. 函数分为无参函数与有参函数。
  2. 函数在声明时可以只写参数类型而不写参数名,如float add(float,float);示例代码:

    include

    int main(){
    int c;
    int add(int ,int );
    c=add(2,6);
    printf(“%d\n”,c);
    return 0;
    }
    int add(int x,int y){
    int z;
    z=x+y;
    return (z);
    }

  3. 递归函数是“自己调用自己”的函数,无论是采用直接或间接调用方式。间接递归意味着函数调用另一个函数(然后可能又调用第三个函数等),最后又调用第一个函数。因为函数不可以一直不停地调用自己,所以递归函数一定具备结束条件。示例代码(二分法搜索):

    long *binarySearch( long val, long array[ ], int n ){
    int m = n/2;
    if ( n <= 0 ) return NULL;
    if ( val == array[m] ) return array + m;
    if ( val < array[m] ) return binarySearch( val, array, m );
    else return binarySearch( val, array+m+1, n-m-1 );}

  4. 形参中的数组可以不用写明大小,直接留空如:float average(float array[],int n);对于二维数组,可以写成array[][10]的形式。

  5. 全局变量通常首字母大写
  6. 数组可以利用函数名或者单个值当做函数实参进行传递。前者如:float(a);、后者可以是a[i];

变量存储方式和生存期

  1. 按照变量的作用域(从空间)的角度来观察,变量可以分为全局变量和局部变量。二按照变量值存在的时间(即生存期)来观察,故分为静态存储方式和动态存储方式。
  2. 内存中的工用户使用的存储空间的情况。这个存储空间可以分为3部分:
    (1)程序区;
    (2)静态存储区;
    (3)动态存储区。
  3. 动态存储区中存放一下数据:
    1、函数形式参数。在调用函数时给形参分配存储空间。
    2、函数中定义的没有关键字static声明的变量,即自动变量。
    3、函数调用时的现场保护和返回地址。
  4. 静态局部变量与自动变量不同,自动变量属于动态存储类别,分配在动态存储区空间,在函数调用结束后会自动释放。而静态局部变量不会自动释放,还会保存当前的数值。一般静态局部变量和静态函数,可以放在程序的开头,以提高程序的可靠性。
  5. 至于寄存器变量,寄存在CPU当中,存储速度远远高于对内存的存取速度。关键字为register。
  6. extern可以对变量做“外部变量声明”,表示把改外部变量扩展到此位置。也可以对另外一个文件模块中的变量进行声明调用。如果不想被其他文件调用,可以使用static进行声明。

二、运算符:
在这里插入图片描述
这些运算符并非仅用于c语言,编程语言之间都有着共通性。这里只对一些特殊运算符进行分析。

  1. 左移运算符,左移,而右边空出的位补0(c++中有其他用法)。例如:10100110,逻辑左移后为:01001100。右移运算符则与左移相反,进行右移时,左边空出的位补0。示例代码:

    int i = 1; //把i赋值为1,二进制为0001
    i =i<<1; //将i左移一位 printf("%d",i); //输出结果为2. i =i>>1; //将i右移一位
    printf(“%d”,i); //输出结果又换回1.

  2. 三元运算符 例如:

    return( z=x>y?x:y);//进行判断,将大者返回

  3. 运算符的优先级可以在这个老兄的博文里面查阅:http://blog.csdn.net/huangblog/article/details/8271791

三、指针:

  1. 进行指针间转换时一定要注意好,传过来如果是2个整形变量的地址,则得到的是2个整形变量,不能用指针变量去交接。
  2. 指针引用数组时,可以这样遍历输出:

    int a[3];
    int i,*p;
    for(i=0;i<3;i++)

    1. scanf("%d",&a[i]);

    for(p=a;p<(a+3);p++)

    1. printf("%d",*p);

也可以这样:

  1. int a[3];
  2. int i,*p;
  3. p=a;
  4. for(i=0;i<3;i++)
  5. scanf("%d",p++);
  6. for(p=a,i=0;i<3;i++,p++)
  7. printf("%d",*p);

要注意的是,下面的那一种方法,先让p指向a数组的首地址后,经过scanf的3次赋值,最后会转到第三个地址,需要重新让p=a,指向首地址,才能重新遍历打印。

  1. (星号(p++)与(星号)(++p)的作用是不同的,前者先取*p的值,然后再+1;后者相反。(星号)(++p)相当于a[++i]。
  2. 0行1列的元素的地址可以用a[0]+1来表示。(星号)(a[i]+j)(星号)((星号)(a+i)+j)等同于a[i]a[j]。地址上会逐个加8个字节。

    int a[2][2]={ 1,2,3,4};
    int i,*p;
    for(p=a[0];p<a[0]+2;p++)

    1. { if({ p-a[0])%4==0) printf("\n");
    2. printf("%d",*p);}
  3. 定义p为指向具有4个元素的以为数组的指针,可以是

    float (*p)[4];

6.定义字符串指针

  1. char *string;
  2. *string="I love China";
  3. //等同于
  4. char *string1="I love China";

7.字符串间的复制,可以直接用地址进行逐个复制

  1. char a[]="I love China";
  2. for(i=0;*(a+i)!='\0';i++)
  3. *(b+i)=*(a+i);
  4. *(b+i)='\0';//在有效字符之后添加\0
  5. for(i=0;b[i]!='\0';i++)
  6. printf("%c",b[i]);

也可以,用2个指针变量按顺序指向不同的元素进行复制。

  1. char a[]="I love China",b[12],*p1,*p2;
  2. p1=a;p2=b;
  3. for(;*p1!='\0';p1++,p2++)
  4. *p2=*p1;
  5. *p2='\0';//在有效字符之后添加\0
  6. for(i=0;b[i]!='\0';i++)
  7. printf("%c",b[i]);

8.指向函数

  1. int i;
  2. int max(int ,int);
  3. int (*p)(int ,int);
  4. if (n==1)
  5. p=max;
  6. int max(int x,int y){
  7. return z=x>y?x:y);}
  1. 全局变量分配到内存中的静态存储区,非静态局部变量分配到栈(stack)存储区。使用malloc函数可以将一些临时用的数据放到堆里面(这与c++的new何其酷似)进行动态分配,带回的是void指针。函数原型为

    void malloc(unsigned int size);/开辟size(n字节)的临时分配区*/

  2. calloc函数,其得到的空间很大,可以容纳一个数组。

    void calloc(unsigned n,unsigned size);/n是元素个数, 每个的长度就是size*/

  3. free函数是用来释放掉calloc分配的动态内存的,使这一部分空间能重新被其他变量使用。应该对应的是最近一次调用calloc或者malloc函数时得到的函数返回值。如free(p);

  4. realloc函数,可以对calloc或者malloc函数已经分配的动态空间的大小进行重新分配。如:realloc(p,50);
  5. void指针类型是指向空类型的,也就是不确定的类型,与其他类型的指针对接时,系统自动跟随着改变其类型。
  6. 指向结构体的指针,示例代码:

    struct Student{ long name;}
    struct Student stu_1;
    struct Student p;
    p=&stu_1;
    strcpy(stu_1.name,”耗子”);
    printf(“%ld\n”,stu_1.name);
    printf(“%ld\n”,(
    p).name);

  7. 指向结构体数组的指针,示例代码:(与c++通用的是,指向结构体数组用的->而不是.)

    struct Student{ long name;char sex;}
    int main(){
    struct Student stu[4]={ { “耗子”,’男’},{ “小张”,’男’},{ “小观”,’男’},{ “小李”,’男’}};
    //其他人不言而喻,自己琢磨
    struct Student *p;
    for(p=stu;pname,p->sex);

  8. 野指针:野指针是未指向合法内存的指针。

  9. 多级指针

    char *p1; //普通的二级指针
    char (
    p2)[5]; //指针,指向char[5]数组的指针
    char p3[5]; //数组,以char 为元素的指针数组

  10. 链表与指针的基佬关系
    在这里插入图片描述
    ①链表有一个头指针变量,head,它存放指向下一个元素的地址。最后一个元素,即表尾,它的地址部分放一个NULL。
    ②链表中每一个元素称为结点,结点分为:用户所需数据与下一个结点地址。
    建立简单的静态链表

    include

    struct Student
    {

    1. int num;
    2. float score;
    3. struct Student *next;

    }
    int main()
    { struct Student a,b,c,head,p;
    a.num=10101;a.score=89.5;
    b.num=10102;a.score=90.5;
    b.num=10104;a.score=92.5;
    head=&a;
    a.next=&b;//节点互绑
    b.next=&c;
    c.next=NULL;
    p=head;
    do

    1. { printf("%ld%5.1lf\n",p->num,p->score);
    2. p=p->next;
    3. }while(p!NULL);

    return 0;
    }

建立简单动态链表

  1. struct Student *head;
  2. struct Student *p;
  3. p = (struct Student *)malloc(sizeof(struct Student));
  4. head = (struct Student *)malloc(sizeof(struct Student));
  5. if (NULL == head)
  6. {
  7. printf("Memory create error!\n");
  8. return 1;
  9. }

四、文件:

  1. fopen函数打开数据文件:fopen(文件名,使用文件方式);fclose函数关闭如:fclose(文件指针)。
  2. 通常用一个指针指向文件。如:

    FILE*fp;
    fp=fopen(“book.txt”,”r”);//使文件指针fp与文件连接

  3. 调用一个文件,且在找不到文件的时候自动关闭所有文件。

    FILE *fp;
    if((fp=fopen(“E:/book.txt”,”w”))==NULL){
    printf(“文件打开错误!\n”);
    exit(0); }
    fclose(fp);

  4. 向文件读写一个字符串

    fgets(str,n,fp);//向文件读入一个长度未n-1的字符串

  5. 以二进制形式向向文件读写入一组数据
    格式为:fread(buffer,size,count,fp);与fwrite(buffer,size,count,fp);
    buffer是传送的数据;size是大小;count是写入数据项个数,一般写为1;
    fp是文件指针。

    for(i=0;i<M;i++){
    fwrite(&book[i],sizeof(struct classmate),1,fp); fclose(fp); }

  6. 位置标记:fseek函数。

  7. ferror(fp)功能是检测出错反馈信息。

附件:一些奇妙的功能

  1. c的3个数据流:stdin(标准输入流),stdout(标准输出流),stderr(标准出错输出流)。
  2. typedef (变量类型名)(变量名称):指定某个新的名称的变量类型与前者作用相同。
  3. 逗号运算从右往左
  4. printf的输出的先后顺序为从左往右
  5. 系统时间的调用

    time_t t;

    1. struct tm * lt;
    2. time (&t);//获取Unix时间戳。
    3. lt = localtime (&t);//转为时间结构。
    4. printf ( "%d/%d/%d %d:%d:%d\n",lt->tm_year+1900,
    5. lt->tm_mon,lt->tm_mday, lt->tm_hour,
    6. lt->tm_min, lt->tm_sec);//输出结果

发表评论

表情:
评论列表 (有 0 条评论,18人围观)

还没有评论,来说两句吧...

相关阅读

    相关 c语言核心难点——函数与递归

    本篇给大家带来一篇关于函数的文章,c语言,最离不开的就是函数。那究竟什么是函数,什么是递归呢??相信大家看完本篇文章,都会有一个清晰的认识 1.函数 函数是什么? 在计算

    相关 c语言难点综合

    上学期c语言后半期老师没怎么教,自己又不大学,学得比较菜。但基于打基础考虑和后续的与数据结构相关的链表、数据库相关的指针、c++里的类似于结构体的类与对象等都有着一衣带水的关系

    相关 C/C++易错难点笔记02

    C++有很多基础但是,又容易出错的地方,也有很多我们 没有关注的地方,这里慢慢总结积累,记录下来。 基础知识点 1. 易误解:如果int a\[5\], 那么a与&a