关于c:获取数组的全排列

依据给定的int型数组,给出全排列 比方:[1,2] => [[1,2],[2,1][1,2,3] =>[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] #include <stdio.h>#include <stdlib.h>int *concat(int* list, int length, int x) { int *result = (int*)malloc((length + 1) * sizeof(int)); for (int i = length; i > 0; i--) { result[i] = list[i - 1]; } result[0] = x; return result;}int getFactorial(int n) { int total = 1; for (int i = 1; i <= n; i++) { total *= i; } return total;}int** getPermutation(int * list ,int n) { int** result; int total = getFactorial(n); if (n == 2) { result = (int**)malloc(total * sizeof(int*)); for (int i = 0; i < total; i++) { result[i] = (int*)malloc(n * sizeof(int)); } result[0][0] = list[0]; result[0][1] = list[1]; result[1][0] = list[1]; result[1][1] = list[0]; return result; }else{ result = (int**)malloc(total * sizeof(int*)); for (int i = 0; i < n; i++) { int* tempList = (int*)malloc((n - 1) * sizeof(int)); int curIdx = 0; for (int j = 0; j < n; j++) { if (i == j) continue; tempList[curIdx] = list[j]; curIdx++; } int** tempResult = getPermutation(tempList, n - 1); int tempResultLength = getFactorial(n - 1); for (int k = 0; k < tempResultLength; k++) { result[tempResultLength * i + k] = concat(tempResult[k], n - 1, list[i]); } free(tempList); free(tempResult); } return result; }}int main() { int n =4; int* p = (int*)malloc(n * sizeof(int)); for (int i = 0; i < n; i++) { p[i] = i + 1; } int **result = getPermutation(p,n); for (int i = 0; i < getFactorial(n); i++) { for (int j = 0; j < n; j++) { printf("%d,", result[i][j]); } printf("\n"); } free(p); free(result); return 0;}

February 23, 2022 · 2 min · jiezi

关于c:CSCI-2100B数据结构

CSCI 2100B Data StructuresAssignment 2Due Date: 16 March 2021Written Exercises Write the following function that makes use of the listADT of list of integers:listADT moveMinToHead(listADT);which moves the minimum element in the list to the head of the list if the argumentlist is nonempty, or returns an empty list otherwise. For examples,• moveMinToHead([]) = []• moveMinToHead([3,4,8,2,4]) = [2,3,4,8,4]• moveMinToHead([3,5]) = [3,5]• moveMinToHead([7]) = [7]a) Write this function as a recursive function. Hint: Call moveMinToHead with the tailas the argument.b) Write this function as a nonrecursive function.Write the following function that sorts the argument list into ascending order byselection sort:listADT selectionSort(listADT);Hint: Make use of the moveMinToHead function.Use the selection sort algorithm to sort the following sequence of integers intoascending order:1, 8, 6, 6, 5, 7, 9Show clearly each step in the process of sorting.Write the following functions as recursive functions in C. You should use the listoperations defined in list ADT shown in the lecture notes. You can simply callexit(EXIT_FAILURE) when error conditions are encountered. Note that your functionsshould work well with any correct implementation of list ADT.a) The function listIsSorted that accepts a listADT argument and returns an int valueif the argument list is sorted, or 0 otherwise. For examples:§ listIsSorted([7,8,1,5,3]) = 0§ listIsSorted([4,5,6,7]) = 1§ listIsSorted([0]) = 1§ listIsSorted([]) = 1b) The function lastButOne that accepts a listADT argument and returns an int valuethat is the last-but-one value in the list. For examples:§ lastButOne([3,4,8,2,4]) = 2§ lastButOne([0,1]) = 0§ lastButOne([]) = ERROR§ lastButOne([4]) = ERRORc) The function member that accepts an int argument and a listADT argument, andreturns an int value true if the int argument is in the listADT argument, or 0otherwise. For examples:§ member(2, [3,4,8,2,4]) = 1§ member(4, [3,5]) = 0d) The function firstN that accepts a listADT argument and an int argument N, andreturns a listADT value that is the list of the first N elements of the argument, untilthe end of the list. For examples:§ firstN([3,4,8,2,4], 3) = [3,4,8]§ firstN([2,4,6], 8) = [2,4,6]§ firstN([], 0) = []§ firstN([], 1) = []§ firstN([8,7,6], 3) = [8,7,6]e) The function evenOnly that accepts an int argument and a listADT argument, andreturns a listADT result that is the same as the List argument, except that all theodd numbers are removed. For examples:§ evenOnly([3,4,8,2,4]) = [4, 8, 2, 4]§ evenOnly([3,5]) = []§ evenOnly([2,8,4]) = [2, 8, 4]§ evenOnly([]) = []f) The function listsAreDifferent that accepts two listADT arguments, and returns anint value 1 if the listADT arguments are different, or 0 otherwise. For examples:§ listsAreDifferent([], [3,4,8,2,4]) = 1§ listsAreDifferent([2], []) = 1§ listsAreDifferent([], []) = 0§ listsAreDifferent([39,3,8,12,3], [39,3,8,11,3]) = 1§ listsAreDifferent([39,3,8,12,3], [39,3,8,12,3]) = 0In the implementation version 2.0 of list ADT, we use a linked list-basedimplementation of lists. On page 13 of lecture notes LN6-2a, we show list1 and list2after a few statements are executed. For each of the code segments shown below,show the linked list-based implementation of lists list1, list2 and list3 after all thestatements in the code segment are executed (you should assume that list1, list2 andlist3 are all properly declared as listADT variables). You should also indicate what willbe outputted from each of the code segments that contain printf statements.a) list1 = Cons(4, Cons(5, Cons(6, EmptyList())));list2 = Cons(Head(list1), list1);b) list1 = Cons(3, Cons(7, Cons(6, EmptyList())));list2 = Cons(Head(list1), Tail(list1));list3 = Cons(0, list2);c) listElementT firstElement, secondElement;list1 = Cons(8, Cons(4, Cons(7, EmptyList())));firstElement = Head(list1);secondElement = Head(Tail(list1));list3 = Cons(secondElement, Tail(Tail(list1)));list2 = Cons(secondElement, Cons(firstElement, list3));d) if (listEqual(EmptyList(), EmptyList()))printf("listEqual(EmptyList(), EmptyList())\n");elseprintf("Not listEqual(EmptyList(), EmptyList())\n");if (EmptyList() == EmptyList())printf("EmptyList() == EmptyList()");elseprintf("EmptyList() != EmptyList()");e) list1 = Cons(8, Cons(4, Cons(7, EmptyList())));list3 = Tail(Tail(list1));list2 = Cons(Head(Tail(list1)), Cons(Head(list1), list3));Programming ExercisesThere are two parts in this programming exercise.a) (Part 1) In the lecture notes we have seen how to implement symbol tables usingHash tables. In the version we present in the lecture notes, we use the techniqueof separate chaining to resolve collisions. We shall call this version 1.0.Implement version 2.0 of symtabADT, in which you use quadratic probing (insteadof separate chaining) for collision resolution. You should use F(i)=iin yourimplementation. Also you should set the table size at 51. You should use thefollowing hash function.int Hash(char *s, int n) { unsigned long hashcode = 0UL; for (int i=0; s[i]!='\0'; i++) hashcode = (hashcode<<6) + (unsigned long) s[i]; return (int) (hashcode % n);}In your implementation, you should use the following definition for structsymtabCDT:typedef struct bucketT { int inUse; // This is 1 if the bucket is in use, or 0 otherwise char *key; void *value; } bucketT;struct symtabCDT { bucketT bucket[nBuckets]; };where nBuckets is constant 51 defined using #define in symtab.c.You shall need to implement at least four functions: EmptySymbolTable, Enter,Lookup, and ForEachEntryDo.Note: you only need to submit symtab.c that implements version 2.0 ofsymtabADT.b) (Part 2) Prof. Chan is teaching a course that is open to both postgraduate andundergraduate students. Prof. Chan decides to use different scales forpostgraduate and undergraduate students to convert from numeric marks togrades.The class list with marks of individual students is stored in a student data filestudentData.txt. The format of the student data file is shown as follows:218432CHAN TAI MAN78200987CHEUNG MAN MING90217748MAN TAI SUN75216639YEUNG WING KEUNG98A student’s information is stored in four separate lines in the student data file. Thefirst line is a 6-digit student number, the second line is the student’s name, andthe third line the student’s mark (which is an integer). Whether a student is apostgraduate student or an undergraduate student is indicated by his or herstudent number: if the second digit is 0, then the student is a postgraduate student;otherwise, the student is an undergraduate student. The total number of studentsis not known in advance, so you need to read the file until the end of file is reached.There is another file called the data correction file dataCorrection.txt. If there isany mistake in the studentData.txt file, then the correction information willappear in the data correction file for correction purpose. A student’s informationis stored in two separate lines in the data correction file. The first line is a 6-digitstudent number, and the second line the student’s correct mark (which is aninteger). We assume that there is only one data correction file for all teachers,that is, it might contain information about a student whose student number doesnot appear in the original student data file. This is because it is actually a correctionfor the student data file of another teacher. If this happens, the you can simplyignore it. The following is an example of the data correction file:In this case the student whose student number is 200100 does not appear in thedata file, so it can be ignored.Write a program that first reads the student data file and then the data correctionfile, and outputs the grades of each of the students in a file. The following is asample output for the above input file (the order is not important).CHAN TAI MANBCHEUNG MAN MINGAMAN TAI SUNBYEUNG WING KEUNGANote 1You must use the following implementation:You must first use typedef to define a structure type StudentT for a structurewith 3 fields.§ The first field sName is a string that stores the name of the student.§ The second field level is a value of type studentLevelT(studentLevelT level), where studentLevelT is an enum type definedastypedef enum {UG, PG} studentLevelT;§ The last field mark is an int value (int mark) that stores the student’sexamination mark.There is a function char getGrade(StudentT) to determine the grade foreach of the students.The conversion schemes for undergraduates and postgraduates are as follows:Undergraduate Postgraduate– 100 A 90 – 100 A– 86 B 75 – 89 B– 71 C 65 – 74 C– 58 D < 65 F< 50 FNote 2You should use a symbol table to store the students’ information in your program.The key is the student IDs. The data stored in the table should be pointers of typeStudentT*, which point to structures of type StudentT. For simplicity, you canassume that the table will never be full.Your program should work well using the symtab.h and symtab.c in the lecturenotes and in Part 1 of the question.Note 3To output the grades of all students, you must use a call back functionvoid displayStudentNameAndGrade(char, StudentT)to display all entries in the table (the order is not important). You may use themapping function forEachEntryDo defined in the lecture notes.

February 23, 2022 · 7 min · jiezi

关于c:蓝桥杯cPython每日练习每日刷题day9流浪的小灰灰数小灰分苹果

一,漂泊的小灰题目形容 小灰,是一只出世在逸夫楼(大略是吧╮(╯▽╰)╭)的老鼠。它从小就受到各个科技类社团的陶冶,精通c/c++等语言的编译器装置,精通Windows、Unix、linux等操作系统的开关机,是一只有文化的老鼠。它始终在逸夫楼到处游荡,寻找一个和煦的家。 有一天,他发现了ACM程序设计协会这个小家庭。在无数次目击过协会成员们舒适的日常生活后,小灰终于按捺不住心中的激动,决定退出ACM协会,成为一只ACMer(^o^/)。然而,退出协会是须要通过考试的,摆在小灰背后的是一道数学题,题目如下: 给出两个数字A和B,两个数字之间用”+”“-”“”“/”连贯,如果给出的是A+B,则计算(A-B)的值;如果给出的是A-B,则计算(A+B)的值;如给出的是A/B,则计算(AB)的值;如果给出的是A*B,则计算(A/B)的值。(你这是在难为我小灰(╯‵□′)╯︵┻━┻) 这道题对于小灰来说太过于麻烦,所以它找到了聪慧的你,请你帮帮它吧! 输出 输出数据仅有一行,蕴含一个形如A+B的式子。 输入 请你输入计算结果,不要蕴含多余的空格和换行。 样例输出 1+1样例输入 0提醒 题目保障输出数据为正整数且计算结果在int范畴内。 对于除法保障不会呈现除零谬误,运算后果间接保留整数局部即可。c++解法: #include<bits/stdc++.h>using namespace std;int main(){ char a[10000]; scanf("%s",a); int len,l=0; len=strlen(a); int flag1=0,flag2; for(int i=0;i<len;i++) { if(a[i]=='+'||a[i]=='-'||a[i]=='*'||a[i]=='/') { flag1=i; break; } } char b[10000]; for(int j=flag1+1;j<len;j++) { b[l]=a[j]; l++; } long long c,d; c=atoi(a); d=atoi(b); if(a[flag1]=='+') { cout<<c-d; } if(a[flag1]=='-') { cout<<c+d; } if(a[flag1]=='/') { cout<<c*d; } if(a[flag1]=='*') { cout<<c/d; } return 0;}心得:应用atoi函数。atoi()函数的性能:将字符串转换成整型数;atoi()会扫描参数nptr字符串,跳过后面的空格字符,直到遇上数字或正负号才开始做转换,而再遇到非数字或字符串时('\0')才完结转化,并将后果返回(返回转换后的整型数)。 二,灰数题目形容 小灰是一只灰鼠,灰鼠有一个灰数,灰数来自于灰鼠,灰鼠想求出灰数···…… 不要问我为什么这次不是小灰求算数题,你们总是让小灰做算数、剪树叶、拼拼图,小灰曾经累了,小灰不想做题,小灰只想做一只宁静的小灰鼠,然而你们想过小灰的的感触吗,没有!你们只想着让小灰做题·····……^o^/我没疯^o^/放开我……………(拖走ヽ(゜▽゜ )-C<(/;◇/~) ...

February 22, 2022 · 1 min · jiezi

关于c:线程间同步信号量控制Semaphore

上一篇生产者-消费者的例子是基于链表的,其空间能够动态分配,当初基于固定大小的环形队列重写这个程序,这次不再利用mutex而是semaphore来实现线程间同步!上一篇文章链接:https://segmentfault.com/a/11... 仍旧是生产者生产一个构造体串在链表的表头上,消费者从表头取走构造体,生产者未生产或生产的曾经被拿完,则消费者须要挂起期待. 1 #include <stdlib.h> 2 #include <pthread.h> 3 #include <stdio.h> 4 #include <semaphore.h> 5 6 #define NUM 5 7 int queue[NUM]; 8 sem_t blank_number, product_number; 9 10 void *producer(void *arg) 11 { 12 int p = 0; 13 while (1) { 14 sem_wait(&blank_number);//wait能够取得信号,使init初始化中semaphore值-1,如果减到0则挂起期待,胜利取 用后持续进行后续操作 15 queue[p] = rand() % 1000 + 1; 16 printf("Produce %d\n", queue[p]); 17 sem_post(&product_number);//能够开释上述操作所占用的资源并唤醒期待执行的下个线程,并且使semaphore的> 值+1 18 p = (p+1)%NUM;//循环队列+1 19 sleep(rand()%5); 20 } 21 } 22 23 void *consumer(void *arg) 24 { 25 int c = 0; 26 while (1) { 27 sem_wait(&product_number);//此时product线程的semophore值曾经从init中的0变1,故此处有1个资源可供wait应用,不会阻塞!取用后在此变回0,但能够执行 后续操作了。 28 //此处因为还有一个信号可供wait取用,胜利取用而后持续后续操作 29 printf("Consume %d\n", queue[c]); 30 queue[c] = 0;//取用过的队列值设为0,便于察看过程间是否同步(即是否consumer取了曾经取过的队列值:) 31 sem_post(&blank_number);//开释一个信号(此处开释的是wait后续操作所占用的线程信号)给blank_number并唤醒下一个阻塞或期待中的过程,semaphore+1 32 c = (c+1)%NUM; 33 sleep(rand()%5); 34 } 35 } 36 37 int main(int argc, char *argv[]) 38 { 39 pthread_t pid, cid; 40 41 sem_init(&blank_number, 0, NUM); 42 sem_init(&product_number, 0, 0); 43 pthread_create(&pid, NULL, producer, NULL); 44 pthread_create(&cid, NULL, consumer, NULL); 45 pthread_join(pid, NULL); 46 pthread_join(cid, NULL); 47 sem_destroy(&blank_number); 48 sem_destroy(&product_number); 49 return 0; 50 }linux环境下执行:gcc semaphore.c -o semaphore -lpthread ...

February 19, 2022 · 1 min · jiezi

关于c++:CSCI1200数据结构

CSCI-1200 Data StructuresTest 2 — Practice ProblemsNote: This packet contains selected practice problems from Test 2 from three previous years.Your test will contain approximately one third to one half as many problems (totalling ∼100 pts).1 Linked Tube Repair [ / 33 ]Alyssa P. Hacker is working on a modified linked list that is both twodimensionaland circular. A small sample with height=3 and circumference=4is shown below. Each templated Node has pointers to its 4 neighbors. Thetop and bottom edges of the tube structure have NULL pointers. But the leftand right edges wrap around, like a circularly linked list. This cylindrical tubestructure may have any number of nodes for its height and its circumference.template <class T>class Node {public:// REPRESENTATIONT value;Node<T> *up;Node<T> *down;Node<T> *left;Node<T> *right;}; 1.1 Tube repair Diagram [ / 4 ]First Alyssa wants to tackle the challenge of repairing a hole in the structure. Assume a single Node ismissing from the structure, and we have a pointer n to the Node immediately to the left of the hole. Modifythe diagram below to show all of the necessary edits for a call to repair(n,7);nup:1.2 Thinking about Tube repair Complexity [ / 3 ]The repair function should have constant running time in most cases. Describe an example structure witha single missing Node that can be repaired, but not in constant time. Write 2-3 concise and well-writtensentences. You may want to complete the implementation on the next page before answering.11.3 Tube repair Implementation [ / 13 ]Now, implement repair, which takes 2 arguments: a pointer to the Node immediately to the left of thehole and the value to be stored in the hole. You may assume a single Node is missing from the structure.sample solution: 26 line(s) of code21.4 Non-Iterative destroy tube Implementation [ / 13 ]Now write destroy_tube (and any necessary helper functions) to clean up the heap memory associatedwith this structure. The function should take a single argument, a pointer to any Node in the structure.You may assume the structure has no holes or other errors. You cannot use a for or while loop.sample solution: 17 line(s) of code32 Rehashing the Vec Assignment Operator [ / 15 ]Complete the Vec assignment operator implementation below, while minimizing wasted heap memory.Assume the allocator is most efficient when all heap allocations are powers of two (1, 2, 4, 8, 16, etc.)1 template <class T>2 Vec<T>& Vec<T>::operator=(const Vec<T>& v) {3 if (this != &v) {4 delete ;5 m_size = ;6 m_alloc = ;7 m_data = ;8 for (int i = 0; i < ; ++i) {9 m_data[i] = ;10 }11 }12 return *this;13 }Add code below to perform a simple test of the assignment operator:Vec<double> v; v.push_back(3.14159); v.push_back(6.02); v.push_back(2.71828);Is line 12 necessary? Continue your testing code above with a test that would break if line 12 was omitted.What is the purpose of line 3? Write code for a test that would break if lines 3 and 10 were omitted.43 Essay Revision: Embellishment [ / 14 ]Write a function embellish that modifies its single argument, sentence (an STL list of STL strings),adding the word “very” in front of “pretty” and adding “with a wet nose” after “grey puppy”. Forexample:the pretty kitty sat next to a grey puppy in a pretty gardenShould become:the very pretty kitty sat next to a grey puppy with a wet nose in a very pretty gardensample solution: 20 line(s) of codeIf there are w words in the input sentence, what is the worst case Big O Notation for this function? If weswitched each STL list to STL vector in the above function, what is the Big O Notation?STL list: STL vector:54 Essay Revision: Redundant Phrases [ / 15 ]Complete redundant, which takes a sentence and 2 phrases and replaces all occurrences of the first phrasewith the second, shorter phrase. For example “pouring down rain” is replaced with “pouring rain”:it is pouring down rain so take an umbrella → it is pouring rain so take an umbrellaOr we can just eliminate the word “that” (the replacement phrase is empty):I knew that there would be late nights when I decided that CS was the career for me→ I knew there would be late nights when I decided CS was the career for metypedef std::list<std::string> words;void redundant( sentence, phrase, replace) {sample solution: 19 line(s) of code}65 Don’t Ignore Compilation Warnings! [ / 15 ]Write a useful but buggy segment of code (or function) that will compile with no errors but will producethe indicated compilation warning. Put a star next to the line of code that will trigger the warning.Write a concise and well-written sentence describing the intended vs. actual (buggy) behavior of the code.warning: comparison of integers of different signs: 'int' and 'unsigned int'warning: control reaches / may reach end of non-void functionwarning: variable is uninitialized when used here / in this functionwarning: returning reference to local temporary object / reference to stack memoryassociated with a local variable returned7warning: expression result unused / expression has no effectwarning: unused variable / unused parameter6 Cyber Insecurity [ / 5 ]Ben Bitdiddle wrote the following code fragment to manage his personal information.1 std::ifstream istr("my_information.txt");2 std::string s;3 std::vector<std::string> data;4 while (istr >> s) { data.push_back(s); }5 std::vector<std::string>::iterator password = data.begin()+4;6 data.push_back("credit_card:");7 data.push_back("1234-5678-8765-4321");8 data[4] = "qwerty";9 std::cout << "my password is: " << *password << std::endl;my information.txtname: Ben Bitdiddlepassword: pa$$wordSSN: 123-45-6789Write “True” in the box next to each true statement. Leave the boxes next to the false statements empty.Lines 2 & 3 will produce an “uninitialized read” error when run under gdb or lldb.Line 5 is not a valid way to initialize an iterator.Ben’s credit card information is not saved back to the file.This program might behave differently if re-run on this computer or another computer.A memory debugger might detect an “unaddressable access of freed memory” error on Line 9.If we move lines 6 & 7 after line 9, this code fragment will run without memory errors.This code contains memory leaks that can be detected by Dr. Memory or Valgrind.These password choices disqualify Ben from any job in computer security.87 Boxy Storage Solutions [ / 25 ]Eva Lu Ator is working on her capstone project to manage physical storage facilities. She’s mapped outthe overall design and started implementation of the two classes.class Box {public:Box(int w, int d, int h) :width(w), depth(d), height(h) {}int width;int depth;int height;};BwidthdepthheightACStorage storage(4,3,2);assert (storage.available_space() == 24);Box *a = new Box(2,2,2);assert (storage.add(a,0,0,0));Box *b = new Box(3,2,1);assert (!storage.add(b,2,0,0));delete b;Box *b_rotated = new Box(2,3,1);assert (storage.add(b_rotated,2,0,0));Box *c = new Box(1,1,1);assert (storage.add(c,2,0,1));assert (storage.available_space() == 9);class Storage {public:Storage(int w, int d, int h);// FILL IN FOR PART 1bool add(Box *b, int w, int d, int h);int available_space();private:void remove(Box *b, int w, int d, int h);Box **data;int width;int depth;int height;};bool Storage::add (Box *b, int w, int d, int h) {for (int i = w; i < w+b->width; i++) {if (i >= width) return false;for (int j = d; j < d+b->depth; j++) {if (j >= depth) return false;for (int k = h; k < h+b->height; k++) {if (k >= height) return false;if (datai[k] != NULL) return false;}}}for (int i = w; i < w+b->width; i++) {for (int j = d; j < d+b->depth; j++) {for (int k = h; k < h+b->height; k++) {datai[k] = b;}}}return true;}97.1 Missing functions from Storage Class Declaration [ / 5 ]Her friend Ben Bitdiddle doesn’t remember much from Data Structures, but he reminds her that classeswith dynamically-allocated memory need a few key functions. Fill in the missing prototypes for PART 1.7.2 Storage Destructor [ / 20 ]Eva explains to Ben that the private remove member function will be useful in implementing the destructor.First write the remove member function:sample solution: 10 line(s) of codeNow write the Storage class destructor:sample solution: 14 line(s) of code108 Transpose Linked Grid [ / 27 ]Louis B. Reasoner is working on a new member function for our Homework 5 Linked Grid named transpose.This function should mirror or flip the elements along the diagonal. Here’s a sample grid with integer dataand how it prints before and after a call to transpose:grid.print();std::cout << std::endl;grid.transpose();grid.print();1 2 3 48 7 6 59 10 11 121 8 92 7 103 6 114 5 12template <class T>class Node {public:// REPRESENTATIONT value;Node<T> *up;Node<T> *down;Node<T> *left;Node<T> *right;}; 8.1 Diagram [ / 7 ]First neatly modify the diagram of this smaller grid below to show all of the necessary edits that must beperformed by a call to transpose().:upper_leftup:down:right:value::leftup:down:right:value::leftup:down:right:value::leftup:down:right:value::leftup:down:right:value::leftup:down:right:value::leftheight:upper_right:width::lower_left lower_left:Grid<int>NULLNULL NULL NULLNULLNULLNULL NULL NULLNULL4 5 61 2 33 28.2 Complexity Analysis [ / 5 ]What is the Big ’O’ Notation for the running time of the transpose() member function? Assume the gridwidth is w and the height is h. Write 1-2 concise and well-written sentences justifying your answer. Youprobably want to complete the implementation on the next page before answering.118.3 Implementation [ / 15 ]Louis has suggested that we first implement a helper non-member function named swap, which will makethe implementation of transpose more concise.sample solution: 5 line(s) of codeNow implement transpose, as it would appear outside of the Grid class declaration.sample solution: 16 line(s) of code129 Organizing Words [ / 30 ]Alyssa P. Hacker is working on a program to clean up a dataset of words. The task is to write a functionnamed organize_words that takes in an STL vector of STL lists of words (STL strings). The functionshould organize the words into groups by word length, and ensure that the words are sorted within eachgroup. Many or most of the words will already be in the right place. That is, they will already be in theslot of the vector that matches the length of the word. And the neighboring words in each slot/list willalready be mostly alphabetized.For example, given the data shown on the left, your implementation should move the four misplaced wordsto produce the data shown on the right.01 diamond23 gem malachite4 jade opal rock ruby5 geode pearl talc stone topaz6 garnet quartz gypsum7 amethyst azurite emerald8 fluorite sapphire90123 gem4 jade opal rock ruby talc5 geode pearl stone topaz6 garnet gypsum quartz7 azurite diamond emerald8 amethyst fluorite sapphire9 malachiteTo make the problem a little more “fun”, you are NOT ALLOWED to use:• the STL vector subscript/indexing operator, [ ], or .at(),• the STL sort function, or• any of the push or pop functions on vector or list.You may assume that the initial vector has at least as many slots as the longest word in the structure.9.1 Complexity Analysis - Big ’O’ Notation [ / 6 ]Once you’ve finished your implementation on the next pages, analyze the running time of your solution.Assume there are w total words in the whole structure, v slots in the vector, a maximum of m wordsper list, and x words are misplaced and need to be moved. Write 2-3 concise and well-written sentencesjustifying your answer.139.2 Helper Function Implementation [ / 12 ]Alyssa suggests writing a helper function named place that will place a word in the correct location in thestructure. Work within the provided framework below. Do not add any additional for or while loops.void place( ) {sample solution: 2 line(s) of codewhile ( ) {sample solution: 3 line(s) of codewhile ( ) {sample solution: 5 line(s) of code}sample solution: 5 line(s) of code}}149.3 Organize Implementation [ / 12 ]And now write the organize function, which calls the place function. Again, work within the providedframework below and do not add any additional for or while loops.void organize_words( ) {sample solution: 2 line(s) of codewhile ( ) {sample solution: 2 line(s) of codewhile ( ) {sample solution: 8 line(s) of code}sample solution: 2 line(s) of code}}1510 Merge-Spiration: Recursive Interval Computation [ / 15 ]Ben Bitdiddle was inspired by the recursive merge sort examplefrom Data Structures lecture and proposes it as a guide to computethe smallest interval that contains a collection of floating pointnumbers (e.g., the minimum and maximum). Implement Ben’s idea,a recursive function named compute interval that takes in an STLvector of floats and returns an Interval object.For example: 6.2 4.3 10.4 2.5 8.4 1.5 3.7 → [1.5, 10.4]class Interval {public:Interval(float i, float j): min(i), max(j) {}float min;float max;};sample solution: 12 line(s) of codeWithout resorting to personal insults, explain in two or three concise and well-written sentences why Ben’sidea isn’t going to result in significant performance improvements. Be technical.1611 How many DS students to change a lightbulb? [ / 38 ]In this problem you will complete the implementation of two new classes named Bulb and Lamp. We beginwith an example of how these classes are used.First, we create a new lamp that will hold 3 bulbs and make a note of the manufacturer’s recommendedbulb: a 60 watt bulb with an estimated lifetime of 300 hours from Phillips. Note that initially this lamphas no bulbs installed. We install one of manufacturer’s recommended bulbs and use the lamp (turn it“on”) for a total of 50 hours.Lamp floorlamp(Bulb(60,300,"Phillips"),3);bool success;success = floorlamp.install(); assert(success);floorlamp.On(50);assert (floorlamp.getTotalWattage() == 60);Next, we attempt to install 3 bulbs, another of the manufacturer’s recommended bulbs, and then two otherbrands of bulbs. The installation of the 3rd bulb made by Sylvania fails because there are no availablesockets slots in the lamp and no bulbs are burnt out and need replacement.success = floorlamp.install(); assert(success);success = floorlamp.install(Bulb(40,120,"GE")); assert(success);success = floorlamp.install(Bulb(120,500,"Sylvania")); assert(!success);We then use the lamp for another 100 hours. Once the wattage drops (due to a burnt out bulb), we againtry to install the Sylvania bulb and it is successful.floorlamp.On(100);assert (floorlamp.getTotalWattage() == 160);floorlamp.On(50);assert (floorlamp.getTotalWattage() == 120);success = floorlamp.install(Bulb(120,500,"Sylvania")); assert(success);assert (floorlamp.getTotalWattage() == 240);Finally, we create a duplicate lamp. Note that when we do this, we match the bulbs currently installed inthe original lamp, but the bulbs installed in the new lamp are brand new (and unused).Lamp another(floorlamp);assert (floorlamp.getTotalWattage() == another.getTotalWattage());for (int i = 0; i < 10; i++) {floorlamp.On(50);another.On(50);std::cout << "compare " << floorlamp.getTotalWattage() << " "<< another.getTotalWattage() << std::endl;}Which results in this output:compare 240 240compare 240 240compare 180 240compare 120 240compare 120 240compare 120 240compare 120 120compare 120 120compare 120 120compare 120 12011.1 Bulb Class Declaration [ / 14 ]The Bulb class is missing only one function. You will need to read the rest of the problem to determine what’smissing. Fill in the missing function – implement the function right here, within the class declaration.17class Bulb {public:// constructorsBulb(int w, int l, const std::string &b) :wattage(w),lifetime(l),hours_used(0),brand(b) {}sample solution: 2 line(s) of code// accessorsint getWattage() const { return wattage; }bool burntOut() const { return hours_used > lifetime; }const std::string& getBrand() const { return brand; }// modifiervoid On(int h) { hours_used += h; }private:// representationint wattage;int lifetime;int hours_used;std::string brand;};11.2 Lamp Class Declaration [ / 14 ]The Lamp class has a few more missing pieces. Read through the rest of the problem before attempting to fillthis in. Write the prototypes (not the implementation!) for the four missing functions. You will implementsome of these missing functions later. Also, fill in the member variables for the Lamp representation.Important: You may not use STL vector on this problem.class Lamp {public:// constructors, assignment operator, destructorsample solution: 4 line(s) of code18// accessorint getTotalWattage() const;// modifiersbool install(const Bulb &b = Bulb(0,0,""));void On(int h);private:// representationsample solution: 3 line(s) of code};Lamp Class ImplementationHere’s the implementation of one of the key member functions of the Lamp class.bool Lamp::install(const Bulb &b) {// first, let's figure out where to install the bulbint which = -1;for (int i = 0; i < max_bulbs; i++) {// check for an empty socketif (installed[i] == NULL) {which = i;break;}// or a socket that contains a burnt out bulbif (installed[i]->burntOut()) {which = i;delete installed[i];break;}}// return false if we cannot install this bulbif (which == -1) return false;if (b.getWattage() == 0) {// install the manufacturer's recommended bulb typeinstalled[which] = new Bulb(recommended);} else {// install the specified bulbinstalled[which] = new Bulb(b);}return true;}On the last two pages of this problem you will implement three important functions for the Lamp class, asthey would appear outside of the class declaration (in the lamp.cpp file) because their implementationsare > 1 line of code.1911.3 Lamp Constructor [ / 9 ]sample solution: 7 line(s) of code11.4 Lamp Destructor [ / 5 ]sample solution: 8 line(s) of code2011.5 Lamp Assignment Operator [ / 9 ]sample solution: 10 line(s) of code2112 Singly Linked List Subsequence Sum [ / 18 ]Write a recursive function named FindSumStart that takes the head Node of asingly-linked list storing positive numbers. The function should return a pointerto the Node that begins a subsequence of numbers that ends in the sum of thatsubsequence. For example, given this sequence: 5 1 4 2 3 9 6 7 the functionshould return a pointer to the Node storing 4, because 4 + 2 + 3 = 9.template <class T>class Node {public:Node(const T& v): value(v),next(NULL) {}T value;Node* next;};sample solution: 15 line(s) of codeAssuming the sequence has n numbers, what is the order notation for the running time of your function?2213 Reverse Splice [ / 20 ]Write a function named reverse_splice that takes in 3 arguments: an STL list named data and twoiterators i and j. The function should reverse the order of the data between those iterators. For example,if data initially stores this sequence: 1 2 3 4 5 6 7 8 9 and i refers to 3 and j refers to 7, then afterthe call reverse_splice(data,i,j), data will contain: 1 2 7 6 5 4 3 8 9 , i will refer to element 7,and j will refer to element 3. Your function should return true if the operation was successful, and false ifthe request is invalid. Note: Your function may only use a constant amount of additional memory.sample solution: 21 line(s) of code2314 Doubly Linked Factorization [ / 17 ]class Node {public:Node(int v) :value(v),next(NULL),prev(NULL) {}int value;Node* next;Node* prev;};Write a recursive function named Factor that takes in two arguments, pointers to the head and tail Nodesof a doubly linked list. This function should look for a non-prime number in the linked list structure, breakthe Node into two Nodes storing two of its factors, and then return true. If all elements are prime thefunction returns false. For example, if we start with a 3 element list containing 35 30 28 and repeatedlycall Factor:PrintNodes(head);while (Factor(head,tail)) { PrintNodes(head); }This is the output:35 30 285 7 30 285 7 2 15 285 7 2 3 5 285 7 2 3 5 2 145 7 2 3 5 2 2 75 7 2 3 5 2 2 7You may write a helper function. You do not need to write the PrintNodes function. ...

February 18, 2022 · 15 min · jiezi

关于c++:CMDA-3634-图像处理

CMDA 3634 SP2020 The Wave Equation with C Project 02Project 02: The Wave Equation with CVersion: Current as of 2021-02-27 11:01:25Due:– Preparation: 2021-02-27 23:59:00– Coding & Analysis: 2021-03-12 23:59:00 (24 hour grace period applies to this due date.)Points: 100Deliverables:– Preparation work as a PDF, typeset with LaTeX, through Canvas.– All code through code.vt.edu, including all LaTeX source.– Project report and analysis as a PDF, typeset with LaTeX, through Canvas.Collaboration:– This assignment is to be completed by yourself.– For conceptual aspects of this assignment, you may seek assistance from your classmates. In your submissionyou must indicate from whom you received assistance.– You may not assist or seek assistance from your classmates on matters of programming, code design, orderivations.– If you are unsure, ask course staff.Honor Code: By submitting this assignment, you acknowledge that you have adhered to the Virginia TechHonor Code and attest to the following:I have neither given nor received unauthorized assistance on this assignment. The work I am presentingis ultimately my own.References C:– Introduction to C https://www.cprogramming.com/... The Wave Equation:– General overview https://en.wikipedia.org/wiki... https://mathworld.wolfram.com... OpenStax: Mathematics of Waves (link)– Standing Waves (especially in 2D with a rectangular boundary) https://en.wikipedia.org/wiki...– Chapter 5.1 of Gilbert Strang’s course notes “5.1 Finite Difference Methods” https://math.mit.edu/classes/...– Chapter 5.3 of Gilbert Strang’s course notes “5.3 The Wave Equation and Staggered Leapfrog” https://math.mit.edu/classes/... LaTeX:– Writing pseudo-code in Latex: https://en.wikibooks.org/wiki...– General topics: https://www.overleaf.com/learn1CMDA 3634 SP2020 The Wave Equation with C Project 02Code Environment For this project, use a terminal-based programming environment.– Use a terminal-based editor such as Vim, Emacs, or nano.– Compile your project from the terminal with make.– In particular, do NOT use IDEs such as Visual Studio or Eclipse. All necessary code must be put in your class Git repository. Your Git repository must have the following structure:cmda3634/projects/proj02/code/data/report/ Data and any scripts which are necessary to recreate your data, must be in the data directory.DO NOT INCLUDE LARGE NUMBERS OF IMAGE FILES OR LARGE VIDEO FILES IN YOURGIT REPOSITORY! Your tex source for project preparation and final report go in the report directory. Remember: commit early, commit often, commit after minor changes, commit after major changes. Pushyour code to code.vt.edu frequently. You must separate headers, source, and applications. You must include a makefile. You must include a README explaining how to build and run your programs.2CMDA 3634 SP2020 The Wave Equation with C Project 02RequirementsPreparation (20%) ...

February 17, 2022 · 11 min · jiezi

关于c#:ASPNET与NET-Framework和C的关系

你好,是我琉忆。明天咱们讲一讲ASP.NET与.NET Framework和C#的关系。 在开始介绍ASP.NET之前,咱们须要先理解以下运行ASP.NET的开发平台.NET框架。如果你之前学过C#那么对.NET框架会有肯定的理解。当你在编写ASP.NET代码时会发现ASP.NET的代码和C#相近甚至等同。那么你肯定会有一些疑难。他们三者是什么关系呢?咱们一起来看看。 一、.NET Framework介绍Microsoft.net是2000年6月22日微软向全世界推出的,全新的软件开发和服务平台,目标是向全世界的客户提供弱小的、个性化的互联网服务。从2002年公布最后的版本1.0,到2012年正式推出4.5,共经验了1.0、1.1、2.0、3.0、3.5 、4.0、4.5、4.7八个版本。 .NET的外围就是.NET Framework(.Net框架)是.NET程序开发和运行的环境,在这个平台下能够用不同的语言进行开发,因为.NET是跨语言的一个平台。语言能够是C#,F#,Visual Basic.NET等等。JAVA和.NET不同的是java是跨平台的,不跨语言的。.NET跨平台仅限于安卓零碎和IOS苹果零碎。 1、.NET Framework蕴含以下两个次要组件: CLR:公共语言运行库(Common Language Runtime),提供外在治理,代码安全性检测等性能。 FLC:.NET框架类库(.NET Framework Class Library),提供大量利用类库,类库中有很线程的资源可应用(比方:类、办法、属性)提高效率。 它的底层构造如图:2、公共语言运行时(CLR) .NET Framework 的外围是其运行库的执行环境,称为公共语言运行时(CLR)或.NET运行库。通常将在CLR的管制下运行的代码称为托管代码。 CLR次要负责托管代码的编译和运行。在.NET中代码的编译分为两个阶段: (1)把源代码编译为Microsoft两头语言(MSIL Microsoft Intermediate Language)。 (2)CLR把MSIL编译为平台专用的机器代码。 3、CLR的构造 CLR的构造由以下三局部组成: ①CLS:公共语言标准,获取各种语言转换成对立的语法标准。 ②CTS:通用类型零碎,将各种语言中的数据类型转换成对立的类型 ③JIT:实时编译器(即时编译器)用于将转换之后的语言编译为二进制语言,交给CPU执行。 4、.NET框架类库(FCL) .NET框架类库提供了实现基本功能的类,例如输入输出、字符串的操作、网络通信等。 .NET Framework中,所有的命名空间都是从System的命名空间造成的。System命名空间又称为根命名空间。对应命名空间的作用如下图所示: 【如果你还没关注我的话,能够点点关注,每天更新文章我告诉你。】 二、C# 随着.NET 平台的诞生,微软推出了配合 .NET平台的利用程序开发语言——C#(C Sharp)。 学习C#语言,能开发什么样的程序呢?能够开发的程序如下图: C#是一个.NET平台下的一个编程设计语言,仅仅是一个语言。是运行在.NET CLR上的,用于创立应用程序的高级语言。程序设计语言是为了不便开发人员和计算机沟通工具。 C#.NET应用程序编译步骤如下: 1、应用C#语言编写利用程序代码; 2、把C#源程序编译为Microsoft两头语言(MSIL Microsoft Intermediate Language),以程序集的模式存在; 3、在执行代码时,必须应用JIT编译器将程序集编译老本机代码; 4、在托管的CLR环境下运行本机代码,程序执行结果显示进去; 三.ASP.NET ASP.NET 是微软 .NET 体系提供的 Web 开发框架,是网站开发的技术,是.NET框架中的一个利用模型,用于生成基于Web的应用程序的内容丰盛的编程框架。应用ASP.NET开发Web应用程序并维持其运行,比其余开发语言更加简略。与Java、PHP和Per等高级技术相比,ASP.NET具备方便性、灵活性、生产效率高、安全性高及面向对象等长处,是目前支流的网络编程技术之一。 ASP.NET 反对 3 种开发模式: 1、Web Pages ...

February 17, 2022 · 1 min · jiezi

关于c++:PIC-10B-解析

PIC 10B Homework 5 Due Wednesday, March 10Problem 1:Using good coding practices, design your own Linked List of int types. It will consistof classes List, Node, and Iterator granting friendship and defining functions as needed.Write constructors, destructors, and all necessary member functions such as insert, erase,increment and decrement operators, operator* to dereference, as well as operator== andoperator!= to check whether two iterators are pointing to the same element. You will thenuse this list to write the following member functions:(1) List::reverse to reverse your nodes(2) List::push front to add a value to the beginning of a list(3) List::sort to sort the elements of a linked list (without copying them into a vector oranother data type)(4) List::merge which accepts another List object and merges the two lists into one, alternatingelements from each list such that merging 1 7 12 and 8 3 11 2 2 1 yields the list 18 7 3 12 11 2 2 1.Write a main function to test your list such that it follows the output shown in Figure 1.Figure 1: sample output.Due Wednesday, March 10 Homework 5 PIC 10BGood Coding Practices:• think about cross-platform. Don’t use Windows or Mac only commands. For example,pause == cin.get() twice, write many \n vs. system(clear) or system(’cls).• passing objects by reference & or const & when possible• using field initializer list when possible in all constructorsInstructions for submission:• Name your files exactly hw5.cpp, List.h, List.cpp, Node.h, Node.cpp, Iterator.h,and Iterator.cpp.• You may not use #include "stdafx.h".• Add code description in the comment at the beginning of the file.A sample description may look like:/*PIC 10B 2A, Homework 1Purpose: Tic-tac-toe gameDate: 10/10/2019*/• Submit your header files and source codes to CCLE in separate files. Only .h and .cppfiles should be uploaded. ...

February 17, 2022 · 2 min · jiezi

关于c#:net-core下分表分库解决方案多租户

介绍本期配角:ShardingCore 一款ef-core下高性能、轻量级针对分表分库读写拆散的解决方案,具备零依赖、零学习老本、零业务代码入侵 dotnet下惟一一款全自动分表,多字段分表框架,领有高性能,零依赖、零学习老本、零业务代码入侵,并且反对读写拆散动静分表分库,同一种路由能够齐全自定义的新星组件,通过本框架你岂但能够学到很多分片的思维和技巧,并且更能学到Expression的奇思妙用 你的star和点赞是我坚持下去的最大能源,一起为.net生态提供更好的解决方案 我的项目地址github地址 https://github.com/xuejmnet/s...gitee地址 https://gitee.com/dotnetchina...背景因为之前有小伙伴在应用ShardingCore的时候问过我是否能够利用ShardingCore的分库性能实现多租户呢,我的答复是能够的,然而须要针对分库对象进行路由的编写,相当于我一个我的项目须要实现多租户所有的表都须要实现分库才能够,那么这个在理论利用中将是不切实际的,所以尽管分库能够用来进行多租户然而个别没人会真的这样操作,那么就没有方法在ShardingCore应用正当的多租户外加分表分库了吗,针对这个问题ShardingCore在新的版本x.4.x.x+中进行了实现 性能ShardingCorex.4.x.x+版本中具体实现了哪些性能呢 多配置反对,能够针对每个租户或者这个配置进行独自的分表分库读写拆散的链接配置多数据库配置,反对多配置下每个配置都能够领有本人的数据库来进行分表分库读写拆散动静多配置,反对动静增加多配置(目前不反对动静删减多配置,后续会反对如果有须要)场景假如咱们有这么一个多租户零碎,这个零碎在咱们创立好账号后会调配给咱们一个独自的数据库和对应的表信息,之后用户能够利用这个租户配置信息进行操作解决 首先咱们创立一个AspNetCore的我的项目这边才用的.Net6版本的webapi 增加依赖 这边咱们增加了三个包,别离是ShardingCore,Microsoft.EntityFrameworkCore.SqlServer,Pomelo.EntityFrameworkCore.MySql,其中ShardingCore用的是预览版的如果不勾选那么将无奈显示进去,为什么咱们须要增加额定的两个数据库驱动呢,起因是因为咱们须要在不同的租户下实现不同的数据库的配置,比方租户A和咱们签订的协定外面有阐明零碎应用开源数据库,或者心愿应用Linux平台那么能够针对租户A进行配置MySql或者PgSql,租户B是资深软粉说须要应用MSSQL那么就能够针对其配置MSSQL.个别状况下咱们可能不会呈现多数据库的状况然而为了关照到非凡状况咱们这边也针对这种状况进行了反对。 公共用户存储首先在我还没有创立租户的时候是不存在数据库的所以我的数据自然而然不会存在以后租户下,这边咱们采纳的是存储到其余数据库中,假如咱们应用一个公共的数据库作为用户零碎. 创立用户零碎创立零碎用户和创立零碎用户在数据库内的映射关系 public class SysUser { public string Id { get; set; } public string Name { get; set; } public string Password { get; set; } public DateTime CreationTime { get; set; } public bool IsDeleted { get; set; } } public class SysUserMap:IEntityTypeConfiguration<SysUser> { public void Configure(EntityTypeBuilder<SysUser> builder) { builder.HasKey(o => o.Id); builder.Property(o => o.Id).IsRequired().IsUnicode(false).HasMaxLength(50); builder.Property(o => o.Name).IsRequired().HasMaxLength(50); builder.Property(o => o.Password).IsRequired().IsUnicode(false).HasMaxLength(50); builder.HasQueryFilter(o => o.IsDeleted == false); builder.ToTable(nameof(SysUser)); } }创立这个数据库该有的配置信息表,便于前期启动后重建 ...

February 16, 2022 · 6 min · jiezi

关于c++:深入理解C对象模型开始由virtual继承说起

0 引言最近在工作之余,从新拾起了深度摸索C++对象模型 这本书,想要进一步温习了解 C++对象模型相干的原理。 以往看这本书,仅仅是浮于外表,并没有入手去实现和验证书中所说的内容。因而这次,便想既然再度学习,那么就深刻去看一看目前风行的编译器对C++对象模型 是如何实现的。故有了本专题。 目前应用较宽泛的编译器有gcc,clang, msvc,但作为C++后盾开发置信应用gcc,clang较多,而我也是应用两者较多,因而 本专题中以gcc编译器为主,次要深入研究其对C++对象模型的实现。 如果你感觉深度摸索C++对象模型 让你深入了内力,想要进一步摸索古代编译器对其的实现,进一步加深相应的了解,那心愿本专题会对你有所帮忙。 学习本专题,须要你先学习深刻了解计算机系统(原书第3版) 次要相熟 ATT汇编,根本的函数调用规定等, 同时也须要你学习了深度摸索C++对象模型 这本书,毕竟,本专题以此书为主。 此外,你须要相熟GDB, 特地是如下几个命令, 具体的解说 可参考后续链接局部 set print pretty onset print vtbl onset print object on也心愿你能常常应用如下两个在线工具: https://cppinsights.io/ godblot 本专题所应用的机器环境如下 uname -aLinux qls-VirtualBox 5.11.0-38-generic #42~20.04.1-Ubuntu SMP Tue Sep 28 20:41:07 UTC 2021 x86_64 x86_64 x86_64 GNU/Linuxgcc编译器版本为 gcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04)最初,自己也只是因为趣味而想进一步钻研,两头可能会有些了解不对的中央,欢送大家随时斧正;同时因为工作比较忙,因而我可能会断断续续更新该专栏。 1 故事的开始对于C++对象模型,咱们以深度摸索C++对象模型 第三章开篇所给的例子说起,其例子如下 #include <iostream>#include <string>class X {};class Y : public virtual X {};class Z : public virtual X {};class A : public Y, public Z {};int main() { std::cout << "sizeof(X): " << sizeof(X) << "\n"; std::cout << "sizeof(Y): " << sizeof(Y) << "\n"; std::cout << "sizeof(Z): " << sizeof(Z) << "\n"; std::cout << "sizeof(A): " << sizeof(A) << "\n"; return 0;}上述例子很简略,通过我的试验,在我的环境下上述输入的后果为 ...

February 16, 2022 · 2 min · jiezi

关于c:COMP281-讲解

COMP281 2020-2021 – Assignment 2• In the following, you will find the problems that constitute Assignment 2. They will be also availableon the online judging (OJ) system available at https://student.csc.liv.ac.uk...• You need to write a C program (not C++ or C#) that solves each problem – it must read the input, asspecified in the problem description then print the solution to the given problem for that input.o Note that code is “correct” only if it correctly implements a solution to the problem statedin the assignment, not "if online judge accepts it".o That is, even if OJ accepts your code, it could be wrong. Read the problems carefully.• Input is read from the standard input, in the same way that you read input from the keyboard as shownin lectures (e.g., using scanf). Output is also printed to the standard output, as you have seen (e.g.,using printf).• When you are satisfied that your C programs work correctly, you must submit them through thedepartmental submission system.o Even if the program is not correct, still submit whatever you have! You can still earn points ifcertain parts of the code are done right.• You must also include a brief report describing your solutions to the problems. This should bemaximum two sides of A4 paper and should give a description of how each of your solutions works.This should include describing the algorithm used to reach the solution, describing your use of any Clanguage features (that were not discussed in lectures) and identifying any resources that you haveused to help you solve the problems.• This assignment is worth 50% of the total mark for COMP281.o Both problems are weighted equally.o For each problem, you can earn a total of 50 points§ 25 points for “Functionality and Correctness” awarded for programs that correctlysolve the problem for all test cases.§ 20 points for “Programming style, use of comments, indentation and identifiers”awarded depending on the style, comments and efficiency of the solution§ 5 points for the quality and depth of the accompanying reporto The final grade results from normalising the earned points to a scale of 100.o See separate “comp281-detailed-marking-guidelines.pdf” for more details.Submission Instructions• Create a folder, and name it using your Student ID and User ID, e.g. 201234567_sgpj6• In the folder, there should be 3 files:o 1 report file, in PDF format. Name it with your Student ID and User ID, e.g.201234567_sgpj6.pdfo 2 source code files. Name each using the Problem Number, e.g. 1006.c§ In your source code, include your Student Info and Problem Info, e.g.:/* ...

February 16, 2022 · 8 min · jiezi

关于c++:Comp-218EC-面向对象编程

Concordia UniversityComp 218/EC – Winter 2021Fundamentals of Object Oriented ProgrammingAssignment 2__Deadline: By 11:59pm Friday March 12th , 2021.Evaluation: 2.5 % of your final gradeLate Submission: Late assignments will be discounted by 25%. Late assignments are accepted up to 5days late (grace period) and weekends count.Teams: The assignment is to be done individually.Purpose: The purpose of this assignment is to have you experience the basic steps involved inwriting a complete C++ program (from algorithm development to coding) and topractice with string data type variables, selection statements and the whilerepetition statement.General Guidelines When Writing Programs:Same as for assignment #1 – Refer to assignment #1 handout for details.RECOMMENDATION for this Assignment:Take the time to write out an algorithm for these problems to help clarify the logic BEFORE you startprogramming. (No need to hand in the algorithm.)Question #1: Speed System Program (6 pts)In this question, you will write a program that determines the penalty of a driver who is speeding onhighway with the speed limit of 100km/h based on Ontario Courts.Your program should follow the following rules:• Prompt the user to enter name, id and score and validates the information.• The student name should be entered as “LastName, FirstName” (separated by comma).Please note the whole name should be saved in one string.• The driver ID must have 7 digits.• The driver’s SPEED must greater than 0.• If the user enter correct information, your program should display the fine based on thespeed. When the fine is displayed, the output should be“FirstName LastName got SPEED. Based on the speed system, FirstName (ID) will pay X.”Please note the calculation of X is based on the following rules: ...

February 16, 2022 · 5 min · jiezi

关于c#:MASA-Framework-DDD设计1

DDD畛域驱动设计是一个无关软件开发的方法论,它提出基于畛域开发的开发模式,基于DDD实践,咱们能够设计出高质量的软件模型。 它围绕业务概念构建畛域模型来管制业务的复杂度,解决软件难以了解和演变的问题。 微服务微服务是一种架构格调,通过过程间通信、容错和故障隔离等形式,实现去中心化的服务治理。 DDD与微服务它们都是高内聚、低耦合,从业务视角拆散复杂度,进步响应能力。 高内聚:把相干的业务汇集在一起 低耦合:把关联性较低的拆分为独立的服务 应用DDD搭建微服务咱们将取得以下劣势: 设计清晰,标准基于畛域模型,有利于畛域常识的传递和传承帮忙团队建设良好的沟通帮助零碎架构的演进进步团队的设计能力(面向对象,架构)设计畛域设计波及技术与业务,如何让它们合作起来呢? 策略设计(业务)畛域、子域、限界上下文 将畛域拆分成子域,并划分外围子域、撑持子域和通用子域以子域开展事件风暴,依据上下文语义划分限界上下文,建设通用语言,实现领域建模领域建模将作为能力核心布局的重要依据实现能力核心地图和优先级后,作为微服务设计的输出实现战术设计战术设计(技术)聚合、聚合根、实体、值对象、畛域服务等 依照畛域模型实现微服务设计和落地建设聚合、聚合根、实体、值对象、畛域服务等对象之间的依赖关系,以代码对象的模式映射到服务中,采纳分层架构实现微服务设计和落地 分层架构能够采纳Clean ArchitectureDDD实际过程咱们将通过DDD + Clean Architecture实现业务与技术的残缺落地 对立语言(策略设计)对立: 畛域模型术语DDD模式名称技术: 技术设计术语技术术语技术设计模式业务: 畛域模型术语DDD模式名称业务术语设计无关的业务术语 事件风暴(策略设计)Event Storming是一种领域建模的实际,能够让畛域相干人员疾速了解业务模型 残缺流程包含如对立语言、提出畛域事件、规定、命令、读模型、角色、划分子域、票选、补充商机与价值等, 接下来咱们先精简一点步骤 流动筹备人:业务人员,领域专家,技术人员,架构师,测试等 看板:能够将事件流可视化的白板或者画图工具等 黑白贴纸:填写事件,命令等 业务场景规定业务场景,上面我以一个电商我的项目为例 事件风暴后果 命令风暴后果 寻找聚合聚合:一组相干畛域模型的汇合,尽量保障封装业务的不变性,确保关联关系严密的畛域模型内聚 按事件程序顺次剖析三个问题 事件扭转的畛域模型是什么畛域模型是否能够独立拜访,是就是聚合不能独立拜访,须要通过哪个畛域模型(聚合)来拜访,将其放到对应聚合内命令贴在聚合右边代表输出,事件贴到聚合左边代表输入测验是否合乎聚合规定,不匹配的从新调整聚合聚合后果寻找聚合过程中可能会因为业务连接产生新的输出命令,以虚线示意 划分限界上下文限界上下文:某个场景或环境下的业务边界 基于聚合和畛域模型,判断它们要解决的业务问题,如果是同一个问题则放到一个限界上下文中,否则就拆分如果一个聚合同时解决多个问题,则须要对聚合进行拆分,将拆分后的聚合划分到不同的限界上下文解决的业务问题大小(变动起因,外在逻辑等)需与领域专家共同完成限界上下文后果 界线上下文映射当上下文很多的时候,不同的团队负责不同的上下文,为了保障无效的工作能够定义不同的上下文之间的关系来创立一个所有模型上下文的全局视图。两个上下文之间是有方向的,上游(U或Upstream),上游(D或Downstream) 界线上下文映射后果 子域一个业务畛域或子域是一个业务范围。一个业务畛域或子域能够包含多个业务能力,一个业务能力对应一个服务。 外围子域指业务胜利的次要促成因素,是企业的外围竞争力。 通用子域被整个业务零碎应用。 撑持子域是实现业务的必要能力,但不是胜利的因素。 除了下面限界上下文后果中标注的子域外,还能够扩大出财务,市场,洽购等子域畛域对象关系(战术设计)合成聚合,提取该聚合蕴含的畛域对象 畛域对象的业务不变性畛域对象具备统一的生命周期 定义实体与值对象(战术设计)实体:存在唯一性标识,实体间是否相等的判断根据也是惟一标识 值对象:示意属性的不变值 以订单聚合为例: 订单聚合蕴含订单实体,订单行实体订单实体蕴含收货地址值对象架构设计咱们简略的把架构设计看作是三个层面: 业务架构:依据业务需要设计业务模块及其关系 DDD的领域建模其实就曾经帮助咱们做了业务架构和零碎架构零碎架构:设计零碎与子系统的模块及其关系 在DDD中业务架构是能够间接映射到零碎架构上的 业务变动会演变为零碎架构变动,影响到技术架构变动 技术架构:设计技术和框架细节 技术架构(微服务)则解决子系统之间的解耦,去中心化的服务治理和数据治理Clean Architecture寻找聚合时咱们提到过输出和输入。而Clean Architecture与DDD汇合后就非常适合作为采纳DDD方法论的架构落地领导 为了更好的落地读模型设计(查问业务比拟往往占八成以上),搭配CQRS可能是个不错的抉择。 CQRS劣势在于职责拆散,进步零碎性能、可扩展性、安全性等。也能够从数据驱动转为事件驱动。 要理解CQRS能够看第二篇 MASA Framework - EventBus设计 示例能够参考MASA EShop源码:https://github.com/masalabs/M... 除了DDD以外,咱们还提供了EventBus、Dapr、CQRS等多种实现形式 老零碎演进绞杀者模式在现有零碎外围将新性能用新的形式构建为新的服务的策略,通过将新性能做成微服务形式,而不是间接批改原有零碎,逐渐的实现对老零碎替换。采纳这种策略,随着工夫的推移,新的服务就会逐步“绞杀”老的零碎。对于那些规模很大而又难以对现有架构进行批改的遗留零碎,举荐采纳绞杀者模式。 毛病:可能须要一段时间同时保护两个或以上的我的项目修理模式修理者模式就如修房或修路一样,将老旧待修理的局部进行隔离,用新的形式对其进行独自修复。修复的同时,需保障与其余局部仍能协同性能。从这种思路登程,修理者模式更多体现为一种重构技术。 DDD实际流程 ...

February 16, 2022 · 1 min · jiezi

关于c:分析COMP206-Advanced-Unix-Utils

School of Computer Science, McGill UniversityCOMP-206 Introduction to Software Systems, Winter 2021Mini Assignment 3: Advanced Unix UtilsDue Date March 10th, 18:00 ESTThis is an individual assignment. You need to solve these questions on your own. If you have questions,post them on Piazza, but do not post major parts of the assignment code. Though small partsof code are acceptable, we do not want you sharing your solutions (or large parts of them) on Piazza.If your question cannot be answered without sharing significant amounts of code, please make a privatequestion on Piazza or utilize TA/Instructors office hours. Late penalty is -15% per day. Even ifyou are late only by a few minutes it will be rounded up to a day. Maximum of 2 late days are allowed.You MUST use mimi.cs.mcgill.ca to create the solution to this assignment. You must not use yourMac command-line, Windows command-line, nor a Linux distro installed locally on your laptop. You can accessmimi.cs.mcgill.ca from your personal computer using ssh or putty and also transfer files to your computer usingfilezilla or scp as seen in class and in Lab A and mini assignment 1.All of your solutions must be composed of commands from the list provided at the end of thisassignment description and your scripts must be executable as is in mimi.For this assignment, you will have to turn in one shell script. Instructors/TAs upon their discretion may ask youto demonstrate/explain your solution. No points are awarded for commands that do not execute at all. (Commandsthat execute, but provide incorrect behavior/output will be given partial marks.) All questions are graded proportionally.This means that if 40% of the question is correct, you will receive 40% of the grade.Please read through the entire assignment before you start working on it. You can loose severalpoints for not following the instructions. There are also some helpful hints given at the end of this documentthat can be useful to you.Lab E provides some background help for this mini assignment.Total Points: 20Ex. 1 — Parsing sensor logs for analysis (20 Points)The output produced by specialized software applications often contain a mixture of diagnostic details as well asuseful data. By processing their log files, we can glean for various useful information. In this assignment, we willuse the advanced Unix utilities that we covered in class to analyze the output log files from a temperature sensorsmonitoring program.The log files that we will be using for this assignment is available under the directory hierarchy of/home/2013/jdsilv2/206/m3/sensorlogs. Please note that this directory may not be accessible through FileZilla,etc. It is primarily meant to be accessed from the Unix command line in mimi. These will also be the files that TAswill be using to test your scripts.The log files are generated by a program that reads five different temperature sensors, once every hour (24 readings ina given day) and records these readings. If it was unable to read a particular sensor, it will indicate the correspondingsensor’s reading as ERROR. Along with this, the program also logs various other information (such as rebooting sensors,etc.) which we are not concerned with.A sample output of one of these log files is given below. (truncated for brevity). You can deduce the message formatsfrom the log files given to you as part of this assignment. Please note that positive temperature readings do not havean explicit + sign associated with them. For simplicity, you can assume that the temperature values are limited inthe range of 100.00 to -100.00, inclusive.2021-02-01 00:02:07 sensor readouts -12.35 -11.90 -11.97 -11.05 -11.6512021-02-01 01:03:01 rebooting sensor 42021-02-01 01:03:02 sensor readouts -13.85 -11.90 -12.97 ERROR -11.652021-02-01 02:04:00 rebooting sensor 5...2021-02-01 18:03:57 rebooting sensor 22021-02-01 18:08:47 rebooting sensor 32021-02-01 18:12:00 sensor readouts -10.35 ERROR ERROR -7.05 -3.652021-02-01 19:04:22 sensor readouts -11.85 -7.40 -6.97 -7.55 -4.15...2021-02-01 23:00:39 sensor readouts -12.85 -10.90 -7.47 -10.55 -8.65You will be writing a shell script dataformatter.sh that would process these log files. ...

February 15, 2022 · 11 min · jiezi

关于c++:Leetcode专题数组163缺失的区间

力扣链接:https://leetcode-cn.com/probl...解题思路: 这道题整体上自身比较简单,然而要解决的边界条件绝对比拟多数组是排序的,那么在[lower, upper]这个区间中,如果没有缺失数字/区间的话,实践上每个数字都应该是相邻的,那么就能够从lower做为终点,顺次进行遍历,如果数组中的数字大于lower开始的游标(每次比拟完lower加一),那么就阐明有缺失,此时的缺失能够分为两种状况:(1)只缺失了一个数字,那么lower就等于nums[i] - 1 (2)缺失多个数字:lower 就小于nums[i] - 1.最初整个数组遍历完结之后,游标此刻指向数组最初一个数+1,然而upper不肯定和最初一个数相等,也有可能大于最初一个数字,那么这个时候就须要比拟游标和upper的大小,如果相等则将upper退出,如果upper大于l,那么退出l->upperclass Solution {public: vector<string> findMissingRanges(vector<int>& nums, int lower, int upper) { long l = lower; vector<string> ans; for(int i = 0; i < nums.size(); ++i) { if(l == nums[i]) l++;//相等,我跳过你 else if(l < nums[i]) { //有空缺 if(l < nums[i]-1)//大于1 ans.push_back(to_string(l)+"->"+to_string(nums[i]-1)); else if(l == nums[i]-1)//等于1 ans.push_back(to_string(l)); l = long(nums[i])+1;//更新l到nums[i]下一个数 // [2147483647] // 0 // 2147483647 } } if(l < upper) ans.push_back(to_string(l)+"->"+to_string(upper)); else if(l==upper) ans.push_back(to_string(l)); return ans; }};

February 15, 2022 · 1 min · jiezi

关于c:COM-S-352-Shell-Project

Project 1: 352> ShellCOM S 352 Spring 2021 IntroductionThis project consists of designing a C program to serve as a shell interface that accepts usercommands and then executes each command in a separate process. Your implementation willsupport input and output redirection, pipes, and background processes. Completing this projectwill involve using the Linux fork(), exec(), wait(), waitpid(), pipe() and dup2()system calls. It must be tested on pyrite.Main LoopIn its normal mode of operation, the shell prompts the user, after which the next command isentered. In the example below, the prompt is 352> and the user's next command is cat -nprog.c.352> cat -n prog.cThe command is executed while the shell waits for it to complete, after completion the shellprompts the user for the next command. Following the UNIX philosophy, most commands areseparate utility programs distributed along with the OS, there are only a few built-incommands: exit, jobs and bg. The purpose of exit should be clear, jobs and bg aredescribed in Section 7.Most of the main loop is provided for you in the starter code in Section 9.Basic CommandsA basic command consists of the name of an executable file, followed by zero or more spaceseparated arguments. The input and parsing of the command line is performed for you in thestarter code. Parsing populates an instance of the Cmd struct. For example, calling the parserwith the argument cmd having the field cmd->line of "cat -n prog.c" results in thefollowing assignments (note that the character \0 in a string literal means NULL).cmd->line = "cat -n prog.c";cmd->tokenLine = "cat\0-n\0prog.c";cmd->args = {pointer_to_c, pointer_to_minus_sign, pointer_to_p, NULL…};cmd->symbols = {NULL, NULL, NULL, NULL…};Commands should be run in a separate child process. Basic commands must be executed in theforeground, this means the shell is blocked (waiting) until the child process terminates. Thechild process is created using the fork() system call, the user's command is executed using one of the system calls in the exec() family and the shell waits for the command to completeusing one of the system calls in the wait() family. Get started by writing a function to executea command and call it from main() at the location indicated by the line:/ TODO: Run command in foreground. /File RedirectionYour shell should be modified to support the ‘>’ and ‘<’ redirection operators, where ‘>’redirects the output of a command to a file and ‘<’ redirects the input to a command from afile. For example, if a user enters352> ls > out.txtthe output from the ls command will be redirected to the file out.txt. Similarly, input canbe redirected as well. For example, if the user enters352> sort < in.txtthe file in.txt will serve as input to the sort command.The parser recognizes ‘<’ and ‘>’ as special symbols, for example, calling the parser with theargument cmd having the field cmd->line of "sort < in.txt" results in the following.cmd->line = "sort < in.txt";cmd->tokenLine = "sort\0<\0in.txt";cmd->args = {pointer_to_s, NULL, pointer_to_i, NULL…};cmd->symbols = {NULL, pointer_to_lt, NULL, NULL…};Simplifying Assumption: You can assume that commands will contain either one input or oneoutput redirection and will not contain both. In other words, you do not have to be concernedwith command sequences such as sort < in.txt > out.txt.PipesYour shell should be modified to support the ‘|’ pipe operator, which connects the stdoutof one process to the stdin of another.352> ls | grep txtThe output from the ls command will be piped to the utility grep.Managing the redirection of both input and output will involve using the dup2() function,which duplicates an existing file descriptor to another file descriptor. For example, if fd is a filedescriptor to the file out.txt, the calldup2(fd, STDOUT_FILENO);duplicates fd to standard output (the terminal). This means that any writes to standard outputwill in fact be sent to the out.txt file.Simplifying Assumption: You can assume that commands will contain no more than one pipe.In other words, you do not have to be concerned with command sequences such asls | grep txt | wc -l.Background CommandsThe use of an ampersand (&) at the end of a line indicates that the command should beexecuted in the background. The shell does not wait for background commands to complete, itimmediately prompts the user for the next command. However, the shell is expected tomonitor the status of background commands, in order to inform the user when a commandcompletes. Helper functions should be created and called from main() to start a command andcheck if a command is completed at the following TODO lines./ TODO: Run command in background. // TODO: Check on status of background processes. /When a background command is started the shell assigns it a number (starting at 1) anddisplays the pid of the process. When the process exits normally the shell displays themessage Done commandArgs as shown in the following example.352> ls -la &[1] 84653-rw-r--r-- 1 user group 100 Aug 28 03:22 file1-rw-r--r-- 1 user group 100 Aug 28 03:22 file2-rw-r--r-- 1 user group 100 Aug 28 03:22 file3352>[1] Done ls -laIt is common for the Done message to not be displayed immediately, for example it may onlybe displayed after the user’s next line of input (which can be a blank line as shown above). Thisis due to the status check only being called once per iteration of the main loop. Because thestatus check cannot block the shell, like it does with foreground processes, waitpid() shouldbe called in a non-blocking mode as discussed in lecture.Sometimes a process exits with a non-zero exit code, in that case the shell should display(replacing exitCode and commandArgs): Exit exitCode commandArgs352> grep &[1] 84867usage: grep [-abcDEFGHhIiJLlmnOoqRSsUVvwxZ] [-A num][-B num] [-C[num]] [-e pattern] [-f file][--binary-files=value] [--color=when][--context[=num]] [--directories=action] [--label][--line-buffered] [--null] [pattern] [file ...]352>[1] Exit 2 grepA process might not exit on its own and instead it is terminated using the kill command, whenthat happens the shell should display (replacing commandArgs): TerminatedcommandArgs.352> cat &[1] 84665352> kill 84665[1] Terminated catThe kill command works by sending an unhandled signal such as SIGTERM to a process. Youcan test if a child process was terminated in this way, as opposed to the process self-exitingwith a call to exit(), by using WIFSIGNALED.Finally, add the capacity to run multiple background processes concurrently.352> sleep 15 &[1] 85119352> sleep 8 &[2] 85120352> sleep 20 &[3] 85122352>[2] Done sleep 8352>[1] Done sleep 15352>[3] Done sleep 20Your shell can now perform sleep sort!Simplifying Assumption: You can assume that background commands will not contain a pipe. Inother words, you do not have to be concerned with command sequences such asls | grep txt &.Job Control CommandsJobs include background commands and stopped foreground commands. Implement thefollowing built-in commands to control jobs.jobsImplement the built-in jobs command which prints the list of background commands andstopped commands. The status of a job can be running or stopped. Background commandscreated with & are running by default. The following is an example.352> jobs[1] Stopped sleep 100[2] Running sleep 100 &[3] Running sleep 100 &The next two requirements provide situations where a command may switch between runningand stopped.control+zImplement control+z to stop the currently running foreground command. When a userpresses control+z, the terminal send the signal SIGTSTP (SIGnal - TerminalSToP) to the shell. Forwarding this signal, from the shell to the process running in theforeground, has already be implemented for you with the function sigtstpHandler().What still needs to be done, is the stopped command needs to be add to the list of jobs. Itsstatus is stopped.bg job_idImplement the bg job_id command which resumes a stopped command. The status of thecommand should be set to running. For example, consider the following scenario.352> sleep 100[User presses control+z.]352> jobs[1] Stopped sleep 100352> bg 1[1] Running sleep 100To make a process continue from a stopped state, send it a SIGCONT signal.Simplifying Assumption: You can assume that stoped commands will not contain a pipe. Inother words, you do not have to be concerned with the user pressing control+z on a commandsequence such as ls | grep txt.Additional Requirementsmakefile (5 points)You get 5 points for simply using a makefile. Name your source files whatever you like. Pleasename your executable shell352. Be sure that "make" will build your executable on pyrite.Documentation (10 points)If you have more than one source file, then you must submit a Readme file containing a briefexplanation of the functionality of each source file. Each source file must also be welldocumented.There should be a paragraph or so at the beginning of each source file describingthe code; functions and data structures should also be explained. Basically, anotherprogrammer should be able to understand your code from the comments.Project SubmissionPut all your source files (including the makefile and the README file) in a folder. Then usecommand zip -r <your ISU Net-ID> <src_folder> to create a .zip file. Forexample, if your Net-ID is ksmith and project1 is the name of the folder that contains allyour source files, then you will type zip -r ksmith project1 to create a file namedksmith.zip and then submit this file.Starter CodeYou are not required to use this code, however, it is highly recommended. Use the TODOs as aguide to start working on the project. ...

February 11, 2022 · 9 min · jiezi

关于c:kprobelf-高延迟内核函数定位分析工具

1.kprobe-lf是什么kprobe-lf是一款基于kprobe和中断定时器的高提早函数定位剖析工具 kprobe-lf能够定位剖析大多数内核函数,当设置提早足够小时也能够察看失常提早函数的堆栈 1.1 为什么叫kprobe-lf因为这款工具有两个重要的设置,一个是LATENCY,一个是FUNCTION,简称LF 1.2 适配问题目前在内核4.15.0,5.4.54,5.13.0上进行了测试,这几个版本都能够适配 2.如何应用git clone https://github.com/1978629634/kprobe_lf.gitcd kprobe_lfbash start.sh -f [FUNCTION_NAME] -l [LATENCY_TIME]运行脚本之后应用ctrl + c进行获取log,并且生成火焰图 脚本启动之后会在当前目录生成三个文件 lf.log 是函数运行前堆栈lf.svg 是火焰图lf.graph 是火焰图原始文件3.为什么须要kprobe-lf3.1 找到高提早首恶kprobe-lf能够定位超时函数并将它的运行堆栈制作成火焰图 比方咱们遇到软中断提早过长的问题时能够设置函数为__do_softirq,设置提早为1000us,定位剖析超时软中断 root@cluster1-worker1:~/kprobe_lf# bash start.sh -f __do_softirq -l 1000FUNCTION: __do_softirq, LATENCY_TIME: 1000 us (>=100us)find kprobe_lf.koinsmod kprobe_lf.kosave log to lf.log, ctrl + c to stop取得到超时__do_softirq运行时火焰图和超时__do_softirq运行前堆栈如下 运行时火焰图: 运行前堆栈: __do_softirq cpu:2 PID:0 COMMAND:swapper/2 LATENCY:5978us __do_softirq+0x1/0x2dc irq_exit+0xd5/0xe0 smp_apic_timer_interrupt+0x74/0x130 apic_timer_interrupt+0xf/0x20 native_safe_halt+0xe/0x10 default_idle+0x1c/0x140 do_idle+0x1aa/0x250 cpu_startup_entry+0x19/0x20 start_secondary+0x162/0x1c0 secondary_startup_64+0xa4/0xb0...通过LATENCY咱们能够晓得超时软中断提早高达6ms 通过火焰图咱们能够看到所有的高提早软中断都是在运行estimation_timer(IPVS BUG) 很快就能够定位到首恶函数 3.2 内核性能剖析在咱们对内核作性能剖析的状况下,有时想剖析批改一个参数对内核的性能影响是怎么的,咱们就能够利用这款工具对相干函数做剖析 ...

February 11, 2022 · 1 min · jiezi

关于c:csapp之第10章系统级I⁄O

0. 学习起因大多时候,高级别I/O函数工作良好,没必要间接用Unix I/O,为何需学习? 理解Unix I/O将帮忙了解其余零碎概念。I/O是零碎操作不可或缺的局部,因而常常遇到I/O和其余零碎概念之间的循环依赖有时必须用Unix I/O,用高级I/O不太可能或不适合,如规范I/O库没提供读取文件元数据的形式,此外I/O库存在一些问题1. Unix I/O输出/输入(I/O)是主存和外部设备之间复制数据的过程,在 Linux 中,文件就是字节的序列。所有的 I/O 设施(如网络、内核、磁盘和终端等)都被模型化为文件,而所有的输出和输入都被当作对相应文件的读和写来执行。这种将设施映射为文件的机制,容许内核引出简略、优雅的利用接口Unix I/O,使得所有输出和输入都以对立的形式执行,如 open()/close() 关上/敞开文件,read()/ write() 读/写文件。seek()扭转以后文件地位。Unix I/O次要分为两大类: 为辨别不同文件的类型,会有一个 type 来进行区别: 一般文件:蕴含任意数据目录:相干文件组的索引Socket:用于另一台机器上的过程通信还有一些特地的类型仅做理解:命名管道(FIFOs)、符号链接、字符和块设施 一般文件 一般文件蕴含任意数据,应用程序通常需辨别文本文件和二进制文件。前者只蕴含 ASCII 或 Unicode 字符。除此之外的都是二进制文件(对象文件, JPEG 图片, 等等)。内核不能辨别出区别。 文本文件是文本行的序列,每行以 \n 结尾,新行是 0xa,和 ASCII 码中LF一样。不同零碎判断行完结的符号不同(End of line, EOL),Linux & Mac OS是\n(0xa)等价line feed(LF),而Windows & 网络协议是\r\n (0xd 0xa)等价Carriage return(CR) followed by line feed(LF) 目录 目录蕴含一个链接(link)数组,且每个目录至多蕴含两记录:.(dot) 当前目录、..(dot dot) 下层目录 操作命令次要有 mkdir, ls, rmdir。目录以树状构造组织,根目录是 /(slash)。 内核会为每个过程保留当前工作目录(cwd, current working directory),可用 cd 命令进行更改。通过路径名来确定文件的地位,分为绝对路径和相对路径。 ...

February 8, 2022 · 4 min · jiezi

关于c#:CVBNET向PDF文档添加文本水印

水印是呈现在文档中现有内容后面或前面的文本或图像。它通常用于避免文档被非法应用。在下文中,我将介绍如何应用Spire.PDF for .NET在C#和VB.NET程序中向PDF增加单行或多行文本水印。 • 增加单行文本水印到PDF• 增加多行文本水印到PDF 装置Spire.PDF首先,你须要从这个链接下载Spire.PDF的最新版本,并手动将DLL文件增加到你的应用程序中作为援用。或者,你能够通过NuGet间接装置它。示例1 增加单行文本水印到PDF[C#] using Spire.Pdf;using Spire.Pdf.Graphics;using System.Drawing; namespace AddTextWatermarkToPdf{ class Program { static void Main(string[] args) { //创立一个PdfDocument 对象 PdfDocument pdf = new PdfDocument(); //加载一个示例PDF文档 pdf.LoadFromFile(@"C:\Users\Administrator\Desktop\sample.pdf"); //创立一个PdfTrueTypeFont 对象 PdfTrueTypeFont font = new PdfTrueTypeFont(new Font("Arial", 55f), true); //设置水印文本 string text = "Internal Use"; //测量文本大小 SizeF textSize = font.MeasureString(text); //计算两个偏移变量的值,用于计算坐标系的平移量float offset1 = (float)(textSize.Width * System.Math.Sqrt(2) / 4); float offset2 = (float)(textSize.Height * System.Math.Sqrt(2) / 4); //遍历文档中的所有页面 foreach (PdfPageBase page in pdf.Pages) { //设置页面透明度 page.Canvas.SetTransparency(0.8f); //将坐标系平移到右下角 page.Canvas.TranslateTransform(page.Canvas.Size.Width / 2 - offset1 - offset2, page.Canvas.Size.Height / 2 + offset1 - offset2); //将坐标系逆时针旋转45度 page.Canvas.RotateTransform(-45); //在页面上绘制水印文本 page.Canvas.DrawString(text, font, PdfBrushes.DarkGray, 0, 0); } //将更改保留到另一个文件 pdf.SaveToFile("TextWatermark.pdf"); } }}[VB.NET] ...

February 8, 2022 · 3 min · jiezi

关于c++:2022-技术趋势报告C-重新受宠-dataPythonJava上榜热搜词-安全话题备受关注

近日,O'Reilly 出炉了“2022 技术趋势”报告。该报告数据展现了以后在 AI 技术推动下为行业带来的微小转变,让咱们对接下来新技术趋势带来的全新思维形式及其意义,以及将来塑造软件开发和软件架构的大变动有了进一步理解。 该报告通过对 2021 年 1 月 - 9 月的四种特定类型的数据进行了钻研(搜寻查问、向 O’Reilly Answers 提出的问题、按 title 列出的资源应用状况、按主题分类法列出的资源应用状况),并将其与 2020 年前 9 个月的数据行比照后最终得出了乏味的论断。 报告结果显示,随着勒索软件的“流行”,“data”数据及平安话题正成为开发者关注的焦点,而 IoT 及游戏开发的衰亡则从新激发了开发者对 C++ 编程语言的趣味。同时 Go 和 Rust 等较新的语言倒退迅猛,也正在“威逼”着 C 语言的位置。 热搜词: “data”、“Python”、“Java”上榜一个令人诧异的景象是,很多用户会抉择间接从题库里将问题输出 O’Reilly Answers (该平台的搜索引擎)搜寻栏。这也很好的解释了为什么 O’Reilly Answers 外面常常会呈现一些高频热搜问题。 比方“什么是动静布局?(What is dynamic programming?)”这个问题就会经常出现在题库中。当然,这个问题仅次于“如何编写好的单元测试用例?(How do I write good unit test cases?)”该问题在题库中也很热门。 该热搜数据显示,“data”数据依然是用户最关注的重要话题之一。热搜词前五的单词别离是:“data”、“Python”、“Git”、“test”和“Java”(能在下面两个热门问题里看到热搜词top 15 / 20 里的大部分单词。)而与“数据”一词最常呈现的词组是“数据治理”(其次是“数据迷信”“数据分析”和“数据工程”),看得出,“数据治理”将会是接下来值得关注的话题。 另外,Python 和 Java 仍旧是该平台上的两大编程语言,不过此次数据显示往年对于 Python 和 Java 的内容使用率略有降落,而对于 Rust 和 Go 的内容使用率正在快速增长(只管绝对较小)。 ...

February 7, 2022 · 1 min · jiezi

关于c:Redis使用SET命令覆盖旧值后旧值是同步还是异步删除

背景最近调研了redis大key的同步和异步删除形式,大key同步删除会造成主线程长时间阻塞。set命令笼罩旧值时,旧值的开释是同步还是异步执行的呢?查看源码在原key已有值时,set命令对应的操作函数为:/* Overwrite an existing key with a new value. Incrementing the reference * count of the new value is up to the caller. * This function does not modify the expire time of the existing key. * * The program is aborted if the key was not already present. */void dbOverwrite(redisDb *db, robj *key, robj *val) { dictEntry *de = dictFind(db->dict,key->ptr); serverAssertWithInfo(NULL,key,de != NULL); dictEntry auxentry = *de; robj *old = dictGetVal(de); if (server.maxmemory_policy & MAXMEMORY_FLAG_LFU) { val->lru = old->lru; } dictSetVal(db->dict, de, val); if (server.lazyfree_lazy_server_del) { /** * 异步删除旧值 */ freeObjAsync(old); /** * 将以后须要开释的旧值auxentry的值指针设置为NULL * 这样做是为了防止下一步的dictFreeVal操作执行实在的开释操作 */ dictSetVal(db->dict, &auxentry, NULL); } /** * 执行开释操作 */ dictFreeVal(db->dict, &auxentry);}能够看到,在服务器参数lazyfree_lazy_server_del为true时,redis服务器会采纳异步删除的形式,否则同步删除。配置项lazyfree_lazy_server_del参数能够通过配置文件中的lazyfree-lazy-server-del来进行管制,其值为yes或no。论断当lazyfree-lazy-server-del配置项的值为no时,redis的set操作采纳同步的形式开释旧值;值为yes时,采纳异步的形式开释旧值。lazyfree-lazy-server-del的默认值为no。

February 7, 2022 · 1 min · jiezi

关于c:csapp之labshell-lab

试验目标shell lab次要目标是为了相熟过程管制和信号。具体来说须要比对16个test和rtest文件的输入,实现五个函数: void eval(char *cmdline):剖析命令,并派生子过程执行 次要性能是解析cmdline并运行int builtin_cmd(char **argv):解析和执行bulidin命令,包含 quit, fg, bg, and jobsvoid do_bgfg(char **argv) 执行bg和fg命令void waitfg(pid_t pid):实现阻塞期待前台程序运行完结void sigchld_handler(int sig):SIGCHID信号处理函数void sigint_handler(int sig):信号处理函数,响应 SIGINT (ctrl-c) 信号 void sigtstp_handler(int sig):信号处理函数,响应 SIGTSTP (ctrl-z) 信号辅助函数可用辅助函数: int parseline(const char *cmdline,char **argv):获取参数列表,返回是否为后盾运行命令void clearjob(struct job_t *job):革除job构造体。void initjobs(struct job_t *jobs):初始化jobs链表。void maxjid(struct job_t *jobs):返回jobs链表中最大的jid号。int addjob(struct job_t *jobs,pid_t pid,int state,char *cmdline):在jobs链表中增加jobint deletejob(struct job_t *jobs,pid_t pid):在jobs链表中删除pid的job。pid_t fgpid(struct job_t *jobs):返回以后前台运行job的pid号。struct job_t *getjobpid(struct job_t *jobs,pid_t pid):返回pid号的job。struct job_t *getjobjid(struct job_t *jobs,int jid):返回jid号的job。int pid2jid(pid_t pid):将pid号转化为jid。void listjobs(struct job_t *jobs):打印jobs。void sigquit_handler(int sig):解决SIGQUIT信号。简介shell是交互式的命令行解释器,打印提示符并在stdin上期待输出命令,并依照命令行的内容执行。命令行是ASCII单词组成的命令和参数序列。若首个单词是内置命令,shell会立刻在以后过程中执行。否则是可执行文件门路,shell派生出子过程,而后在该子过程的上下文中加载和运行程序。解释单个命令行而创立的子过程叫作业,通常由Unix管道连贯的多个子过程组成。若命令行以&号“&”完结,则作业将在后盾运行且不会期待作业完结。否则作业将在前台运行且期待作业终止。故在任何工夫点最多仅一个作业在前台运行。但可在后盾运行任意数量的作业。 ...

February 2, 2022 · 16 min · jiezi

关于c++:动态创建二维数组

本文基于《数据结构、算法与利用 C++语言形容》一书。创立二维数组 template<class T>void make2dArray(T ** &a, int numberOfRows, int numberOfColumns){ // 创立行指针 a = new T * [numberOfRows]; // 为每一行调配空间 for(int i = 0; i < numberOfRows; i++) a[i] = new T[numberOfColumns];}删除二维数组 template<class T>void delete2dArray(T ** &a, int numberOfRows){ // 删除行数组空间 for(int i = 0; i < numberOfRows; i++) delete [] a[i]; // 删除行指针 delete [] a; a = NULL;}残缺代码 #include <iostream>using namespace std;/* 创立二维数组*/template<class T>void make2dArray(T ** &a, int numberOfRows, int numberOfColumns){ // 创立行指针 a = new T * [numberOfRows]; // 为每一行调配空间 for(int i = 0; i < numberOfRows; i++) a[i] = new T[numberOfColumns];}/* 删除二维数组*/template<class T>void delete2dArray(T ** &a, int numberOfRows){ // 删除行数组空间 for(int i = 0; i < numberOfRows; i++) delete [] a[i]; // 删除行指针 delete [] a; a = NULL;}/* 初始化数组为全0*/template<class T>void initArray(T ** &a, int numberOfRows, int numberOfColumns){ for(int i = 0; i < numberOfRows; i++) for(int j = 0; j < numberOfColumns; j++) a[i][j] = 0;}/* 打印数组内容*/template<class T>void printArray(T ** &a, int numberOfRows, int numberOfColumns){ for(int i = 0; i < numberOfRows; i++) { for(int j = 0; j < numberOfColumns; j++) cout << a[i][j] << " "; cout << "\n"; }}int main(){ int **a; try { int rows, columns; rows = 3; columns = 4; make2dArray(a, rows, columns); initArray(a, rows, columns); a[1][2] = 1; printArray(a, rows, columns); delete2dArray(a, rows); } catch(bad_alloc &e) { cerr << "Could not create two-dimensional array a\n"; cerr << "bad_alloc capture: " << e.what() << "\n"; } system("pause"); return 0;}后果 ...

January 30, 2022 · 2 min · jiezi

关于c++:模板函数中以引用的方式传递数组

本文基于《数据结构、算法与利用C++语言形容》一书。其中,在第一章的练习2中,有一个题目是这样形容的: 编写一个模板函数 count,返回值是数组 a[0:n-1] 中 value 呈现的次数。测试你的代码。书中给出的代码是这样的: template<class T>T count(T a[], int n, const T& value){ int theCount = 0; for(int i = 0; i < n; i++) if(a[i] == value) theCount++; return theCount;}然而出于好奇想要尝试一下以援用的形式去传递这个数组,于是有 template<class T, int n>T count(T (&a)[n], const T& value){ int i, t; t = 0; // t -> time for(i = 0; i < n; i++) if(a[i] == value) ++t; return t;}残缺代码 #include <iostream>#include <iterator>using namespace std;template<class T, int n>T count(T (&a)[n], const T& value){ int i, t; t = 0; // t -> time for(i = 0; i < n; i++) if(a[i] == value) ++t; return t;}int main(){ int a[6] = {1, 2, 3, 4, 1, 1}; cout << "a[0:5] = "; copy(a, a+6, ostream_iterator<int>(cout, " ")); cout << "\n"; cout << "count(a, 1) = " << count(a, 1) << "\n"; cout << "count(a, 2) = " << count(a, 2) << "\n"; system("pause"); return 0;}后果 ...

January 29, 2022 · 1 min · jiezi

关于c++:现代C设计魅力虚函数继承thunk技术初探

简介:工作中应用LLDB调试器调试这一段C++多继承程序的时候,发现通过lldb print(expression命令的别名) 命令获取的指针地址和理论了解的C++的内存模型的地址不一样。那么到底是什么起因呢? 作者 | 扬阜起源 | 阿里技术公众号 一 问题背景1 实际验证工作中应用LLDB调试器调试这一段C++多继承程序的时候,发现通过lldb print(expression命令的别名) 命令获取的指针地址和理论了解的C++的内存模型的地址不一样。那么到底是什么起因呢?程序如下: class Base {public: Base(){}protected: float x;};class VBase {public: VBase(){} virtual void test(){}; virtual void foo(){};protected: float x;};class VBaseA: public VBase {public: VBaseA(){} virtual void test(){} virtual void foo(){};protected: float x;};class VBaseB: public VBase {public: VBaseB(){} virtual void test(){ printf("test \n"); } virtual void foo(){};protected: float x;};class VDerived : public VBaseA, public Base, public VBaseB {public: VDerived(){} virtual void test(){} virtual void foo(){};protected: float x;};int main(int argc, char *argv[]){ VDerived *pDerived = new VDerived(); //0x0000000103407f30 Base *pBase = (Base*)pDerived; //0x0000000103407f40 VBaseA *pvBaseA = static_cast< VBaseA*>(pDerived);//0x0000000103407f30 VBaseB *pvBaseB = static_cast< VBaseB*>(pDerived);//0x0000000103407f30 这里应该为0x0000000103407f48,然而显示的是0x0000000103407f30 unsigned long pBaseAddressbase = (unsigned long)pBase; unsigned long pvBaseAAddressbase = (unsigned long)pvBaseA; unsigned long pvBaseBAddressbase = (unsigned long)pvBaseB; pvBaseB->test();}通过lldb print命令获取的地址如下图: ...

January 29, 2022 · 10 min · jiezi

关于c:编程把INI文件转换成XML文件

来自宋劲波老师《linuxc》的习题 INI文件是一种很常见的配置文件,很多Windows程序都采纳这种格局的配置文件,在Linux零碎中Qt程序通常也采纳这种格局的配置文件。比方: ;Configuration of http[http]domain=www.mysite.comport=8080cgihome=/cgi-bin ;Configuration of db[database]server = mysqluser = mynamepassword = toopendatabase 一个配置文件由若干个Section组成,由[]括号括起来的是Section名。每个Section上面有若干个key = value模式的键值对(Key-value Pair),等号两边能够有零个或多个空白字符(空格或Tab),每个键值对占一行。以;号结尾的行是正文。每个Section完结时有一个或多个空行,空行是仅蕴含零个或多个空白字符(空格或Tab)的行。INI文件的最初一行前面可能有换行符也可能没有。当初XML衰亡了,INI文件显得有点土。当初要求编程把INI文件转换成XML文件首先咱们本人创立一个文本文件ini.txt如下: #include<stdio.h>#include<stdlib.h>#include<errno.h>#include<string.h>#define MAX_LINE 128//初始化buf用'\0'填充void ainit( char *buf ){ int i; for ( i = 0; i< MAX_LINE; i++ ) { buf[i] = '\0'; }}//将'\n'替换为'\0'void adell( char *buf ){ int i; for ( i = 0; buf[i] != '\0'; i++ ) { if ( buf[i] =='\n' ) { buf[i] = '\0'; } }}//去除数组中的'\t','空格'void abdel( char *buf ){ int i = 0, j = 0; for ( ; buf[i] != '\0'; i++ ) { if ( (buf[i] == '\t') || (buf[i] == ' ') ) { j = i; while ( buf[j] != '\0' ) { buf[j] = buf[j + 1]; j++; } i = i - 1; } }}int main(){ FILE *fp_xml,*fp_ini; //定义缓冲区 char buf[MAX_LINE] = {0}; char dbuf[MAX_LINE] = {0}; char ch = '\0'; char *kv, *key, *val; int i = 0; fp_ini = fopen("ini.txt","r+"); fp_xml = fopen("xml.txt","w+"); if ( fp_ini == NULL ) { perror("config.ini is not exist\n"); exit(1); } if ( fp_xml == NULL ) { perror("xml is not exist\n"); exit(1); } while((ch = fgetc(fp_ini)) != EOF){ if(ch == ';'){ //该语句管制</http>的打印和两个section之间的空一行 if( buf[0] != '\0' )//只有,此时曾经生成了<http>,由buf缓存,且并未flush时才成立 //所以该条件旨在生成第二个,即</http> fprintf( fp_xml, "</%s>\n\n", buf );//多空一行 //因为这个语句蕴含在while中(;语句转换之前),所以最初一个</xxxx>无奈生成 //见line:105来生成 //而后再进行;局部的转换 fgets(buf,MAX_LINE,fp_ini); adell(buf);//将;Configuration of http\n后跟的\n去掉,前面咱们本人管制换行 fprintf(fp_xml,"<!-- %s -->\n",buf); fflush(NULL);//该语句是确保所有文件写操作从cache传给内核到磁盘,不写也不影响 continue; } if(ch == '['){ ainit(buf);//持续利用buf进行[http]的转换 for(i = 0; (ch = fgetc(fp_ini)) != ']'; i++ ) { buf[i] = ch;//留神此处不能用fgets,咱们只有[]外部的字符,不要括号和\n } fprintf(fp_xml,"<%s>\n",buf); fflush(NULL); continue; } if((ch != '\n') && (ch != '\t') && (ch != ' ')){ ainit(dbuf); fgets(dbuf,MAX_LINE,fp_ini);//此处便能够间接获一行 // for( i = 0; (ch = fgetc(fp_ini)) != '\n' ; i++ ) { // dbuf[i] = ch; // }//如果用这个循环来给dbuf赋值会gdb提醒索引越界,未找到起因 adell(dbuf);//同上 abdel(dbuf);//后面如果有\t,以及两头夹的空格等都去掉 kv = dbuf; key = strtok(kv,"="); val = strtok(NULL,"=");//获取第一次截去后残余的字符串 fprintf(fp_xml," <%c%s>%s</%s>\n",ch,key,val,key);//留神此处ch //以后fgets读取的一行少了第一个字符(他被while中ch = fgetc()读去了,所以要把它补上) fflush(NULL); continue; } } fprintf(fp_xml, "</%s>", buf); fclose(fp_xml); fclose(fp_ini); return 0;}参考https://www.cnblogs.com/shish...这种写法应该工夫复杂度高一点,然而可读性好一点,适宜我这个老手!留神他的代码中失落了一个个字符:fprintf(fp_xml," <%c%s>%s</%s>\n",ch,key,val,key);//留神此处ch 以后fgets读取的一行少了第一个字符(他被while中ch = fgetc()读去了,所以要把它补上) ...

January 28, 2022 · 2 min · jiezi

关于c:Redis命令DEL与UNLINK的区别如何正确删除大Key

背景在这篇文章中做过应用del命令删除大key的试验,后果是del命令随着key的增大,主线程阻塞的工夫就越长。这与之前看redis5.0.8版本的代码中对于多线程删除操作的感官不符,于是决定先查看redis对于删除操作的代码,找出关键点,再做试验进行验证。筹备工作须要复用这篇文章中,应用过的数据构造方法和测试脚本代码。代码剖析步骤在server.c中找到redisCommandTable(命令表,redis的所有命令都对应这张表中的一个回调函数),找到del命令对应的回调函数delCommand。查看delCommand函数的代码内容如下:void delCommand(client *c) { delGenericCommand(c,0);}delCommand持续只是单纯的调用了一个通用删除办法delGenericCommand,持续追踪delGenericCommand,代码如下:/* This command implements DEL and LAZYDEL. */void delGenericCommand(client *c, int lazy) { int numdel = 0, j; for (j = 1; j < c->argc; j++) { expireIfNeeded(c->db,c->argv[j]); int deleted = lazy ? dbAsyncDelete(c->db,c->argv[j]) : dbSyncDelete(c->db,c->argv[j]); if (deleted) { signalModifiedKey(c->db,c->argv[j]); notifyKeyspaceEvent(NOTIFY_GENERIC, "del",c->argv[j],c->db->id); server.dirty++; numdel++; } } addReplyLongLong(c,numdel);}该办法就比拟有意思了,首先正文就说这个命令实现了删除和懒删除(也就是咱们想要的异步删除)。再看此行代码:int deleted = lazy ? dbAsyncDelete(c->db,c->argv[j]) : dbSyncDelete(c->db,c->argv[j]);也就是说依据参数lazy的不同而调用异步删除或同步删除。那么那里调用了这个办法,传递了什么参数呢?依据ide的追踪,发现有2个函数调用了以后函数,且lazy参数一个传0,一个传1,刚好对应了一个同步,一个异步。void delCommand(client *c) { delGenericCommand(c,0);}void unlinkCommand(client *c) { delGenericCommand(c,1);}其中,delCommand是del命令的回调,unlinkCommand是unlink命令的回调。这就阐明unlink命令才会让redis采纳异步删除的形式。试验验证结构数据和测试php脚本请参考这篇文章。首先采纳redis-cli --pipe的形式向redis增加一个key为sigkey的hash数据,其hlen为3000万,占用内存约1.8G。向redis增加一个key为m的string类型数据,用于测试获取。应用redis-cli连贯redis。开启测试php脚本。redis-cli中执行命令unlink ligkey。敞开观测php脚本,观测后果。试验后果有呈现标记信号的输入如下:0.57013500 1643333929--$4mack-------------------xxx---------------------0.70107700 1643333929--$4mack0.80816900 1643333929--$4mack0.92466400 1643333929--$4mack0.03091900 1643333930--$4mack0.13540800 1643333930--$4mack0.23995700 1643333930--$4mack0.34635700 1643333930--$4mack0.45889300 1643333930--$4mack0.56787100 1643333930--$4mack-------------------xxx---------------------0.69811500 1643333930--$4mack能够看到呈现稳定的两次距离均与0.13秒相差不大,且呈现这两个稳定的工夫节点与执行删除命令不同(执行命令的时候观测并未呈现标记),能够确认为失常网络稳定,排除unlink阻塞影响。总结依据源码剖析及理论试验操作可得,del命令应用同步删除,unlink应用异步删除。在删除数据体量很小的简略类型时倡议应用del命令,在删除大key时应该应用unlink命令。删除小key应用del的起因是:尽管del是同步删除,会阻塞主线程,然而unlink同样会在主线程执行一些判断和其它操作。而这些操作可能带来的开销比理论删除一个小key还略大。所以能间接删的key就没必要应用异步删除了。

January 28, 2022 · 1 min · jiezi

关于c:编程读写一个文件logcreatetxt每隔1秒向文件中写入一行记录

该程序应该有限循环,直到按Ctrl-C终止。下次再启动程序时在test.txt文件开端追加记录,并且序号可能接续上次的序号,比方: 1 2009-7-30 15:16:422 2009-7-30 15:16:433 2009-7-30 15:19:024 2009-7-30 15:19:035 2009-7-30 15:19:04这相似于很多零碎服务保护的日志文件.[阐明]获取以后的零碎工夫须要调用time()函数,返回的后果是一个time_t类型,其实就是一个大整数,其值示意从UTC(Coordinated Universal Time)工夫1970年1月1日00:00:00(称为UNIX零碎的Epoch工夫)到以后时刻的秒数。而后调用localtime()将time_t所示意的UTC工夫转换为本地工夫(咱们是+8区,比UTC多8个小时)并转成struct tm类型,该类型的各数据成员别离示意年月日时分秒,具体用法请查阅Man Page。调用sleep()函数能够指定程序睡眠多少秒。 #include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <unistd.h>//蕴含睡眠管制函数slepp();// struct tm//该构造体类型(tm)为内置类型,在time.h中,不必本人再反复定义// {// int tm_sec; /* 秒,范畴从 0 到 59 */// int tm_min; /* 分,范畴从 0 到 59 */// int tm_hour; /* 小时,范畴从 0 到 23 */// int tm_mday; /* 一月中的第几天,范畴从 1 到 31 */// int tm_mon; /* 月,范畴从 0 到 11(留神) */// int tm_year; /* 自 1900 年起的年数 */// int tm_wday; /* 一周中的第几天,范畴从 0 到 6 */// int tm_yday; /* 一年中的第几天,范畴从 0 到 365 */// int tm_isdst; /* 夏令时 */// };int main(){ FILE *file; struct tm *t1; time_t t;//c内置宏定义 // char * buf = (char *)malloc(100);不能定义成动静,要不每次执行过程会背地扭转行号 char buf[100]; int line = 0; memset(buf,0,sizeof(buf)); if ((file = fopen("log_create.txt", "a+")) < 0) { perror("failed to open log_create.txt"); exit(-1);//此处能够换成exit(1);exit(0)示意程序失常退出,非0示意非正常退出 } while( fgets(buf,sizeof(buf),file) != NULL){//逐行获取字符串 line++;//将用于记录的行号每次更新,下次计算时候要连接上 } while(1){ time(&t);//time_t time(time_t *timer), //如果 timer不为空,则返回值也存储在变量 timer即本例的t中 t1 = localtime(&t);//获取以后工夫 //struct tm *localtime(const time_t *timer) //应用 timer 的值来填充 tm 构造。timer 的值被合成为 tm 构造,并用本地时区示意 fprintf(file,"%d %d-%d-%d %d:%d:%d\n",++line, t1->tm_year + 1900, t1->tm_mon + 1, t1->tm_mday, t1->tm_hour, t1->tm_min, t1->tm_sec); //构造体tm中的tm_year是1900年到以后的工夫距离,tm_mom从一月开始,0代表一月 printf("%d %d-%d-%d %d:%d:%d\n",line, t1->tm_year + 1900, t1->tm_mon + 1, t1->tm_mday, t1->tm_hour, t1->tm_min, t1->tm_sec); fflush(file);//将改文件流cache写回缓存区,并使其写到内核或内存(设施)中! sleep(1);//能够指定程序睡眠多少秒 } fclose(file); return 0;}本函数以a+追加形式应用fopen()函数,不必本人创立文件,会主动生成并读写更新日志内容。能够看到,我第一次运行的后果如下: ...

January 27, 2022 · 1 min · jiezi

关于c#:C-官方文档导读及推荐书单

本文次要是心愿帮忙想学习 C# 和 .NET 技术栈的同学找到入门的路径!微软在官方网站上提供了全套 C# 文档,提供从入门到精通的齐全领导。 官网文档地址:主动/英文/中文 英文原版:https://docs.microsoft.com/en...中文版:https://docs.microsoft.com/zh...因为长期积攒,C# 官网文档提供的内容较多,但比拟芜杂,对初学者来说并不是很敌对。而对曾经学习了 C# 的人,作为参考和知识点查找工具来说是十分有用的。然而,官网文档提供了最全、最具体的学习内容,初学者能够追随导读,在这里学习 C# 的基础知识。 对于初学者来说,能够从「C# 基础知识」开始浏览。 C# 基础知识导读第一章 「入门」次要是对 C# 及其环境的介绍,通读即可,不须要认真去咀嚼。这一章提到的概念,大部分都会在「C# 编程指南」和「语言参考」局部找到具体的形容。 其中,「C# 语言介绍」中介绍了 C# 和 .NET 体系结构。C# 和 .NET 密不可分。能够说,C# 就是为了 .NET 而创造的一种语言,所以在学习 C# 的同时,肯定要理解 .NET。学任何一门语言,都有两个重点:一是语法自身,二是撑持该语言的 API 库(函数库/类库等)。.NET SDK 为 C# 提供了根底而且全面的 API 库。 「教程」局部次要通过两种模式进行教学,「基于浏览器的教程」能够在浏览器上一步一步的理解 C# 开发的一些基本概念。但学完「基于浏览器的教程」之后,肯定不要疏忽了「在本地环境中工作」,这是实际环节,是在真正的日常工作环境中编写 C# 程序。这一部分介绍了基于命令行的 C# 我的项目操作和基于 Visual Studio 2019/2022 的 C# 我的项目操作,倡议间接学习后者。基于 dotnet CLI 的局部理解即可,在前面学完 C#,深刻 C# 构建技术和继续集成相干高级常识的时候再进行具体的学习。 第二章「根底」局部须要通读。这一部分的内容最好是每读完一节都在 Visual Studio 或 dotnetfiddle.net 中进行实际。其中「面向对象的编程」局部须要仔细阅读,如果有 C++ 或 Java 的根底,这一部分浏览起来可能会轻松一些;如果没有学过 OOP(Object Oriented Programming,面向对象程序设计)的同学,能够参照别的相干书箱或资料辅助浏览了解。留神,这里提到的「多形性」在少数书籍中叫作「多态性」。 ...

January 27, 2022 · 2 min · jiezi

关于c++:多视角三维模型纹理映射-02

前言通过前篇文章《多视角三维模型纹理映射 01》,根本对OpenMVS框架和应用办法有了一个简略的了解,这里持续基于上一篇文章进行本人的探索,也对上篇文章中留下的问题进行解释。 已知: 1、手头有从8个角度拍摄的点云数据,且点云曾经通过配准、交融、网格化造成了Mesh; 2、8个点云的外参(确认正确无误); 3、8个角度的图片; 原始点云是这样的: 点云配准后如上篇文章《G2O与多视角点云全局配准优化》图片所示。 实现基于OpenMVS,次要实现代码片段如下: void texture() { int number_of_thread = 1; Scene scene(number_of_thread); Eigen::Matrix4d temp; std::string t_inPath = "./test/scene/1_in.txt"; loadMat4(t_inPath, temp); Eigen::Matrix3d _k = temp.block<3, 3>(0, 0); //相机内参 //归一化 _k(0, 0) = _k(0, 0) / 1600; _k(1, 1) = _k(1, 1) / 1600; _k(0, 2) = _k(0, 2) / 1600; _k(1, 2) = _k(1, 2) / 1600; { //填充platform Platform &plat = scene.platforms.AddEmpty(); //1、name plat.name = "platform"; CameraIntern &cam = plat.cameras.AddEmpty(); cam.R = RMatrix::IDENTITY; cam.C = Point3(0, 0, 0); cam.K = _k; //已知 有8个相机位姿 std::string matrix_path = "./test/scene/"; for (int i = 1; i <= vieNum; ++i) { std::string _path = matrix_path + std::to_string(i) + "_ex.txt"; Eigen::Matrix4d temp; loadMat4(_path, temp); Platform::Pose &pose = plat.poses.AddEmpty(); pose.C = temp.block<3, 1>(0, 3); pose.R = temp.block<3, 3>(0, 0); } } {//填充images std::string imag_path = "test/image/"; std::string matrix_path = "test/scene/"; //ImageArr imgarr = scene.images; for (int i = 1; i <= vieNum; ++i) { std::string t_img = imag_path + std::to_string(i) + ".jpg"; String _imgP(t_img); Image &_img = scene.images.AddEmpty(); _img.ID = i-1; _img.platformID = 0; _img.cameraID = 0; _img.poseID = i-1; _img.LoadImage(_imgP); scene.images.push_back(_img); } } scene.mesh.Load("test/sm_mesh.ply"); unsigned nResolutionLevel = 0; unsigned nMinResolution = 1280; float fOutlierThreshold = 0.f; float fRatioDataSmoothness = 0.0f; bool bGlobalSeamLeveling = true; bool bLocalSeamLeveling = true; unsigned nTextureSizeMultiple = 0; unsigned nRectPackingHeuristic = 0; bool res = scene.TextureMesh(nResolutionLevel, nMinResolution, fOutlierThreshold, fRatioDataSmoothness, bGlobalSeamLeveling, bLocalSeamLeveling, nTextureSizeMultiple, nRectPackingHeuristic); std::cout << "texture res:" << res << std::endl; //scene.Save("./test/res_tex.mvs",ARCHIVE_TEXT); scene.mesh.Save("test/res_tex.ply");}依照上篇文章《多视角三维模型纹理映射 01》中所述,须要填充Scene中的相干数据成员。在这里我增加了一个Platform以及一个camera,而后增加了8个相机的Pose,这是合乎本人的理论应用状况的,我有一个相机,拍摄了指标的8个角度的图像,所以我只有一个平台,一个相机,然而复原了8个相机的位姿。 ...

January 26, 2022 · 2 min · jiezi

关于c++:多视角三维模型纹理映射-01

本片文章算是作为上一篇文章【G2O与多视角点云全局配准优化】 的连续。从上篇文章杠已知,当初目前手头曾经有了配准好的全局点云、每块点云的变换矩阵以及对应每块点云的RGB图像。接下来,自然而然的便是:对全局点云重建三维网格,并对重建后的三维网格进行纹理贴图。已知:三维模型(三角面片,格局任意),多视角RGB图片(纹理)、变换矩阵;求:为三维模型贴上纹理图。针对上述待求解纹理,相熟的小伙伴必定直到,其实在求解多视角立体匹配的最初一步--外表重建与纹理生成。接上篇,为实现本人的目标,首先须要重构三角网格,从点云重建三角网格,与相机、纹理图片等没有任何关系,可间接应用pcl中的重建接口或者cgal甚至meshlab等软件,间接由三维点云重建三角网格。在实现重建三角网格之前,还有很重要--然而能够酌情省略的一个关键步骤:多视角三维点云交融!上面持续应用本人之前所拍摄的8个点云片段为例进行示例记录。(留神,此处强调8个点云片段,并不示意8个视角的点云,后续阐明)。 多视角点云交融将多个点云片段拼接之后,无奈防止的存在多个视角下点云互相重叠的状况。如下图所示,在重叠区域的点云疏密水平个别都大于非重叠区域点云。进行点云交融的目标一是为了点云去重,升高点云数据量;二是为了进一步平滑点云,进步精度,为后续的其余计算(如测量等)提供高质量的数据。 凑巧,本人对挪动最小二乘算法有肯定理解,在pcl中,N年之前【pcl之MLS平滑】和【pcl之MLS算法计算并对立法向量】也做过一些小测试。在我的印象中,挪动最小二乘是这样工作的:针对深刻数据,计算指标点及其邻域,这些待计算的部分数据便形成了指标点的紧支域,在紧支域内有某个函数对指标点进行运算,运算的根本规定是根据紧支域内其余点到指标点的权重不同,这里的某个函数即所谓的紧支函数。紧支函数 + 紧支域 +权重函数形成了挪动最小二乘算法的根本数学概念,所谓移动性则体现在紧支域在容许的空间中“滑动”计算,直至笼罩所有数据。最小二乘个别针对全局求最优,而挪动最小二乘因为其 “移动性”(紧支)不仅能针对全局优化求解,而且也具备局部优化性,更进一步的,针对三维点云,其可能提取等值面,联合MC(挪动立方体)算法,实现外表三角网格的重建。 pcl中,对于MLS算法的例子很多很多,本人之前的两篇水文也算也有个根本的利用介绍,此处不在过多记录。在这里,间接应用如下代码: pcl::PointCloud<pcl::PointXYZRGB> mls_points; //存后果pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZRGB>);pcl::MovingLeastSquares<pcl::PointXYZRGB, pcl::PointXYZRGB> mls;mls.setComputeNormals(false);mls.setInputCloud(res);mls.setPolynomialOrder(2); //MLS拟合的阶数,mls.setSearchMethod(tree);mls.setSearchRadius(3);mls.setUpsamplingMethod(pcl::MovingLeastSquares<pcl::PointXYZRGB, pcl::PointXYZRGB>::UpsamplingMethod::VOXEL_GRID_DILATION);mls.setDilationIterations(0); //设置VOXEL_GRID_DILATION办法的迭代次数mls.process(mls_points);留神,上述计算过程中,应用了pcl::MovingLeastSquares::VOXEL_GRID_DILATION办法,依照pcl官网解释,该办法不仅可能修复大量点云空洞,而且可能对点云坐标进行局部优化,输入为全局疏密水平一样的点云,通过设置不同的迭代次数,该办法不仅可能降采样,还能上采样(次要通过迭代次数管制). 将本人的数据放入上述计算过程,点云交融部分成果如下: 肉眼可见点云更加平均、平滑,同同时数据量从100w+ 降到 10w+. 上述操作,根本满足了本人下一步的要求。 进一步的,鉴于外表重建并非重点,针对上述后果,这里间接应用MeshLab软件中的泊松重建,后果记录如下: 多视角纹理映射在这里,正式引入本人对所谓“多视角”的了解。 首先,多视角与多角度,通常状况下,这两个概念根本都是在说同一件事件,即从不同方位角拍摄三维模型。然而这其中又隐含两种不同的 [操作形式],其一如手持式三维扫描仪、SLAM中的状态预计、甚至搭载摄像机/雷达的主动驾驶汽车等,这些场景下根本都是相机在动,指标不动,即相机绕指标静止;其二 如转台式三维扫描仪等,这些场景根本都是相机不动,指标动,即指标自身具备静止属性。所以这里,有必要对多视角与多角度做进一步的辨别,多视角指的是相机的多视角(对呀,相机才具备实在的物理视角、位姿、拍摄角度 巴拉巴拉...),多角度指的是指标物体的不同角度(对呀,一个物体能够从不同的角度被察看)。 其次,外参,外参是很重要的一个概念(废话,还用你说!),可真的引起其余使用者足够的器重吗?未必! 咱们个别常说的外参,其实是带有主语的,只是咱们太司空见惯从而把主语省略了。外参---个别指相机的外参,即形容相机的变动。在多视角三维点云配准中,每个点云都有一个变动矩阵,该变动矩阵能够称其为点云的外参,即形容点云的变动。至此,至多呈现了两个外参,且这两个外参所代表的物理意义齐全不一样,然而又有千头万绪的分割。咱们都晓得,宏观下静止是互相的,则必然点云的外参和对应相机的外参互逆。 注: 之所以这里对上述概念做严格辨别,次要还是因为本人之前对上述所提到的概念没有真正深刻了解,尤其是对外参的了解,导致前期算法计算呈现谬误;其二还是后续库、框架等对上述有严格辨别。 OpenMVS与纹理映射终于到了OpenMVS。。。。 已知OpenMVS能够用来浓密重建(点云)、Mesh重建(点云-->网格)、Mesh优化(非风行解决、补洞等)、网格纹理映射,正好对应源码自带的几个APP。 此处,目标只是单纯的须要OpenMVS的网格纹理映射性能!浏览国内外无关OpenMVS的应用办法,尤其国内,根本都是”一条龙“服务,总结应用流程就是 colmap/OpenMVG/visualSFM...+ OpenMVS,根本都是应用可执行文件的傻瓜式形式(网上一查一大堆),而且根本都是翻来覆去的互相”援用“(剽窃),显然不合乎本人要求与目标。吐个槽。。。 为了应用Openmvs的纹理映射模块,输出数据必须是 .mvs格式文件,额。。。.mvs是个什么鬼,我没有啊,怎么办?! 好吧,进入OpenMVS源码吧,用本人的数据去填充OpenMVS所需的数据接口。(Window10 + VS2017+OpenMVS编译省略,次要是本人过后编译的时候没做记录,不过CMake工程个别不太简单)。 场景Scene查看OpenMVS自带的几个例子,发现其必须要填充Scene类,针对本人所面对的问题,Scene类的次要构造如下: class MVS_API Scene{public: PlatformArr platforms; //相机参数和位姿 // camera platforms, each containing the mounted cameras and all known poses ImageArr images; //纹理图,和相机对应 // images, each referencing a platform's camera pose PointCloud pointcloud; //点云 // point-cloud (sparse or dense), each containing the point position and the views seeing it Mesh mesh; //网格 // mesh, represented as vertices and triangles, constructed from the input point-cloudunsigned nCalibratedImages; // number of valid imagesunsigned nMaxThreads; // maximum number of threads used to distribute the work load ... //省略代码 bool TextureMesh(unsigned nResolutionLevel, unsigned nMinResolution, float fOutlierThreshold=0.f, float fRatioDataSmoothness=0.3f, bool bGlobalSeamLeveling=true, bool bLocalSeamLeveling=true, unsigned nTextureSizeMultiple=0, unsigned nRectPackingHeuristic=3, Pixel8U colEmpty=Pixel8U(255,127,39)); ... //省略代码 }本人所须要的次要函数为bool TextureMesh(),可见其自带了很多参数,参数意义前期应用时再探讨。 ...

January 26, 2022 · 2 min · jiezi

关于c:简单小游戏-剪刀石头步

首先阐明规定: 0、1、2三个整数别离是剪刀石头布在程序中的外部示意,用户也要求输出0、1或2,而后和计算机随机生成的0、1或2比输赢,这个程序的主体是一个死循环,须要按Ctrl-C退出程序! #include <stdio.h> #include <stdlib.h> #include <time.h> int main(void) { char gesture[3][10] = {"scissor", "stone","cloth"}; int man, computer, result, ret; srand(time(NULL)); while (1) { computer = rand() % 3; printf("\nInput your gesture (0-scissor 1 -stone 2 - cloth) :\n "); ret = scanf("%d", &man); if (ret != 1 || man < 0 || man > 2) { printf("Invalid input! Please input 0, 1 or 2.\n"); continue; } printf("Your gesture: %s\tComputer's gesture: % s\n ", gesture[man],gesture[computer]); result = (man - computer + 4) % 3 - 1; //此处为外围代码! if (result > 0) printf("You win!\n"); else if (result == 0) printf("Draw!\n"); else printf("You lose!\n"); } return 0; }依据对result的输赢判断条件可知,当result(即咱们输出的和电脑随机生成的后果通过计算之后的后果)大于0,咱们赢,小于0,咱们输,等于0,打成平手!那么(man - computer + 4) % 3 - 1这个神奇的表达式是如何管制比拟出0、1、2这三个数字在“剪刀石头布”意义上的大小和输赢的?凑的过程见上面表格: ...

January 25, 2022 · 1 min · jiezi

关于c++:几行代码随机生成362368℃娱乐练手切记不可拿来虚报温度

#include <iostream>#include<cstdlib>#include<ctime>#define LEN 20//此处指定要生成多少个温度值int main(){ /*初始化随机数发生器*/ srand(time(NULL)); for(int i = 0; i < LEN; i++){ double x = 36.0 + (((rand()%7) + 2) / 10.0); printf("%.1f\n",x); } return 0;}仅供娱乐,事实中不要应用哦!

January 25, 2022 · 1 min · jiezi

关于c++:文本方式实现编一个函数输入一个字符串要求将所有无效字符去除空格tnr

[题目形容]编一个函数,输出一个字符串,要求做一个新字符串,把其中所有的一个或多个间断的空白字符都压缩为一个空格。这里所说的空白包含空格、'\t'、'\n'、'\r'。例如原来的字符串是:This Content hohook?file systemuttered wordsok okend.is ok?压缩了空白之后就是:This Content hoho is ok ok? file system uttered words ok ok ? end.实现该性能的函数接口要求合乎下述标准:char shrink_space(char dest, const char *src, size_t n); 给的字符比拟凌乱,所以咱们能够将其保留在文本(shrink_file.txt)中,而后将解决好的字符放在另一个输入文本(shrink_file_output.txt)中。上面是具体的实现过程:先看一下指标文本的内容代码共分为三个局部:1、一个函数判断以后字符是否为有效字符! bool is_space(char c){ if(c==' ' || c=='\t' || c=='\n' || c=='\r') return true; else return false;}2、解决凌乱字符串的外围函数shrink_space()! char *shrink_space(char *dest, const char *src, size_t n){ size_t i=0, j=0; while(i<n && src[i]) { if(is_space(src[i])) { dest[j++] = ' '; while(is_space(src[++i])) ; }else dest[j++] = src[i++]; } for(; i<n; ++i) dest[i] = '\0'; return dest;}3、而后是咱们的main函数(此处我用的是文本按行输入输出) ...

January 25, 2022 · 1 min · jiezi

关于c++:三种stdvector并发安全的设计思路

vector的并发读写问题家喻户晓,C++规范库中的vector不保障线程平安。当咱们在并发读写vector时,往往会面临两方面的危险: 内容读取异样:例如两个线程一个在读,一个在写,或者两个线程同时在写,都会导致单个数据外部呈现不统一的状况。vector扩容时,内存地位产生扭转导致Segmentation fault谬误。因为vector在扩容时会将内容全副拷贝到新的内存区域中,原有的内存区域被开释,此时如果有线程仍然在向旧的内存区域读或写就会出问题。举一个简略的例子: vector<int> vec;void add_vector(int range, unsigned int seed){ srand(seed); for(int i = 0 ; i < range; i++){ vec.push_back(rand()); }}int main(){ vec.reserve(100); thread t1 = thread(add_vector, 1000, 2); thread t2 = thread(add_vector, 1000, 1); t1.join(); t2.join();}两个线程都在向vec中增加元素,如果没有任何解决,很容易解体,就是因为第二个起因。而这种并发写的状况,在很多业务场景中都是很可能呈现的,例如:在举荐零碎中,为了进步运算效率每个线程都依照不同的策略生产举荐召回,这些线程产生召回后就会向同一个数组中合并。而后依据这些召回中选出最好的举荐后果。 在文章中提出了三种向vector并发增加元素的计划,目标是保障多线程并发条件下能正确向vector中。我的项目放在了safe_vector。 多线程平安的vector设计---有锁的设计对于解决并发问题中的最简略的设计就是加锁。在这里咱们应用规范库为咱们提供的mutex来对push_back临界区加锁。 template<typename T>class lock_vector{ std::mutex mlock; vector<T> mvec;public: T operator[](unsigned int idx){ return mvec[idx]; } lock_vector()=default; lock_vector(lock_vector<T>& vec){ vec.getVector(mvec); }; lock_vector(lock_vector<T>&& vec){ vec.getVector(mvec); }; void push_back(const T& value) noexcept{ mlock.lock(); mvec.push_back(value); mlock.unlock(); } void getVector(vector<T> & res){ res = mvec; }};多线程平安的vector设计---无锁设计除了应用互斥锁,还能够通过无锁的设计来实现线程同步。其中一种常见的思路就是CAS(compare-and-swap)。C++的原子变量(atomic)就提供了compare_exchange_weak和compare_exchange_strong来实现CAS机制。上面的代码是基于CAS实现的多线程平安计划。 ...

January 24, 2022 · 2 min · jiezi

关于c++:找出一组序列中第k小的元素要求时间复杂度为On

在浏览linuxc中看到一种快排的利用,求最小值,然而要求工夫复杂度放弃在O(n).实现如下,k代表要找的第k小! #include<iostream>using namespace std;#define LEN 8int order_partition(int a[], int low, int high,int k){ k = a[low]; while(low<high){ while(low <high && a[high]>= k ) high--; if(low<high) a[low++] = a[high]; while( low<high && a[low]<= k ) low++; if(low<high) a[high--] = a[low]; } a[low] = k; return low;}int order_K_statistic(int a[],int start,int end, int k){ int i; while(end>=start){ i = order_partition(a,start,end,k); if(k == i){ return a[i]; }else if(k > i && k < LEN){ return order_K_statistic(a,i+1,end,k); }else if(k < i && k >= 0){ return order_K_statistic(a,start,i-1,k); }else{ return -1; } }}int main(){ int a[LEN] = { 5, 2, 4, 7, 1, 3, 2, 6 }; int x = 0; for(int i = 0; i < LEN; i++){ x = order_K_statistic(a,0,LEN-1,i); printf("%d\n",x); } return 0;}能够剖析一下为什么工夫复杂度是(n),在最好状况下每次丢掉一半的元素,n+n/2+n/4+n/8+...=2n,均匀状况下的剖析比较复杂,但疾速排序相似,工夫复杂度和最好状况下统一。(摘自《linuxc》) ...

January 18, 2022 · 1 min · jiezi

关于c:什么是安全函数

公司的大佬说之前某大厂为了平安函数的替换耗资10亿美金。可想平安很重要,平安函数很重要,对于咱们做系统软件的来说很重要。为什么要替换成平安函数,这外面就波及到了一种破绽攻打,缓冲区溢出攻打。 缓冲区溢出是指当计算机向缓冲区内填充数据位数时超过了缓冲区自身的容量,溢出的数据笼罩在非法数据上。现实的状况是:程序会检查数据长度,而且并不容许输出超过缓冲区长度的字符。然而绝大多数程序都会假如数据长度总是与所调配的贮存空间相匹配,这就为缓冲区溢出埋下隐患。操作系统所应用的缓冲区,又被称为“堆栈”,在各个操作过程之间,指令会被长期贮存在“堆栈”当中,“堆栈”也会呈现缓冲区溢出。缓冲区溢出攻打是利用缓冲区溢出破绽所进行的攻打口头。利用缓冲区溢出攻打,能够导致程序运行失败、零碎关机、重新启动等结果。 缓冲区溢出中,最为危险的是堆栈溢出,因为入侵者能够利用堆栈溢出,在函数返回时扭转返回程序的地址,让其跳转到任意地址,带来的危害一种是程序解体导致拒绝服务分段谬误(Segmentation fault),另外一种就是跳转并且执行一段恶意代码,比方失去shell,而后随心所欲。 C语言没有提供字符串类型,字符串以字符数组的模式呈现,C规范库提供了一些操作字符串的函数,次要有:strcmp 字符串比拟函数,strcpy 字符串拷贝函数, strlen 字符串测长函数, strcat字符串连贯函数,sprintf格式化字符串拷贝函数等等。因为字符串就是以‘\0’完结的一段内存,这些函数本质上也就是操作内存的函数。 也就是说,平安函数和非平安函数最大的差别就是:为了避免堆栈溢出,平安函数多了一个确定buff长度的参数。 举个例子: 非平安函数: 头文件:#include <string.h>函数原型:char *strcpy(char *dest, const char *src);函数阐明:把从src地址开始且含有NULL结束符的字符串复制到以dest开始的地址空间。src和dest所指内存区域不能够重叠且dest必须有足够的空间来包容src的字符串。平安函数: 头文件:#include <string.h>函数原型:char *strncpy(char *dest, const char *src, size_t n);函数阐明:把从src地址开始且含有NULL结束符的字符串复制到以dest开始的地址空间。最多复制n个字符。src和dest所指内存区域不能够重叠且dest必须有足够的空间来包容src的字符串。关注&&分割开源轻量操作系统: https://gitee.com/cmcc-oneos/OneOS-Lite docs文档核心: https://oneos-lite.com/

January 18, 2022 · 1 min · jiezi

关于c++:利用OpenCV进行ORB角点提取和匹配

首先构建CMakeLists.txt cmake_minimum_required(VERSION 3.21)project(ORB)set(CMAKE_CXX_STANDARD 14)find_package( OpenCV REQUIRED )include_directories( ${OPENCV_INCLUDE_DIRS} )add_executable(ORB main.cpp)target_link_libraries(ORB ${OpenCV_LIBS})编写cpp #include <iostream>#include <opencv2//core/core.hpp>#include <opencv2/features2d/features2d.hpp>#include <opencv2/highgui/highgui.hpp>using namespace std;首先读取图片 cv::Mat img_1 = cv::imread("../1.png");cv::Mat img_2 = cv::imread("../2.png");cv::imshow("img_1", img_1);cv::imshow("img_2", img_2);cv::waitKey(0);cv::destroyAllWindows();其次进行ORB角点提取的一些初始化工作 vector<cv::KeyPoint> keypoints_1, keypoints_2;cv::Mat descripions_1, descripions_2;cv::Ptr<cv::FeatureDetector> detector = cv::ORB::create(); //检测FAST角点cv::Ptr<cv::DescriptorExtractor> extractor = cv::ORB::create(); //提取形容子cv::Ptr<cv::DescriptorMatcher> matcher = cv::DescriptorMatcher::create("BruteForce-Hamming"); //匹配器,应用汉明间隔STEP1 & STEP2 检测FAST角点、计算BRIEF形容子 //STEP1 检测FAST角点detector->detect(img_1, keypoints_1); //提取img_1中的角点,存储到keypoints_1中detector->detect(img_2, keypoints_2);//STEP2 计算BRIEF形容子extractor->compute(img_1, keypoints_1, descripions_1);extractor->compute(img_2, keypoints_2, descripions_2);cv::Mat outimg_1, outimg_2;cv::drawKeypoints(img_1, keypoints_1, outimg_1, cv::Scalar::all(-1), cv::DrawMatchesFlags::DEFAULT);cv::drawKeypoints(img_2, keypoints_2, outimg_2, cv::Scalar::all(-1), cv::DrawMatchesFlags::DEFAULT);cv::imshow("ORB Keypoints_img_1", outimg_1);cv::imshow("ORB Keypoints_img_2", outimg_2);cv::waitKey(0);cv::destroyAllWindows();STEP3 & STEP4 特色点匹配、特色点筛选 ...

January 16, 2022 · 1 min · jiezi

关于c++:C编译cmake简明教程

cmake简介CMake 是一个开源、跨平台的工具系列,旨在构建、测试和打包软件。CMake 用于应用简略的平台和编译器独立配置文件来控制软件编译过程,并生成可在您抉择的编译器环境中应用的本机 makefile和工作区。 cmake 存在的意义在介绍g++/gcc原理的文章中C++编译原理,咱们用一个简略的例子解说了C++编译的原理,以及g++的应用。对于生成可执行文件这项工作,咱们须要蕴含相应的头文件,以确保咱们写的源代码文件能够顺利的被编译为二进制文件。对于在代码中应用的,定义在其余库的函数和变量,咱们须要通过链接,将其具体的二进制内容,退出到可执行文件中(动静库是运行时加载),这样可执行文件能力顺利执行。 然而对于大型项目来说,为了可读性和可维护性,源代码文件往往依据性能扩散在不同层级的不同目录下,须要的第三方库和第三方头文件也是十分多的。这种状况下,如果间接用g++命令来进行我的项目构建,无疑是十分麻烦的。兴许一些老手会说能够应用MakeFile,但其实MakeFile其实就是将g++命令对应的脚本文件。 cmake的呈现就是为了帮忙构建这种大型简单我的项目。cmake为咱们提供了简洁的接口,不便咱们设置编译参数(如优化等级,报警设置等等),增加依赖(头文件和库),编译源代码等等。 须要留神的是cmake的工作并不是构建我的项目,而是生成构建我的项目的g++命令(更确切的来说就是MakeFile)。 cmake的一个简略的例子例子的源代码在这里cmake例子。例子的目录构造如下: .├── CMakeLists.txt├── include│ └── header.h├── library├── main.cpp└── src ├── add │ └── add.cpp ├── distinct │ └── distinct.cpp └── printer.cppCMakeLists.txt的内容如下: # cmake 最低版本需要cmake_minimum_required(VERSION 3.10)# 工程名称project(leak_example)# 设置编译规范为C++11set(CMAKE_CXX_STANDARD "11")# 设置编译动态库的产出目录为我的项目根目录下的library文件夹set(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/library/)# 设置编译可执行文件的产出目录为我的项目根目录下set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/)# 设置蕴含头文件门路include_directories(include/)# 编译源码生成指标# 寻找src目录下所有的cpp文件(源代码文件)file(GLOB_RECURSE SRC_LIST src/*.cpp)# 将src目录下的cpp文件编译为动态库libcommon.aadd_library(common STATIC ${SRC_LIST})# 设置链接库目录link_directories(${CMAKE_SOURCE_DIR}/library/)# 将main.cpp编译为可执行文件add_executable(main main.cpp)# 减少可执行文件须要链接的动态库。肯定要放在add_executable前面,否则cmake会对main产生困惑。add_executable相当于申明了可执行文件main的存在。target_link_libraries(main libcommon.a)构建我的项目时,顺次执行以下命令: mkdir buildcd build && cmake ..此时,就能够在build文件夹下看到MakeFile文件了,cmake也就正式实现了它的使命,接着执行make,就能够看到上面的目录构造,主文件曾经呈现了可执行文件main和生成的动态库libcommon.a: ├── CMakeLists.txt├── include│ └── header.h├── library│ └── libcommon.a├── main├── main.cpp└── src ├── add │ └── add.cpp ├── distinct │ └── distinct.cpp └── printer.cpp然而可怜的是,这个程序并不能正确执行,因为外面有一些内存泄露的问题,在下一篇文章中将会介绍如何利用一些工具来定位内存泄露问题。 ...

January 14, 2022 · 1 min · jiezi

关于c++:TensorRT-开始

TensorRT 是 NVIDIA 自家的高性能推理库,其 Getting Started 列出了各材料入口,如下: 本文基于以后的 TensorRT 8.2 版本,将一步步介绍从装置,直到减速推理本人的 ONNX 模型。 装置进 TensorRT 下载页 抉择版本下载,需注册登录。 本文抉择了 TensorRT-8.2.2.1.Linux.x86_64-gnu.cuda-11.4.cudnn8.2.tar.gz,能够留神到与 CUDA cuDNN 要匹配好版本。也能够筹备 NVIDIA Docker 拉取对应版本的 nvidia/cuda 镜像,再 ADD TensorRT 即可。 # 解压进 $HOME (免得 sudo 编译样例,为以后用户)tar -xzvf TensorRT-*.tar.gz -C $HOME/# 软链到 /usr/local/TensorRT (以固定一个门路)sudo ln -s $HOME/TensorRT-8.2.2.1 /usr/local/TensorRT之后,编译运行样例,保障 TensorRT 装置正确。 编译样例样例在 TensorRT/samples,阐明见 Sample Support Guide 或各样例目录里的 README.md。 cd /usr/local/TensorRT/samples/# 设定环境变量,可见 Makefile.configexport CUDA_INSTALL_DIR=/usr/local/cudaexport CUDNN_INSTALL_DIR=/usr/local/cudaexport ENABLE_DLA=export TRT_LIB_DIR=../libexport PROTOBUF_INSTALL_DIR=# 编译make -j`nproc`# 运行export LD_LIBRARY_PATH=/usr/local/TensorRT/lib:$LD_LIBRARY_PATHcd /usr/local/TensorRT/./bin/trtexec -h./bin/sample_mnist -d data/mnist/ --fp16运行后果参考: ...

January 12, 2022 · 10 min · jiezi

关于c++:ffmpeg源码编译环境搭建

ffmpeg是视频开发最罕用到的开源软件,ffmpeg功能强大,用处宽泛,提供简直所有你可能想到的与视频开发相干的操作,许多商业软件都以ffmpeg为根底进行开发定制。 FFmpeg: FFmpeg is a free and open-source project consisting of a vast software suite of libraries and programs for handling video, audio, and other multimedia files and streams. At its core is the FFmpeg program itself, designed for command-line-based processing of video and audio files, and widely used for format transcoding, basic editing (trimming and concatenation), video scaling, video post-production effects, and standards compliance (SMPTE, ITU) . 摘自wikipediaffmpeg性能宏大,向开发者提供了丰盛的函数库调用,罕用的函数库包含: ...

January 12, 2022 · 3 min · jiezi

关于c++:-Onlogn-复杂度之排序

疾速排序不稳固 void quick_sort(int q[], int l, int r) { if (l >= r) return; // 位移和按位逻辑运算优先级低于加减 int i = l - 1, j = r + 1, pivot = q[l + r >> 1]; while (i < j) { while (q[ ++ i] < pivot); while (q[ -- j] > pivot); if (i < j) swap(q[i], q[j]); } quick_sort(q, l, j), quick_sort(q, j + 1, r);}归并排序稳固 void merge_sort(int q[], int l, int r) { if (l >= r) return; int mid = l + r >> 1; merge_sort(q, l, mid), merge_sort(q, mid + 1, r); int i = l, j = mid + 1, k = 0; while (i <= mid && j <= r) if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ]; else tmp[k ++ ] = q[j ++ ]; while (i <= mid) tmp[k ++ ] = q[i ++ ]; while (j <= r) tmp[k ++ ] = q[j ++ ]; for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];}希尔排序不稳固 ...

January 12, 2022 · 2 min · jiezi

关于c++:二分

整数二分算法bool check(int x) {/* ... */} // 查看x是否满足某种性质// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时应用:int bsearch_1(int l, int r) { while (l < r) { int mid = l + r >> 1; if (check(mid)) r = mid; else l = mid + 1; } return l;}// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时应用:int bsearch_2(int l, int r) { while (l < r) { int mid = l + r + 1 >> 1; if (check(mid)) l = mid; else r = mid - 1; } return l;}浮点数二分算法bool check(double x) {/* ... */} // 查看x是否满足某种性质double bsearch_3(double l, double r) { const double eps = 1e-6; // eps示意精度,取决于题目对精度的要求 while (r - l > eps) { double mid = (l + r) / 2; if (check(mid)) r = mid; else l = mid; } return l;}

January 11, 2022 · 1 min · jiezi

关于c++:位运算

位运算// 求n的第k位数字n >> k & 1 // 返回n的最低一位1示意的数字n & -n

January 11, 2022 · 1 min · jiezi

关于c#:分表分库百亿级大数据存储

NewLife.XCode是一个有15年历史的开源数据中间件,反对netcore/net45/net40,由新生命团队(2002~2019)开发实现并保护至今,以下简称XCode。整个系列教程会大量联合示例代码和运行日志来进行深入分析,蕴含多年开发教训于其中,代表作有百亿级大数据实时计算我的项目。开源地址:https://github.com/NewLifeX/X (求star, 938+) XCode是重度充血模型,以单表操作为外围,不反对多表关联Join,简单查问只能在where上做文章,整个select语句肯定是from单表,因而对分表操作具备人造劣势!!! 浏览本文之前,倡议回顾《百亿级性能》,其中“索引齐备”章节详细描述了大型数据表的外围要点。 100亿数据其实并不多,一个比拟常见的数据分表分库模型:MySql数据库8主8从,每服务器8个库,每个库16张表,共1024张表(从库也有1024张表) ,每张表1000万到5000万数据,整好100亿到500亿数据! 例程分析 例程地位:https://github.com/NewLifeX/X...新建控制台我的项目,nuget援用NewLife.XCode后,建设一个实体模型(批改Model.xml):<Tables Version="9.12.7136.19046" NameSpace="STOD.Entity" ConnName="STOD" Output="" BaseClass="Entity" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:schemaLocation="http://www.newlifex.com https://raw.githubusercontent.com/NewLifeX/X/master/XCode/ModelSchema.xsd" xmlns="http://www.newlifex.com/ModelSchema.xsd"> <Columns> <Column Name="ID" DataType="Int32" Identity="True" PrimaryKey="True" Description="编号" /> <Column Name="Category" DataType="String" Description="类别" /> <Column Name="Action" DataType="String" Description="操作" /> <Column Name="UserName" DataType="String" Description="用户名" /> <Column Name="CreateUserID" DataType="Int32" Description="用户编号" /> <Column Name="CreateIP" DataType="String" Description="IP地址" /> <Column Name="CreateTime" DataType="DateTime" Description="工夫" /> <Column Name="Remark" DataType="String" Length="500" Description="详细信息" /> </Columns> <Indexes> <Index Columns="CreateTime" /> </Indexes> </Tables>在Build.tt上右键运行自定义工具,生成实体类“历史.cs”和“历史.Biz.cs”。不必批改其中代码,待会咱们将借助该实体类来演示分表分库用法。为了不便,咱们将应用SQLite数据库,因而不须要配置任何数据库连贯,XCode检测到没有名为STOD的连贯字符串时,将默认应用SQLite。此外,也能够通过指定名为STOD的连贯字符串,应用其它非SQLite数据库。 按数字散列分表分库大量订单、用户等信息,可采纳crc16散列分表,咱们把该实体数据拆分到4个库共16张表外面:static void TestByNumber(){ XTrace.WriteLine("按数字分表分库");// 事后筹备好各个库的连贯字符串,动静减少,也能够在配置文件写好for (var i = 0; i < 4; i++){ var connName = $"HDB_{i + 1}"; DAL.AddConnStr(connName, $"data source=numberData\\{connName}.db", null, "sqlite"); History.Meta.ConnName = connName; // 每库建设4张表。这一步不是必须的,首次读写数据时也会创立 //for (var j = 0; j < 4; j++) //{ // History.Meta.TableName = $"History_{j + 1}"; // // 初始化数据表 // History.Meta.Session.InitData(); //}}//!!! 写入数据测试// 4个库for (var i = 0; i < 4; i++){ var connName = $"HDB_{i + 1}"; History.Meta.ConnName = connName; // 每库4张表 for (var j = 0; j < 4; j++) { History.Meta.TableName = $"History_{j + 1}"; // 插入一批数据 var list = new List<History>(); for (var n = 0; n < 1000; n++) { var entity = new History { Category = "交易", Action = "转账", CreateUserID = 1234, CreateTime = DateTime.Now, Remark = $"[{Rand.NextString(6)}]向[{Rand.NextString(6)}]转账[¥{Rand.Next(1_000_000) / 100d}]" }; list.Add(entity); } // 批量插入。两种写法等价 //list.BatchInsert(); list.Insert(true); }}}通过 DAL.AddConnStr 动静向零碎注册连贯字符串:var connName = $"HDB_{i + 1}"; ...

January 11, 2022 · 3 min · jiezi

关于c:SNAT的MASQUERADE地址选择与端口选择

环境:版本:kernel-5.4.54 amd64 双核 ubuntu18.04k8s集群网络组件:flannel,kube-proxy: ipvs代码工具:vs code1.概述SNAT(源地址转换)是IPTABLES的NAT表的外围性能,广泛应用与路由器,云服务器,K8S集群等内网环境中,是内核网络子系统中不可或缺的性能IPTABLES的NAT齐全依赖于netfilter的conntrack,对于没有进行conntrack的数据包无奈进行NAT在K8S集群中DNAT用于负载平衡,SNAT用来保障节点转发的数据包能回到节点去实现de-DNAT还原,而不是间接发给客户端。 客户端拜访的是负载平衡IP,后端IP间接回包给客户端的话,客户端无奈辨认;后端IP回包先转给负载均衡器,将后端IP还原成负载平衡IP之后再发给客户端IPTABLES和IPVS都能够实现DNAT负载平衡的性能,然而SNAT只能由IPTABLES实现查看集群中IPTABLES的SNAT规定root@cluster1-worker1:~# iptables -t nat -nLChain PREROUTING (policy ACCEPT)target prot opt source destination KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCALChain INPUT (policy ACCEPT)target prot opt source destination Chain OUTPUT (policy ACCEPT)target prot opt source destination KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */DOCKER all -- 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCALChain POSTROUTING (policy ACCEPT)target prot opt source destination KUBE-POSTROUTING all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes postrouting rules */MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0 RETURN all -- 10.244.0.0/16 10.244.0.0/16 MASQUERADE all -- 10.244.0.0/16 !224.0.0.0/4 RETURN all -- !10.244.0.0/16 10.244.2.0/24 MASQUERADE all -- !10.244.0.0/16 10.244.0.0/16 ...Chain KUBE-POSTROUTING (1 references)target prot opt source destination /* Kubernetes endpoints dst ip:port, source ip for solving hairpin purpose */ MASQUERADE all -- 0.0.0.0/0 0.0.0.0/0 match-set KUBE-LOOP-BACK dst,dst,srcRETURN all -- 0.0.0.0/0 0.0.0.0/0 mark match ! 0x4000/0x4000MARK all -- 0.0.0.0/0 0.0.0.0/0 MARK xor 0x4000/* kubernetes service traffic requiring SNAT */MASQUERADE all -- 0.0.0.0/0 0.0.0.0/0 ...剖析MASQUERADE是如何SNAT的对于咱们理解集群间网络通信很有帮忙 ...

January 10, 2022 · 6 min · jiezi

关于c:IPTABLES的连接跟踪与NAT分析

1.Netfilter 结构图Netfilter框架的外围是五个钩子点,能够通过在钩子点注册函数,实现过滤批改数据包的性能IPTABLES和IPVS就是通过注册钩子函数的形式来实现它们的次要性能的ip_rcv是三层协定栈的入口函数dev_queue_xmit最初会调用网络设备驱动发送数据包包 2.Netfilter & CONNTRACK & IPTABLES NAT 结构图 2.1 Netfilter的每个钩子点的钩子函数都有不同的优先级/* hook函数默认优先级设置,数值越小优先级越高 */enum nf_ip_hook_priorities { NF_IP_PRI_FIRST = INT_MIN, /* 最高优先级 */ NF_IP_PRI_RAW_BEFORE_DEFRAG = -450, /* 波及IP分片重组的RAW */ NF_IP_PRI_CONNTRACK_DEFRAG = -400, /* 波及IP分片重组的连贯跟踪 */ NF_IP_PRI_RAW = -300, /* RAW表,用于勾销连贯跟踪 */ NF_IP_PRI_SELINUX_FIRST = -225, NF_IP_PRI_CONNTRACK = -200, /* 连贯跟踪开始 */ NF_IP_PRI_MANGLE = -150, NF_IP_PRI_NAT_DST = -100, /* NAT的扭转目标地址, DNAT or de-SNAT */ NF_IP_PRI_FILTER = 0, /* IPTABLES的数据包过滤 */ NF_IP_PRI_SECURITY = 50, NF_IP_PRI_NAT_SRC = 100, /* NAT的扭转源地址, SNAT or de-DNAT */ NF_IP_PRI_SELINUX_LAST = 225, NF_IP_PRI_CONNTRACK_HELPER = 300, NF_IP_PRI_CONNTRACK_CONFIRM = INT_MAX, /* 连贯确认 */ NF_IP_PRI_LAST = INT_MAX, /* 最低优先级 */};优先级CONNTRACK > DNAT > FILTER > SNAT > CONNTRACK_CONFIRM3.CONNTRACK3.1 conntrack注册的钩子static const struct nf_hook_ops ipv4_conntrack_ops[] = { { .hook = ipv4_conntrack_in, /* return nf_conntrack_in */ .pf = NFPROTO_IPV4, .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP_PRI_CONNTRACK, }, { .hook = ipv4_conntrack_local, /* return nf_conntrack_in */ .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP_PRI_CONNTRACK, }, { .hook = ipv4_confirm, /* 调用nf_conntrack_confirm */ .pf = NFPROTO_IPV4, .hooknum = NF_INET_POST_ROUTING, .priority = NF_IP_PRI_CONNTRACK_CONFIRM, }, { .hook = ipv4_confirm, /* 调用nf_conntrack_confirm */ .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP_PRI_CONNTRACK_CONFIRM, },};3.2 nf_conntrack_innf_conntrack_in是conntrack的外围函数,次要作用是: ...

January 10, 2022 · 9 min · jiezi

关于c:IPVS分析

1.Netfilter & CONNTRACK & IPVS结构图 2.IPVSipvs只有DNAT和de-DNAT性能 ,它独立与iptables和conntrack,实现了本人的一套连贯跟踪表和NAT机制 2.1 ipvs与conntrack的分割:ipvs仅仅在做DNAT后对conntrack连贯进行更新,避免回包因为没有记录而被抛弃ipvs在TUNNEL模式下,会调用nf_conntrack_confirm函数对连贯进行确认 2.2 ipvs注册的钩子函数static const struct nf_hook_ops ip_vs_ops[] = { /* After packet filtering, change source only for VS/NAT */ { .hook = ip_vs_reply4, /* ip_vs_out */ .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP_PRI_NAT_SRC - 2, }, /* After packet filtering, forward packet through VS/DR, VS/TUN, * or VS/NAT(change destination), so that filtering rules can be * applied to IPVS. */ { .hook = ip_vs_remote_request4, .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP_PRI_NAT_SRC - 1, }, /* Before ip_vs_in, change source only for VS/NAT */ { .hook = ip_vs_local_reply4, .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP_PRI_NAT_DST + 1, }, /* After mangle, schedule and forward local requests */ { .hook = ip_vs_local_request4, .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP_PRI_NAT_DST + 2, }, /* After packet filtering (but before ip_vs_out_icmp), catch icmp * destined for 0.0.0.0/0, which is for incoming IPVS connections */ { .hook = ip_vs_forward_icmp, .pf = NFPROTO_IPV4, .hooknum = NF_INET_FORWARD, .priority = 99, }, /* After packet filtering, change source only for VS/NAT */ { .hook = ip_vs_reply4, .pf = NFPROTO_IPV4, .hooknum = NF_INET_FORWARD, .priority = 100, },};2.3 IPVS中tcp协定的状态转换表/* * Timeout table[state] */static const int tcp_timeouts[IP_VS_TCP_S_LAST+1] = { [IP_VS_TCP_S_NONE] = 2*HZ, [IP_VS_TCP_S_ESTABLISHED] = 15*60*HZ, [IP_VS_TCP_S_SYN_SENT] = 2*60*HZ, [IP_VS_TCP_S_SYN_RECV] = 1*60*HZ, [IP_VS_TCP_S_FIN_WAIT] = 2*60*HZ, [IP_VS_TCP_S_TIME_WAIT] = 2*60*HZ, [IP_VS_TCP_S_CLOSE] = 10*HZ, [IP_VS_TCP_S_CLOSE_WAIT] = 60*HZ, [IP_VS_TCP_S_LAST_ACK] = 30*HZ, [IP_VS_TCP_S_LISTEN] = 2*60*HZ, [IP_VS_TCP_S_SYNACK] = 120*HZ, [IP_VS_TCP_S_LAST] = 2*HZ,};#define sNO IP_VS_TCP_S_NONE#define sES IP_VS_TCP_S_ESTABLISHED#define sSS IP_VS_TCP_S_SYN_SENT#define sSR IP_VS_TCP_S_SYN_RECV#define sFW IP_VS_TCP_S_FIN_WAIT#define sTW IP_VS_TCP_S_TIME_WAIT#define sCL IP_VS_TCP_S_CLOSE#define sCW IP_VS_TCP_S_CLOSE_WAIT#define sLA IP_VS_TCP_S_LAST_ACK#define sLI IP_VS_TCP_S_LISTEN#define sSA IP_VS_TCP_S_SYNACKstatic struct tcp_states_t tcp_states[] = {/* INPUT ip_vs_in调用 *//* sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI, sSA 初始状态 *//*syn*/ {{sSR, sES, sES, sSR, sSR, sSR, sSR, sSR, sSR, sSR, sSR }},/*fin*/ {{sCL, sCW, sSS, sTW, sTW, sTW, sCL, sCW, sLA, sLI, sTW }},/*ack*/ {{sES, sES, sSS, sES, sFW, sTW, sCL, sCW, sCL, sLI, sES }},/*rst*/ {{sCL, sCL, sCL, sSR, sCL, sCL, sCL, sCL, sLA, sLI, sSR }},/* OUTPUT ip_vs_out调用 *//* sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI, sSA 初始状态 *//*syn*/ {{sSS, sES, sSS, sSR, sSS, sSS, sSS, sSS, sSS, sLI, sSR }},/*fin*/ {{sTW, sFW, sSS, sTW, sFW, sTW, sCL, sTW, sLA, sLI, sTW }},/*ack*/ {{sES, sES, sSS, sES, sFW, sTW, sCL, sCW, sLA, sES, sES }},/*rst*/ {{sCL, sCL, sSS, sCL, sCL, sTW, sCL, sCL, sCL, sCL, sCL }},/* INPUT-ONLY ip_vs_in在没有收到回包时调用*//* sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI, sSA *//*syn*/ {{sSR, sES, sES, sSR, sSR, sSR, sSR, sSR, sSR, sSR, sSR }},/*fin*/ {{sCL, sFW, sSS, sTW, sFW, sTW, sCL, sCW, sLA, sLI, sTW }},/*ack*/ {{sES, sES, sSS, sES, sFW, sTW, sCL, sCW, sCL, sLI, sES }},/*rst*/ {{sCL, sCL, sCL, sSR, sCL, sCL, sCL, sCL, sLA, sLI, sCL }},};2.4 ip_vs_in为目的地为虚构服务器的数据包确认连贯,并为连贯调配后端,而后转发数据包 ...

January 10, 2022 · 9 min · jiezi

关于c:LeetCode刷题学习278第一个错误的版本使用二分查找解决01模型问题

C语言二分查找解决 01模型从000000011111111中找到第一个1样例输出:n = 5, bad = 4输入:4解释:调用 isBadVersion(3) -> false 调用 isBadVersion(5) -> true 调用 isBadVersion(4) -> true所以,4 是第一个谬误的版本 int firstBadVersion(int n) { int i=1; int j=n; while(i<j){ int mid=i+(j-i)/2; if(!isBadVersion(mid)){ i=mid+1; } else if(isBadVersion(mid)){ j=mid; } } return i;}

January 10, 2022 · 1 min · jiezi

关于c:LeetCode刷题学习704二分查找

二分查找C语言版本LeetCode 704题给定正序数组,应用二分查找测试样例输出: nums = [-1,0,3,5,9,12], target = 9输入: 4解释: 9 呈现在 nums 中并且下标为 4 int search(int* nums, int numsSize, int target){ int i=0; int j=numsSize-1; while(i<=j){ int mid=(j-i)/2+i; if(target==nums[mid]){ return mid; } else if(target>nums[mid]){ i=mid+1; } else if(target<nums[mid]){ j=mid-1; } } return -1;}

January 10, 2022 · 1 min · jiezi

关于c++:leveldb-memdb源码分析上

前言最近在钻研学习leveldb的源码,并且尝试用Rust进行重写leveldb-rs,leveldb中memdb模块是应用skiplist作为一个kv的内存存储,相干代码实现十分丑陋,所以有了这篇文章。 leveldb通过应用Arena模式来实现skiplist。简略来说,就是利用线性数组来模仿节点之间的关系,能够无效防止循环援用。 c++版本的leveldb尽管也是应用的arena模式,然而节点数据内存的申请和拜访进行了封装,skiplist的构造定义和实现跟传统意义上的skiplist的代码实现十分类似,如果如果大家之前理解过skiplist的话,c++版本的代码是非常容易看懂的。golang版本leveldb 不足arena的封装,间接操作slice,如果对arena模式不相熟的话,了解起来就比拟麻烦。从软件工程角度上开,golang版本的memdb的代码写的不太好,能够进一步优化的和重构arena的操作。在本文中将会解说上面内容: 比照c++和golang版本中查问、插入、删除的实现剖析golang版本中能够优化的中央而后在下一篇文章中将会介绍 基于golang版本应用rust重写memdb(arena版本)应用rust重写一个非arena版本的memdb,也就是经典的链表构造实现形式类型申明首先咱们来比照C++和Golang的代码中的skiplist定义: C++https://github.com/google/lev... 这里次要列出要害的成员变量,具体的能够去看源码: template <typename Key, class Comparator>class SkipList {... // Immutable after construction Comparator const compare_; Arena* const arena_; // Arena used for allocations of nodes Node* const head_; // Modified only by Insert(). Read racily by readers, but stale // values are ok. std::atomic<int> max_height_; // Height of the entire list // Read/written only by Insert(). Random rnd_;};Comparator const compare_; 用来在遍历skiplist进行节点key的比拟Arena* const arena_; 应用Arena模式的内存治理Node* const head_; 首节点std::atomic max_height_; skiplist的层高,在插入的时候可能会变动Random rnd_; 随机数生成器,用于在每次插入的时候生成新节点的层高Golanghttps://github.com/syndtr/gol... ...

January 7, 2022 · 7 min · jiezi

关于c++:Eigen初见

Eigen是基于C++模板的矩阵运算库,在SLAM中是必须把握的。Eigen有一个特地的中央就是它是一个齐全用头文件搭建的库,不须要链接库文件Eigen中矩阵的定义 在CMakeLists.txt中指定Eigen的头文件目录 include_directories("usr/include/eigen3")//Eigen外围局部#include <Eigen/Core>//用于浓密矩阵的代数运算#include <Eigen/Dense>Matrix<double, 3, 3> A; Matrix<double, 3, Dynamic> B; Matrix<double, Dynamic, Dynamic> C; // 反对动静大小的矩阵Matrix3f P, Q, R; // 3x3 float matrix.Vector3f x, y, z; // 3x1 float matrix.RowVector3f a, b, c; // 1x3 float matrix.VectorXd v; // Dynamic column vector of doubles矩阵类型转换。Eigen矩阵不反对主动类型晋升,必须显式地对矩阵类型进行转换。 //// Type conversion// Eigen // MatlabA.cast<double>(); // double(A)A.cast<float>(); // single(A)A.cast<int>(); // int32(A)A.real(); // real(A)A.imag(); // imag(A)// if the original type equals destination type, no work is doneEigen 求解线性方程组 Ax = b,个别不会间接求逆,而是采纳矩阵合成,速度会快很多 ...

January 7, 2022 · 1 min · jiezi

关于c++:树与图

树的存储树的父亲表示法// datastring nodes[N];int fa[N];fa[0] = -1;void add(int b, int a) { fa[b] = a;}二叉树的儿子表示法struct Node { string data; int lc; // 未应用指针 int rc; // 未应用指针 Node() { lc = rc = -1; }};Node nodes[N];二叉树的数组表示法// datastring nodes[N];// ch[i][0]示意左儿子,ch[i][1]示意右儿子int ch[N][2];树与图的存储树是一种非凡的图,与图的存储形式雷同。无向图也是一种非凡的有向图。对于无向图中的边 xy ,存储两条有向边 x->y , y->x 。因而咱们能够只思考有向图的存储。 邻接矩阵(浓密图)bool g[N][N];void add(int x, int y) { g[x][y] = 1; }邻接表(稠密图)#include <vector>std::vector<int> g[N];// 增加一条边x->yvoid add(int x, int y) { g[x].push_back(y); }树与图的遍历深度优先遍历(邻接表)void dfs(int i) { st[i] = true; // 点i曾经被遍历过 for (auto j : g[i]) if (!st[j]) dfs(j);}宽度优先遍历(邻接表)void bfs(int i) { queue<int> q; q.push(i); st[i] = true; // 点i曾经被遍历过 while (!q.empty()) { int t = q.front(); q.pop(); for (auto j : g[t]) if (!st[j]) { q.push(j); st[j] = true; // 点j曾经被遍历过 } }}

January 6, 2022 · 1 min · jiezi

关于c++:C运算符优先级

C++的各运算符按优先级由高到低排列如下:

January 6, 2022 · 1 min · jiezi

关于c++:C数据类型

常见数据类型 浮点数binary32IEEE 754 single-precision binary floating-point format: binary64IEEE 754 double-precision binary floating-point format:

January 6, 2022 · 1 min · jiezi

关于c++:CC气象数据中心实战手把手教你做工业级项目

C/C++气象数据中心实战,手把手教你做工业级我的项目为什么要对SpringBoot返回对立的标准格局在默认情况下,SpringBoot的返回格局常见的有三种: 第一种:返回 String @GetMapping("/hello")public String getStr(){ return "hello,javadaily";}复制代码此时调用接口获取到的返回值是这样: hello,javadaily复制代码第二种:返回自定义对象download@GetMapping("/aniaml")public Aniaml getAniaml(){ Aniaml aniaml = new Aniaml(1,"pig"); return aniaml;}复制代码此时调用接口获取到的返回值是这样: { "id": 1, "name": "pig"}复制代码第三种:接口异样 @GetMapping("/error")public int error(){ int i = 9/0;return i;}复制代码此时调用接口获取到的返回值是这样: {download "timestamp": "2021-07-08T08:05:15.423+00:00", "status": 500, "error": "Internal Server Error", "path": "/wrong"}复制代码基于以上种种情况,如果你和前端开发人员联调接口她们就会很懵逼,因为咱们没有给他一个对立的格局,前端人员不知道如何处理返回值。 还有甚者,有的同学比如小张喜爱对后果进行封装,他使用了Result对象,小王也喜爱对后果进行包装,然而他却使用的是Response对象,当出现这种情况时我相信前端人员肯定会抓狂的。 所以咱们我的项目中是需要定义一个对立的标准返回格局的。 定义返回标准格局一个标准的返回格局至多蕴含3部分: status 状态值:由后端对立定义各种返回后果的状态码message 描述:本次接口调用的后果描述data 数据:本次返回的数据。{ "status":"100", "message":"操作胜利", "data":"hello,javadaily"}复制代码当然也可能按需加入其余扩大值,比如咱们就在返回对象中增加了接口调用工夫 timestamp: 接口调用工夫定义返回对象@Datadownloadpublic class ResultData<T> { /* 后果状态 ,具体状态码参见ResultData.java/ private int status; private String message; private T data; private long timestamp ; public ResultData (){ ...

January 5, 2022 · 1 min · jiezi

关于c:TCP协议connect的端口选择

connect端口抉择在socket编程中, 客户端应用connect向服务端发动申请时,如果不指定本地端口(个别都不指定), 内核会主动为连贯调配一个可用的端口. connect是如何进行端口抉择的呢?connect端口抉择逻辑如下: 如果sock曾经指定了端口, 应用指定的端口如果sock没有指定端口, 调配一个端口 先获取内核参数设置的本地可用端口范畴,默认为low: 32768 - high: 60999依据hint和三元组的hash失去一个随机的偏移量offset从low+offset开始, 在可用端口范畴内遍历判断端口是否可用, 每次端口值+2 不容许应用用户设置的保留端口如果端口曾经应用 不容许应用bind绑定的端口查看端口是否可重用 1. ehash表中没有四元组匹配的sock时端口可重用2. 有四元组匹配的sock时进行TIME_WAIT判断 1. 合乎以下条件可重用 1. 匹配的连贯处于TIME_WAIT状态 2. 满足TIME_WAIT端口复用条件如果端口没有被应用,应用此端口内核容许同一个端口向两个不同的服务端发动连贯申请 源码剖析:connect端口抉择外围函数inet_hash_connect剖析:/* * Bind a port for a connect operation and hash it. */int inet_hash_connect(struct inet_timewait_death_row *death_row, struct sock *sk){ u32 port_offset = 0; /* 如果sk的本地源端口设置为0 */ if (!inet_sk(sk)->inet_num) /* 依据源IP、目标IP、目标端口,用hash函数计算出一个随机数,作为端口的初始偏移值 */ port_offset = inet_sk_port_offset(sk); return __inet_hash_connect(death_row, sk, port_offset, __inet_check_established); /* __inet_check_established为查看端口是否可用的回调函数 */}__inet_hash_connect剖析:int __inet_hash_connect(struct inet_timewait_death_row *death_row, struct sock *sk, u32 port_offset, int (*check_established)(struct inet_timewait_death_row *, struct sock *, __u16, struct inet_timewait_sock **)){ struct inet_hashinfo *hinfo = death_row->hashinfo; struct inet_timewait_sock *tw = NULL; struct inet_bind_hashbucket *head; int port = inet_sk(sk)->inet_num; struct net *net = sock_net(sk); struct inet_bind_bucket *tb; u32 remaining, offset; int ret, i, low, high; static u32 hint; int l3mdev; /* sock曾经设置了端口 */ if (port) { head = &hinfo->bhash[inet_bhashfn(net, port, hinfo->bhash_size)]; tb = inet_csk(sk)->icsk_bind_hash; spin_lock_bh(&head->lock); if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) { inet_ehash_nolisten(sk, NULL); spin_unlock_bh(&head->lock); return 0; } spin_unlock(&head->lock); /* No definite answer... Walk to established hash table */ ret = check_established(death_row, sk, port, NULL); local_bh_enable(); return ret; } /* * sock没有设置端口时会走到这里,以下是内核主动抉择端口的过程 * connect主动抉择端口会保障和ip_local_port_range的low的奇偶性保持一致 * bind主动抉择端口会保障和low奇偶性相同 */ /* * 绑定的VRF(Virtual Routing and Forwarding)设施 * 内核默认不开启tcp_l3mdev_accept,间接返回0 */ l3mdev = inet_sk_bound_l3mdev(sk); /* 获取本地可用端口范畴,ip_local_port_range是能够设置的内核参数,默认是32768-60999 */ inet_get_local_port_range(net, &low, &high); high++; /* [32768, 60999] -> [32768, 61000[ */ /* 计算端口范畴差值 */ remaining = high - low; if (likely(remaining > 1)) /* 确保remaining为偶数,保障和low的奇偶性保持一致 */ remaining &= ~1U; /* * 依据hint和port_offset计算出一个remaining范畴内的偏移量 * hint是一个动态变量,每次+(i+2),i为上次的可用端口-初始抉择端口 * hint尽量使每次抉择的端口递增,进步端口命中率 * port_offset是之前依据源地址,目标地址,目标端口hash进去的一个随机数 */ offset = (hint + port_offset) % remaining; /* In first pass we try ports of @low parity. * inet_csk_get_port() does the opposite choice. */ /* 确保offset为偶数,保障和low的奇偶性保持一致 */ offset &= ~1U;other_parity_scan: /* 抉择第一个port的值 */ port = low + offset; /* 从第一个port开始判断端口是否可用,每次port+2,保障和low的奇偶性保持一致 */ for (i = 0; i < remaining; i += 2, port += 2) { /* port超范围则返回low持续查找 */ if (unlikely(port >= high)) port -= remaining; /* * 排除ip_local_reserved_ports内核参数中设置的保留端口 * 参数默认为空,能够本人配置想要为某些服务保留的端口 */ if (inet_is_local_reserved_port(net, port)) continue; /* 依据端口号和命名空间的哈希失去哈希表头 */ head = &hinfo->bhash[inet_bhashfn(net, port, hinfo->bhash_size)]; /* 锁住此表头 */ spin_lock_bh(&head->lock); /* Does not bother with rcv_saddr checks, because * the established check is already unique enough. */ /* 从哈希失去的链表中查找对应的命名空间和端口号的bind_bucket */ inet_bind_bucket_for_each(tb, &head->chain) { /* 比照命名空间,端口号和VRF设施(默认不开启) */ if (net_eq(ib_net(tb), net) && tb->l3mdev == l3mdev && tb->port == port) { /* 不容许应用bind创立或者应用的端口 * bind创立构造体时,会使得fastreuse和fastreuseport>=0 * connect创立构造体时,两个值为-1 */ if (tb->fastreuse >= 0 || tb->fastreuseport >= 0) goto next_port; WARN_ON(hlist_empty(&tb->owners)); /* 查看端口是否可重用 * 1.ehash表中没有四元组,命名空间匹配的sock时可重用 * 2.有四元组命名空间匹配的连贯时进行TIME_WAIT判断 * 合乎以下条件可重用 * - 匹配的连贯处于TIME_WAIT状态 * - 满足TIME_WAIT端口复用条件 */ if (!check_established(death_row, sk, port, &tw)) goto ok; goto next_port; } } /* 没有找到对应的bind_bucket时会走到这里 * 阐明还没有创立端口的inet_bind_bucket构造,端口肯定可用 */ /* 为端口创立inet_bind_bucket构造 */ tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep, net, head, port, l3mdev); if (!tb) { spin_unlock_bh(&head->lock); return -ENOMEM; } /* fastreuse和fastreuseport设置为-1 */ tb->fastreuse = -1; tb->fastreuseport = -1; goto ok;next_port: spin_unlock_bh(&head->lock); cond_resched(); } /* 走到这里阐明没有适合端口,扭转奇偶性再选一次 */ offset++; if ((offset & 1) && remaining > 1) goto other_parity_scan; /* 扭转奇偶性仍然没有适合端口,返回谬误Cannot assign requested address */ return -EADDRNOTAVAIL;ok: /* 保留动态变量的值,下个雷同三元组会应用新的hint,缩小反复判断 */ hint += i + 2; /* Head lock still held and bh's disabled */ /* 将sock增加到inet_bind_bucket构造的owner链表中 */ inet_bind_hash(sk, tb, port); /* 如果sokc没有增加到ehash表,将sock增加到ehash表中 */ if (sk_unhashed(sk)) { inet_sk(sk)->inet_sport = htons(port); inet_ehash_nolisten(sk, (struct sock *)tw); } /* 提前结束time_wait状态 */ if (tw) inet_twsk_bind_unhash(tw, hinfo); spin_unlock(&head->lock); if (tw) inet_twsk_deschedule_put(tw); local_bh_enable(); return 0;}__inet_check_established剖析:/* called with local bh disabled */static int __inet_check_established(struct inet_timewait_death_row *death_row, struct sock *sk, __u16 lport, struct inet_timewait_sock **twp){ struct inet_hashinfo *hinfo = death_row->hashinfo; struct inet_sock *inet = inet_sk(sk); __be32 daddr = inet->inet_rcv_saddr; __be32 saddr = inet->inet_daddr; int dif = sk->sk_bound_dev_if; struct net *net = sock_net(sk); int sdif = l3mdev_master_ifindex_by_index(net, dif); INET_ADDR_COOKIE(acookie, saddr, daddr); const __portpair ports = INET_COMBINED_PORTS(inet->inet_dport, lport); /* 依据四元组和命名空间失去ehash表的哈希值 */ unsigned int hash = inet_ehashfn(net, daddr, lport, saddr, inet->inet_dport); /* 获取指定哈希值的哈希桶 */ struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash); /* 指定哈希桶的锁 */ spinlock_t *lock = inet_ehash_lockp(hinfo, hash); struct sock *sk2; const struct hlist_nulls_node *node; struct inet_timewait_sock *tw = NULL; /* 锁住哈希桶 */ spin_lock(lock); /* 遍历哈希桶匹配四元组,命名空间,绑定设施雷同的sock */ sk_nulls_for_each(sk2, node, &head->chain) { /* 比拟hash值 */ if (sk2->sk_hash != hash) continue; /* 有四元组,命名空间,绑定设施齐全匹配的连贯 */ if (likely(INET_MATCH(sk2, net, acookie, saddr, daddr, ports, dif, sdif))) { /* 连贯处于TIME_WAIT状态 */ if (sk2->sk_state == TCP_TIME_WAIT) { tw = inet_twsk(sk2); /* 判断是否满足TIME_WAIT端口复用条件 */ if (twsk_unique(sk, sk2, twp)) break; } /* 如果有齐全匹配的连贯,且不可TIME_WAIT复用,会走到这里,返回不可用 */ goto not_unique; } } /* 没有匹配到雷同的连贯,或者time_wait重用会走到这里 */ /* Must record num and sport now. Otherwise we will see * in hash table socket with a funny identity. */ inet->inet_num = lport; inet->inet_sport = htons(lport); sk->sk_hash = hash; WARN_ON(!sk_unhashed(sk)); /* 增加sock到ehash哈希桶中 */ __sk_nulls_add_node_rcu(sk, &head->chain); /* 从ehash哈希桶中删除TIME_WAIT连贯 */ if (tw) { sk_nulls_del_node_init_rcu((struct sock *)tw); __NET_INC_STATS(net, LINUX_MIB_TIMEWAITRECYCLED); } spin_unlock(lock); /* 减少端口应用计数 */ sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); /* 提前终止time_wait */ if (twp) { *twp = tw; } else if (tw) { /* Silly. Should hash-dance instead... */ inet_twsk_deschedule_put(tw); } /* 返回可用 */ return 0;not_unique: spin_unlock(lock); return -EADDRNOTAVAIL;}

January 5, 2022 · 4 min · jiezi

关于c:C标识符最长长度

visual studio 2019编译器下,c标识符长度 最长为4095个,半角字符输出一个字符占用一个字符,全角字符占用两个字符,汉字占用两个字符。超过则会报错 作者:点墨版权:本文版权归作者所有转载:欢送转载,但未经作者批准,必须保留此段申明;必须在文章中给出原文连贯;否则必究法律责任

January 4, 2022 · 1 min · jiezi

关于c:C进阶28指针和数组分析

Summary1)数组是一段间断的内存空间,数组的元素个数为 #define DIM(a) (sizeof(a) / sizeof(*a)) 2)指针是一种非凡的变量,与整数的运算规定为: p + n; <--> (unsigned int)p + n * sizeof(*p)当指针p指向一个数组里的元素时,p + 1将指向以后元素的下一元素;p - 1将指向以后元素的上一元素。 3)指针之间只反对减法运算;参加减法运算的指针必须类型雷同:留神:只有当2个指针指向同一个数组中的元素时,指针相减才有意义,意义为指针所指元素的下标差;当2个指针指向的元素不在同一个数组时,未定义。p1 - p2; <--> ((unsigned int)p1 - (unsigned int)p2) / sizeof(type); 4)char* pEnd = s + DIM(s); pEnd指向了数组s中最初一个元素的后一地位,尽管这个地位不属于数组,但在C语言中,依然认为这个边界地位是属于数组的,这个知识点在STL中也有利用。 5)指针也能够进行关系运算(<, <=, >, >=),但前提是同时指向同一个数组中的元素;两个指针间能够进行比拟运算(==,!=),但两个指针的类型必须雷同; 6)for (p = pBegin; p < pEnd; p++) ,p指向了数组的首元素,pEnd在C语言中被认为是数组的元素,所以p和pEnd都指向了同一个数组里的元素,类型雷同,可能进行比拟。 指针和数组剖析数组是一段间断的内存空间数组的空间大小为 sizeof(arr_type) * arr_size数组名可看做指向数组第一个元素的指针常量 1、指针的运算问题:对于数组int a[5],a + 1的意义是什么?后果是什么?指针运算的意义是什么,后果又是什么? 论断:指针是一种非凡的变量,与整数的运算规定为: p + n; <--> (unsigned int)p + n * sizeof(*p)当指针p指向一个数组里的元素时,p + 1将指向以后元素的下一元素;p - 1将指向以后元素的上一元素。 ...

December 30, 2021 · 3 min · jiezi

关于c++:静态成员实现单例模式

单例模式是一种罕用的软件设计模式。在它的外围构造中只蕴含一个被称为单例的非凡类。通过单例模式能够保证系统中一个类只有一个实例而且该实例易于外界拜访,从而不便对实例个数的管制并节约系统资源。如果心愿在零碎中某个类的对象只能存在一个,单例模式是最好的解决方案。Singleton(单例):在单例类的外部实现只生成一个实例,同时它提供一个动态getInstance()工厂办法,让客户能够拜访它的惟一实例;为了避免在内部对其实例化,将其默认构造函数和拷贝构造函数设计为公有;在单例类外部定义了一个Singleton类型的动态对象,作为内部共享的惟一实例。 用单例模式,模仿公司员工应用打印机场景,打印机能够打印员工要输入的内容,并且能够累积打印机应用次数。 class Printer{public: static Printer* getInstance(){ return pPrinter;} void PrintText(string text){ cout << "打印内容:" << text << endl; cout << "已打印次数:" << mTimes << endl; cout << "--------------" << endl; mTimes++; }private: Printer(){ mTimes = 0; } Printer(const Printer&){}private: static Printer* pPrinter; int mTimes;};Printer* Printer::pPrinter = new Printer;void test(){ Printer* printer = Printer::getInstance(); printer->PrintText("到职报告!"); printer->PrintText("入职合同!"); printer->PrintText("提交代码!");}

December 30, 2021 · 1 min · jiezi

关于c:Mac-OS上用命令行执行C程序

用命令行新建C文件touch hello.c编辑C文件vim hello.c编写C程序代码#include <stdio.h>int main(){ printf("Hello World!"); return 0;} 编译C程序文件cc -c hello.c 生成可执行文件cc hello.o 执行文件./a.out

December 30, 2021 · 1 min · jiezi

关于c:C进阶27数组的本质分析

Summary1)数组是雷同类型的变量的有序汇合,数组在一片间断的内存空间中存储元素。 2)数组名a代表数组首元素的地址,a同时也代表数组这一段间断的内存; a是数组首元素的地址,类型是int*;*a就是首元素,sizeof(*a)能够取得数组首元素的内存大小;a同时也代表这一段内存,sizeof(a)能够取得数组的内存大小;sizeof(a) / sizeof(*a) = 数组元素的个数3)数组的地址须要用取地址符&取到,&a; &a是数组的地址,类型是int(*)[n].4)数组首元素的地址值与数组的地址 值雷同,然而意义不同;(比方现实生活中,小区的地址和我家的地址是雷同的,但并不能说小区就是我家的)咱们所说的地址通常蕴含2个概念:起始地址 + 长度 在值上,a == &a[0] == &a;但意义不同,体现在指针运算上,a + 1,会挪动sizeof(*a)个字节,&a + 1,会挪动sizeof(a)个字节5) 数组名能够看做一个指针常量(留神是看做,数组名并不是指针),因为数组名指向的是首元素的起始地位,是一个地址,并且不能作为左值,同时数组名在很多时候能够像指针一样操作,比方指针运算等。 6)在下列场合中,数组名就不能看做指针常量(也证实了数组名并不是指针) 数组名作为sizeof的参数,这时候取的是数组内存的大小。(a就不是个指针了,如果看做指针,就永远取到的是4或8字节,而不是数组a的大小)数组作为&运算符的参数,此时取到的是数组a的地址,同首元素的值。数组的实质剖析1、数组的概念数组是雷同类型的变量的有序汇合,数组在一片间断的内存空间中存储元素。 数组元素的个数能够显示或隐式指定: 详见:【C入门】7、C语言中的数组int a[5] = {1, 2};int b[] = {1, 2};问题:1. a[2], a[3], a[3]的值是多少? -- 0,如果后面的元素指定了值,后续未初始化的均为02. b蕴含了多少个元素? -- 2,编译器会隐式推断b有多少元素2、数组名的盲点2.1 数组名a代表数组首元素的地址,a同时也代表数组这一段间断的内存; a是数组首元素的地址,类型是int*;*a就是首元素,sizeof(*a)能够取得数组首元素的内存大小;a同时也代表这一段内存,sizeof(a)能够取得数组的内存大小;sizeof(a) / sizeof(*a) = 数组元素的个数2.2 数组的地址须要用取地址符&取到,&a; &a是数组的地址,类型是int(*)[n].2.3 数组首元素的地址值与数组的地址 值雷同,然而意义不同;(比方现实生活中,小区的地址和我家的地址是雷同的,但并不能说小区就是我家的)咱们所说的地址通常蕴含2个概念:起始地址 + 长度 在值上,a == &a[0] == &a;但意义不同,体现在指针运算上,a + 1,会挪动sizeof(*a)个字节,&a + 1,会挪动sizeof(a)个字节2.4 数组名能够看做一个指针常量(留神是看做,数组名并不是指针),因为数组名指向的是首元素的起始地位,是一个地址,并且不能作为左值,同时数组名在很多时候能够像指针一样操作,比方指针运算等。 2.5 在下列场合中,数组名就不能看做指针常量(也证实了数组名并不是指针) 数组名作为sizeof的参数,这时候取的是数组内存的大小。(a就不是个指针了,如果看做指针,就永远取到的是4或8字节,而不是数组a的大小)数组作为&运算符的参数,此时取到的是数组a的地址,同首元素的值。本文总结自“狄泰软件学院”唐佐林老师《C语言进阶课程》。如有错漏之处,恳请斧正。

