zoukankan      html  css  js  c++  java
  • 翁恺C语言基础学习——位运算概念,自定义容器

    C语言位运算符

    •   ‘&’ —— 按位与 ,'(x)i == (y)i  ==1  则--> (x & y ) i=1,否则(x & y ) =0 ',也就是两个二进制数两位都都为1时,则为1  ,否则为0

    •    ‘|’  ——按位或 ,   '(x)i=1 或者  (y)i =1 则--> (x | y)i =1'   两个二进制数两位只要有一个不为0,则为1,否则为0

    •    ‘~’ ——按位取反, '~(x)i = 1-(x)i' , 把1位变成 0, 0位变成1   ,

    •         ‘^’—— 按位异或 '(x) i=(y)i 则  (x)i ^ (yi) =0    否则为 1'    任何一个数  用同一个值异或两次,等于原来的自己

    •   '<<'——左移运算   'i << j' 将 'i'中所有的位向左移动'j'个位置, x<<1 == > x *=2     x<< n  ==> x *= 2的‘n’次方, 所有小于int类型的值,移位以int方式来做,结果是int

    •   '>>'——右移运算  ' i>> j' 将 'i'中所有的位向右移动'j'个位置, x>> 1  ==> x /=2 , x>>n ==> x /= 2的'n'次方!所有小于int类型,移位以int方式来做,结果是int,对于 unsigned类型左边填入0,有符合位,则符号位不变

    位移不能使用负数 ,未定义的行为

    void print_bit(int n);
    void print_unsigned_bit(unsigned n);
    
    
    
    //按位的与
    void test_bit_with_and() {
        //应用一:让某一位或某些位为0 如:x & 0xFE   (0xFE-->1111,1110,进行位运算后这个数的最后一位就为0)
        int a = 33;
        print_bit(a);
        int res = a & 0xFE; //(32-->'0010,0001'  & '1111,1110'  ===> 0010,0000)
        print_bit(res);
        printf("%d
    ", res);
        //应用二:获取某个数当中的一段: x & 0xFF    (0xFF-- > '1111,1111', 位运算后 得出这个数最后8位的值)
        int data =0xfffe ;
        print_bit(data);    //输出 binary->1111,1111,1111,1110
        data = data & 0xff;    //取后8位
        print_bit(data);    //输出 binary-->1111,1110
    }
    
    //按位或 
    void test_bit_with_or() {
        //应用一:使得一位,或者几位为 1
        int data = 0xAA;    //binary -->    1010,1010
        int data1 = 0x54;    //binary -->    0101,0100
        data = data | data1;
        print_bit(data);    //binary -->    1111,1110
        //应用二:把两个数拼接起来
        data = 0xff00;        //binary -->111,1111,0000,0000
        data1 = 0x00ff;        //binary -->0000,0000,1111,1111
        data = data | data1;
        print_bit(data);    //binary -->111,1111,1111,1111
    }
    
    void test_bit_with_xor() {
        //应用,简单的数据加密,解密
        int data = 0xAA;    //binary -->    1010,1010
        int data1 = 0x54;    //binary -->    0101,0100
        data = data ^ data1;
        data = data ^ data1;
        print_bit(data);    //binary -->    1010,1010
    }
    
    
    /*
        打印二进制数据
    */
    void test_mybitprintf(int number) {
        if (number == 0) { 
            printf("binary-->%d", 0); 
            return;
        }
        unsigned int mask = 1u << 31; //int类型4个字节,无符号 左移31位则 1000,0000,0000,0000,0000,0000,0000,0000
        printf("%d-binary===>", number);
        //直到mask 右移32位 得到结果 0 时,for循环退出
        for ( ; mask; mask >>= 1)
        {
            // (1000,0000,0000,0000,0000,0000,0000,0000)  & (0000,0000,0000,0000,0000,0000,0000,0010)  
            // 得出结果===> 0000,0000,0000,0000,0000,0000,0000,0000   非零才为真,直到倒数第二位的'1' 结果=1 输出1 否则输出0
            int temp = number & mask;
            printf("%d", temp ? 1 : 0 );
        }
        printf("
    ");
    }
    
    /*    位段, 常用于单片机特殊寄存器结构,编译器会安排其中位的排列,不可移植性 
              当所需要的位超过一个int(32位)时,使用多个int,直到容纳这个“位段”
              可以用位段的成员名称访问指定数据的第几位,比移位,与,或更直观让人接受
    */
    //位段结构体
    struct  U0
    {
        unsigned int leading : 3;
        unsigned int flag1 : 1;
        unsigned int flag2 : 1;
        int trailing : 27;
    
    };
    void testU0(){
        struct U0 uu;
        uu.leading = 2;
        uu.flag1 = 1;
        uu.flag2 = 1;
        uu.trailing = 0;
        printf("sizeof(uu)==%lu
    ", sizeof(uu));
        int res = *(int*)&uu ;  // 取结构体地址,强转成 int指针,获取它的整形值,单片机常用
        test_mybitprintf(res);    //binary===>00000000000000000000000000011010
    }
    
    int main() {
        //test_bit_with_and();
        //test_bit_with_or();
        //test_bit_with_xor();
        //test_mybitprintf(2);
        testU0();
        return 0;
    }
    位运算小例子

    自定义容器——可变数组

    头文件

    #ifndef __ARRAY_H__
    #define __ARRAY_H__
    
    typedef struct
    {
        int *array;
        int size;
    }Array;
    
    Array array_create(int init_size);                //初始化数组大小
    void array_free(Array *a);                        //释放数组空间
    int    array_size(const Array *a);                    //返回数组的大小
    int* array_at(Array *a, int index);                //获取指定位置的数组内容的指针
    void array_inflate(Array *a, int more_size);    //对数组进行扩容
    #endif __ARRAY_H__ 

    可变数组实现

    #define _CRT_SECURE_NO_WARNINGS
    #include <ctype.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include "array.h"
    
    //typedef struct
    //{
    //    int *array;
    //    int size;
    //}Array;
    
    const BLOCK_SIZE = 20;
    
    //初始化数组大小
    Array array_create(int init_size)
    {
        Array a;
        a.size = init_size; 
        a.array = (int*)malloc(sizeof(int)*  a.size);
        return a;
    }
    //释放数组空间
    void array_free(Array *a) 
    {
        free(a->array);
        a->array = NULL;
        a->size = 0;
    }
    //返回数组的大小,封装的概念,保护size不被直接访问,
    int    array_size(const Array *a) 
    {
        return a->size;
    }
    //获取结构的数组指定位置的指针
    //返回指针而不是int的意义: 指针既可以获取值,也可以重新赋值, 
    int* array_at(Array *a, int index)
    {  
        if (index >= a->size) {
            array_inflate(a, ((index / BLOCK_SIZE + 1) *BLOCK_SIZE ) - a->size);
        }
        return &(a->array[index]);
    }
    //对数组进行扩容
    void array_inflate(Array *a, int more_size) {
        printf("扩容前的大小=%d
    ", a->size);
        int *p = (char*)malloc(sizeof(int)* (a->size + more_size));
        int i = 0;
        /*for (; i < a->size; i++) {
            p[i] = a->array[i];
        }*/
        memcpy(p,a->array);
        free(a->array);
        a->array = p;
        a->size += more_size;
        printf("扩容后的大小=%d
    ", a->size);
    }
    
    
    
    
    int main() 
    {
        //可变数组的缺陷:拷贝数据的时间,内存受限的情况下,当size超过一半的内存大小时,无法继续申请内存
        //    如 内存 16k, 当前array大小 已经达到8k ,剩余8k内存,然而申请 8K + block_size 大小内存时,系统内存不够用
        Array a = array_create(1);
        printf("接受的a的地址==>%x
    ", &a);
        *array_at(&a,3) = 10;
        printf("%d
    ", *array_at(&a, 3));
        int number = 0;
        int cnt = 0;
        while (number != -1) {
            scanf("%d", &number);
            if (number != -1) {
                *(array_at(&a, cnt++)) = number;
            }
        }
        array_free(&a);
     
    
    
        return 0;
    }
    自定义容器实现

    自定义链表简单实现

    #include <stdio.h>
    #include <stdlib.h>
    #include "node.h"
    
    
    //typedef struct _node {
    //    int value;
    //    struct _node *next;
    //}Node;
    
    
    
    typedef struct  _list{
        Node *head ;
        Node *tail;
    }List;
    
    void add(List *list, int number);
    void list_print(List *list);
    int list_remove(List *list, int number);
    int list_clear(List *list);
    
    int main()
    {
    /*
        int number;
        do {
            scanf("输入一个整数%d", &number);
            if (number != -1) {
                add(&list, number);
            }
        } while (number != -1);*/
    
        List list;
        list.head = NULL;
        int len = 8;
        int arr[] = { 1,2,3,4,5,6,7,8};
        int i;
        for ( i = 0; i < len; i++)
        {
            printf("第%d次
    ",i);
            add(&list, arr[i]);
        }
        list_print(&list);
        list_remove(&list, 1);
    
    
        List list1;
        list1.head = NULL;
        int res = list_remove(&list, 1);
    
        if (res > 0) {
    
            printf("删除成功
    ");
        }
        list_clear(&list);
        list_print(&list);
    
        printf("Hello World! linked-list
    ");
        return 0;
    
    }
    
    //清除所有的链表
    
    int list_clear(List *list) {
        Node *p;
        Node *q;
        for (p = list->head; p; p = q) {
            q = p->next;
            free(p);
        }
        printf("clear ...list size==>%d
    ", sizeof(&list));
        //list->head = NULL;
    
    }
    
    //移除链表中某一个数据
    int list_remove(List *list, int number) {
        //问题1.数据是否存在
        //问题2.边界处理?数据是在第一个
        Node* p;
        Node* pTemp;
        int res = -1;
        if (list->head) {
            for (pTemp = NULL, p = list->head; p; pTemp = p, p = p->next) {
                if (number == p->value) {
                    if (pTemp) {
                        pTemp->next = p->next;
                    }
                    else {
                        list->head = p->next;
                    }
                    free(p);
                    res = 1;
                    break;
                }
            }
        }
        
        return res;
    
    }
    
    
    //输出链表中所有的数据
    void list_print(List *list) {
        Node *p ;
    
        if (list->head) {
            printf("the list is null...
    ");
            return;
        }
        for (p = list->head; p; p = p->next) {
            printf("-%d", p->value);
        }
        printf("
    ");
    }
    
    //将一个数据添加到列表当中
    void add(List* pList,int number) {
        Node *p = (Node*)malloc(sizeof(Node));
        p->value = number;
        p->next = NULL;
        Node* last = pList->head;
        if (last) {
            while (last->next)
            {
                last = last->next;
            }
            last->next = p;
        }
        else {
            pList->head = p;
        }
    }
    自定义链表
  • 相关阅读:
    Mybatis学习(3)实现数据的增删改查
    Mybatis学习(2)以接口的方式编程
    Mybatis学习(1)开发环境搭建
    Apache Commons 工具类介绍及简单使用
    JAVA枚举使用详解
    Spring中的<context:annotation-config/>配置
    SpringMVC(12)完结篇 基于Hibernate+Spring+Spring MVC+Bootstrap的管理系统实现
    SpringMVC(11)表单标签
    面试题
    开发辅助网址
  • 原文地址:https://www.cnblogs.com/shenwenbo/p/14972528.html
Copyright © 2011-2022 走看看