多執行緒排序-覆盤
阿新 • • 發佈:2022-04-01
除錯工具
valgrind記憶體洩漏檢測
參考連線:
- https://zhuanlan.zhihu.com/p/75416381
- https://www.cnblogs.com/lidabo/p/4377545.html
- https://www.cnblogs.com/bokeyuan-dlam/articles/9157857.html
GDB
time exe
程式碼實現
專案目標
- 實現多執行緒排序
程式碼
/** * @file sort.c * @author binary (binary@techbootcamp) * @brief 多執行緒排序專案 * @version 0.1 * @date 2021-11-03 * * @copyright Copyright (c) 2021 * */ /////////////////////////////////////////////////////////////////////////////// //標頭檔案區域,所需要的標頭檔案,新增到這裡。 #include <stdio.h> #include <stdlib.h> // exit() #include <pthread.h> #include <unistd.h> #include <string.h> /* gcc -o sort sort.c -w -lpthread ./sort */ /////////////////////////////////////////////////////////////////////////////// //巨集定義 #define SIZE 500 #define thread_MAX 2 /////////////////////////////////////////////////////////////////////////////// //結構體 typedef struct { int size; int data[SIZE]; } datas; datas numbers; typedef struct { int start; int end; } parameters; /////////////////////////////////////////////////////////////////////////////// //變數宣告 /////////////////////////////////////////////////////////////////////////////// //函式宣告 /** * @brief 列印資料 * * @param array */ void print_data(datas array); // OK /** * @brief 檢測資料是否已經排序 * * @param array * @return true * @return false */ int is_sorted(datas array); // OK /** * @brief 排序執行緒的回撥函式 * * @param params * @return void* */ void *sorter(void *params); /** * @brief 合併執行緒的回撥函式 * * @param params * @return void* */ void *merger(void *params); /** * @brief 從檔案中讀取資料。(原始資料,未排序的) * */ void input_data(); // OK /** * @brief 排序執行緒的初始化和工作過程 * */ void handle_sorting(); // OK /** * @brief 合併執行緒的初始化和工作過程 * */ void handle_merge(); /** * @brief 顯示排序資料是否正確 * * 排序不正確,顯示排序不正確,並打印出排序資料。 * 排序正確,則顯示排序正確。 * */ void show_data(); // OK /** * @brief 輸出資料到檔案。(已經排好序的) * */ void output_data(); /** * @brief 清理一些資源。比如動態記憶體分配的資源 * */ void cleanup(); //TODO:你的排序演算法函式在這裡宣告 /////////////////////////////////////////////////////////////////////////////// //函式實現 /** * @brief 主函式人口 * * @param argc 引數個數 * @param argv 引數陣列 * @return int 返回狀態 */ int main(int argc, char *argv[]) { input_data(); handle_sorting(); handle_merge(); show_data(); output_data(); cleanup(); return 0; } // @brief 列印資料 void print_data(datas array) { printf("列印資料:"); for (int k = 0; k <= array.size - 1; k++) { printf("%d,", array.data[k]); } putchar('\n'); } // @brief 檢測資料是否已經排序 int is_sorted(datas array) { char flag = 0; if (array.size < 1) { printf("Input array is empty.\n"); return 1; } for (int i = 1; i < array.size; i++) { if (array.data[i - 1] > array.data[i]) { flag = 1; } if (flag) { return 1; } } return 0; } // @brief 排序執行緒的回撥函式 void swap(int *a,int *b) //交換兩個變數 { int temp = *a; *a = *b; *b = temp; } /* 排序 */ void sort_select(int * data, int size) { int i, j, min; if (data == NULL || size <= 0) { printf("data error,sort_select().\n"); } for (i = 0; i < size; i++) // 從第一個,到最後第二個,每個都要和後面所有比較 { min = i; // 預設選第一個是最小值 for (j = i + 1; j <= size; j++) // 後面一次比較的迴圈 { if (data[i] > data[j]) { swap(&data[i], &data[j]); } } } } // @params:存放起止位置的指標,p=params void *sorter(void *params) { // 選擇排序 parameters * p = (parameters *)params; // data指向儲存源陣列的開始位置 int *data = &numbers.data[p->start]; int size = p->end - p->start; // 執行緒處理資料的大小 //printf("size:%d.\n", size); sort_select(data, size); } void *merger(void *params) { //printf("asdasdasd\n"); parameters * p = (parameters *)params; int *data = &numbers.data[p->start]; int size = p->end - p->start; // 執行緒處理資料的大小 sort_select(data, size); } void input_data() { FILE *fp; char ch; char str[30] = {0}; int i = 0, j = 0; numbers.size = 0; fp = fopen("sort", "r"); // 開啟數資料夾 if (fp == NULL) // 如果為空資料夾 { printf("Empty txt file.\n"); exit(1); } while ((ch = fgetc(fp)) != EOF) // 迴圈處理檔案內容 { if (ch != ',') // 逗號分隔輸入資料,不是逗號就是有效資料 { str[i] = ch; // 儲存兩個逗號之間的所有數字字元 i++; } else // 這時出現逗號,表示一個有效數字輸入完畢 { i = 0; // 清零 numbers.data[j++] = atoi(str); // 將一個有效數字字元轉成數字,並存入陣列 numbers.size++; // 儲存陣列數量加一 memset(str, 0, sizeof(str)); // 清空暫存陣列 } } if (i != 0) // 最後一個數組後面可能沒有逗號 { numbers.data[j] = atoi(str); numbers.size++; } // print_data(numbers); // 測試列印函式,測試輸入資料是否正確 // printf("is_sorted() : %d.\n", is_sorted(numbers)); // 測試是否正確排序函式 fclose(fp); } // @brief 排序執行緒的初始化和工作過程 void handle_sorting() { pthread_t ntid1, ntid2; parameters * param[2]; int err1, err2; int len = numbers.size / thread_MAX; // 兩個執行緒的情況下,第二個開始位置 //parameters * para[2]; param[0] = (parameters *)malloc(sizeof(parameters)); param[0]->start = 0; param[0]->end = len; param[1] = (parameters *)malloc(sizeof(parameters)); param[1]->start = len + 1; param[1]->end = numbers.size - 1; // printf("param[0]->start=%d\nparam[0]->end=%d\nparam[1]->start=%d\nparam[1]->end=%d\n", // param[0]->start, param[0]->end, param[1]->start, param[1]->end); /* 如何用for迴圈,建立任意多個執行緒處理, 主要是地址分配,不清楚怎麼任意分配 */ // for (int i = 0; i < thread_MAX ; i++) // { // err = pthread_create(&ntid, NULL, sorter, (void *)i); // 建立新執行緒 // if(err != 0){ // fprintf(stderr, "error create:%s\n", strerror(err)); // exit(1); // } // } err1 = pthread_create(&ntid1, NULL, sorter, (void *)param[0]); // 建立新執行緒 if(err1 != 0){ fprintf(stderr, "error create:%s\n", strerror(err1)); exit(1); } err2 = pthread_create(&ntid2, NULL, sorter, (void *)param[1]); // 建立新執行緒 if(err2 != 0){ fprintf(stderr, "error create:%s\n", strerror(err2)); exit(1); } pthread_join(ntid1, NULL); pthread_join(ntid2, NULL); free(param[0]); free(param[1]); } void handle_merge() { pthread_t ntid; int err; parameters * para = (parameters *)malloc(sizeof(parameters)); para->start = 0; para->end = numbers.size - 1; err = pthread_create(&ntid, NULL, merger, (void *)para); // 建立新執行緒 if(err != 0){ fprintf(stderr, "error create:%s\n", strerror(err)); exit(1); } pthread_join(ntid, NULL); //sleep(1); // 不加延時會排序出錯??? free(para); // 還不能放上面??? } // @brief 顯示排序資料是否正確 void show_data() { int res = is_sorted(numbers); if (res) { printf("不正確排序.\n"); print_data(numbers); } else { printf("正確排序.\n"); print_data(numbers); } } void output_data() { FILE *fp; int i = 0; char ch; fp = fopen("out", "w"); if (fp == NULL) { printf("error out.\n"); exit(1); } while (i < numbers.size) { fprintf(fp, "%d,", numbers.data[i]); i++; } fclose(fp); } void cleanup() { ; }