December 29, 2021 · 1 min · jiezi

关于c#:Blazor是春天还是寒风里的挣扎

官网解释BlazorBlazor容许您应用c#而不是JavaScript构建交互式web UI。 Blazor利用由可重用的web UI组件组成,这些组件应用c#、HTML和CSS实现。客户端和服务器代码都是用c#编写的,容许您共享代码和库。 Blazor 是一个应用 .NET 生成交互式客户端 Web UI 的框架: 应用 C# 代替 JavaScript 来创立信息丰盛的交互式 UI。共享应用 .NET 编写的服务器端和客户端应用逻辑。将 UI 出现为 HTML 和 CSS,以反对泛滥浏览器,其中包含挪动浏览器。与旧式托管平台(如 Docker)集成。应用 .NET 进行客户端 Web 开发可提供以下劣势: 应用 C# 代替 JavaScript 来编写代码。利用现有的 .NET 库生态系统。在服务器和客户端之间共享应用逻辑。受害于 .NET 的性能、可靠性和安全性。在 Windows、Linux 和 macOS 上应用 Visual Studio 放弃高效工作。以一组稳固、功能丰富且易用的通用语言、框架和工具为根底来进行生成。看到这里有些小伙伴手中的瓜曾经要丢进去了,确实有局部是夸张了的,起码VS在三个平台高效工作这事儿,嗯。。。其余的持续吃瓜吧Blazor Vs MVC什么是MVC官网解释:ASP.NET Core MVC 是应用“模型-视图-控制器”设计模式构建 Web 利用和 API 的丰盛框架。 圈重点,Blazor是交互式Web UI,而MVC是Web利用和API什么是交互式Web UI谷歌、百度转了一圈,没有这个解释,连Wiki也是一脸懵逼。 尝试了解一下吧,交互式Web UI重点在于交互,而Blazor的官网解释是用C#代替JavaScript,那咱们看看JavaScript有什么性能,我百度找一段过去: 嵌入动静文本于HTML页面对浏览器事件做出响应读写HTML元素在数据被提交到服务器之前验证数据检测访客的浏览器信息。管制cookies,包含创立和批改等有这些根底性能,用户不须要在动态页面里跳来跳去了,确实体验会好很多Blazor有什么劣势提供了一些交互能力,不再是纯正的动态页,尽管mvc能够应用JavaScript达到同样的成果,但你须要把握JavaScript,甚至还要再学习jQuery、Angular、Vue等。而Blazor提供的交互能力则是应用C#。 吹是吹完了,但你真的能够100% C#吗?这很难,你会遇到各种问题,比方兼容性、性能等。好了,那我能够不必了吗?等等,上面还有瓜Blazor Vs 古代前端(Angular、Vue等)咱们从几个方面来比照一下吧 调试Blazor:Vistual Stuidio + F5,VS Code/命令行工具 + dotnet watch ...

