把数组的前k位逆置:递归算法和迭代算法

把数组的前k位逆置 /* * 逆置数组arr的前k位: * (1)递归实现 * (2)迭代实现 * PS.通常递归算法能解决一些不能直接解决的问题, * 但是递归算法通常要做出效率上的牺牲 * By Guv 2011.06.04 * */ #include <stdio.h> /*递归实现*/ void invert(int arr[], int k) { if(k>1){ invert(arr+1,k-2); int tmp = arr[0]; arr[0] = arr[k-1]; arr[k-1] = tmp; } } /*迭代*/ /* void invert(int arr[], int k) { int tmp=0, mid = k/2; if (k<2) return; for(int i=0;i<mid;++i){ tmp = arr[i]; arr[i] = arr[k-1-i]; arr[k-1-i] = tmp; } } */ /*testing*/ int main() { int array[] = {1,2,5,9,8,7,6,3,5,6,7,8,9,5,6,4,1,5,2,6,3,5}; int num = sizeof(array)/sizeof(int); printf("before inverted:"); for(int i=0;i<num;++i){ if (i%5==0) printf("\n"); printf("%d, ", array[i]); } invert(array, num); printf("\nafter inverted:"); for(int i=0;i<num;++i){ if (i%5==0) printf("\n"); printf("%d, ", array[i]); } }

2015年3月19日 · 1 分钟 · Jid

使用 Google Analytics 追踪 404 页面

为什么追踪 404 404 页面意味着用户访问了不存在的 URL。追踪这些请求可以: 发现损坏的内部链接 了解用户想找什么内容(可能值得补充) 找到哪些外部网站链到了你已删除的页面 实现方法 在 404 页面的 Google Analytics 追踪代码中,将页面路径改为包含请求 URL 的自定义路径: 新版 GA(gtag.js): <script> gtag('config', 'GA_MEASUREMENT_ID', { page_path: '/404?page=' + document.location.pathname + document.location.search + '&from=' + document.referrer }); </script> 旧版 GA(analytics.js): <script> ga('send', 'pageview', '/404?page=' + document.location.pathname + document.location.search + '&from=' + document.referrer); </script> 查看报告 在 Google Analytics 中查看 行为 → 网站内容 → 所有页面,搜索 /404,即可看到: 哪些 URL 触发了 404 来源页面(from 参数) 访问频率和趋势 根据这些信息修复损坏链接或补充缺失内容。 参考:月光博客

2015年3月19日 · 1 分钟 · Jid

用C语言实现简单的链式栈结构

C语言实现简单的链式栈结构 /* * 用链式存储结构实现的栈称为链栈。若链栈元素的数据类型为valuetype,以LinkStack记链栈结构,其类型定义为: * typedef struct node * { * valuetype data; * struct node * next; * } StackNode, *LinkStack; * * 由于栈的主要操作都是在栈顶进行的,因此把链表的头部作为栈顶。设top为栈顶指针,即:LinkStack top. * 下面为各函数的功能说明: * (1)LinkStack Init_LinkStack() : 建立并返回空的链栈 * (2)int Empty_LinkStack(LinkStack top) : 判断top所指链栈是否为空 * (3)LinkStack Push_LinkStack(LinkStack top, valuetype x) : 将数据x压入top所指的栈顶,并返回新栈指针 * (4)LinkStack Pop_LinkStack(LinkStack top, valuetype *x) : 弹出top所指链栈的栈顶元素x,返回新栈指针 * */ #include <stdio.h> #include <malloc.h> typedef int valuetype; typedef struct node { valuetype data; struct node * next; } StackNode, *LinkStack; LinkStack Init_LinkStack() { return NULL; } int Empty_LinkStack(LinkStack top) { if (top==NULL) return 1; else return 0; } LinkStack Push_LinkStack(LinkStack top, valuetype x) { StackNode *s = (StackNode *)malloc(sizeof(StackNode)); s->data = x; s->next = top; return s; } LinkStack Pop_LinkStack(LinkStack top, valuetype *x) { StackNode *p; if (top==NULL) return NULL; else { *x = top->data; p = top->next; free(top); return p; } } int main() { LinkStack linkstack = Init_LinkStack(); int i=0; int x=0; for (i=0;i<10;++i) { linkstack = Push_LinkStack(linkstack, i); } while(linkstack) { linkstack = Pop_LinkStack(linkstack, &x); printf("%d ",x); } printf("\n"); }

2015年3月18日 · 1 分钟 · Jid

cppman:在终端查看 C++ 文档的利器

