这也是我最近才发现的一个技巧,就是如果一个问题特别复杂,我们就应该从最简单的东西入手,那么,对于, 对于ebpf有什么简单的呢?
答案就是在第一个commit.commit
跟着这个commit,你就能抛开一些繁琐的东西,这是最本质的东西,我在想能不能将这些程序自己重新跑一遍看看。
通过这两个项目你就可以建立libbpf,就可以测试一些自己改动了,根据自己的需要。
https://blog.cloudflare.com/tag/ebpf/
https://blogs.oracle.com/linux/notes-on-bpf-1
为什么使用虚拟环境,这篇文章解释的明白,下面记录下自己的操作。
pip更新命令:
sudo Python3 -m pip install --upgrade pip
上面这条命令就会把pip升级为pip3, 不然,pip默认还是python2
pip install virtualenv
接着安装 虚拟环境 模拟器:
pip install virtualenvwrapper
首先确定各种命令的执行路径:
which virtualenvwrapper.sh
/home/vimer/.local/bin/virtualenvwrapper.sh
# which python3 as same
修改 ./bashrc 文件:
export WORKON_HOME=$HOME/.virtualenvs
source ~/.local/bin/virtualenvwrapper.sh # which virtualenvwrapper.sh命令获取
VIRTUALENVWRAPPER_PYTHON=/usr/bin/Python3 # which Python3命令获取
更新 .bashrc 文件:
source .bashrc
上面咱们安装了 virtualenvs的工具,然后就可以在具体的项目创建之前使用它了,这也是虚拟环境的优势了。
上面一切ok之后,就可以创建虚拟项目了。
vimer@host:~/Projs$ mkvirtualenv opencv
created virtual environment CPython2.7.17.final.0-64 in 82ms
creator CPython2Posix(dest=/home/vimer/.virtualenvs/opencv, clear=False, no_vcs_ignore=False, global=False)
seeder FromAppData(download=False, pip=bundle, wheel=bundle, setuptools=bundle, via=copy, app_data_dir=/home/vimer/.local/share/virtualenv)
added seed packages: pip==20.3.1, setuptools==44.1.1, wheel==0.36.1
activators PythonActivator,CShellActivator,FishActivator,PowerShellActivator,BashActivator
virtualenvwrapper.user_scripts creating /home/vimer/.virtualenvs/opencv/bin/predeactivate
virtualenvwrapper.user_scripts creating /home/vimer/.virtualenvs/opencv/bin/postdeactivate
virtualenvwrapper.user_scripts creating /home/vimer/.virtualenvs/opencv/bin/preactivate
virtualenvwrapper.user_scripts creating /home/vimer/.virtualenvs/opencv/bin/postactivate
virtualenvwrapper.user_scripts creating /home/vimer/.virtualenvs/opencv/bin/get_env_details
(opencv) vimer@host:~/Projs$ # 已经处于opencv
使用 pip list
则可以看到该pip管理的python packets,这里还需要深入了解,感觉还是有一些问题的。
(opencv) vimer@host:~/Projs$ deactivate
vimer@host:~/Projs$
vimer@host:~/Projs$ workon
n
opencv
# 或者这个也可以
vimer@host:~/Projs$ lsvirtualenv
n
=
opencv
======
vimer@host:~/Projs$ rmvirtualenv n
Removing n...
vimer@host:~/Projs$ workon opencv
(opencv) vimer@host:~/Projs$
以上后面两个操作可以在一个正在进行中的虚拟项目中执行。
知乎1 知乎2 网络营销,看着很简单,实则无从下手的一门实践课程,如果仅仅学习成功的案例,我们仅仅是过了眼瘾, 对于我们的思维模式没有一点的提高,最好的方案就是,努力找到一个自己可以拿出来的产品,尽善尽美地去改进它,从而为社会创造价值。
网络上的虚拟资源非常多,这就需要同学们结合自己的兴趣去寻找了。
你为什么现在就应该写博客 这篇文章很长,建议大家好好拜读一下。阅读一个人的文章,最好也了解一下作者本人的简历。
c语言有关字符串的函数很多,每本教材的附录都会有一些库函数,大家可以了解一些。今天,给大家介绍几个常用的。
strcat(str1, str2): 连接str2到str1中,注意str1的大小能够容下两者。
strlen(str1),计算str1的长度,不包括结尾’\0’
strcpy(str1,str2)将str2复制给str1
这一句是输出字符串,没啥好说的
这个gets函数不要再使用了,切记,众多的计算机安全问题就是和这个函数有关,相反,使用fgets()函数代替。 众所周知,gets()可以读取一个包含空格的字符串(不限量),这就是他问题的根源所在,不限制的字符读入会造成计算机的栈溢出,导致种种问题。那有同学说了,不用gets那用什么,scanf(“%s”, string_array_name)不符合要求?好,记住,大家以后使用fgets.
下面借助代码具体说一下: 原来的意图是:
...
char s[20];
gets(s);
puts(s);
...
现在用的话,使用下面的方法:
char s[20];
fgets(s, 20, stdio);
puts(s);
也就是多了两个参数,20就是你想要读入的字符串的最大值,这样就避免了无限量读入的问题,stdio表示从输入终端读取,就是那个黑色的框框。
puts(str), 输出str.
int main()
{
char str[100];
printf("请输入一串字符串,最好英文,以回车键结尾\n");
fgets(str, 100, stdin);
int i;
int nums = 0;
for(i = 0; str[i] != '\0'; i++)
{
if(str[i] != ' ' && str[i+1] == ' ' || str[i+1] == '\0')
nums++;
}
printf("the numbers of words is %d\n", nums);
}
以”I want to C program \0”,以这个例子带进去,就可以测出来。”I”作为一个独立的单词,目前不为” “,但是紧跟着空格,所以单词加1,或者最后一个单词也得加1.
已经确认了,leetcode的题目没有头结点,都是不带头结点的。
707 这是一道基础题,但是有许多值得称道的地方,主要是边界的处理,这么说吧,现在,数据结构参考书上很多的代码都是错的,或者说不是全面的,因为没有处理一个边界值的问题。
这个题目有几个注意的地方:
list的长度是多少?是结点的个数。obj->1->2->null,那么这个长度是2.
index 是从0开始的,以上面的例子举例子,也就是1是第0个,2是第1个。
我处理的失误是,删除元素没有想到最后一个元素的问题。
#include <stdio.h>
#include <stdlib.h>
typedef struct list_node {
int val;
struct list_node *next;
} MyLinkedList;
/* Initialize data struct */
MyLinkedList *myLinkedListCreate(){
MyLinkedList *obj = (MyLinkedList *)malloc(sizeof(MyLinkedList));
if (obj == NULL)
{
printf("error\n");
}
/* here, the linkedlist has head node , so, when you reverse the node, you must pass the tempery list with obj->next */
obj->next = NULL;
return obj;
}
/* insert node with head, we must master it */
void myLinkedListAddAtHead(MyLinkedList *obj, int val){
MyLinkedList *p = obj; // alter ways
MyLinkedList *temp = (MyLinkedList *)malloc(sizeof(MyLinkedList));
if (temp == NULL)
{
printf("error\n");
/* code */
}
temp->val = val;
temp->next = p->next;
p->next = temp;
}
/** Append a node of value val to the last element of the linked list. */
void myLinkedListAddAtTail(MyLinkedList* obj, int val) {
MyLinkedList *temp = (MyLinkedList *)malloc(sizeof(MyLinkedList));
MyLinkedList *p = obj;
if(temp == NULL)
{
printf("error\n");
}
while(p->next != NULL){
p = p->next;
}
temp->val = val;
temp->next = NULL;
p->next = temp;
}
/* 0-index */
int myLinkedListLength(MyLinkedList *obj)
{
int length = 0;
MyLinkedList *p = obj;
if (obj->next == NULL)
{
return 0;
/* code */
}
while(p->next != NULL)
{
length++;
p = p->next;
}
return length;
}
/** Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list,
the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted. */
void myLinkedListAddAtIndex(MyLinkedList* obj, int index, int val) {
MyLinkedList *p = obj;
int length = myLinkedListLength(obj);
int i = 0;
if( index < 0 || index > length){
//printf("index is greater than the list\n");
return ;
}
if (index == length)
{
myLinkedListAddAtTail(p, val);
return ;
/* code */
}
while(p->next && i < index){
p = p->next;
i++;
}
MyLinkedList *temp = (MyLinkedList *)malloc(sizeof(MyLinkedList));
if (temp == NULL)
{
printf("error\n");
/* code */
}
temp->val = val;
temp->next = p->next;
p->next = temp;
}
/* 很多程序*/
/** Delete the index-th node in the linked list, if the index is valid. */
void myLinkedListDeleteAtIndex(MyLinkedList* obj, int index) {
MyLinkedList *p = obj->next, *p_temp;
int length = myLinkedListLength(obj);
int i = 0;
if( index < 0 || index > length){
printf("index is greater than the list\n");
exit(1);
}
while(p && i < index-1){
p = p->next;
i++;
}
if (p == NULL)
return ;
else
{
p_temp = p->next;
if (p_temp == NULL)
{
return ;
}
else
{
p->next = p_temp->next;
free(p_temp);
}
}
}
/** Get the value of the index-th node in the linked list. If the index is invalid, return -1. */
int myLinkedListGet(MyLinkedList* obj, int index) {
MyLinkedList *p = obj;
int length = myLinkedListLength(obj);
int i = 0;
if( index < 0 || index >= length){
//printf("index is greater than the list\n");
return -1;
}
if(length == 0)
return -1;
while(p->next && i <= index){
p = p->next;
i++;
}
return p->val;
}
void myLinkedListFree(MyLinkedList* obj) {
MyLinkedList *p;
while(obj){
p = obj->next;
obj = p;
free(p);
}
}
void myLinkedListshow(MyLinkedList *obj)
{
MyLinkedList *p = obj->next;
while(p)
{
printf("%d->", p->val);
p = p->next;
}
}
int main()
{
MyLinkedList *obj = myLinkedListCreate();//= myLinkListCreate();
//int rc = myLinkedListGet(obj, 0);
//printf("0-index is %d\n", rc);
//myLinkedListAddAtIndex(obj, 1,2);
//int rc2 = myLinkedListGet(obj, 0);
myLinkedListAddAtHead(obj, 1);
// myLinkedListAddAtTail(obj, 3);
myLinkedListAddAtIndex(obj, 1,2);
// myLinkedListDeleteAtIndex(obj, 1);
//printf("b,0-index is %d\n", rc2);
myLinkedListshow(obj);
//int len = myLinkedListLength(obj);
int rc1 = myLinkedListGet(obj, 1);
int rc2 = myLinkedListGet(obj, 0);
int rc3 = myLinkedListGet(obj, 2);
printf("\nthe is %d %d %d \n", rc1, rc2,rc3);
/* myLinkedListAddAtIndex(obj, 1,2);
myLinkedListshow(obj);
printf("\n");
myLinkedListDeleteAtIndex(obj, 1);
rc = myLinkedListGet(obj, 1);
printf("\nthe %d-th is %d\n", 1, rc);
myLinkedListshow(obj);
myLinkedListFree(obj);
len = myLinkedListLength(obj);
printf("\nthe last length is 5\n");
*/
}
int main函数是我方便测试写的,希望大家注意。
update:2019-07-14:为什么这里更新了呢?大家有没有发现,这里使用一级指针的问题在哪?对了,就是处理特殊节点显得特别啰嗦,那怎么办?我们选择一个二级指针就可以轻松解决 这个问题。
void push(Node** head_ref, int new_key)
{
/* allocate node */
Node* new_node = new Node();
/* put in the key */
new_node->key = new_key;
/* link the old list off the new node */
new_node->next = (*head_ref);
/* move the head to point to the new node */
(*head_ref) = new_node;
}
思路:
建立三个结点, pre, cur, rear,分别对应链表里的三个点,比如,==1->2->3->4->nul==, 当然,在
结点1前面还有head头指针,那么,初始化就是pre指向1, cur指向2,rear指向3.这三者之间的关系对应好之后,立马将cur的指针指向pre,==并将pre传递给cur==,这一句话非常重要,我自己经常搞混,然后,rear立即传递给cur,保证下次的循环,直至到cur == NULL。此时pre作为最后一个节点,head -> next = null
是保证此时生产新的链表具有尾指针, head = pre
成功地将头结点给head.具体代码请参考下面的代码。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverseList(struct ListNode* head) {
struct ListNode *pre, *cur, *rear;
if(head == NULL || head->next == NULL)
return head;
pre = head;
cur = head->next;
while(cur){
rear = cur->next;
cur->next = pre;
pre = cur;
cur = rear;
}
head -> next = NULL;
head = pre;
return head;
}
题目 Write a program to find the node at which the intersection of two singly linked lists begins.
Notes:
解释说明这个算法题目不是很清晰,是这样的,intersection是指两个链表的起始部分到终点位置一直相等才可以,如果有一个不同则不符合题目要求,比如: A链==1->2->3->4->5->NULL==,B链==3->4->5->null==,那么==3->4->5==即可满足,但是,如果B链为==3->4->6==则不符合要求。也就是从起始部分到末尾一直都相同才行。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
struct ListNode *p1, *p2;
if(headA == NULL || headB == NULL)
return NULL;
int len1 = 0, len2 = 0;
p1 = headA, p2 = headB;
while(p1->next != NULL){
len1++;
p1 = p1->next;
}
while(p2->next != NULL){
len2++;
p2 = p2->next;
}
p1 = headA, p2 = headB;
if(len1 > len2){
p1 = headA;
p2 = headB;
}else{
p1 = headB;
p2 = headA;
} /* 调整链表 */
int diff = abs(len1 - len2);
while(diff){
p1 = p1->next;
diff--;
}
while(p1 != p2){
p1 = p1->next;
p2 = p2->next;
}
return p1;
}
上面的代码显而易见,将长链赋给指针p1,p1自增,然后一一对比,直到结点相等,如果结点不同,会一直延顺到末尾,直接返回NULL.
利用上面已知的条件,还可以使用环形的概念。两条链同时遍历,如果已遍历完短链,此时将短链的头指针赋值给长链对应的元素,此时相同的话就相同了,如果首个元素不同,继续上面的步骤。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
struct ListNode *p1, *p2;
if(headA == NULL || headB == NULL)
return NULL;
p1 = headA;
p2 = headB;
while(p1 != p2){
if(p1 != NULL)
p1 = p1->next;
else
p1 = headB;
if(p2 != NULL)
p2 = p2->next;
else
p2 = headA;
}
return p1;
}
效率只能说符合题目要求,但是还没有爆机,还得找。
leetcode 很简单的一个问题,就是将一个排序好的链表中重复的结点去除掉,注意头结点的问题。
struct ListNode* deleteDuplicates(struct ListNode* head) {
struct ListNode *p = head, *q, *r;
if(p == NULL)
return head;
while(p){
for(r = p, q = p->next; q != NULL; q = q->next){
if(q->val == p->val){
r->next = q->next;
free(q);
q = r;
}
else
r = r->next;
}
p = p->next;
}
return head;
}
删除节点的题目无论在计算机工作面试中还是计算机考研中,这方面的题目还是非常多的,今天的这道题目是这样的,删除给定链表的指定数据,这和删除指定位置的数据是不一样的。比如,1->2->4->6->5->6删除6,则为1->2->4->5,这道题如果使用普通的删除节点的,是有些复杂的。下面的代码是可以达到这个目的的,有些不一样,你能看的懂吗?
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeElements(struct ListNode* head, int val) {
struct ListNode *dump = (struct ListNode*)malloc(sizeof(struct ListNode));
dump->next = head;
struct ListNode *pre = dump;
struct ListNode *cur = head;
while(cur){
if(cur->val == val){
pre->next = cur->next;
}
else {
pre = cur;
}
cur = cur->next;
}
return dump->next;
}
这一部分是简单题目,初次可以写的乱一些。没有仔细考虑,有错误还望指正。
下面第一个程序太臃肿,还不好理解,可以参考第二种方案。
程序一:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
/* 求 10! + 9! + .. + 1! = ? */
int main()
{
int i,j;
int factorial = 1, sum = 0;
int temp = 1;
for (i = 1; i <= 10; i++){
sum += temp;
for(j = 10 - i + 1; j >= 1; j--){
factorial = j * factorial;
}
temp = factorial;
printf("the %dth factorial is %d\n", i, factorial);
factorial = 1;
}
printf("The sum of 1! + 2! + 3! +...+ 10!=%d\n", sum);
}
程序二:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
int i,j,sum = 0, c = 1;
for(i = 1; i <= 10; i++){
c = i * c;
sum = sum + c;
}
printf("1! + 2! + 3! + ...+ 10!= %d\n",sum);
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
/* 输入n 个 a, 计算 a + aa + aaa + ... + aaaaaa(n个a) = ? , 此时n = 6*/
int main()
{
int n, a;
printf("请输入n 和a的值:\n");
scanf("%d %d", &n, &a);
int i, j, sum = 0, per_sum = 0;
for(j = n; j > 0; j--){
/* 下面这个for循环只是运行了最后一个的数字,比如3333,前面的没有算进来 */
per_sum = 0;
for(i = j; i >= 1; i--){
per_sum += a*pow(10, i-1);
// printf("The %dth sum is %d\n", i, per_sum);
}
sum += per_sum;
// printf("the a + aa +...+ = %d\n",sum);
}
printf("the a + aa +...+ = %d\n", sum);
}
甲队为a b c,乙队为x, y, z,且a不与x比, c不和x,y比,求可能的比赛名单。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
/* a 的ascii码是97 x 是120 ...*/
int main()
{
int a = 97, x = 120;
for(a = 97; a <= 99; a++){
for(x = 120; x <= 122; x++){
if(a == 97 && x == 120) continue;
if(a == 99 && x == 120) continue;
if(a == 99 && x == 121) continue;
printf("对阵的双方可以%c VS %c\n", a, x);
}
printf("\n");
}
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
/*由于教材的编排原因,这个时候还没有学习数组,故使用p80页的二大题
* 第一小题的例子
*/
/* 这里的技巧就是通过判断输入的字符是否为特定字符从而结束判断,比如'\n' */
int main()
{
int zimu = 0, spaces = 0, nums = 0, others = 0;
char c;
printf("请输入一串字符串,以换行结尾\n");
c = getchar();
while(c != '\n'){
if(c >= 65 && c <= 90 || c >= 97 && c <= 122){
/* 字母在A-Z, a-z之间*/
zimu++;
} else if(c == ' ')
spaces++;
else if (c >= 48 && c <= 57)
nums++;
else
others++;
c = getchar();
}
printf("统计情况如下:字母:%d 空格: %d, 数字: %d 其他: %d\n", zimu, spaces, nums, others);
}
输入p,q值, q>0, p>0,试分析能否分解,比如,x^2+5x+6=0(p=5, q=6),问能否分解。
int main()
{
int p,q;// p > 0, q >0
int a, b;
int flag = 0; // 标志变量
scanf("%d %d", &p, &q);
for(a = 1; a < sqrt(q); a++){
if(q % a == 0){
b = q/a;
if(a + b == p){
flag = 1;
break;
}
}
}
if(flag)
printf("p,q 可以分解,其两个根分别为x1=-%d,x2=-%d\n", a, b);
else
printf("不可以分解\n");
}