December 28, 2021 · 2 min · jiezi

关于c:C进阶26指针的本质分析

Summary1)指针的实质是变量,非凡在于存储的内容是一段内存地址。 2)在指针申明时,*号示意所申明的变量为指针;在指针应用时,*号示意取指针所指向的内存空间中的值 3)指针作为函数参数: 指针是变量,因而能够申明指针参数当一个函数体外部须要扭转实参的值则须要应用指针参数;函数调用时实参值将复制到形参指针实用于简单数据类型作为参数的函数中4)口诀:左数右指 -- 当const呈现在*号左侧时,指向的数据为常量;当const呈现在*号右侧时,指针为常量。 const int* p; // 指针p可变,指向的数据*p不可变int const* p; // 指针p可变,指向的数据*p不可变int* const p; // 指针p不可变,指向的数据*p可变const int* const p; // 指针p不可变,指向的数据*p也不可变指针的实质剖析问题:程序中的变量只是一段存储空间的别名,那么是不是必须通过这个别名能力应用这段存储空间? 1、指针的申明和应用上面的程序输入什么?为什么 int i = 5;int* p = &i;printf("%d, %p\n", i, p); // 5, 0XBFDB216C*p = 10;printf("%d, %p\n", i, p); // 10, 0XBFDB216C在指针申明时,*号示意所申明的变量为指针在指针应用时,*号示意取指针所指向的内存空间中的值2、传值调用和传址调用指针是变量,因而能够申明指针参数当一个函数体外部须要扭转实参的值,则须要应用指针参数函数调用时实参值将复制到形参指针实用于简单数据类型作为参数的函数中 // 指针作为参数剖析void swap1(int a, int b){ int t = a; a = b; b = a;}void swap2(int* pa, int* pb){ int t = *pa; *pa = *pb; *pb = t;}int main(){ int a = 1, b = 2; swap1(a, b); // 将实参a和b的值,赋值给swap1参数a、b,函数外部理论批改的是函数的形参a和b,不会影响实参 printf("%d, %d\n", a, b); // 1, 2 swap2(&a, &b); // 将实参a和b的地址,赋值给参数指针pa和pb,函数外部应用*号关上了这两个地址,并批改了外面的值,所以里面的实参也会变 printf("%d, %d\n", a, b); // 2, 1 return 0;}3、const和指针口诀:左数右指 -- 当const呈现在*号左侧时,指向的数据为常量;当const呈现在*号右侧时,指针为常量。 ...