简介 cppman 从 cplusplus.com 抓取 C++ 标准库文档,以 man page 格式在终端中展示。比 libstdc++ 文档更方便,是 C++ 程序员的效率工具。 安装(Ubuntu) # 1. 添加 PPA 源 sudo add-apt-repository ppa:aitjcize/manpages-cpp sudo apt-get update # 2. 安装 sudo apt-get install manpages-cpp # 3. 缓存文档数据(首次需要,耗时较长) cppman -c 使用 # 查询标准库组件 cppman cout cppman vector cppman string cppman iterator # 查看 STL 算法 cppman sort cppman find_if # 更新缓存 cppman -u 为什么推荐 直接按名称查询:不用记 std:: 前缀,cppman cout 即可 格式统一:和 man 命令一样的阅读体验 离线可用:缓存后无需联网

2015年3月17日 · 1 分钟 · Jid

C++ man pages 的使用方法

前提:已安装 C++ man pages,参见上篇。 问题 man cout 提示 No manual entry for cout,无法直接查询 C++ 标准库函数。 解决方法 C++ man pages 按命名空间和头文件组织,查询格式为: man 命名空间::头文件名 示例 # 查询 cout —— 属于 std 命名空间,定义在 iostream 中 man std::iostream # 打开后按 /cout 搜索 # 查询 slist —— 属于 __gnu_cxx 命名空间 man __gnu_cxx::slist # 查询 vector man std::vector 与 C 语言 man pages 的对比 操作 C 语言 C++ 查询 printf man 3 printf — 查询 cout — man std::iostream 后搜索 章节指定 man 2 open(系统调用) man std::vector 直接按函数名查 ✅ ❌ 需要知道所属头文件 注意:C++ man pages 由 Doxygen 生成,描述可能不如 C 的 man pages 详细。 ...

2015年3月16日 · 1 分钟 · Jid

Linux 安装 C++ man pages

本篇介绍在ubuntu上安装C++在线文档(man pages),下篇将介绍C++在线文档的使用。需要注意的一点是:在这里的方法有别于通常的 man func_name,因此需要单独说明,以免安装后也不知道怎么用。 另外,为了达到最好的使用效果,请首先把C的开发文档提前安装上吧,命令: sudo apt-get update sudo apt-get install manpages-dev glibc-doc 然后安装C++的开发文档,命令通常是 sudo apt-get install libstdc++6-4.4-doc 上面的4.4是gcc的版本,可以是4.2、4.3、4.4, 4.4是最新的。至于软件库中有无4.4,请参见下文的说明,使用命令查询: apt-cache search libstdc++|grep "doc" 以决定安装4.2、4.3或4.4 下面是英文原文: It’s so easy to search for any C related programming functions. All you need is to search the man pages. Take for example, if you want to know more about printf, simply type `$ man 2 printf` But that’s not the case with C++ functions. Every time, you have to go to the web for any doubts related to C++ functions. There are two ways by which you can search for documentation related to C++ functions. Man pages for C++ functions HTML documentation Both of the above are available from a single package. To install C++ documentation `$ sudo apt-get install libstdc++6-4.4-doc` This installs both the man pages and HTML documentation. The HTML documentation is found in the following path:file:///usr/share/doc/libstdc++6-4.4-doc/libstdc++/html/index.html If you are struggling to search C++ man pages, ReferHow to search C++ man pages Now there may be case that when you are referring this article the documentation 6.4.4 version is no longer available. In that case, follow the following steps `$ apt-cache search libstdc++|grep"doc"` libstdc++6-4.4-doc - The GNU Standard C++ Library v3 (documentation files)libstdc++6-4.1-doc - The GNU Standard C++ Library v3 (documentation files)libstdc++6-4.3-doc - The GNU Standard C++ Library v3 (documentation files) Search for the libstdc++ docs as shown above and install the version you want, preferably the latest ones (as shown above) `$ sudo apt-get install libstdc++6-4.4-doc`

2015年3月15日 · 2 分钟 · Jid

C 语言实现单向链表

实现一个简单的单向链表,包含头插法、逆序复制、遍历打印和释放操作。 代码 #include <stdio.h> #include <stdlib.h> typedef struct node { int val; struct node *next; } NODE; /* 头插法:在链表头部插入新节点 */ void first_insert(NODE **head, int v) { NODE *q = malloc(sizeof(NODE)); q->val = v; q->next = *head; *head = q; } /* 逆序复制链表,返回新链表头 */ NODE *reverse_copy(NODE *p) { NODE *new_list = NULL; for (; p != NULL; p = p->next) first_insert(&new_list, p->val); return new_list; } /* 遍历打印 */ void print_link(NODE *p) { for (; p != NULL; p = p->next) printf("%d ", p->val); printf("\n"); } /* 释放整个链表 */ void free_link(NODE *p) { while (p != NULL) { NODE *next = p->next; free(p); p = next; } } int main(void) { NODE *list1 = NULL, *list2; /* 构建链表:9 8 7 6 5 4 3 2 1(头插法导致逆序) */ for (int i = 1; i < 10; i++) first_insert(&list1, i); list2 = reverse_copy(list1); /* 1 2 3 4 5 6 7 8 9 */ print_link(list1); print_link(list2); free_link(list1); free_link(list2); return 0; } 关键点 头插法(first_insert):新节点插到链表头部,时间复杂度 O(1) 逆序复制:利用头插法的特性——正序遍历原链表、头插到新链表,自然得到逆序 释放链表:先保存 next 指针再 free 当前节点,避免访问已释放内存

