#
晚上在跟同事聊到字符串匹配的时候,同事提到了矩阵,觉着是个很牛的东西,它的结果如果出现连续的斜线的话,则说明有匹配了,这可以用于做快速搜索,而且也可以搜索最大公共字符串。据说有个很牛的算法专门用来做“最大公共字符串”的,但我还没去找,先将这个矩阵输出试试。
本程序提供两种输出方式,以参数-w和-wo进行区分,分别用于显示人眼识别的信息,以及可供后续程序进行处理的纯净信息。本程序同时提供通用的帮助查看方式,参数为-h或/?等。
通过矩阵,我们就很容易得出最大匹配结果。至于如何分析,暂时还没有做考虑,有空会进行分析。
// max_match.cpp : 定义控制台应用程序的入口点。
//
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define BOOL int
#define TRUE 1
#define FALSE 0
typedef char element_t;
#define ele_space ' '
#define ele_break '\n'
#define ele_placeholder '*'
#define ele_end '\0'
element_t *malloc_space(element_t* str1, element_t* str2, BOOL with_illuminate);
element_t *max_match_matrix(element_t* str1, element_t* str2, BOOL with_illuminate, element_t *matrix);
/*display the help informations*/
void man_this(void);
/*
purpose:
Generate a matrix for max match with str1 & str2.
e.g:
str1 = "abcdefghijk";
str2 = "define";
The str2 with the same substring "def" in str1.
Show the relationship between the two string by matrix.
You can use the pipe for dealing with the result.
invoke:
max_match {options} str1 str2
options:
@-w(default): Display the result infomations for view.
@ --with_illuminate: The same function as option -w;
@-wo: Don't display the result infomations for view.
@ --without_illuminate: The same function as option -wo;
@-h: Display the help info for users.
@ --help: The same function as option -h;
@ /h: The same function as option -h;
@ /help: The same function as option -h;
@ /?: The same function as option -h;
@ -?: The same function as option -h;
*/
int main(int argc, char* argv[])
{
char *str1, *str2;
BOOL with_illuminate = TRUE;
if(argc == 3)
{
str1 = argv[1];
str2 = argv[2];
}
else if(argc == 4)
{
if(strcmp(argv[1], "-w") == 0 || strcmp(argv[1], "--with_illuminate") == 0)
with_illuminate = TRUE;
else if(strcmp(argv[1], "-wo") == 0 || strcmp(argv[1], "--without_illuminate") == 0)
with_illuminate = FALSE;
else
{
printf("ERROR: error paramaters in!\n");
return -2;
}
str1 = argv[2];
str2 = argv[3];
}
else if(argc == 2)
{
if(strcmp(argv[1], "-h") == 0
|| strcmp(argv[1], "/h") == 0
|| strcmp(argv[1], "--help") == 0
|| strcmp(argv[1], "/help") == 0
|| strcmp(argv[1], "/?") == 0
|| strcmp(argv[1], "-?") == 0)
{
man_this();
return 0;
}
}
else
{
printf("ERROR: No enough paramaters!\n");
return -1;
}
if(with_illuminate)
{
printf("str1:\t|%s\n", str1);
printf("str2:\t|%s\n", str2);
printf("\nresult:\n");
}
element_t *matrix = malloc_space(str1, str2, with_illuminate);
printf("%s", max_match_matrix(str1, str2, with_illuminate, matrix));
free(matrix);
return 0;
}
element_t *max_match_matrix(element_t* str1, element_t* str2, BOOL with_illuminate, element_t *matrix)
{
int curr = with_illuminate ? 0 : -1;
if(with_illuminate)
{
matrix[curr] = ele_space;
int i = -1;
while(str1[++i] != ele_end)
{
matrix[++curr] = str1[i];
}
matrix[++curr] = ele_break;
}
int j = -1;
while(str2[++j] != ele_end)
{
if(with_illuminate) matrix[++curr] = str2[j];
int z = -1;
while(str1[++z] != ele_end)
{
if(str1[z] == str2[j])
matrix[++curr] = ele_placeholder;
else
matrix[++curr] = ele_space;
}
matrix[++curr] = ele_break;
}
matrix[++curr] = ele_end;
return matrix;
}
element_t *malloc_space(element_t* str1, element_t* str2, BOOL with_illuminate)
{
int len1 = strlen(str1);
int len2 = strlen(str2);
int len = 0;
if(with_illuminate)
len = (len1 + 2) * (len2 + 1) + 1;
else
len = (len1 + 1) * len2 + 1;
element_t* result;
if((result = (element_t*)malloc((size_t)(len * sizeof(element_t)))) == NULL)
{
printf("ERROR: No enough space!");
return NULL;
}
return result;
}
void man_this(void)
{
printf("%s", "purpose:\n");
printf("%s", " Generate a matrix for max match with str1 & str2.\n");
printf("%s", " e.g:\n");
printf("%s", " str1 = \"abcdefghijk\";\n");
printf("%s", " str2 = \"define\";\n");
printf("%s", " The str2 with the same substring \"def\" in str1.\n");
printf("%s", " Show the relationship between the two string by matrix.\n");
printf("%s", " You can use the pipe for dealing with the result.\n");
printf("%s", "invoke:\n");
printf("%s", " max_match {options} str1 str2\n");
printf("%s", "options:\n");
printf("%s", " @-w(default): Display the result infomations for view.\n");
printf("%s", " @ --with_illuminate: The same function as option -w;\n");
printf("%s", " @-wo: Don't display the result infomations for view.\n");
printf("%s", " @ --without_illuminate: The same function as option -wo;\n");
printf("%s", " @-h: Display the help info for users.\n");
printf("%s", " @ --help: The same function as option -h;\n");
printf("%s", " @ /h: The same function as option -h;\n");
printf("%s", " @ /help: The same function as option -h;\n");
printf("%s", " @ /?: The same function as option -h;\n");
printf("%s", " @ -?: The same function as option -h;\n");
}
Copy from “Computer Systems A Programmer’s Perspective(CS:APP)” P12
The 1960s was an era of huge, complex operating systems, such as IBM’s OS/360 and Honeywell’sMultics systems.
While OS/360 was one of the most successful software projects in history, Multics dragged on for years and never
achieved wide-scale use. Bell Laboratories was an original partner in the Multics project, but dropped out in 1969
because of concern over the complexity of the project and the lack of progress. In reaction to their unpleasant
Multics experience, a group of Bell Labs researchers — Ken Thompson, Dennis Ritchie, Doug McIlroy, and Joe
Ossanna — began work in 1969 on a simpler operating system for a DEC PDP-7 computer, written entirely in
machine language. Many of the ideas in the new system, such as the hierarchical file system and the notion of a
shell as a user-level process, were borrowed from Multics, but implemented in a smaller, simpler package. In 1970,
Brian Kernighan dubbed the new system “Unix” as a pun on the complexity of “Multics.” The kernel was rewritten
in C in 1973, and Unix was announced to the outside world in 1974 [61].
Because Bell Labs made the source code available to schools with generous terms, Unix developed a large following
at universities. The most influential work was done at the University of California at Berkeley in the late 1970s and
early 1980s, with Berkeley researchers adding virtual memory and the Internet protocols in a series of releases called
Unix 4.xBSD (Berkeley Software Distribution). Concurrently, Bell Labs was releasing their own versions, which
become known as System V Unix. Versions from other vendors, such as the Sun Microsystems Solaris system, were
derived from these original BSD and System V versions.
Trouble arose in the mid 1980s as Unix vendors tried to differentiate themselves by adding new and often incompatible
features. To combat this trend, IEEE (Institute for Electrical and Electronics Engineers) sponsored an effort
to standardize Unix, later dubbed “Posix” by Richard Stallman. The result was a family of standards, known as
the Posix standards, that cover such issues as the C language interface for Unix system calls, shell programs and
utilities, threads, and network programming. As more systems comply more fully with the Posix standards, the
differences between Unix version are gradually disappearing. End Aside.
将Fedora10升级至Fedora11(试验性的)
只能从Fedora10升级到Fedora11。更早的版本则需要先升级至Fedora10。RPM格式已经为Fedora11做了改变,因此首先必须升级旧的rpmlib。否则进程将出现rpmlib(FileDigests)依赖问题。对新格式的支持已经是Fedora10升级的一部分了。
yum update rpm
Fedora 10 -> Fedora 11 (tentative)
阅读全文
- New
initrd
built when installing a new kernel while running Fedora 10 might fail. To solve that boot with an old kernel (to get the new userspace) and (re)install the new kernel. - Systems with PAE support (indicated by
pae
in /proc/cpuinfo
) should use kernel-PAE.i686
. The new kernel must be changed/installed manually: Set DEFAULTKERNEL=kernel-PAE
in /etc/sysconfig/kernel
and yum install kernel-PAE
. Refer to Dave Jones' blog post for details. - The yum update step should NOT be run inside a gnome desktop session/gnome-terminal.
- REDIRECT Archive:Template:Bz could result in a unusable install when gnome-terminal segfaults during the upgrade. Update should be run in a vty, runlevel 3, or a screen session.
- fedora-release-11-1.noarch changes the yum mirrorlist URL so that it uses a "metalink", but the version of yum currently in F10 doesn't understand this syntax, leading to yum downloads failing with this error message:
YumRepo Error: All mirror URLs are not using ftp, http[s] or file.
Eg. </metalink>/
This is RHBZ #498720. Workaround is to manually edit the URL in /etc/yum.repos.d/fedora.repo as described at https://www.redhat.com/archives/fedora-list/2009-June/msg00783.html
- Some packages in Fedora 10 are regarded as newer than those supplied by Fedora 11 and its updates repository. These include ntpd, ntpdate (RHBZ #506040, RHBZ #504980), unique, unique-devel, eclipse-changelog, eclipse-svnkit and svnkit. You may wish to remove these before performing the upgrade, then reinstall them afterwards. Doing so may require
--nodeps
.
- Some i386 packages in Fedora 10 are replaced with i586, i686 or x86_64 packages in Fedora 11. These include gpm.i386, glibc-2.9-3.i386. You may wish to remove these before performing the upgrade, then reinstall them afterwards. Doing so may require
--nodeps
.
- mplayer-1.0-0.104.20090204svn.fc10 from the RPM Fusion repository has a dependency on libfaad.so.0 that the depsolve doesn't find, but rpm_check_debug does. You may wish to remove mplayer before performing the upgrade, then reinstall them afterwards. Doing so may require
--nodeps
.
C:\Documents and Settings\a>help subst
Associates a path with a drive letter.
SUBST [drive1: [drive2:]path]
SUBST drive1: /D
drive1: Specifies a virtual drive to which you want to assign a path.
[drive2:]path Specifies a physical drive and path you want to assign to
a virtual drive.
/D Deletes a substituted (virtual) drive.
Type SUBST with no parameters to display a list of current virtual drives.
可以将一个文件夹虚拟成一个驱动器。
记录一下。
这个问题源自对'\0',0,以及NULL的探究!
先看看标题所提到的内容:
根据https://research.microsoft.com/en-us/um/redmond/projects/invisible/include/__defs.h.htm文档中的定义:
#if !defined(NULL) && defined(__NEEDS_NULL)
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
在C和C++中,分别是由(void*)0和0来表示的。
而'\0'是ASCII中的值,ASCII中它的值就是0。
所以它们三者是相同的。
参考资料:
https://research.microsoft.com/en-us/um/redmond/projects/invisible/include/__defs.h.htm
在探究的过程中找到下面的一个帖子。很是不错,COPY如下。
转载自:http://blog.chinaunix.net/u/18517/showart_309917.html
帖子里讨论了C语言中的空指针、空指针常量、NULL、0等概念及相互关系及区别。这里摘录whyglinux兄的总结。做个标签,呵呵^_^
- 什么是空指针常量(null pointer constant)?
[6.3.2.3-3] An integer constant
expression with the value 0, or such an expression cast to type void *, is
called a null pointer constant.
这里告诉我们:0、0L、'\0'、3 - 3、0 * 17
(它们都是“integer constant expression”)以及 (void*)0 (tyc:
我觉得(void*)0应该算是一个空指针吧,更恰当一点)等都是空指针常量(注意 (char*) 0 不叫空指针常量,只是一个空指针值)。至于系统选取哪种形式作为空指针常量使用,则是实现相关的。一般的 C 系统选择 (void*)0 或者 0
的居多(也有个别的选择 0L);至于 C++ 系统,由于存在严格的类型转化的要求,void* 不能象 C 中那样自由转换为其它指针类型,所以通常选 0
作为空指针常量(tyc: C++标准推荐),而不选择 (void*)0。
- 什么是空指针(null pointer)?
[6.3.2.3-3] If a null pointer constant is
converted to a pointer type, the resulting pointer, called a null pointer, is
guaranteed to compare unequal to a pointer to any object or
function.
因此,如果 p 是一个指针变量,则 p = 0;、p = 0L;、p = '\0';、p = 3 - 3;、p = 0 *
17; 中的任何一种赋值操作之后(对于 C 来说还可以是 p = (void*)0;), p 都成为一个空指针,由系统保证空指针不指向任何实际的对象或者函数。反过来说,任何对象或者函数的地址都不可能是空指针。(tyc: 比如这里的(void*)0就是一个空指针。把它理解为null pointer还是null pointer
constant会有微秒的不同,当然也不是紧要了)
- 什么是 NULL?
[6.3.2.3-Footnote] The macro NULL is defined in
<stddef.h> (and other headers) as a null pointer constant
即 NULL 是一个标准规定的宏定义,用来表示空指针常量。因此,除了上面的各种赋值方式之外,还可以用 p =
NULL; 来使 p 成为一个空指针。(tyc:很多系统中的实现:#define NULL
(void*)0,与这里的“a null pointer constant”并不是完全一致的)
- 空指针(null
pointer)指向了内存的什么地方(空指针的内部实现)?
标准并没有对空指针指向内存中的什么地方这一个问题作出规定,也就是说用哪个具体的地址值(0x0
地址还是某一特定地址)表示空指针取决于系统的实现。我们常见的空指针一般指向 0 地址,即空指针的内部用全 0 来表示(zero null
pointer,零空指针);也有一些系统用一些特殊的地址值或者特殊的方式表示空指针(nonzero null pointer,非零空指针),具体请参见C
FAQ。
幸运的是,在实际编程中不需要了解在我们的系统上空指针到底是一个 zero null pointer 还是
nonzero null pointer,我们只需要了解一个指针是否是空指针就可以了——编译器会自动实现其中的转换,为我们屏蔽其中的实现细节。注意:不要把空指针的内部表示等同于整数
0 的对象表示——如上所述,有时它们是不同的。
- 如何判断一个指针是否是一个空指针?
这可以通过与空指针常量或者其它的空指针的比较来实现(注意与空指针的内部表示无关)。例如,假设
p 是一个指针变量,q 是一个同类型的空指针,要检查 p
是否是一个空指针,可以采用下列任意形式之一——它们在实现的功能上都是等价的,所不同的只是风格的差别。
指针变量 p
是空指针的判断:
if ( p == 0 )
if ( p == '\0' )
if (
p == 3 - 3 )
if ( p == NULL ) /* 使用 NULL
必须包含相应的标准库的头文件 */
if ( NULL == p )
if ( !p )
if ( p == q
)
...
指针变量 p 不是空指针的判断:
if ( p != 0 )
if ( p != '\0' )
if ( p
!= 3 - 3 )
if ( p != NULL ) /* 使用 NULL 必须包含相应的标准库的头文件 */
if ( NULL != p
)
if ( p )
if ( p != q )
...
- 可以用 memset 函数来得到一个空指针吗?
这个问题等同于:如果 p 是一个指针变量,那么
memset(
&p, 0, sizeof(p) ); 和 p =
0;
是等价的吗?
答案是否定的,虽然在大多数系统上是等价的,但是因为有的系统存在着“非零空指针” (nonzero null
pointer),所以这时两者不等价。由于这个原因,要注意当想将指针设置为空指针的时候不应该使用
memset,而应该用空指针常量或空指针对指针变量赋值或者初始化的方法。
- 可以定义自己的 NULL 的实现吗?兼答"NULL 的值可以是 1、2、3 等值吗?"类似问题
[7.1.3-2] If the
program declares or defines an identifier in a context in which it is reserved
(other than as allowed by 7.1.4), or defines a reserved identifier as a macro
name, the behavior is undefined.
NULL 是标准库中的一个符合上述条件的 reserved identifier
(保留标识符)。所以,如果包含了相应的标准头文件而引入了 NULL 的话,则再在程序中重新定义 NULL
为不同的内容是非法的,其行为是未定义的。也就是说,如果是符合标准的程序,其 NULL 的值只能是 0,不可能是除 0 之外的其它值,比如 1、2、3
等。
- malloc 函数在分配内存失败时返回 0 还是 NULL?
malloc 函数是标准 C
规定的库函数。在标准中明确规定了在其内存分配失败时返回的是一个 “null pointer”(空指针):
[7.20.3-1] If the
space cannot be allocated, a null pointer is returned.
对于空指针值,一般的文档(比如
man)中倾向于用 NULL 表示,而没有直接说成 0。但是我们应该清楚:对于指针类型来说,返回 NULL 和 返回 0 是完全等价的,因为 NULL 和 0
都表示 “null pointer”(空指针)。(tyc:一般系统中手册中都返回NULL,那我们就用NULL吧)
另外,附C FAQ上关于null pointer的解释:C FAQ:null pointer
#include <stdio.h>
#include <stdlib.h>
int main(void){
int MB = 0;
while(malloc(1 << 20))
++MB;
printf("Allocated %d MB total\n", MB);
return EXIT_SUCCESS;
}
原理,因为2的20次方就是1MB(2的10次方为1KB,2的30次方为1GB,以此类推)。
如果你请求分配的内存块小于1MB,你得到的内存是否比这要多一些呢?为什么?
答:
这不是绝对的!
在本例中使用
1<<22(4MB)得到的结果乘4是2000MB
1<<21(2MB)得到的结果乘2是1972MB
1<<20(1MB)得到的结果是1918MB
1<<19(0.5MB)得到的结果除2是1812MB
1<<18(0.25MB)得到的结果除4是2003MB
1<<17(0.125MB)得到的结果除8是2034MB
显然出现了一个意外的结果。
#include <stdio.h>
#include <stdlib.h>
char * favorite_fruit1(void);
char * favorite_fruit2(void);
void favorite_fruit3(char **);
int main(void) {
char * fruit1 = favorite_fruit1();
printf("%s\n", fruit1);
char * fruit2 = favorite_fruit2();
printf("%s\n", fruit2);
char * fruit3 = NULL;
favorite_fruit3(&fruit3);
printf("%s\n", fruit3);
printf("------END of CODE------");
return EXIT_SUCCESS;
}
char * favorite_fruit1(void){
char deciduous[] = "apple";
return deciduous;
}
char * favorite_fruit2(void){
static char deciduous[] = "apple";
return deciduous;
}
void favorite_fruit3(char ** fruit){
static char deciduous[] = "apple";
*fruit = deciduous;
}
favorite_fruit1很明显会出现问题,原因是因为char deciduous[]是局部变量,在函数调用返回后,就释放了。
favorite_fruit2因为使用了static,而static限定了变量被保存在数据段(data segment)中,它的声明周期同程序一样长。所以不会出错。
favorite_fruit3是另一种有效的写法,其原理同2。
本部分内容详见《C专家编程》P119
查看可执行文件中的段
1.编译“hello world”程序,在可执行文件中执行ls -l,得到文件的总体大小。运行size得到文件里各个段的大小。
2.增加一个全局的int[1000]数组声明,重新进行编译,再用上面的命令得到总体及各个段的大小,注意前后的区别。
3.现在,在数组的声明中增加初始值(记住,C语言并不强迫对数组进行初始化时为每个元素提供初始值)。这将使数组从BSS段转换到数据段。重复上面的测量,注意各个段前后大小的区别。
4.现在,在函数内声明一个巨大的数组。然后再声明一个巨大的局部数组,但这次加上初始值。重复上面的测量。定义于函数内部的局部数组存储在可执行文件中吗?有没有初始化有什么不同吗?
5.如果在调试状态下编译,文件和段的大小有没有变化?是为了最大程度的优化吗?
分析上面“编程挑战”的结果,使自己确信:
- 数据段保存在目标文件中。
- BSS段不保存在目标文件中(除了记录BSS段在运行时所需要的大小)。
- 文本段是最容易受优化措施影响的段。
- a.out文件的大小受调试状态下编译的影响,但段不受影响。
helloworld.c的文件最终如下:
#include <stdio.h>
int global_array[1000] = {100, 101, 102};
void SayGoodBye(void);
int main(void)
{
printf("hello Linux world");
int main_array[1000] = {10, 20, 30, 40};
SayGoodBye();
return 0;
}
void SayGoodBye(void)
{
int goodbye_array[1000] = {1024, 2048, 4096};
printf("good bye user!");
}
以下命令按照文中步骤依次修改上文代码(过程不赘述),运行size后的数据如下所示:
[volnet@GoCool c]$ echo "size helloworld1"; size helloworld1; echo "size helloworld2"; size helloworld2; echo "size helloworld3"; size helloworld3; echo "size helloworld4"; size helloworld4;
size helloworld1
text data bss dec hex filename
1015 252 8 1275 4fb helloworld1
size helloworld2
text data bss dec hex filename
1015 252 4032 5299 14b3 helloworld2
size helloworld3
text data bss dec hex filename
1015 4280 8 5303 14b7 helloworld3
size helloworld4
text data bss dec hex filename
1270 4280 8 5558 15b6 helloworld4
注:
BSS的全称是:Block Started by Symbol(由符号开始的块),它是旧式IBM704汇编程序的一个伪指令,UNIX借用了这个名字,至今依然沿用。
因为硬盘被自己给挤爆了,所以终于肯花钱买个移动硬盘了。把大部分地数据COPY到移动硬盘后,发现自己地硬盘还是有蛮多空间的。一直就想装个
Linux,但苦于没有空间也就没有尝试,机子上的确有个虚拟机的Linux,是Fedora10的LiveCD,但因为是LiveCD,而且是虚拟机上
跑的,加上机器配置本来就是老古董,所以觉得还是很不爽。既然有空间了,就装个实体的吧。
装Linux和装Windows肯定是不一样的,而且大
部分人都会有这样地想法:机器上通常会先有了Windows,然后想拓展个Linux,虽然是Linux粉,但Windows也是必备的,因为大家都需要
淘宝,都需要网上银行,可能还需要安装MSN等,总之Windows要被Linux取代,一时半会还没那么容易。这些是我个人的拙见啦。因为有很多地愤青
和狂热青年会不分青红皂白的把Windows一棒打死,这就完全没必要了,虽然微软是收费的,但你继续用着盗版,连想被黑屏都要苦苦等待一百年,微软只是
摆个姿态,你继续用你的好了。(Linux粉诋毁Windows的不在少数,相关讨论数不胜数,反正大家看自己的需要了,这里不做口水战)
既然说了要Windows+Linux双系统,当然这里我的前提是我已经安装了Windows。其实这个解决的方案在互联网上已经有很多实战地范例,我这篇无非是更符合我自己地情况,当然有可能也能帮助到你。
步骤大致如下:
1、为Linux安排分区
2、下载Linux,并准备好。
3、安装Linux
其实上面的步骤等于没说,因为看似美好,但危机重重,我是在正常安装了,但到您那可能就不是这么回事。
场景:
我有光驱,但我没有光盘,这很让人遗憾,我有U盘,也有移动硬盘,但移动硬盘放了我太多重要的数据,我不敢轻易冒险,我地光盘只有1G,但绰绰有余了。
网上的做法我基本也尝试过了,但很不幸,并不能成功。
方案1(未成功,但您可以再试,因为有些步骤我可能真错了)
1、下载GRUB for DOS,这个软件在GNU的网站上就有,下载应该不是问题,找不到就搜一个吧。
2、我这里是用了Windows地boot.ini来带动GRUB,然后再启动GRUB来做的。GRUB的安装是正确的。步骤如下:
2.1 解压GRUB for DOS到C盘任意目录,这里用了(Windows下)c:\boot\grub
2.2 复制其中地grldr到C盘根目录下。
2.3 修改boot.ini文件,在最下面添加一行c:\grldr="启动GRUB"
其实这里步骤2.2和2.3可以合并为一步,就是修改boot.ini文件到c:\boot\grub\grldr="启动GRUB",这样可能C盘根目录下会好看许多。
现
在重新启动你的计算机,你会发现在启动地时候会出现多行可选的,其中最下面就是“启动GRUB”,点击进入后会有个绿色的界面。其中的内容是在
menu.lst文件中指定的,其实你可以增加你自己地命令到里面去,格式嘛,基本里面随便找一个大致一致的断修改一下就可以了。
当然,这个方法我没有实战成功,原因在下面。
3、
按照网上的说法,我应该要在启动到GRUB后进入command
line(或者事先在menu.lst中编辑好后)再输入启动命令。当然之前要做一些准备工作。比如把Linux
ISO(CD的话是第一张光盘)中images文件夹下的vmlinuz和initrd.img文件copy到某个驱动器下。但现在我可能遇到了下面的问
题(说“可能”,是因为最后我也没有去做一下可能正确的尝试):
首先两行命令大致如下:
grub>kernel /hd(0,5)/vmlinuz
grub>initrd /hd(0,5)/initrd.img
这
句话是网上的某个帖子说的,当然这里可能有错误,关键的地方是在hd(0,5),这是代表盘符,正确的写法可能是(hd0,5)也就是大概是
grub> kernel
/(hd0,5)/vmlinuz,当然这个只是网友的一个例子,在那篇帖子中还说了如何推算驱动器盘符的名字,比如IDE硬盘就用hd开始,SATA硬
盘就用sd,但其实这是错误的(网上也另有帖子说不区分IDE和SATA。(http://blog.guoshuang.com/?p=5742)hd
应该就是hard
disk的缩写,那sd是SCSI Dervice的缩写,而不是SATA,第一轮我一直使用hd,并且尝试了各种排列组合,但当数字增加到了二十几的时候,我毅然决定放弃了。呵
呵。
当然后面在我正确安装(如何正确,见后文)之后,图形界面告诉我我的硬盘情况以及它们的正确命名。
我在Windows下有C,D,E,F分区,其中C为主分区,DEF为一个逻辑扩展分区,在F之后,还有两个linux分区,这是我在Windows中为Linux分配的(使用PQ/Partition Magic 将它们进行调整)
该图片来自http://os.yesky.com/lin/184/2514684.shtml,内含详细步骤(其中我是用“安装另一个操作系统”来给Linux分配分区的)。
我还有插着一个U盘,然后最后的命名对应如下:
sda1对应C
sda5对应D
sda6对应E
sda7对应F
sda4对应Linux分区
sdb1对应U盘
我的失败可能还来自于我地CDEF分区均为NTFS,据说GRUB是不支持NTFS的,但我在GRUB的文件夹下看到了grub-0.97-patch3-ntfs文件,从名字上好像就是ntfs的补丁。当然您可以先试试。反正我是换了其他方案。
方案2(成功)
我
狠心把F盘的空间给格了,将其转换为FAT32,其实我相信不用转的,因为我在Linux的安装过程中看到了CDE盘,也就是
sda1,sda5,sda6等,那么也就是说它们是可以被识别的。其实这不是关键,关键是我用了一个软件(其实它也就是跟我们做了手动的工作差不多。但
可能一些细节被我给弄错了,总之现在这个方案还很方便。)
下载一个unetbootin软件,安装for
windows版的,它可以不需要你提供ISO文件,直接在线制作(也就是帮你下载下来,然后制作),我是消受不起这种高科技的,因为CD嘛,动辄
700MB,哪那么容易。ISO有了,指定完就可以了。U盘准备好,格了,FAT32格式,我之前一次在U盘里放了所谓地U盘启动制作地两个DOS文件,
结果还是出错了。恩,先格式化了就可以了。其实它的做法COPY了太多的数据了,应该跟我们手动制作的时候一样,只COPY几个用于启动安装地img就可
以了。当然也无所谓了,起来了再说。(原因:因为在启动后,它始终是U盘,但是Linux的安装,只限四种方式:CD/DVD,Hard
disk,NFS(也就是网络文件系统,通常就是一个本地局域网的服务器),URL(这种方式一样需要强大的网络带宽支持),并没有指定U盘,所以我们无
法简单地用U盘来取代CD,只能依靠BIOS中用U盘来启动initrd.img而已)
现在可以启动地U盘制作好了,重启后调整BIOS为USB启动,然后会进入一个漂亮的画面,选择第一项(Default)就可以进入了,会要求选择语言和键盘,就和Linux启动的时候类似,选择中文和US就可以了。
因
为我地多个ISO文件都是放在F盘的根目录下的,刚才有CD/DVD,Hard disk,NFS,URL的时候,选择硬盘(hard
disk),然后可能会让你选择引导驱动的盘,原本我都是选择sdb1也就是U盘,其实直接选择sda7就可以了,这里你的硬盘分区情况可能跟我不同,但
其实很容易,你挨个给它试过去,如果不可以它会提示你出错了,你换换就可以了。
随后会出现图形界面,因为我事先为硬盘分出了Linux分区,这里选择一下“删除Linux分区,然后重建”(意思大概这样)。
关键地一步是在下面会有个复选框,意思大概是检测分区(也就是自定义安装),让你能够看到默认地安装过程。我的判断是默认要求C盘是FAT32(网上的说法),但这里我们是F盘才是FAT32,所以我进去后小做修改(具体过程我忘了,大致就是将其中的一项改成了sda7,就顺利过关了),否则可能遭遇“缺少ISO 9660图像”安装程序试图挂载映像#1,但在硬盘上无法找到该映像。请将此映像复制到硬盘中,并点击重试。点击退出来终止安装。
然后就会经过一个漫长的安装过程。直到见到欢迎页面,就没啥难度了。
其实问题还有很多呢,我也还有好多问题没解决。
刚才看一个哥们写的安装过程以及所遭遇的问题,看来是通病,Windows为什么成功,已经看得出来了,当然Linux粉完全可以说是定位不同,咱层次低,门槛感觉就高了,或许习惯后,也会觉得so easy,不过我还是很顶Windows的,确实很棒!
编程之美P117 -
求二进制中1的个数(P119)
除以一个2,如果有余,则有一个1,如果没有余数,则有一个0;
位运算,循环右移,当前值&0x01,要么为0,要么为1,求和,即可得1的个数;
位运算,二进制-1,将会使最靠右的一个1消失,使其右边那个0(如果存在的话)变1,然后与原数做&运算,结果如果非0,则说明还有1存在;
(低效)switch运算,直接给出答案0~255(可求8位二进制);
(神效)将结果放入int[256]中,直接查表即可,时间复杂度O(1)
阶乘,给定一个整数N,那么N的阶乘N!末尾有多少个0呢?例如:N=10,N!=3628800,N!的末尾有两个。(P126)
N!中0的个数就是10的个数,因为10 = 2×5,由于2可能出现的个数肯定比5要多很多倍,所以只要计算含有5的个数即可。所以方法1就是%5(对5取余数);
原理同方法1,但是计算方式不同,一个数假设是250由几个5相乘呢?
等价于
因为54 >250,也就是最后一个加号以后的数在计算机的整数除法中均为0,因此只有前三个有效。
等价于
它们分别可以解释为:
1…5…10…15…25…30……250
:每间隔5,一共有多少个数,其结果也就是整除5的结果
:每间隔25,一共有多少个数,其结果也就是整除25的结果,因为之前这些数已经参与了含有5的计算,因此,现在整除25也就是整除5×5,则表示它有两个5相乘。
依此类推,即可得出5的个数。
求N!的二进制表示中最低位1的位置。
同上一题一样的方式解,把5换成2即可。题目的意思也就是类似,二进制的末尾0表示含有2的个数(类似上题含有5的个数)所以最后一个1的位置必然等于0的个数+1;更高效一点的就是上一题需用/5的做法,而这一题用>>=的做法就可以实现/2的效果了,而移位比除法要高效得多;
N!含有质因数2的个数,还等于N减去N的二进制表示中1的数目。(具体分析见P128)
1的数目
给定一个十进制正整数N,写下从1开始,到N的所有整数,然后数一下其中出现的所有1的个数。
遍历每个数,求每个数含有1的个数,但效率低,时间复杂度为O(N*log2N)
P115
数组int array[]中,最大的N个数。
排序?但是数字一大肯定不可以。
快速排序法,时间复杂度O(N*log2K),因为是求K个数,而快速排序一次可以将数分成两组,最佳状态是一次就将其分成两组{K}X{N-K},其中X为参考数值。
二分搜索法
用容量为K的最小堆来做,使堆顶的元素是K个数中最小,然后其他数进行比较,如果比堆顶的大就替换最小的数,并重新排序堆,……,最后堆中的数据就是所要地数据了。
(快,但是受限)将每个数出现的次数记录一下,假设有3、8、10,每个数出现的次数分别是2、7、3,那么假设K取5,则分别是{10、10、10、8、8}。
最大公约数
辗转相除法
求差判定法,用减法代替方法1中的取模运算,但增加了迭代次数
根据f(x,y) = f(p*x1,y)=f(x1,y),用移位的方式除2(>>=)
Math::gcdNum_t Math::Gcd1(Math::gcdNum_t x, Math::gcdNum_t y)
{
//y, x%y顺序不能错;
return y ? Gcd1(y, x % y) : x;
}
Math::gcdNum_t Math::Gcd2(Math::gcdNum_t x, Math::gcdNum_t y)
{
//与Gcd1相同的方式,但由于x%y计算速度较x-y要慢,但效果相同,所以换用x - y
// 但用减法和除法不同的是,比如和,%20=10,-20=70,也就是-4×=10
// 也就是说迭代次数较Gcd1而言通常是增加了。
return y ? Gcd1(y, x - y) : x;
}
Math::gcdNum_t Math::Gcd3(Math::gcdNum_t x, Math::gcdNum_t y)
{
if(x < y)
return Gcd3(y, x);
if(y == 0)
return x;
else
{
if(IsEven(x))
{
if(IsEven(y))
return (Gcd3(x >> 1, y >> 1) << 1);
else
return Gcd3(x >> 1, y);
}
else
{
if(IsEven(y))
return Gcd3(x, y >> 1);
else
return Gcd3(y, x - y);
}
}
}
bool Math::IsEven(Math::gcdNum_t x)
{
return !(bool)x & 0x0001;
} |