December 27, 2021 · 1 min · jiezi

关于c:C进阶25和运算符

Summary1)'#'用于在预处理期将宏参数转换为字符串;只在宏定义中无效,编译器不晓得'#'的存在 2)能够应用#+函数名,在调用时打印函数名 3)'##'用于在预处理期 拼接两个标识符;只在宏定义中无效,编译器不晓得'##'的存在 4)能够应用'##'疾速定义构造体、应用构造体,疾速定义类等。 ·#和##运算符剖析1、'#''#'运算符用于在预处理期将宏参数转换为字符串(给参数加上双引号);'#'的转换是在预处理期实现的,所以只在宏定义中无效;编译器不晓得'#'的转换作用用法: #define STRING(s) #sprintf("%s\n", STRING(hello world));单步编译:gcc -E test.c -o test.i两头后果:printf("%s\n", "hello world");能够应用#+函数名,在调用时把函数名打印进去: #define CALL(f, p) (printf("call function: %s\n", #f), f(p))void func(){ printf("function output");}int main(){ CALL(f, 1); // C语言中如果不写参数列表,则承受任意多参数 return 0;}2、'##''##'运算符用于在预处理期粘连两个字符(拼接字符)'##'的拼接作用是在预处理期实现的,因而只在宏定义中无效、编译器不晓得'##'的拼接作用用法: #define CONNECT(a, b) a##bint CONNECR(a, 1); // int a1;a1 = 2;工程中能够用'##'疾速定义构造体(定义不同的类等) // 在C语言中应用构造体必须带上struct关键字,就能够用上面的宏封装下typedef,// 而后就能够把struct当成一个类型来用#define STRUCT(type) typedef strtuct __tag_##type type; \ struct __tag_##typeSTRTUCT(Student){ char* name; int id;};int main(){ Student s; s.name = "ss"; s.id = 1; printf("name: %s, id: %d\n"), s.name, s.id); retrun 0;}本文总结自“狄泰软件学院”唐佐林老师《C语言进阶课程》。如有错漏之处,恳请斧正。 ...