2015年3月14日 · 1 分钟 · Jid

C 语言实现 Linux cat 命令

用 C 语言模拟实现 Linux 的 cat 命令,支持查看单个或多个文件内容。 代码实现 /* * 模拟 Linux cat 命令 * 用法:./mycat file1 [file2 ...] */ #include <stdio.h> #include <stdlib.h> /* 将文件内容复制到输出流 */ void file_copy(FILE *in, FILE *out) { int c; while ((c = getc(in)) != EOF) putc(c, out); } int main(int argc, char *argv[]) { FILE *fp; if (argc == 1) { /* 无参数时,从标准输入读取(与 cat 行为一致) */ file_copy(stdin, stdout); } else { while (--argc > 0) { if ((fp = fopen(*++argv, "r")) == NULL) { fprintf(stderr, "cat: %s: 无法打开文件\n", *argv); return 1; } file_copy(fp, stdout); fclose(fp); } } return 0; } 要点 getc / putc 逐字符读写,适合小文件;大文件建议用 fread / fwrite 按块读写 argc == 1 时从 stdin 读取,使程序支持管道:echo hello | ./mycat 错误信息输出到 stderr,不会混入正常输出 编译运行 gcc -o mycat mycat.c ./mycat file1.txt file2.txt

2015年3月13日 · 1 分钟 · Jid

Shell编程:bash内部命令

bash命令解释套装程序包含了一些内部命令。内部命令在目录列表时是看不见的,它们由Shell本身提供。常用的内部命令有:echo, eval, exec, export, readonly, read, shift, wait和点(.)。下面简单介绍其命令格式和功能。 1.echo 命令格式:echo arg 功能:在屏幕上显示出由arg指定的字串。 2.eval 命令格式:eval args 功能:当Shell程序执行到eval语句时,Shell读入参数args,并将它们组合成一个新的命令,然后执行。 3.exec 命令格式:exec命令参数 功能:当Shell执行到exec语句时,不会去创建新的子进程,而是转去执行指定的命令,当指定的命令执行完时,该进程(也就是最初的Shell)就终止了,所以Shell程序中exec后面的语句将不再被执行。 4.export 命令格式:export变量名 或:export变量名=变量值 功能:Shell可以用export把它的变量向下带入子Shell,从而让子进程继承父进程中的环境变量。但子Shell不能用export把它的变量向上带入父Shell。 注意:不带任何变量名的export语句将显示出当前所有的export变量。 5.readonly 命令格式:readonly变量名 功能:将一个用户定义的Shell变量标识为不可变。不带任何参数的readonly命令将显示出所有只读的Shell变量。 6.read 命令格式:read变量名表 功能:从标准输入设备读入一行,分解成若干字,赋值给Shell程序内部定义的变量。 7.shift语句 功能:shift语句按如下方式重新命名所有的位置参数变量,即$2成为$1,$3成为$2…在程序中每使用一次shift语句,都使所有的位置参数依次向左移动一个位并使位置参数$#减1,直到减到0为止。 8.wait 功能:使Shell等待在后台启动的所有子进程结束。wait的返回值总是真。 9.exit 功能:退出Shell程序。在exit之后可有选择地指定一个数位作为返回状态。 10.“.”(点) 命令格式:. Shell程序文件名 功能:使Shell读入指定的Shell程序文件并依次执行文件中的所有语句。

2015年3月12日 · 1 分钟 · Jid

值得阅读源码的开源项目推荐

学习优秀的代码风格和架构设计,是提升编程能力的有效途径。以下是几个代码质量高、适合阅读学习的开源项目: C 语言项目 项目 特点 适合学习 nginx 高性能 Web 服务器 事件驱动架构、内存池、模块化设计 Linux Kernel 操作系统内核 数据结构、并发控制、底层编程 SQLite 嵌入式数据库 SQL 解析、B 树实现、事务管理 Redis 内存数据库 数据结构、网络编程、单线程高性能 mxml 小型 XML 解析库 代码精简、接口设计 lighttpd 轻量 Web 服务器 网络编程、事件处理 C++ 项目 项目 特点 适合学习 LLVM 编译器基础设施 现代 C++、编译原理、架构设计 Chromium 浏览器引擎 大型项目组织、多进程架构 阅读建议 从小项目开始(mxml、lighttpd),再读大项目 先理解整体架构,再深入具体模块 带着问题读代码:它怎么解决某个问题的?

2015年3月11日 · 1 分钟 · Jid