1. 程式人生 > 其它 >翁愷C語言基礎學習——位運算概念,自定義容器

翁愷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\n", 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("\n"); } /* 位段, 常用於微控制器特殊暫存器結構,編譯器會安排其中位的排列,不可移植性 當所需要的位超過一個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\n", 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\n", 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\n", a->size);
}




int main() 
{
    //可變陣列的缺陷:拷貝資料的時間,記憶體受限的情況下,當size超過一半的記憶體大小時,無法繼續申請記憶體
    //    如 記憶體 16k, 當前array大小 已經達到8k ,剩餘8k記憶體,然而申請 8K + block_size 大小記憶體時,系統記憶體不夠用
    Array a = array_create(1);
    printf("接受的a的地址==>%x\n", &a);
    *array_at(&a,3) = 10;
    printf("%d\n", *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次\n",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("刪除成功\n");
    }
    list_clear(&list);
    list_print(&list);

    printf("Hello World! linked-list\n");
    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\n", 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...\n");
        return;
    }
    for (p = list->head; p; p = p->next) {
        printf("-%d", p->value);
    }
    printf("\n");
}

//將一個數據新增到列表當中
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;
    }
}
自定義連結串列