December 25, 2021 · 1 min · jiezi

关于c:C进阶24pragma分析

Summary1)#pragma 用于 批示编译器 实现一些特定的动作;#pragma 所定义的很多批示字是编译器特有的,所以在不同的编译器间是不可移植的 预处理器将疏忽它不意识的#pragma指令不同的编译器可能以不同的形式解释同一条#pragma指令个别用法:#pragma parameter ,不同的parameter参数语法和意义各不相同。2)#pragma message在编译时输入信息到编译输入窗口;和#error、#warning不同,#pragma message仅仅示意一条提示信息,不代表谬误。(vc、bcc和gcc三款编译器行为不同) 3)#pragma once用于保障头文件只被编译一次; #pragma once是编译器相干的,不肯定被反对。(vc和gcc反对,bcc不反对) 4)#ifndef...#define...#endif也能够用来避免头文件被反复蕴含,和#pragma once有何不同? #ifndef形式是C语言反对的,用在各个编译器都能够;如果一个.h被include了n次,预编译器就会判断n次这个头文件是否曾经蕴含了。#pragma once形式是编译器相干的,不肯定所有编译器都反对;预编译器只会解决一次,前面不再判断。5)什么是内存对齐? 不同类型的数据在内存中依照肯定的规定排列,不肯定是程序的一个接一个的排列6)为什么须要内存对齐? CPU对内存的读取不是间断的,而是分成块读取的,块的大小只能是2的幂,1、2、4、8...字节当读取操作的数据未对齐,则须要两次总线周期来拜访内存,因而性能会大打折扣某些硬件平台只能从规定的绝对地址处读取特定类型的数据,否则会产生硬件异样7)编译器默认的对齐形式为4字节对齐, #pragma pack(n) 能够调整编译器的默认对齐形式(vc和bcc编译器反对8字节对齐,然而gcc不反对) 8)内存对齐的规定: ·#pragma剖析#pragma 用于 批示编译器 实现一些特定的动作;#pragma 所定义的很多批示字是编译器特有的,所以在不同的编译器间是不可移植的 预处理器将疏忽它不意识的#pragma指令不同的编译器可能以不同的形式解释同一条#pragma指令个别用法:#pragma parameter ,不同的parameter参数语法和意义各不相同。1、#pragma messagemessage参数在大多数的编译器中都有类似的实现message参数在编译时输入音讯到编译输入窗口中message用于条件编译中可提醒代码的版本信息 #include <stdio.h>#if defined(ANDROID20) #pragma message("Compile Android SDK 2.0...") #define VERSION "ANDROID 2.0"#elif defined(ANDROID30) #pragma message("Compile Android SDK 3.0...") #define VERSION "Android 3.0"#elif defined(ANDROID40) #pragma message("Compile Android SDK 4.0...") #define VERSION "Amdroid 4.0"#else #error Compile version is not provided! #endifint main(){ printf("%s\n", VERSION); return 0;}不同编译器的编译后果: bcc编译器:bcc32 -DANDROID30 test.c 编译输入:Compile Android SDK 3.0... vc编译器:cl -DANDROID30 test.c 编译输入:Compile Android SDK 3.0... gcc编译器:gcc -DANDROID30 test.c 编译输入:note: #pragma message: Compile Android SDK 4.0...三款编译器的输入阐明:#pragma message会输入提示信息,然而行为类似,可能具体实现不同单步编译的两头文件: gcc -DANDROID30 -E test.c -o test.i# 12 "test.c"#pragma message("Compile Android SDK 3.0...")# 12 "test.c"# 20 "test.c"int main(){ printf("%s\n", "Android 3.0"); return 0;}留神:和#error、#warning不同,#pragma message仅仅代表一条编译信息,不代表程序谬误。 ...

December 23, 2021 · 2 min · jiezi

关于c++:数据类型在超出范围赋值情况下的计算方式

背景最近在学习c++,看书看到数据类型时,运行以下代码时打印后果: #include <iostream>#include <iomanip>using namespace std;int main(){ short int i; short unsigned int j; j = 40000; i = j; cout << i << " " << j; return 0;}打印:-25536 40000因而,具体讨论一下对数据类型进行超过范畴赋值时,程序的计算过程 探讨一、首先明确,正数在计算机中是应用补码示意的拿一个字节的char类型举例,-1,原码是1000 0001,其中第8位是符号位反码是1111 1110,补码=反码+1:11111111;用无符号整型示意的话,补码的值为2^8 + (-1)所以当2^8 + (-1) = 255赋值给有符号单字节数据类型a(-128~127)时,a的值为-1 -4原码是1000 0100,反码:1111 1011,补码:1111 1100;用无符号整型示意的话,补码的值为2^8 + (-4) -128没有原码,但在计算机中用补码示意为1000 0000,用无符号整型示意的话,补码的值为2^8 + (-128)。因为2^8的二进制为1 0000 0000,128的二进制为1000 0000,所以2^8 + (-128) = 1 0000 0000 - 1000 0000 = 1000 0000 二、回到以后的场景短整型在c++中占两个字节,short int的范畴为 -32768~32767,unsigned short int的范畴为0~65535.显然,将40000赋值给short int超过了存储范畴,则i的补码的值为40000,假如i的值是-a(a是负数),2^16+(-a)=40000,-a=-25536所以i打印进去的值就是-25536 ...

December 23, 2021 · 1 min · jiezi

关于c++:算法游戏内AOI视野算法十字链表

为什么要有这个算法?对于一个游戏场景内的实体来说,当战斗频繁的时候,可能存在上千实体的数据同步,例如上千实体挪动时的坐标同步,大型战斗场景时全场景实体的属性的同步等等,这样就会造成一个问题,同步数据量十分多,然而对于客户端来说,咱们能够看到的屏幕视线大小是固定的,对于视线之外的实体的所有数据咱们并不需要晓得,所以就不须要同步,这时候就须要一种算法,能够让咱们疾速定位到在我视线范畴内的实体有哪些,而后为这些玩家同步相干的音讯。 算法数据结构设计1、为了保障链表元素的查找速度,链表应用跳表实现。2、须要xlist,ylist两条链表,须要将玩家的x,y坐标别离有序的存储到这两个链表上。 实现细节注:目前的设计仅仅基于二维 public AoiZone(float xLinksLimit, float yLinksLimit){ _xLinks = new AoiLinkedList(limit: xLinksLimit);//x轴链表 _yLinks = new AoiLinkedList(limit: yLinksLimit);//y轴链表}public AoiLinkedList(int maxLayer = 8, float limit = 0){ _limit = limit;//坐标比拟时的容错值 _maxLayer = maxLayer;//跳表层数 Add(float.MinValue);}public AoiNode Add(float target, AoiEntity entity = null){ var rLayer = 1; if (_header == null) { //创立跳表 rLayer = _maxLayer; var tempHeader = _header = new AoiNode(rLayer, target, entity);//头结点 for (var layer = _maxLayer - 1; layer >= 1; --layer) { _header = _header.Down = new AoiNode(layer, target, top: _header); //top:pre指针 down:next指针 } _header = tempHeader; return null; } //随机选取某层插入节点 while (rLayer < _maxLayer && _random.Next(2) == 0) ++rLayer; //最高的一层(节点起码的一层)头结点 AoiNode cur = _header, insertNode = null, lastLayerNode = null; for (var layer = _maxLayer; layer >= 1; --layer) { while (cur.Right != null && cur.Right.Value < target) cur = cur.Right;//与要插入地位的x/y值比拟大小(可能有新插入数据,每次都得比拟) if (layer <= rLayer) // { insertNode = new AoiNode(layer, target, entity: entity, left: cur, right: cur.Right); // if (cur.Right != null) cur.Right.Left = insertNode; cur.Right = insertNode;//节点插入 if (lastLayerNode != null) //跳表上上层指针保护 { lastLayerNode.Down = insertNode; insertNode.Top = lastLayerNode; } lastLayerNode = insertNode; } cur = cur.Down;//下一层 } Count++;//减少节点数目 return insertNode;}游戏中的update函数实现://key:实体ID//area:视线范畴//enter:此帧玩家坐标视线内的玩家public AoiEntity Refresh(long key, Vector2, out HashSet<long> enter){ var entity = Refresh(key, area); enter = entity?.ViewEntity; return entity;}public AoiEntity Refresh(long key, float x, float y, Vector2 area){ if (!_entityList.TryGetValue(key, out var entity)) return null; var isFind = false; if (Math.Abs(entity.X.Value - x) > 0) { isFind = true; _xLinks.Move(entity.X, ref x); } if (Math.Abs(entity.Y.Value - y) > 0) { isFind = true; _yLinks.Move(entity.Y, ref y); } if (isFind) Find(entity, ref area); return entity;}//此函数次要是玩家每帧挪动后,x,y坐标变换后将链表从新变成有序的过程public void Move(AoiNode node, ref float target){ var cur = node; #region Left if (target > cur.Value) //挪动后的值大于以后节点的值 { while (cur != null) { if (cur.Right != null && target > cur.Right.Value) { var findNode = cur; // Find the target node to be moved to. //此处如果节点很多,遍历可能会耗费一些性能 while (findNode.Right != null && findNode.Right.Value < target) findNode = findNode.Right; // Fuse the current node. CircuitBreaker(cur);//从以后地位移除 // Move to the target node location cur.Left = findNode; cur.Right = findNode.Right;//退出到新的地位 if (findNode.Right != null) findNode.Right.Left = cur; findNode.Right = cur; } cur.Value = target; cur = cur.Top;//调整跳表下面层的节点程序 } return; } #endregion Left #region Right while (cur != null)////挪动后的值小于以后节点的值 { if (cur.Left != null && target < cur.Left.Value) { // Find the target node to be moved to. var findNode = cur; while (findNode.Left != null && findNode.Left.Value > target) findNode = findNode.Left; // Fuse the current node. CircuitBreaker(cur); // Move to the target node location cur.Right = findNode; cur.Left = findNode.Left; if (findNode.Left != null) findNode.Left.Right = cur; findNode.Left = cur; } cur.Value = target; cur = cur.Top; } #endregion Right}private void Find(AoiEntity node, ref Vector2 area){ //将上帧的可视实体存到备份HashSet汇合里 SwapViewEntity(ref node.ViewEntity, ref node.ViewEntityBak); #region xLinks //定位到此实体,而后再xlist,ylist上别离进行left、right指针遍历,将distance在指定范畴内的实体存入此帧ViewEntity for (var i = 0; i < 2; i++) { var cur = i == 0 ? node.X.Right : node.X.Left; while (cur != null) { if (Math.Abs(Math.Abs(cur.Value) - Math.Abs(node.X.Value)) > area.X) //cur.value为aoi网格节点的value { break; } if (Math.Abs(Math.Abs(cur.Entity.Y.Value) - Math.Abs(node.Y.Value)) <= area.Y) //cur.Entity.Y.Value为以后网格节点上的实体value { if (Distance( new Vector2(node.X.Value, node.Y.Value), new Vector2(cur.Entity.X.Value, cur.Entity.Y.Value)) <= area.X) { node.ViewEntity.Add(cur.Entity.Key);//在范畴内的话 } } cur = i == 0 ? cur.Right : cur.Left; //别离在左右进行遍历 } } #endregion xLinks #region yLinks for (var i = 0; i < 2; i++) { var cur = i == 0 ? node.Y.Right : node.Y.Left; while (cur != null) { if (Math.Abs(Math.Abs(cur.Value) - Math.Abs(node.Y.Value)) > area.Y) { break; } if (Math.Abs(Math.Abs(cur.Entity.X.Value) - Math.Abs(node.X.Value)) <= area.X) { if (Distance( new Vector2(node.X.Value, node.Y.Value), new Vector2(cur.Entity.X.Value, cur.Entity.Y.Value)) <= area.Y) { node.ViewEntity.Add(cur.Entity.Key); } } cur = i == 0 ? cur.Right : cur.Left; } } #endregion yLinks}//用于函数回调//本帧绝对上帧来到视线的人public IEnumerable<long> Leave => ViewEntityBak.Except(ViewEntity);//本帧绝对上帧进入视线的人public IEnumerable<long> NewEnter => ViewEntity.Except(ViewEntityBak);//本帧绝对上帧进入视线的人测试代码private static void Main(string[] args) { var zone = new AoiZone(.001f, .001f); var area = new Vector2(3, 3); // 增加500个玩家。 for (var i = 1; i <= 500; i++) zone.Enter(i, i, i); // 刷新key为3的信息。 zone.Refresh(3, area, out var enters); Console.WriteLine("---------------id为3玩家以后视线范畴的玩家列表--------------"); foreach (var aoiKey in enters) { var findEntity = zone[aoiKey]; Console.WriteLine($"X:{findEntity.X.Value} Y:{findEntity.Y.Value}"); } // 更新key为3的坐标为(20,20)。 var entity = zone.Refresh(3, 20, 20, new Vector2(3, 3), out enters); Console.WriteLine("---------------id为3玩家挪动后来到玩家视线范畴的玩家列表--------------"); foreach (var aoiKey in entity.Leave) { var findEntity = zone[aoiKey]; Console.WriteLine($"X:{findEntity.X.Value} Y:{findEntity.Y.Value}"); } Console.WriteLine("---------------id为3玩家挪动后新退出玩家视线范畴的玩家列表--------------"); foreach (var aoiKey in entity.NewEnter) { var findEntity = zone[aoiKey]; Console.WriteLine($"X:{findEntity.X.Value} Y:{findEntity.Y.Value}"); } // 来到以后AOI zone.Exit(50);}测试后果---------------id为3玩家以后视线范畴的玩家列表--------------X:4 Y:4X:5 Y:5X:2 Y:2X:1 Y:1---------------id为3玩家挪动后来到玩家视线范畴的玩家列表--------------X:4 Y:4X:5 Y:5X:2 Y:2X:1 Y:1---------------id为3玩家挪动后新退出玩家视线范畴的玩家列表--------------X:20 Y:20X:21 Y:21X:22 Y:22X:19 Y:19X:18 Y:18现存问题此十字链表设计目前存在一个问题:当我的项目中实体数目十分多,每帧实体挪动频繁,每帧都会去进行x,y链表坐标排序,对性能耗费还是蛮大的,还在思考单纯用链表如何解决此问题。 ...

December 22, 2021 · 4 min · jiezi

关于c++:linux-gcc-下-没有c11-时的智能指针实现-参考POCO

AtomicCounter.h 线程平安的原子援用计数 实现 //// AtomicCounter.h//// Library: Foundation// Package: Core// Module: AtomicCounter//// Definition of the AtomicCounter class.//// Copyright (c) 2009, Applied Informatics Software Engineering GmbH.// and Contributors.//// SPDX-License-Identifier: BSL-1.0//#ifndef Foundation_AtomicCounter_INCLUDED#define Foundation_AtomicCounter_INCLUDEDnamespace Poco {class AtomicCounter/// This class implements a simple counter, which/// provides atomic operations that are safe to/// use in a multithreaded environment.////// Typical usage of AtomicCounter is for implementing/// reference counting and similar things.////// On some platforms, the implementation of AtomicCounter/// is based on atomic primitives specific to the platform/// (such as InterlockedIncrement, etc. on Windows), and/// thus very efficient. On platforms that do not support/// atomic primitives, operations are guarded by a FastMutex.////// The following platforms currently have atomic/// primitives:/// - Windows/// - Mac OS X/// - GCC 4.1+ (Intel platforms only){public: typedef int ValueType; /// The underlying integer type. AtomicCounter(); /// Creates a new AtomicCounter and initializes it to zero. explicit AtomicCounter(ValueType initialValue); /// Creates a new AtomicCounter and initializes it with /// the given value. AtomicCounter(const AtomicCounter &counter); /// Creates the counter by copying another one. ~AtomicCounter(); /// Destroys the AtomicCounter. AtomicCounter &operator=(const AtomicCounter &counter); /// Assigns the value of another AtomicCounter. AtomicCounter &operator=(ValueType value); /// Assigns a value to the counter. operator ValueType() const; /// Returns the value of the counter. ValueType value() const; /// Returns the value of the counter. ValueType operator++(); // prefix /// Increments the counter and returns the result. ValueType operator++(int); // postfix /// Increments the counter and returns the previous value. ValueType operator--(); // prefix /// Decrements the counter and returns the result. ValueType operator--(int); // postfix /// Decrements the counter and returns the previous value. bool operator!() const; /// Returns true if the counter is zero, false otherwise.private: typedef int ImplType; ImplType _counter;};AtomicCounter::AtomicCounter() : _counter(0) {}AtomicCounter::AtomicCounter(AtomicCounter::ValueType initialValue) : _counter(initialValue) {}AtomicCounter::AtomicCounter(const AtomicCounter &counter) : _counter(counter.value()) {}AtomicCounter::~AtomicCounter() {}//// GCC 4.1+ atomic builtins.//inline AtomicCounter::operator AtomicCounter::ValueType() const { return _counter;}inline AtomicCounter::ValueType AtomicCounter::value() const { return _counter;}inline AtomicCounter::ValueType AtomicCounter::operator++() // prefix{ return __sync_add_and_fetch(&_counter, 1);}inline AtomicCounter::ValueType AtomicCounter::operator++(int) // postfix{ return __sync_fetch_and_add(&_counter, 1);}inline AtomicCounter::ValueType AtomicCounter::operator--() // prefix{ return __sync_sub_and_fetch(&_counter, 1);}inline AtomicCounter::ValueType AtomicCounter::operator--(int) // postfix{ return __sync_fetch_and_sub(&_counter, 1);}inline bool AtomicCounter::operator!() const { return _counter == 0; }} // namespace Poco#endif // Foundation_AtomicCounter_INCLUDEDSharedPtr 智能指针的实现 ...

December 21, 2021 · 7 min · jiezi

关于c:C进阶error和line使用分析

Summary1)#error用于生成一个编译谬误信息;#warning用于生成一个编译正告信息; 2)编译过程中的任何错误信息意味着无奈生成最终的可执行程序 3)语法:#error/#warning message,message不须要用双引号突围 4)#line用于指定后续代码的起始行号和文件名 5)语法:#line line filename filename可胜率,是个字符串(双引号) ·#error和#line剖析1、#error和#warning#error用于生成一个编译谬误信息;#warning用于生成一个编译正告信息; #error是一种预编译器批示字,可用于提醒编译条件是否满足。留神:编译过程中的任何错误信息意味着无奈生成最终的可执行程序语法:#error message,message不须要用双引号突围 #ifndef __cplusplus #error This file should be processed with C++ compiler.#endif应用gcc编译器编译:gcc test.c输入:test.c 4: error: #error This file should be processed with C++ compiler.不会生成可执行程序应用g++编译器编译:g++ test.c能够生成可执行程序剖析:__cplusplus是C++编译器里特有的宏,应用gcc时,无奈辨认这个宏, 因而输入了一条错误信息,并且因为存在错误信息,可执行程序无奈生成;应用g++时,就会跳过该段预处理。#ifndef __cplusplus #warning This file should be processed with C++ compiler.#endif应用gcc编译器编译:gcc test.c输入:test.c 4: warning: #warning This file should be processed with C++ compiler.尽管提醒了正告,然而会生成可执行程序2、#line#line 用于强制指定新的行号和编译文件名,并对源程序的代码从新编号;实质重定义__LINE__和__FILE__。用法:#line number filename (filename可省略) #line 1 "delphi.c" : 指定以后申明处的下一行为第1行,指定以后文件名为"delphi.c"背景:最开始大家都把代码写在一个文件里,比方3个开发同时实现了一个.c文件,这时候出错了就不好定位是谁写的代码出问题了。所以就用#line这个预处理批示字,来指明每一段代码的行号和文件名。下次出问题报错,就晓得是谁的代码写错了。 本文总结自“狄泰软件学院”唐佐林老师《C语言进阶课程》。如有错漏之处,恳请斧正。 ...

December 21, 2021 · 1 min · jiezi

关于c++:中国矿业大学2021学年算法设计与分析实验课OJ2

1.Contest2425 - 毕老师算法试验一传送门在这里题目总览: A.排列问题 // 排列问题// 输出一个可能含有反复字符的字符串,打印出该字符串中所有字符的全排列。#include<bits/stdc++.h>using namespace std;bool IsSwap(vector<char> &chars, int nBegin, int nEnd){ for(int i=nBegin; i<nEnd; i++) //记住是<nEnd { if(chars[i] == chars[nEnd]) return false; } return true;}void Perm(vector<char> &chars, int k, int m){ if(k==m) { for(const char x:chars) { cout<<x; } cout<<endl; } else { for(int i=k; i<=m; i++) { if(IsSwap(chars, k, i)) { swap(chars[k], chars[i]); Perm(chars, k+1, m); swap(chars[k], chars[i]); } } }}void Foo(vector<char> &chars){ Perm(chars, 0, chars.size()-1);}// 字符串bool IsSwap(string str, int nBegin, int nEnd){ for(int i=nBegin; i<nEnd; i++) //记住是<nEnd { if(str[i] == str[nEnd]) return false; } return true;}void Perm2(string str, int k, int m){ if(k==m) { cout<<str; cout<<endl; } else { for(int i=k; i<=m; i++) { if(IsSwap(str, k, i)) { swap(str[k], str[i]); Perm2(str, k+1, m); swap(str[k], str[i]); } } }}void Foo2(string str){ str.pop_back(); cout<<str<<endl; Perm2(str, 0, str.length()-1);}int main(){ // vector<char> chars; // int n; // cin>>n; // char ele; // for(int i=0; i<n; i++) // { // cin>>ele; // chars.push_back(ele); // } // // for(const char x:chars) cout<<x; // Foo(chars); string str; // scanf("%s", str); https://blog.csdn.net/liu16659/article/details/86772657 不倡议应用scanf输出string类型 cin>>str; Foo2(str); system("pause"); return 0;}B.疾速幂 ...

December 21, 2021 · 13 min · jiezi

关于c++:中国矿业大学2021学年算法设计与分析实验课OJ

1.Contest2411 - 毕老师算法A作业一传送门在这里题目总览: A.进制转换 #include<iostream>using namespace std;long Revert(long x){ long ans = 0; long mutiply = 1; while(x) { ans += ((x%8) * mutiply); mutiply *= 10; x /= 8; } return ans;}int main(){ int x, ans; cin>>x; ans = Revert(x); cout<<ans<<endl; return 0;}B.排列问题 // B.排列问题#include<bits/stdc++.h> //奇怪之处就在于基本上所有的代码只有用了这个头文件就不再写其余头文件了。using namespace std; vector<string> ans;void Perm(string str, int low, int high){ if(low == high) { ans.push_back(str); return; } for(int i=low; i<=high; ++i) { if(i>0 && str[i]==str[i-1]) continue; //判断反复 swap(str[i], str[low]); Perm(str, low+1, high); swap(str[i], str[low]); }}int main(){ string str; cin>>str; str.pop_back(); sort(str.begin(), str.end()); Perm(str, 0, str.size()-1); sort(ans.begin(), ans.end()); for(const auto x:ans) cout<<x<<" "; system("pause"); return 0;}C.疾速幂 ...

December 21, 2021 · 14 min · jiezi

关于c++:模板的分离编译问题

存在问题的代码:test.h: #include <iostream>using namespace std;template<class T1,class T2>void func(T1 t1,T2 t2);test.cpp: #include "test.h"using namespace std;template<class T1,class T2>void func(T1 t1,T2 t2){ cout<<t1<<t2<<endl;}main.cpp: #include "test.h"int main(){ string str("ljt"); int i=5; func(str,5);}编译后果: [root@localhost cpptest]# g++ test.cpp test.h main.cpp -o test/tmp/ccp1HXnh.o:在函数‘main’中:main.cpp:(.text+0x5d):对‘void func<std::string, int>(std::string, int)’未定义的援用collect2: 谬误:ld 返回 1阐明了在main.cpp中没有找到函数func的定义。 查看起因:对test.cpp只进行编译不进行链接: [root@localhost cpptest]# g++ -c test.cpp [root@localhost cpptest]# nm -C -n test.o U __cxa_atexit U __dso_handle U std::ios_base::Init::Init() U std::ios_base::Init::~Init()0000000000000000 t __static_initialization_and_destruction_0(int, int)0000000000000000 b std::__ioinit000000000000003d t _GLOBAL__sub_I_test.cpp会发现符号表中不存在func函数,也就是编译出的二进制文件没有为func分配内存空间。起因是:模板只有在应用的时候才进行实例化。 ...

December 21, 2021 · 2 min · jiezi

关于c#:AgileConfig155-发布-支持-JSON-编辑模式

本次更新退出了2个新的编辑模式:JSON 编辑模式、TEXT 编辑模式。特地是 JSON 编辑模式是大家比拟期待的一个性能。因为大家都习惯了 appsettings.json 的配置编辑模式,所以天生的喜爱 JSON 视图。有了 JSON 编辑模式后,大家就能够间接把原来的 appsettings.json 间接复制过去,点击保留就能够原样导入到 AgileConfig 里了。也能够持续应用对象嵌套对象,数组等高级模式。 JSON 视图编辑模式点击右上角“编辑 JSON”按钮会弹出 JSON 编辑视图。该编辑框集成了一个 json 代码编辑器- monaco-editor 不便用户疾速的编辑 json 配置文件。顺便提一下 monaco 这个是微软开源的一个编辑器,看它的官网介绍你就晓得他有多牛了:The Monaco Editor is the code editor that powers VS Code 。对没错,它就是 VS Code 的编辑器。 当初你能够像应用 appsettings.json 一样来定义配置文件了。比方 { x: {b: 'a' } } 对象嵌套对象,比方数组 ['1', '2' , '3'] 。 留神: 非法的json文件,编辑器会给出提醒,并且不能保留对于 bool 或者 intger 类型定义的时候没有问题,然而保留后零碎会默认给转成文本类型比方 false='false' , 1='1' 。因为所有的json内容转换的时候都会存储成文本类型的键值对。然而释怀这不会影响你在 .NET 程序里应用 IConfiguration 来读取绑定应用配置。编辑好json文件后,点击“保留”按钮,零碎会比照新老配置,主动列出哪些是“新增”的配置项,哪里是“编辑”的配置项,哪些是“删除”的配置项。 ...

December 20, 2021 · 1 min · jiezi

关于c#:AgileConfig轻量级配置中心140发布重构了发布功能

退出 NCC先说一个事,AgileConfig 在 7 月底终于通过了 NCC 社区的审核,正式成为了 NCC 小家庭的一员。这对 AgileConfig 来说是一个里程碑,心愿退出 NCC 后能更好的帮忙到大家。同时责任也更大了,自己会判若两人的对这个我的项目保护上来,感激反对。 release-1.4.0本次1.4.0公布版本是一个比拟大更新。解决了 AgileConfig 一些长期存在的性能上的问题。之前版本的公布、回滚只针对独自某个配置,当对某个配置编辑后会记录批改历史,并且公布后的配置批改是实时失效的。这会带来2个比拟大的问题: 没有方法追踪“删除”的配置 因为批改历史记录针对的是单个配置,然而当应用删除操作的时候,整个配置会在列表里移除,导致想要复原的时候都没有入口能够找到这个被删除的配置。单个配置批改实时上线 之前的版本,当对某个配置批改或者删除后配置会实时同步至客户端。这样会带来一个问题:有的时候咱们心愿批改好多个配置后同时公布上线,因为配置之间很可能是依赖的关系。1.4.0 重构了公布性能,解决了以上2个问题。新版本不在针对某个配置独自管制上线、下线。能够间断对多个配置新增、删除、编辑后进行集中公布,同时反对记录公布日志。 编辑配置上面演示下新版的公布如何应用。 当初新增、编辑、删除配置后,配置不会间接上线,会处于一个待发布的状态。在编辑列表的右上角会提醒待发布配置的统计状况。 公布配置批改完配置后,须要点击“公布”按钮进行确认公布。公布胜利后批改过后的配置会实时更新至客户端。 留神 : 新版本告诉客户端变更的事件不再辨别add、update、delete,全副为reload。历史版本新版本对公布的历史能够进行查看,同时反对回滚至某个公布版本的能力。 历史版本把每次公布的变更状况按时间轴列出。 点击“回滚”能够回滚至某个时刻的公布版本的状态。 留神: 回滚操作会清空以后所有待发布的配置项最初✨✨✨Github地址:https://github.com/dotnetcore/AgileConfig 开源不易,欢送star✨✨✨ 演示地址:http://agileconfig_server.xbaby.xyz/ 超级管理员账号:admin 明码:123456

December 20, 2021 · 1 min · jiezi

关于c:C进阶22条件编译分析

Summary1)条件编译的行为相似于C语言中的if else;条件编译是预编译批示命令,用于管制是否编译某段代码; 2)预编译器依据条件编译指令有抉择的删除代码,所以编译器不晓得代码分支的存在 3)if else在运行期进行分支判断,肯定会被编进指标代码;条件编译指令在预编译期进行分支判断,可能产生不同的代码段,因而编进指标代码的代码段不确定 4)能够通过命令行定义宏:gcc -Dmacro=val file.c或gcc -Dmacro file.c 5)#include 实质 是将曾经存在的文件内容插入到以后文件中;#include的间接蕴含同样会产生嵌入文件内容操作。条件编译指令#ifndef _FILE_H_ #define _FILE_H #endif能够解决这种头文件反复蕴含的谬误。 6)条件编译指令只是能够在同一个.c文件中,避免反复蕴含;如果头文件中有了符号的定义,然而在一个工程的不同c文件里都进行了include,这时候编译这两个文件也会有反复定义的谬误(因为两份include在各自的c文件里都定义了一个global,在同一个全局作用域里定义了同名的symbol)。所以,头文件中只申明、不定义! 7)工程中的条件编译次要用于:不同的产品线共用一份代码;辨别编译产品的调试版和公布版 条件编译剖析条件编译的行为相似于C语言中的if...else...;条件编译是预编译批示命令,用于管制是否编译某段代码; 1、条件编译于if...else的区别预编译器依据条件编译指令有抉择的删除代码,所以编译器不晓得代码分支的存在if...else语句在运行期进行分支判断;条件编译指令在预编译期进行分支判断能够通过命令行定义宏:gcc -Dmacro=val file.c或者gcc -Dmacro file.c#define C1int main(){ #if (C==1) printf("if true\n"); #else printf("if false\n"); #endif return 0;}gcc -E test.c -o test.i// 单步编译后失去的两头文件# 1 "test.c"# 1 "<built-in>"# 1 "<command-line>"# 1 "test.c"int main(){ printf("if true\n"); return 0;}剖析: 通过预编译期的解决后,失去的两头文件中#if #else #endif都被删掉了,这也阐明了下面的预编译器依据条件编译指令有抉择的删除代码,所以编译器在拿到两头.i文件后,基本就不晓得这些代码分支的存在。也阐明,#if #else #endif是在预编译期进行判断的,而if else是在运行期才会判断// 上述代码中去掉#define C 1// 应用命令来定义宏gcc -DC=1 test.c编译后的运行后果为:if truegcc -DC test.cgcc -DC test.c编译后的运行后果为:if true应用#ifdef #else #endif进行预编译分支判断: ...

December 19, 2021 · 1 min · jiezi

关于c:libevent学习使用1

根本应用办法libevent是一个应用事件驱动模型的网络网络库,网络开发,能够通过应用这个库,非常简单、清晰的代码做出一个反对I/O复用的程序。工作中须要应用到此库,所以记录一下学习进度。 根本应用能够参考源码的sample/目录下的应用示例,依据示例名称,我首先看一下 hello-workd.c 这个程序:代码不少,然而单个函数拆分来看,还是分清晰的。 首先是main 函数中: //...... base = event_base_new(); //...... listener = evconnlistener_new_bind(base, listener_cb, (void *)base, LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE, -1, (struct sockaddr*)&sin, sizeof(sin)); //...... /// 注册了一个信号事件,该事件处理函数 signal_cb 解决的Ctrl+C信号 signal_event = evsignal_new(base, SIGINT, signal_cb, (void *)base); if (!signal_event || event_add(signal_event, NULL)<0) { fprintf(stderr, "Could not create/add a signal event!\n"); return 1; } /// 开启工夫轮询 event_base_dispatch(base); /// 进行程序应用资源 evconnlistener_free(listener); event_free(signal_event); event_base_free(base);首先调用 event_base_new 创立了一个 event_base 构造体,也不晓得是干嘛的,然而并没有给他提供任何网络相干的参数,临时先不论它。之后调用了 evconnlistener_new_bind 函数,给他传入了网络的sockaddr构造信息,联合文件名看来就是在这里开始创立套接字和监听了。进入头文件listener.h 中也能看到对于该函数的介绍: /** Allocate a new evconnlistener object to listen for incoming TCP connections on a given address. @param base The event base to associate the listener with. event 会和 event_base 关联 @param cb A callback to be invoked when a new connection arrives. If the callback is NULL, the listener will be treated as disabled until the callback is set. 链接来的socket的处理函数 @param ptr A user-supplied pointer to give to the callback. 参数指针 @param flags Any number of LEV_OPT_* flags @param backlog Passed to the listen() call to determine the length of the acceptable connection backlog. Set to -1 for a reasonable default. @param sa The address to listen for connections on. @param socklen The length of the address. */能够看出 listener_cb 是解决链接客户端的socket,LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE能够依据listen.h中找到解释,设置了socket地址的可重用和敞开时开释, sa 是地址信息。 ...

December 18, 2021 · 2 min · jiezi

关于c++:xmake-v262-发布新增-Linux-内核驱动模块构建支持

Xmake 是一个基于 Lua 的轻量级跨平台构建工具。 它十分的轻量,没有任何依赖,因为它内置了 Lua 运行时。 它应用 xmake.lua 保护我的项目构建,相比 makefile/CMakeLists.txt,配置语法更加简洁直观,对老手十分敌对,短时间内就能疾速入门,可能让用户把更多的精力集中在理论的我的项目开发上。 咱们可能应用它像 Make/Ninja 那样能够间接编译我的项目,也能够像 CMake/Meson 那样生成工程文件,另外它还有内置的包管理系统来帮忙用户解决 C/C++ 依赖库的集成应用问题。 目前,Xmake 次要用于 C/C++ 我的项目的构建,然而同时也反对其余 native 语言的构建,能够实现跟 C/C++ 进行混合编译,同时编译速度也是十分的快,能够跟 Ninja 持平。 Xmake = Build backend + Project Generator + Package Manager我的项目源码官网文档入门课程<img src="https://tboox.org/static/img/xmake/xmake-cmake.jpeg" width="30%" /> 新版本改变这个版本次要新增两大个性: Linux 内核驱动模块的构建反对分组构建和批量运行反对,可用于实现 Run all tests 性能剩下的次要是一些零散的性能改良和 Bugs 修复,能够看下文末的更新内容明细,一些比拟大的改变,上面也会逐个阐明。 新个性介绍构建 Linux 内核驱动模块Xmake 兴许是首个提供 Linux 内核驱动开发 内置反对的第三方构建工具了。 只管网上也有介绍 CMake 如何去配置构建 linux 驱动,然而大都是通过 add_custom_command 形式自定义各种命令,而后执行 echo 去本人拼接生成 Linux 的 Makefile 文件。 也就是说,其实还是依赖 Linux 内核源码的 Makefile 来执行的构建,因而如果想本人追加一些编译配置和宏定义都会十分麻烦。 ...

December 17, 2021 · 5 min · jiezi

关于c:C进阶21宏定义与使用分析

Summary1)#define是预处理器解决的单元实体之一,在预编译期进行文本替换 2)#define定义的宏能够呈现在程序的任意中央,定义之后的代码都能够应用 3)#define能够定义宏常量,实质上是字面量 4)define能够定义表达式,应用上相似函数;性能可能更弱小(类型能够作为参数、求数组大小);更容易出错(当和其余运算混合在一起时) 5)宏因为是间接文本替换,所以没有任何的调用开销;宏表达式里不能呈现递归;宏被预处理器解决,所以编译器不晓得宏的存在,天然宏也不会有作用域的概念,作用域是针对变量和函数的。 6)罕用的预约义宏 宏含意示例__FILE__被编译的文件名file1.c__LINE__以后行号25__DATE__编译时的日期Jan 31 2012__TIME__编译时的工夫17:01:01__STDC__编译器是否遵循规范C标准1宏定义与应用剖析#define是预处理器解决的单元实体之一#define定义的宏能够呈现在程序的任意地位#define定义之后的代码都能够应用这个宏 1、#define定义的宏常量#define定义的宏常量能够间接应用,实质为字面量(不会占用内存,字符串字面量会存在只读存储区) // test.c中 上面的宏定义正确么?#define ERROR -1#define PATH1 "D:\test\test.c"#define PATH2 D:\test\test.c#define PATH3 D:\test\test.cint main(){ int i = ERROR; char* p1 = PATH1; char* p2 = PATH2; char* p3 = PATH3; return 0;}单步编译gcc -E test.c -o test.i ==> 预编译,生成两头文件.igcc -S test.i -o test.s ==> 编译,生成汇编文件.s剖析:在第一步预编译阶段,解决define并生成.i文件,这时候不会出错;下一步编译阶段,将两头文件转换为汇编文件时,就会报错。起因在于:在预编译的阶段,仅仅是做文本替换,没有语法查看;到了编译阶段,会对替换后的.i文件进行语法查看,再生成汇编文件,这时候语法查看就出错了。 2、#define定义的表达式#define表达式的应用相似函数调用#define表达式能够比函数更弱小#define表达式比函数更易出错 #define SUM(a, b) (a) + (b)#define MIN(a, b) ((a) < (b) ? (a) : (b))#define DIM(a) sizeof(a) / sizeof(*a)int main(){ int a = 1; int b = 3; int c[2] = {0}; // expected: 4, 1, 2 printf("SUM(a, b) = %d\n", SUM(a, b)); printf("MIN(a, b) = %d\n", MIN(a, b)); printf("size of array = %d\n", DIM(c)); // unexpected: 3 printf("unexpected: %d", MIN(++a, b)); // 冀望失去++a和b中的较小的值:2 return 0;}剖析: ...

December 17, 2021 · 1 min · jiezi

关于c#:c基础接口

接口和类 其实有很多雷同的中央,但接口不能被实例化,接口更多的是定义一些束缚,标准,比方二个功能模块 都会用到Create办法,惯例的能够应用类 创立二个办法来实现Create但用接口就是先定义接口 /// <summary>/// 接口申明/// </summary>public interface ICreate{ void DoCreate();}再实现接口, /// <summary>/// 接口实现/// </summary>public class ModularA : ICreate{ public void DoCreate() { Console.Write("ModularA"); Console.ReadKey(); }}public class ModularB : ICreate{ public void DoCreate() { Console.Write("ModularB"); Console.ReadKey(); }}咱们再应用的时候 var modularA = new ModularA(); modularA.DoCreate(); var modularB = new ModularB(); modularB.DoCreate();其实在你会发现,后续再新增Create办法 只须要去写实现过程,不须要再定义。

December 17, 2021 · 1 min · jiezi

关于c++:CC气象数据中心实战手把手教你做工业级项目sgsdga

download:C/C++气象数据中心实战,手把手教你做工业级我的项目python字符串/元组/列表/字典互转 --coding:utf-8--1、字典dict = {'name': 'Zara', 'age': 7, 'class': 'First'} 字典转为字符串,返回:<type 'str'> {'age': 7, 'name': 'Zara', 'class': 'First'}print type(str(dict)), str(dict) 字典可能转为元组,返回:('age', 'name', 'class')print tuple(dict) 字典可能转为元组,返回:(7, 'Zara', 'First')print tuple(dict.values()) 字典转为列表,返回:['age', 'name', 'class']print list(dict) 字典转为列表print dict.values 2、元组tup=(1, 2, 3, 4, 5) 元组转为字符串,返回:(1, 2, 3, 4, 5)print tup.__str__() 元组转为列表,返回:[1, 2, 3, 4, 5]print list(tup) 元组不可能转为字典3、列表nums=[1, 3, 5, 7, 8, 13, 20]; 列表转为字符串,返回:[1, 3, 5, 7, 8, 13, 20]print str(nums) 列表转为元组,返回:(1, 3, 5, 7, 8, 13, 20)print tuple(nums) ...

December 16, 2021 · 1 min · jiezi

关于c:C进阶20链接过程简介

Summary1)链接的定义:将指标文件最终链接为可执行程序 2)链接的2种形式: 动态链接:指标文件会被间接*链接*进可执行程序。slib.a被删掉后,程序仍旧能够运行动静链接:程序启动后才动静加载指标文件。dlib.so被删掉后,程序无奈运行3)动态链接和动静链接形式的抉择: 动态链接:实用于比较简单的程序,开发进去不须要变动的,比方纯本地的记事本这种;把所有指标文件都编到可执行程序里,可能会导致可执行程序很大。动静链接:一个大型软件的各个模块,如果采纳动静库的模式,哪个模块须要更新了,只须要批改这个模块,而后把dlib.so传到服务器上。用户在应用软件时,间接去服务器上拿这一个库更新下就能够了,而不须要更新整个程序。链接过程简介问题:工程里的每个.c源文件在编译后都会生成指标文件.o,那这些.o文件怎么生成最终的可执行程序.out呢? 答:链接器的次要作用是把各个模块间互相援用的局部解决好,使得各个模块之间能失常的连接。 1、动态链接链接器在链接时将库的内容间接退出到可执行程序中动态库的创立和应用1)生成动态库指标文件:gcc -c slib.c -o slib.o2)生成动态库:ar -q slib.a slib.o (输入:ar:creating slib.a;ar指的是archive,把前面列出的所有指标文件全都打包进slib.a中)3)应用动态库编译:gcc 20-1.c slib.a -o 20-1.out (应用动态库进行编译)2、动静链接可执行程序在运行时才动静加载库进行链接(运行时才去找我须要的symbol)库的内容不会进入到可执行程序中// dlib.cchar* name(){ return "Dynamic Lib";}int add(int a, int b){ return a+b;}// 20-2.c#include <stdio.h>#include <dlfcn.h>int main(){ void* pdlib = dlopen("./dlib.so", RTLD_LAZY); // pdlib指向了目录下dlib.so这个动静库 // 这个关上就相当于一个加载到内存里的指针 char* (*pName)(); // 定义函数指针 int (*pAdd)(int, int); if(NULL != pdlib) { pName = dlsym(pdlib, "name"); // 查找pdlib指向的动静库里的函数 pAdd = dlsym(pdlib, "add"); if(NULL != pName && NULL != pAdd) { printf("Name: %s\n", pName()); printf("Ret: %d\n", pAdd(2, 3)); } dlclose(pdlib); // 敞开pdlib指向的动静库 } else { printf("Cannot open dynamic lib..."); }}// linux命令gcc -shared dlib.c -o dlib.so : 创立了动静库dlib.sogcc 20-2.c -ldl -o a.out : 应用动静库创立了可执行程序a.out./a.out : 执行可执行程序留神:-ldl通知编译器,这个程序用动静库的形式来编译,咱们的程序依赖动静库。如果动静库dlib.so删掉了,这个程序就运行不起来了,输入cannot open,因为a.out每次执行时须要去动静库里找symbol的(我要用啥,我每次得去你的仓库里拿),库都没了,天然找不到了。 ...

December 15, 2021 · 1 min · jiezi

关于c++:C右值引用与移动语义

背景开始学习C++11和筹备秋招面试时,对右值援用和挪动语义进行的深刻学习,凑巧在面试中又被问到,深刻记录一下。 左值/右值左值:能够取地址、位于等号右边 -> 有地址的变量右值:没法取地址、位于等号左边 -> 没有地址的字面值、长期值两个例子: int a = 5;a->能够通过 & 取地址,位于等号右边,是左值。5位于等号左边,5没法通过 & 取地址,所以5是个右值。struct A { A(int a = 0) { a_ = a; } int a_;};A a = A();a ------------>能够通过&取地址,位于等号右边,是左值A()-> 长期值,没法通过&取地址,位于等号左边,是右值 左值援用/右值援用援用的实质是别名。通过援用批改变量的值,传参时传援用能够防止拷贝。 左值援用右值援用参考资料https://zhuanlan.zhihu.com/p/...

December 10, 2021 · 1 min · jiezi

关于c:01-OCFS2文件系统磁盘布局分析

文件系统实质上是把文件存入磁盘,因而,了解文件系统的磁盘整体布局对于了解一款文件系统十分的重要,文件系统的所有性能都是围绕磁盘布局和对其治理开展的,上面咱们一起看一下OCFS2集群文件系统的磁盘整体布局。一、格式化format:mkfs.ocfs2 -b 4K -C 1M -N 32 -J size=128M -L "xxx" -T vmstore --fs-features=indexed-dirs,refcount --cluster-stack=o2cb --cluster-name=ocfs2 fs.img 格式化参数解释: -b, --block-size block-size 文件系统执行IO的最小单元,本例取 block 4KB=4096=2^10-C, --cluster-size cluster-size 为文件数据调配空间的最小单元,本例取 cluster 1MB=2^20-N, --node-slots number-of-node-slots 节点槽位,指向一系列的系统文件,每个槽位被一个节点惟一应用。槽位的个数示意该volume可同时被多少个节点mount。-J, --journal-options options OCFS2采纳预写日志WAL(Write-Ahead Log),应用了JBD2,用户可配置,依据文件系统类型和卷大小决定,默认值:datafiles类型64MB,vmstore类型128MB,mail类型256MB-L, --label volume-label 对卷做标签,为了方便管理。-T filesystem-type Valid types are mail, datafiles and vmstore.mail:用作邮件服务器存储,将大量的元数据变为大量的小文件,应用大一点的日志journal比拟无益。datafiles:倡议较少地全副调配大文件,要求较少的元数据扭转,因而,应用大一点的日志journal有益。vmstore:正如名字所示,被稠密调配大文件的虚拟机镜像--fs-features=[no]sparse...  指定使能或禁用某些个性,比方:稠密文件、非写入范畴、备份超级块--fs-feature-level=feature-level Valid values are max-compat, default and max-features. 默认反对稠密文件、非写入范畴、内联数据。查看根目录和系统目录通过debugfs.ocfs2,能够看到系统文件,本例格式化指定 -N 32,因而,一些带slot号的系统文件,如:local_allock:0000~0031,如下截图仅显示局部,其余已将其省略,不影响剖析。 通过格式化的参数,能够失去如下根底数据信息,这些信息能够不便的进行计算。 1 block 4KB = 4096 = 2^10 1 cluster 1MB = 2^20 1 cluster = 256 blocks = 2^8二、SuperBlock对于一个文件系统而言SuperBlock是最重要的,它形容了一个文件系统的根本数据信息,含有许多重要的要害信息,文件系统被mount操作后,首先要读取SuperBlock。格式化后,能够看到SuperBlock的信息如下: ...

December 10, 2021 · 3 min · jiezi

关于c:CPT109-C-Programming

CPT109 C Programming and Software Engineering 1 – ASSESSMENT 3Assessment Number 3Contribution to Overall Marks 35%Issue Date 08/11/2021Submission Deadline 17/12/2021 at 17:00 (5pm)Assessment ObjectiveThis assessment aims to evaluate students’ ability to develop a significant software solution to a realworldproblem by working as a member of a team. Your team will be given a vague specification andis expected to deliver a software product in the C programming language, which meets thespecifications before the due date. This size and type of the project is suitable for development inmodular format and so teams are encouraged to devise program structures that allow various parts ofthe code to be developed independently by each team member. Being a team player means you areexpected not only to apply the knowledge gained during the lectures, laboratory classes andassignments to specify, design, implement, test and document your own code, but also to cooperatewith your teammates so that the whole project will be delivered on time with good quality.GroupingThere are 360 students enrolled in this module, and you will be divided into groups consisting of 5students (i.e. 72 groups). Groups will be formed in two stages as follows: Firstly, students will begiven the option to choose their own group members. Students failing to form a group will then berandomly assigned to a group. Randomly formed groups will contain students with a range of abilitybased on their performance in previous assignments. Each group will then be randomly assigned oneof 5 projects. Students wishing to form their own group should submit a hardcopy of the formprovided (The group formation form is part of the Assessment 3 download package) having alldetails filled in and having been signed by all group members.Final DeliverablesEach group should submit the following (only 1 submission per group): ...

December 9, 2021 · 10 min · jiezi

关于c#:ApacheCN-C-译文集-20211124-更新

C# 代码整洁指南 零、前言一、C# 代码规范和准则二、代码审查——过程和重要性三、类、对象和数据结构四、编写整洁的函数五、异样解决六、单元测试七、端到端系统测试八、线程和并发九、设计和开发 API十、应用 API 密钥和 Azure 密钥保存库爱护 API十一、解决横切关注点十二、应用工具来晋升代码品质十三、重构 C# 代码——确定代码异味十四、重构 C# 代码——实现设计模式十五、答案C#10 和 .NET6 代码跨平台开发 零、前言一、你好,C#!欢送应用.NET!二、谈谈 C#三、控制流、转换类型和解决异样四、编写、调试和测试函数五、应用面向对象编程构建本人的类型六、实现接口和继承类七、打包和散发.NET 类型八、应用常见的.NET 类型九、应用文件、流和序列化十、应用实体框架外围解决数据十一、应用 LINQ 查问和操作数据十二、应用多任务进步性能和可扩展性十三、C# 和.NET 的理论利用简介十四、应用 ASP.NETCore 页面构建网站十五、应用模型-视图-控制器模式构建网站十六、构建和应用 Web 服务十七、应用 Blazor 构建用户界面十八、后记C# 数据结构和算法 一、前言二、开始二、数组和列表三、栈和队列四、字典和汇合五、树的变种六、摸索图七、总结C# 机器学习我的项目 零、前言一、机器学习建模根底二、垃圾邮件过滤三、推特情感剖析四、外汇汇率预测五、屋宇和财产的公道价值六、客户细分七、音乐类型举荐八、手写数字辨认九、网络攻击检测十、信用卡欺诈检测十一、下一步是什么?C# 和 .NETCore 设计模式实用指南 零、前言第一局部:C# 和.NETCore 中设计模式的要点 一、NETCore 和 C# 中的 OOP 概述二、古代软件设计模式与准则第二局部:深入探讨.NETCore 中的工具和模式 三、实现设计模式——基础知识第 1 局部四、实现设计模式——基础知识第 2 局部五、实现设计模式——.NETCore六、Web 利用设计模式的实现——第 1 局部七、Web 利用设计模式的实现——第 2 局部第三局部:函数式编程、反应式编程和云编程 八、.NETCore 中的并发编程九、函数式编程实际十、反应式编程模式和技术十一、先进的数据库设计和利用技术十二、云编程十三、其它最佳做法十四、答案C# 神经网络编程实用指南 零、前言一、疾速回顾二、一起构建咱们的第一个神经网络三、决策树与随机森林四、人脸和静止检测五、应用 ConvNetSharp 训练 CNN十、基于 TensorFlowSharp 的指标检测十一、基于 CNTK 与 LSTM 的工夫序列预测十二、GRU 与 LSTM、RNN 和前馈网络的比拟十三、激活函数计时十四、函数优化参考C#5 多线程秘籍 ...

December 8, 2021 · 2 min · jiezi

关于c++:ApacheCN-CC-译文集二-20211204-更新

编写高效程序的艺术 零、序言第一局部:性能根底 一、性能和并发性介绍二、性能测量三、CPU 架构、资源和性能四、内存架构和性能五、线程、内存和并发第二局部:高级并发 六、并发和性能七、并发的数据结构八、 C++ 中的并发九、高性能 C++十、C++ 中的编译器优化十一、未定义的行为和性能十二、性能设计十三、答案Code::Blocks 和 C++ 利用开发 零、前言一、Code::Blocks 入门二、Code::Blocks 利用开发三、Code::Blocks 利用调试四、应用 Code::Blocks 的 Windows 利用开发五、编程工作六、附录 A:功能集C++ 面向对象编程揭秘 零、前言第一局部:C++ 构建块要点 一、了解根本 C 语言假如二、增加语言的必须品三、间接寻址: 指针四、间接寻址: 援用第二局部:在 C++ 中实现面向对象的概念 五、具体探索类六、实现单继承层次结构七、通过多态性应用动静绑定八、把握抽象类九、摸索多重继承十、实现关联、聚合、组合第三局部:扩大您的 C++ 编程技能 十一、解决异样十二、友元和运算符重载十三、应用模板十四、理解 STL 基础知识十五、测试类和组件第四局部:C++ 中的设计模式和习语 十六、应用观察者模式十七、利用工厂模式十八、利用适配器模式十九、应用单例模式二十、应用 pImpl 模式删除实现细节二十一、答案C++17 嵌入式编程实用指南 零、前言第一局部:基础知识——嵌入式编程和 C 的作用 一、什么是嵌入式零碎?二、作为一种嵌入式语言的 C++三、面向嵌入式 Linux 和相似零碎的开发四、资源受限的嵌入式零碎五、示例——应用 WIFI 的土壤湿度监测器第二局部:测试、监控 六、测试基于操作系统的利用七、测试资源受限平台八、示例——基于 Linux 的信息娱乐零碎九、示例——建筑物监控和管制第三局部:与其余工具和框架的集成 十、应用 Qt 开发嵌入式零碎十一、混合 SoC/FPGA 零碎的开发十二、最佳实际C++ 机器人编程实用指南 零、前言第一局部:在树莓派上开始应用 wiringPi 一、树莓派简介二、应用 wiringpi 实现闪动第二局部:树莓派机器人技术 三、对机器人编程四、构建避障机器人五、应用笔记本电脑管制机器人第三局部:人脸和物体辨认机器人 六、应用 OpenCV 拜访 RPi 摄像机七、应用 OpenCV 构建跟踪对象的机器人八、将 Haar 分类器用于人脸检测和跟踪第四局部:智能手机管制机器人 ...

December 8, 2021 · 2 min · jiezi

关于c++:ApacheCN-CC-译文集-20211201-更新

笨办法学C 中文版 前言导言:C的笛卡尔之梦练习0:筹备练习1:启用编译器练习2:用Make来代替Python练习3:格式化输入练习4:Valgrind 介绍练习5:一个C程序的构造练习6:变量类型练习7:更多变量和一些算术练习8:大小和数组练习9:数组和字符串练习10:字符串数组和循环练习11:While循环和布尔表达式练习12:If,Else If,Else练习13:Switch语句练习14:编写并应用函数练习15:指针,可怕的指针练习16:构造体和指向它们的指针练习17:堆和栈的内存调配练习18:函数指针练习19:一个简略的对象零碎练习20:Zed的弱小的调试宏练习21:高级数据类型和控制结构练习22:栈、作用域和全局练习23:意识达夫设施练习24:输入输出和文件练习25:变参函数练习26:编写第一个真正的程序练习27:创造性和防御性编程练习28:Makefile 进阶练习29:库和链接练习30:自动化测试练习31:代码调试练习32:双向链表练习33:链表算法练习34:动静数组练习35:排序和搜寻练习36:更平安的字符串练习37:哈希表练习38:哈希算法练习39:字符串算法练习40:二叉搜寻树练习41:将 Cachegrind 和 Callgrind 用于性能调优练习42:栈和队列练习43:一个简略的统计引擎练习44:环形缓冲区练习45:一个简略的TCP/IP客户端练习46:三叉搜寻树练习47:一个疾速的URL路由后记:“解构 K&R C” 已死捐献名单C++ 高级编程 零、前言一、可移植的 C++ 软件分析二、不容许鸭子——类型和推导(一)三、不容许鸭子——模板和推导(二)四、不容许透露——异样和资源五、关注点拆散——软件架构、函数和可变模板六、哲学家的晚餐——线程和并发七、流和输出/输入八、每个人都会跌倒,这是你爬起来的形式——测试和调试九、对速度的需要——性能和优化十、附录C++ 高级编程秘籍 零、前言一、库的开发入门二、将异样用于错误处理三、实现挪动语义四、将模板用于泛型编程五、并发和同步六、优化代码以进步性能七、调试和测试八、创立和实现您本人的容器九、摸索类型擦除十、对动态分配的深入研究十一、C++ 中的常见模式十二、更认真查看类型推导十三、处分——应用 C++ 20 个性C++ Qt5 GUI 编程 零、前言一、Qt 简介二、Qt 小部件和样式表三、数据库连贯四、图表五、我的项目视图和对话框六、整合网络内容七、地图查看器八、图形视图九、照相机模块十、即时消息十一、实现图形编辑器十二、云存储十三、多媒体查看器十四、Qt Quick 和 QML十五、跨平台开发十六、测试和调试C++ 专家级编程 零、前言第一局部:C++ 编程的背地 一、构建 C++ 利用简介二、C++ 低级编程三、面向对象编程的细节四、了解和设计模板五、内存治理和智能指针第二局部:设计强壮高效的利用 六、STL 中数据结构和算法的开掘七、函数式编程八、并发和多线程九、设计并发数据结构十、设计全球通用的利用十一、应用设计模式设计策略游戏十二、网络和平安十三、调试和测试十四、应用 Qt 的图形用户界面第三局部:人工智能世界中的 C++ 十五、C++ 在机器学习工作中的利用十六、实现基于对话的搜索引擎十七、答案C++ 游戏动画编程实用指南 零、前言一、创立游戏窗口二、实现向量三、实现矩阵四、实现四元数五、实现转换六、构建形象渲染器七、摸索 glTF 文件格式八、创立曲线、帧和轨迹九、实现动画剪辑十、网格蒙皮十一、优化动画流水线十二、动画之间的交融十三、实现逆运动学十四、应用对偶四元数蒙皮十五、应用实例渲染人群C++ 函数式编程实用指南 零、前言第一局部:C++ 中的函数组件 一、函数式编程导论二、了解纯函数三、深刻 lambdas四、函数组合思维五、部分利用与柯里化第二局部:函数设计 六、函数思维——从数据输出到数据输入七、通过函数操作打消反复八、应用类进步内聚性九、面向函数式编程的测试驱动开发第三局部:播种函数式编程的益处 十、性能优化十一、基于属性的测试十二、重构到纯函数和通过纯函数重构十三、不变性和架构——事件源第四局部:C++ 函数式编程的现状和将来 十四、应用范畴库的提早求值十五、STL 反对和倡议十六、规范语言反对和倡议十七、答案C++ 机器学习实用指南 零、前言第一局部:机器学习概述 一、C++ 机器学习导论二、数据处理三、掂量体现和抉择模型第二局部:机器学习算法 四、聚类五、异样检测六、降维七、分类八、举荐零碎九、集成学习第三局部:高级示例 十、用于图像分类的神经网络十一、基于循环神经网络的情感剖析第四局部:生产和部署挑战 十二、导出和导入模型十三、在挪动和云平台上部署模型通过应用 UE4 构建游戏学习 C++ ...

December 8, 2021 · 2 min · jiezi

关于c:深度剖析C语言知识体系-原理实践一课带你吃透C语言jfgjdgjd

download:深度分析C语言常识体系 原理+实际,一课带你吃透C语言结构字符串 你会常常需要打印字符串。要是有很多变量,防止上面这样: name = "Raymond" age = 22 born_in = "Oakland, CA" string = "Hello my name is " + name + "and I'm " + str(age) + " years old. I was born in " + born_in + "." print(string)额,这看起来多乱呀?你能够用个丑陋简洁的办法来代替, .format 。 这样做: 前言去年11月在PyCon China 2018 杭州站分享了 ,讲述了如何通过修改 Python 解释器达到加解密 Python 代码的目标。然而因为笔者迁延症发生,一直没有及时整顿成文字版,现在终于战胜了它,才有了本文。 本文将首先介绍下现有源码加密打算的思路、方法、长处与不足,进而介绍如何通过定制 Python 解释器来达到更好地加解密源码的目标。 现有加密打算因为 Python 的动静个性和开源个性,导致 Python 代码很难做到很好的加密。社区中的一些声音认为这样的限度是事实,应该通过法律手段而不是加密源码达到商业保护的目标;而还有一些声音则是不论如何都心愿能有一种手段来加密。于是乎,人们想出了各种或加密、或混淆的打算,借此来达到保护源码的目标。 常见的源码保护手段有如下几种: 发行 .pyc 文件代码混淆使用 py2exe使用 Cython上面来简略说说这些打算。 发行 .pyc 文件思路大家都知道,Python 解释器在执行代码的过程中会首先生成 .pyc 文件,而后解释执行 .pyc 文件中的内容。当然了,Python 解释器也能够间接执行 .pyc 文件。而 .pyc 文件是二进制文件,无奈间接看出源码内容。如果发行代码到客户环境时都是 .pyc 而非 .py 文件的话,那岂不是能达到保护 Python 代码的目标? ...

December 8, 2021 · 2 min · jiezi

关于c++:More-Effective-C技术篇Reference-counting引用计数

Reference counting这项技术,容许多个等值对象共享同一实值。此技术的倒退有两种动机,第一是为了简化heap object周边的簿记工作。它能够打消“记录对象拥有权”的负荷,因为当对象使用了reference counting技术,它便领有它本人。一旦不再有任何人应用它,它便会主动销毁本人。reference counting的第二个倒退动机则只是为了实现一种常识。如果许多对象有雷同的值,将那个值存储屡次是件愚昧的事。最好是让所有等值对象共享一份实值就好。以下是一个蕴含了Copy-On-Write技术的Reference counting基类,有趣味倡议去看看原书中的文章,作者一步步疏导写出这个类,写的很具体,这里因为篇幅起因就不赘述。 // RCObject.h// template class,用来产生smart pointers-to-T objects;T必须继承自RCObject template<class T>class RCPtr {public: RCPtr(T* realPtr = 0); RCPtr(const RCPtr& rhs); ~RCPtr(); RCPtr& operator=(const RCPtr& rhs); T* operator->() const; T& operator*() const;private: T *pointee; void init();};// base class,用于reference-counted objectsclass RCObject {public: void addReference(); void removeReference(); void markUnshareable(); bool isShareable() const; bool isShared() const;protected: RCObject(); RCObject(const RCObject& rhs); RCObject& operator=(const RCObject& rhs); virtual ~RCObject() = 0; private: int refCount; bool shareable;};// RCObject.cppRCObject::RCObject() : refCount(0), shareable(true) {}RCObject::RCObject(const RCObject& rhs) : refCount(0), shareable(true) {}RCObject& RCObject::operator=(const RCObject& rhs) { return *this;}RCObject::~RCObject () {}void RCObject::addReference() { ++refCount;}void RCObject::removeReference() { if (--refCount == 0) { delete this; }}void RCObject::markUnshareable() { shareable = false;}bool RCObject::isShareable() const { return shareable;}bool RCObject::isShared() const { return refCount > 1;}template<class T>void RCPtr<T>::init () { if (pointee == 0) return; if (pointee->isShareable() == false) { pointee = new T(*pointee); } pointee->addReference();}template<class T>RCPtr<T>::RCPtr(T* realPtr) : pointee(realPtr) { init();}template<class T>RCPtr<T>::RCPtr(const RCPtr& rhs) : pointee(rhs.pointee) { init();}template<class T>RCPtr<T>::~RCPtr() { if (pointee) { pointee->removeReference(); }}template<class T>RCPtr<T>& RCPtr<T>::operator=(const RCPtr& rhs){ if (pointee != rhs.pointee) { if (pointee) { pointee->removeReference(); } pointee = rhs.pointee; init(); } return *this;}template<class T>T* RCPtr<T>::operator->() const { return pointee;}template<class T>T& RCPtr<T>::operator*() const { return *pointee;}而后,定义一个简略的String类,在String中蕴含示意其实值的struct StringValue,其中StringValue继承自下面的RCObject,使其领有援用计数的能力。String代码如下所示。 ...

December 8, 2021 · 2 min · jiezi

关于c#:小失误大问题-为已发布的接口更名

写代码不免呈现失误。在对某些曾经公布的库进行降级或者审查的时候,就有可能会发现一些接口名称须要变更。比方,晚期命名不合乎特定标准,或者呈现了难以发现的拼写错误等。有错当然是要改的,然而间接更名会影响到已公布的接口。粗犷的名称变更实质上是删除了旧接口,创立了新接口,对 API 用户来说极具破坏性 —— 用户会发现所有用到这些接口的中央都编译不过,或者不能运行了,这几乎就是一场劫难。 本文次要以 C# 为例介绍对库接口更名的解决 —— 在 Assembly 外部,间接应用“重命名”重构办法,借助 IDE/Editor 的能力就能够实现变更;然而对于凋谢进来的接口,就必须放弃接口兼容性,并申明过期工夫。 本文以 C# 为例,然而解决形式和重构思维是语言无关的!解决不符合规范的类属性命名这一节次要是解决属性更名的问题。办法更名和属性更名是同样的情理,前面不再赘述。 假如有如下定义: public class ActionResult : IActionResult { public int code { get; set; } public string message { get; set; }}这个定义命名不合乎“公开属性应用 Pascal Case 命名规定”的标准。但作为一个曾经被宽泛应用的库,间接重命名将产生微小的毁坏,所以这里应该按正确的名称增加属性,并将旧的属性申明为过期。 public class ActionResult : IActionResult { public int Code { get; set; } public string Message { get; set; } [Obsolete("因标准命名,将从 v3.4 版本中删除,请应用 Code 代替")] public int code { get => Code; set => Code = value; } [Obsolete("因标准命名,将从 v3.4 版本中删除,请应用 Message 代替")] public string message { get => Message; set => Message = value; }}不过批改后的 ActionResult 会在序列化的时候呈现问题。库中应用了 Newtonsoft JSON 来失去 JSON,按我的项目中的 JSON 标准,键名会应用 Camel Case 命名规定,所以在配置中增加了 CamelCasePropertyNamesContractResolver 实例。那么 ActionResult 的 Code 和 code 属性都会被解决为 "code" 这个键名,于是产生了重名的抵触。 ...

December 8, 2021 · 2 min · jiezi

关于c#:C80-可空引用类型

介绍咱们的我的项目代码运行时最频繁的谬误之一就是 System.NullReferenceException 异样,c#8.0减少的可为空援用类型就是用来帮忙开发者升高甚至打消NULL异样。咱们须要留神的是可空援用类型是语法级别的性能,也就是代码编写的时候就会受到编程束缚,这个与可为空值类型是不一样的。我的项目反对c#8.0请参见C# 语言版本控制。 目录在我的项目中启用可空援用类型反对将变量标注为可空援用类型应用示例进阶缺点在我的项目中启用可空援用类型反对<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>net6.0</TargetFramework> <Nullable>enable</Nullable> </PropertyGroup> </Project>在我的项目文件中减少<Nullable>enable</Nullable>后,我的项目代码中的援用类型将被解析拆分为不可空援用类型和可空援用类型。 将正告晋升为异样可空援用类型性能是以正告的模式呈现,并不会烦扰我的项目生成编译,约束力较弱。如果想严格要求本身,那咱们可将特定的正告变为异样来晋升约束力。 <Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>net6.0</TargetFramework> <Nullable>enable</Nullable> <WarningsAsErrors> $(WarningsAsErrors);CS8600;CS8601;CS8602;CS8603;CS8604;CS8609;CS8610;CS8614;CS8616;CS8618;CS8619;CS8622;CS8625 </WarningsAsErrors> </PropertyGroup> </Project>相干技术文档C# 编译器选项 - 谬误和正告 | Microsoft Docs,Non-nullable references with C# 8 and .NET Core 3.0 · Cezary Piątek Blog (cezarypiatek.github.io),大家在编写代码时遇到Microsoft.CodeAnalysis.CSharp分析器所给的正告代码,都可依照本人的要求将其变为异样来束缚本人。 将变量标注为可空援用类型咱们平时应用的援用类型属于不可空援用类型,在其后附加?便为可空援用类型。 string name; //不可空字符串string? adress; //可空字符串泛型public TKey GetKey<TKey>(){ //必须返回不可空类型}public TValue? GetValue<TValue>(){ //可返回可空类型}应用示例 如上示例,因为Student领有默认的空构造函数new Student(),此构造函数会使Name和Adress属性为null,所以分析器收回了CS8618的正告。 咱们将空构造函数写上,此时正告智能的转移到构造函数上了。 咱们在构造函数中将可能为null的string类型属性附上值,正告打消。而string?类型无需解决,因为它是容许为null的。 以上两种形式也能够打消正告。 在GetStudentNames办法中,咱们应用Student的EnglishName属性时,分析器收回了CS8604正告,因为EnglishName属性是可空援用类型,无奈放入List<string>中,只能放入在List<string?>中。 咱们应用??判断当EnglishName为null时,应用不可空援用类型属性Name,此时CS8604正告打消。 进阶可空援用类型模式中,属性是能够被拆分为两种模式的,其一是属性是否可被赋值null,其二是属性的值是否可能为null。大家可能对这句话了解起来有点懵,请接着看上面的解说。 [AllowNull]不可为null的援用类型属性容许被赋值null 下面代码中,Adress属性即便被赋值null,也不会使其值为null,不会在代码中引发潜在的Null异样。所以此场景是正当且被容许的。 [DisallowNull]可为null的援用类型属性不容许赋值为null ...

December 8, 2021 · 1 min · jiezi

关于c++:CC气象数据中心实战手把手教你做工业级项目adafa

download:C/C++气象数据中心实战,手把手教你做工业级我的项目构造字符串 你会常常需要打印字符串。要是有很多变量,避免上面这样: name = "Raymond" age = 22 born_in = "Oakland, CA" string = "Hello my name is " + name + "and I'm " + str(age) + " years old. I was born in " + born_in + "." print(string)额,这看起来多乱呀?你可能用个丑陋简洁的方法来代替, .format 。 这样做: name = "Raymond" age = 22 born_in = "Oakland, CA" string = "Hello my name is {0} and I'm {1} years old. I was born in {2}.".format(name, age, born_in) print(string)返回tuple元组 ...

December 8, 2021 · 2 min · jiezi

关于c:闲聊C语言结构体

构造体是 C 语言次要的自定义类型计划,这篇就来认识一下构造体。一、构造体的状态C源程序(struct.c): #include <stdio.h>typedef struct{ unsigned short int a; unsigned short int b;}Data;int main(){ Data c, d; c.a = 1; c.b = 2; d = c; printf("d.a:%d\nd.b:%d\n", d.a, d.b); return 0;}赋值局部翻译后: movw $1, 28(%esp) # c.a = 1 movw $2, 30(%esp) # c.b = 2 movl 28(%esp), %eax # movl %eax, 24(%esp) # d = c 能够看出: c.a 是在 28(%esp) 之后的2个字节c.b 是在 30(%esp) 之后的2个字节c 是 28(%esp) 之后的4个字节d 是 24(%esp) 之后的4个字节不得不感叹名字(构造体名字、子元素名字)再一次被抛弃了,子元素名代表的是绝对于构造体的偏移。 ...

December 8, 2021 · 1 min · jiezi

关于c#:如何在-ASPNET-Core-中构建轻量级服务

在 ASP.NET Core 中解决 Web 应用程序时,咱们可能常常心愿构建轻量级服务,也就是没有模板或控制器类的服务。 轻量级服务能够升高资源耗费,而且可能进步性能。咱们能够在 Startup 或 Program 类中创立这些轻量级服务或 API。 1. 应用 VS2022 创立 ASP.NET Core 我的项目咱们在 Visual Studio 2022 中创立一个 ASP.NET Core 我的项目。依照以下步骤在 Visual Studio 2022 中创立一个新的 ASP.NET Core Web API 6 我的项目。 1) 启动 Visual Studio 2022 IDE。2) 单击 “Create new project”。3) 在 “Create new project” 窗口中,从显示的模板列表中抉择 “ASP.NET Core Web API”。4) 点击下一步。5) 在 “Configure your new project” 窗口中,指定新我的项目的名称和地位。6) 依据您的偏好,可抉择选中 “Place solution and project in the same directory” 复选框。7) 点击下一步。8) 在接下来显示的 “Additional Information” 窗口中,从顶部的下拉列表中抉择 .NET 6.0 作为指标框架。将 “Authentication Type” 保留为 “None”(默认)。9) 确保未选中 “Enable Docker,”、“Configure for HTTPS” 和 “Enable Open API Support” 复选框,因为咱们不会在此处应用任何这些性能。您也能够抉择勾销选中 “Use controllers(勾销选中以应用起码的 API)” 复选框,因为咱们将创立本人的控制器。10) 单击创立。这将在 Visual Studio 2022 中创立一个新的 ASP.NET Core 6 Web API 我的项目。咱们将在本文的后续局部中应用该我的项目,来阐明如何应用轻量级服务。 ...

December 8, 2021 · 3 min · jiezi

关于c#:如何使用Redis实现令牌桶算法

在限流算法中有一种令牌桶算法,该算法能够应答短暂的突发流量,这对于事实环境中流量不怎么平均的状况特地有用,不会频繁的触发限流,对调用方比拟敌对。 例如,以后限度10qps,大多数状况下不会超过此数量,但偶然会达到30qps,而后很快就会恢复正常,假如这种突发流量不会对系统稳定性产生影响,咱们能够在肯定水平上容许这种刹时突发流量,从而为用户带来更好的可用性体验。这就是应用令牌桶算法的中央。 令牌桶算法原理如下图所示,该算法的基本原理是:有一个容量为X的令牌桶,每Y单位工夫内将Z个令牌放入该桶。如果桶中的令牌数量超过X,那么它将被抛弃。解决申请时,须要先从令牌桶中取出令牌,如果拿到了令牌,则持续解决;如果拿不到令牌,则拒绝请求。 能够看出,在令牌桶算法中设置X,Y和Z的数量尤为重要。Z应该比每Y单位工夫内的申请数稍大,零碎将长时间处于此状态;X是零碎容许的刹时最大申请数,并且零碎不应该长时间处于此状态,否则就会频繁触发限流,此时表明流量呈现了超预期的状况,须要及时考察起因并采取相应措施。 Redis实现令牌桶算法之前看过有些程序实现的令牌桶,其向桶中放入令牌的办法是启动一个线程,每隔Y单位工夫减少一次令牌数量,或者在Timer中定时执行这一过程。我不太称心这种办法, 起因有二,一是节约线程资源,二是因为调度的问题执行工夫不准确。 这里确定令牌桶中令牌数量的办法是通过计算得出,首先算出从上次申请到这次申请通过了多长时间,是否达到发令牌的工夫阈值,而后减少的令牌数是多少,这些令牌可能放到桶中的是多少。 Talk is cheap! 下边就来看看Redis中怎么实现的,因为波及到屡次与Redis的交互,这里为了进步限流解决的吞吐量,缩小程序与Redis的交互次数,采纳了Redis反对的Lua script,Lua script的执行是原子的,所以也不必放心呈现脏数据的问题。 代码节选自 FireflySoft.RateLimit ,它不仅反对一般主从部署Redis,还反对集群Redis,所以吞吐量能够通过程度扩大的形式进行晋升。为了不便浏览,这里减少一些正文,理论是没有的。 -- 定义返回值,是个数组,蕴含:是否触发限流(1限流 0通过)、以后桶中的令牌数local ret={}ret[1]=0-- Redis集群分片Key,KEYS[1]是限流指标local cl_key = '{' .. KEYS[1] .. '}'-- 获取限流惩办的以后设置,触发限流惩办时会写一个有过期工夫的KV-- 如果存在限流惩办,则返回后果[1,-1]local lock_key=cl_key .. '-lock'local lock_val=redis.call('get',lock_key)if lock_val == '1' then ret[1]=1 ret[2]=-1 return ret;end-- 这里省略局部代码-- 获取[上次向桶中投放令牌的工夫],如果没有设置过这个投放工夫,则令牌桶也不存在,此时:-- 一种状况是:首次执行,此时定义令牌桶就是满的。-- 另一种状况是:较长时间没有执行过限流解决,导致承载这个工夫的KV被开释了,-- 这个过期工夫会超过天然投放令牌到桶中直到桶满的工夫,所以令牌桶也应该是满的。local last_time=redis.call('get',st_key)if(last_time==false)then -- 本次执行后残余令牌数量:桶的容量- 本次执行耗费的令牌数量 bucket_amount = capacity - amount; -- 将这个令牌数量更新到令牌桶中,同时这里有个过期工夫,如果长时间不执行这个程序,令牌桶KV会被回收 redis.call('set',KEYS[1],bucket_amount,'PX',key_expire_time) -- 设置[上次向桶中放入令牌的工夫],后边计算应放入桶中的令牌数量时会用到 redis.call('set',st_key,start_time,'PX',key_expire_time) -- 返回值[以后桶中的令牌数] ret[2]=bucket_amount -- 无需其它解决 return retend-- 令牌桶存在,获取令牌桶中的以后令牌数local current_value = redis.call('get',KEYS[1])current_value = tonumber(current_value)-- 判断是不是该放入新令牌到桶中了:以后工夫-上次投放的工夫 >= 投放的工夫距离last_time=tonumber(last_time)local last_time_changed=0local past_time=current_time-last_timeif(past_time<inflow_unit)then -- 不到投放的时候,间接从令牌桶中取走令牌 bucket_amount=current_value-amountelse -- 须要放入一些令牌, 预计投放数量 = (距上次投放过来的工夫/投放的工夫距离)*每单位工夫投放的数量 local past_inflow_unit_quantity = past_time/inflow_unit past_inflow_unit_quantity=math.floor(past_inflow_unit_quantity) last_time=last_time+past_inflow_unit_quantity*inflow_unit last_time_changed=1 local past_inflow_quantity=past_inflow_unit_quantity*inflow_quantity_per_unit bucket_amount=current_value+past_inflow_quantity-amountend-- 这里省略局部代码ret[2]=bucket_amount-- 如果桶中残余数量小于0,则看看是否须要限流惩办,如果须要则写入一个惩办KV,过期工夫为惩办的秒数if(bucket_amount<0)then if lock_seconds>0 then redis.call('set',lock_key,'1','EX',lock_seconds,'NX') end ret[1]=1 return retend-- 来到这里,代表能够胜利扣减令牌,则须要更新令牌桶KVif last_time_changed==1 then redis.call('set',KEYS[1],bucket_amount,'PX',key_expire_time) -- 有新投放,更新[上次投放工夫]为本次投放工夫 redis.call('set',st_key,last_time,'PX',key_expire_time)else redis.call('set',KEYS[1],bucket_amount,'PX',key_expire_time)endreturn ret通过以上代码,能够看出,其次要处理过程是: ...

December 8, 2021 · 1 min · jiezi

关于c++:算法笔记经典模板

BFS模板void BFS(int s){ queue<int> q; q.push(s); while(!q.empty()){ 取出队首元素front; 访问队首元素front; 将队首元素出队; 将front的下一层结点中未曾入队的结点全副入队,并设置已入队 }}DFS模板递归 priority_queue的cmp函数模板:struct fruit{ string name; int price;}struct cmp{ bool operator () (fruit f1,fruit f2){ return f1.price > f2.price; }}int main(){ priority_queue<fruit,vector<fruit>,cmp> q; return 0;}中序序列和先序序列、后序序列、层序序列配合重建二叉树的模板://记住create函数模板,不论中序和谁配合,模板如下//postL是后序序列的左端点//postR是后序序列的右端点//inL是中序序列的左端点//inR是中序序列的右端点//postOrder是后序序列//inOrder是中序序列node* create(int postL,int postR,int inL,int inR){ if(postL>postR){ return NULL; } int in = postOrder[postR]; node* root = new node; root->data = in; int k; for(k=inL;k<=inR;k++){ if(inOrder[k]==in){ break; } } int numLeft = k-inL;//这一步肯定要有 root->lChild = create(postL,postL+numLeft-1,inL,inL+numLeft-1); root->rChild = create(postL+numLeft,postR-1,inL+numLeft+1,inR); return root;}并查集寻找根节点的模板://递归写法int findFather(int n){ if(n==father[n]){ return n; } else{ //小括号和中括号要离开 return findFather(father[n]); }}并查汇合并汇合的模板:void unionS(int a,int b){ int fA = findFather(a); int fB = findFather(b); if(fA != fB){ father[fA] = fB; } return;}迪杰斯特拉算法+新增点权+求最短门路条数:void Dij(){ //以下三行是初始化工作: //终点到终点的间隔是0; //终点到终点的最短门路有1条; //终点到终点累计能够取得的最大资源=该终点自身领有的资源 d[now] = 0; shortestNum[now] =1; maxRescue[now] = cityRescue[now]; //整个for循环中没有用到i的中央,i只用来计数 for(int i=0; i<cityNum; i++) { int u = -1; int minLen = inf; //寻找以后间隔终点间隔最短的点 for(int j=0; j<cityNum; j++) { if(!vis[j] && d[j]<minLen) { u = j; minLen = d[j]; } } if(u==-1) { return; } //阐明u曾经被拜访过了 vis[u] = true; int len = save[u].size(); //通过u来更新 for(int j=0; j<len; j++) { int number = save[u][j].num; int roadLen = save[u][j].road; //首先要确定该结点没有被拜访过 if(!vis[number]) { if(d[number]> d[u]+roadLen) { d[number] = d[u]+roadLen; shortestNum[number] = shortestNum[u]; //如果最短门路变了,那么累计取得的最大资源要无条件扭转 maxRescue[number] = maxRescue[u]+cityRescue[number]; } else if(d[number]==d[u]+roadLen) { shortestNum[number] += shortestNum[u]; //如果最短门路没变,那么累计取得的最大资源要有条件扭转 if(maxRescue[u]+cityRescue[number]>maxRescue[number]){ maxRescue[number] = maxRescue[u]+cityRescue[number]; } } } } }}弗罗伊德算法模板void Floyed(){ for(int k=0; k<n; k++) { for(int i=0; i<n; i++) { for(int j=0; j<n; j++) { if(dis[i][k]!=INF && dis[k][j]!=INF && dis[i][k]+dis[k][j]<dis[i][j]) { dis[i][j] = dis[i][k]+dis[k][j]; } } } }}普里姆算法模板//G为图,个别设置成全局变量;数组d为顶点与汇合S的最短距离Prime(G,d[]){ 初始化; for(循环n次){ u = 使d[u]最小的还未被拜访的顶点的标号; 记u已被拜访; for(从u登程能达到的所有顶点v){ if(v未被拜访 && 以u为中介点使得v与汇合S的最短距离d[v]更优){ 将G[u][v]赋值给v与汇合S的最短距离d[v]; } } }}求素数模板//给定一个数,判断它是不是素数#include <iostream>#include <stdio.h>#include <math.h>using namespace std;//外围代码bool isPrime(int n){ if(n<=1){ return false; } int a = (int)sqrt(1.0*n);//向下取整 for(int i=2; i<=a; i++){ if(n%i==0){ return false; } } return true;}int main(){ int n; scanf("%d",&n); bool is = isPrime(n); if(is){ printf("Yes"); } else{ printf("No"); } return 0;}求素数表模板(埃氏筛法)//求1到n之间的所有素数,#include <iostream>#include <stdio.h>using namespace std;const int maxn = 1000;bool is[maxn] = {false};int prime[maxn];int p=0;int n;//外围代码void findPrime(){ for(int i=2;i<=n;i++){ if(!is[i]){ prime[p] = i; p++; for(int j=i+i;j<=n;j = j+i){ is[j] = true; } } }}int main(){ scanf("%d",&n); findPrime(); for(int i=0; i<p;i++){ printf("%d\n",prime[i]); } return 0;}求解最大公约数的模板//给定两个数n和m,求n和m的最大公约数a#include <iostream>#include <stdio.h>using namespace std;//外围代码;不用关怀a和b的大小,默认a>b,就算a<b,通过一轮迭代之后,也会变成a>bint gcd(int a,int b){ if(b==0){ return a; } else{ return gcd(b,a%b); }}int main(){ int n; int m; scanf("%d%d",&n,&m); int a = gcd(n,m); printf("%d",a); return 0;}求解最小公倍数的模板//给定两个数n和m,求n和m的最小公倍数b#include <iostream>#include <stdio.h>using namespace std;//外围代码int gcd(int a,int b){ if(b==0){ return a; } else{ return gcd(b,a%b); }}int main(){ int n; int m; scanf("%d%d",&n,&m); int a = gcd(n,m); int b = (n/a)*m;//先求最大公约数,而后再求最小公倍数 printf("%d",b); return 0;}求斐波拉契数列模板(动静布局办法)一个问题能用动静布局办法求解,须要满足以下两个条件: ...

December 7, 2021 · 5 min · jiezi

关于c#:TIOBE-12-月榜C-有望冲击年度编程语言奖PHP-遗憾跌出前十

近日,TIOBE 颁布了 12 月份编程语言指数排行榜。其中,Python、C、Java 仍旧分列前三甲,而 PHP 已遗憾跌出前十,C# 或将无望冲击“TIOBE 年度编程语言奖”。 据悉,TIOBE 将于下个月发表 “TIOBE年度编程语言奖”,该奖项将在 2021 年度评分最高的编程语言中选出。目前,C# 被看做是最有可能取得这一头衔的候选者。 TIOBE CEO Paul Jansen 示意,C# 在其 21 年的历史中从未取得过“TIOBE索引编程语言年度奖”,只管它在过来 20 年中始终名列前十,让咱们一起期待下个月的惊喜吧! 本次 TIOBE 指数榜单前 10 位里,Python 已间断三个月霸榜第一;排名变动最大的就是 PHP ,它在上个月位列第 10 名,本月已跌至第 12 位,取而代之的是 Swift (上个月第 14 名,本月升至第 10 名)。其余前十语言的排名与上个月雷同。 榜单第 11-20 名中,相比上个月,R 从第 15 升至第 11 名、Delphi/Object Pascal从第 17 名升至第 16 名、Fortran 从第 19 名升至第 17 名。 同时,PHP 从上个月的第 10 名跌至第 12 名、Classic Visual Basic 从上个月的第 11 名降落至第 13 名、Groovy 从上个月的第 12 名降落至第 14 名、Ruby 从上个月的第 13 名降落至第 15 名、Perl 从上个月的第 16 名降落至第 18 名、GO 也从上个个月的第 18 名降落至第 19 名,行将要跌出前20名,而 MATLAB 则与上个月排名雷同,本月仍然位列第 20 名。 ...

December 7, 2021 · 1 min · jiezi

关于c++:算法笔记STL以及常见问题

vectorvector<typename> name 函数性能工夫复杂度push_back(x)在vector前面增加一个元素O(1)pop_back()删除vector的尾元素O(1)size()取得vector的元素个数O(1)clear()清空vector中的所有元素O(N),N为vector元素个数insert(it,x)向vector的任意迭代器it处插入一个元素xO(N)erase(it)删除迭代器it处的元素O(N)erase(first,last)删除[first,last)内的所有元素O(N)queuequeue<typename> name 函数性能工夫复杂度push(x)将x进行入队O(1)front()取得队首元素,应用前调用empty()函数O(1)back()取得队尾元素,应用前调用empty()函数O(1)pop()令队首元素出队O(1)empty()检测queue是否为空O(1)size()返回queue内元素的个数O(1)priority_queuepriority_queue<typename> name 函数性能工夫复杂度push(x)将x入队O(logN),N为以后优先队列中的元素个数top()取得队首元素(即堆顶元素),应用前调用empty()函数O(1)pop()令队首元素(即堆顶元素)出队O(logN),N为以后优先队列中的元素个数empty()检测优先队列是否为空O(1)size()返回优先队列内元素的个数O(1)priority_queue<int> q 数字越大优先级越大 priority_queue<int ,vector<int>,less<int>> q 数字越大优先级越大 priority_queue<int,vector<int>,greater<int>> q 数字越小优先级越大 #include <iostream>#include <stdio.h>#include <queue>using namespace std;struct fruit{ string name; int price; friend bool operator < (fruit f1,fruit f2)//只能对小于号进行重载 { return f1.price>f2.price; //具体了解:如果f1.price>f2.price为true,那么就认为f1 "<" f2,所以f1应该在f2前面 //与sort函数中的cmp正好相同 }} f1,f2,f3;int main(){ priority_queue<fruit> q; f1.name = "桃子"; f1.price = 3; f2.name = "梨子"; f2.price = 4; f3.name = "苹果"; f3.price = 1; q.push(f1); q.push(f2); q.push(f3); //printf("%s %d\n",q.top().name,q.top().price); cout<<q.top().name<<" "<<q.top().price<<endl; return 0;}priority_queue的用处:解决贪婪问题;对Dijkstra算法进行优化。 ...

December 5, 2021 · 1 min · jiezi

关于c++:算法笔记深度优先搜索

“让右手始终贴着左边的墙壁走” 举荐应用递归实现DFS,应用递归的时候零碎会调用零碎栈,因而用递归来实现DFS的实质还是栈 vector罕用函数: 函数性能工夫复杂度push_back(x)在vector前面增加一个元素O(1)pop_back()删除vector的尾元素O(1)size()取得vector的元素个数O(1)clear()清空vector中的所有元素O(N),N为vector元素个数insert(it,x)向vector的任意迭代器it处插入一个元素xO(N)erase(it)删除迭代器it处的元素O(N)erase(first,last)删除[first,last)内的所有元素O(N)上面给出《算法笔记》书本中的两个经典例子 背包问题求解留神点(《算法笔记》P272页)#include <iostream>#include <stdio.h>#include <algorithm>using namespace std;const int maxn = 30;int n=0;int V=0;int maxWeight=0;int maxValue=0;int w[maxn];int v[maxn];void DFS(int index,int sumW,int sumV){ if(index==n){ return; } DFS(index+1,sumW,sumV); if(sumW+w[index]<=maxWeight){//if条件里是<=,等于号不能漏,否则会漏解,可能要完第index号物品后,背包满了,且恰好价值最大 if(sumV+v[index]>maxValue){ maxValue = sumV+v[index]; } DFS(index+1,sumW+w[index],sumV+v[index]); }}int main(){ scanf("%d%d",&n,&maxWeight); for(int i=0; i<n; i++){ scanf("%d",&w[i]); } for(int i=0; i<n; i++){ scanf("%d",&v[i]); } DFS(0,0,0); printf("%d",maxValue); return 0;}给定N个整数(可能有正数),从中选取K个数,使得这K个数之和恰好等于一个给定的整数X,如果有多种计划,抉择它们中元素平方和最大的一个(《算法笔记》P273页)#include <iostream>#include <stdio.h>#include <vector>using namespace std;const int maxn = 10000;int n=0;int k=0;int x=0;int maxSquare=-1;int A[maxn];vector<int> st;vector<int> temp;void DFS(int index,int nowk,int sum,int sumSqu)//第二个参数nowK(以后已选整数个数)容易漏写{ //死胡同1 if(nowk == k && sum == x) { if(sumSqu>maxSquare) { maxSquare = sumSqu; st = temp; } return; } //死胡同2 if(index == n || nowk >k || sum>x) ////index==n容易写成index==n-1,第n-1个数是存在的,不能被返回 { return; } //岔路口 temp.push_back(A[index]); DFS(index+1,nowk+1,sum+A[index],sumSqu+A[index]*A[index]); temp.pop_back(); DFS(index+1,nowk,sum,sumSqu);}int main(){ scanf("%d",&n); for(int i=0; i<n; i++) { scanf("%d",&A[i]); } scanf("%d",&k); scanf("%d",&x); DFS(0,0,0,0); printf("%d\n",maxSquare); for(int i=0; i<st.size(); i++) { printf("%d ",st[i]); } return 0;}参考书目:《算法笔记》 ...

December 5, 2021 · 1 min · jiezi