linux 下 C 编程和make的方法 ( 六:补充 关于搭窝)

中山野鬼 发布于 2012/04/01 02:10
阅读 1K+
收藏 13
   前面堆了一堆代码,说件让刚码过的朋友吐血的事,就上面这些代码我没有写一行,除了一些修改,整体就是COPY。从哪COPY来的,后面会说。先谈搭窝。

    这事得从资源利用说起。我说了。大家的智商都差不多,你想做的更好,就得利用好你的脑袋的资源聚焦在一点上。有经验的老鸟能处理大项目,没经验的菜鸟,一碰到复杂点点的,就完了。差异除了老鸟有知识技术方面的积累外,还有工作方法的经验。复杂的东西,抽丝剥茧,分成模块,集中注意力,盯住当前的目标。系统明确,模块明确,目标明确。老鸟,一天搞一点,但是每天都有积累,汇总起来就OK。

    因此,对于菜鸟而言,在你没学到广泛的知识前(这得花时间,毕竟你耳朵根子没有个USB口),集中你当前要解决的问题,这最重要的。尽可能把要面对的问题,切得足够小。这还不够。还要最短时间内,能验证问题是否解决了。你可以把有些事情切出去,拖后处理,但当前的行为,要尽快验证。
    所以,搭窝对于新手,是必须要。10个函数,2个C文件,洋洋洒洒的写完,才编译,好嘛,错误填满整个屏幕都不够,这也太打击你积极性了。
    不过,我也不能每次介绍新模块时,都贴上 cd .. mkdir ..等等东西。怎么办呢?这里给了一个弱智版的脚本文件。用于自动生成模块目录,和生成对应模块文件。包括.h包括.c。包括测试文件。弱智版的我觉得好啊,至少你们能看得懂。而且,没有必要搞那么复杂,我当然希望各位能理解configure文件的内部每个操作。但是这得解释太多东西。不如一步步来。
    先说下,弱智版的自动生成模块的脚本怎么用。
    有几个参数。
    第一个参数必须要有,是表示模块名的。由这个模块,会自动创建目录。如果目录已经存在则会提示已经存在。或无法创建,比如有同名的文件在当前目录下。
    第二个参数可以选择,目前有 -f -t两个。后面要对应跟上文件名。
    -f 是你需要给模块module目录下自动生成src/a.c 和inc/a.h。并添加些基本代码。如下操作
   
$./create_module.sh module -f a
    -t 是自动生成测试文件,但是测试文件总要至少针对一个文件进行测试(别吐,目前也只能添加对一个文件进行测试的基本代码)。因此 -t有两个参数
  
$./create_module.sh module -t b a
    此时会在src/下自动生成一个test_b_main.c,而且会自动加上 #include "a.h"这类的代码。
    需要注意,如果已经有对应文件存在,会提示,是否覆盖。这里没有追加的代码,毕竟弱智版的,我不想一下把脚本写的太多。目前已经够弱智的了。
    对于前面那些搭窝的工作。你可以如下操作。
  
$./create_module.sh data_struct -f ds_tree -t ds_tree ds_tree
    这和  
$./create_module.sh data_struct -t ds_tree ds_tree -f ds_tree 
    你也可以尝试如下命令,换个测试名字   
$./create_module.sh data_struct -f ds_tree -t ds_tree ds
    当然你也可以 
   $./create_module.sh data_struct -t ds_tree ds
   $./create_module.sh data_struct -f ds_tree
    上面两个命令没有顺序。都会检测目录是否存在,是否需要创建。
    此时生成的是test_ds_main.c文件,在src/下。
清单如下。
#!/bin/bash
MODULE_NAME=$1

SRC_DIR_NAME=src
INC_DIR_NAME=inc
BIN_DIR_NAME=bin
OBJ_DIR_NAME=obj
C_FILE_SUFFIX=.c
H_FILE_SUFFIX=.h
TEST_FILE_SUFFIX=.t
CREATE_FILE_FLAG=-f
CREATE_TEST_FILE_FLAG=-t
OVERWRITE_FILE=0
NOT_OVERWRITE_FILE=1

create_mkdir(){
mkdir $1 > /dev/null 2>&1
if [ $? = 0 ];then   
echo /$1 had created
else
echo /$1 had exist
fi

}
check_file_exist(){
    if [ -e $1 ];then
        while :;do
            echo -n "the $1 had exist , do you want to overwrite?(y(Y) done:n(N) not:e(E) exit) : "
            read check_file_exist_ans
            case $check_file_exist_ans in
            y|Y)
                echo you answer y
                return $OVERWRITE_FILE
            ;;
            n|N)
                echo you answer n
                return $NOT_OVERWRITE_FILE
            ;;
            e|E)
                exit
            ;;
            *)
                echo  "fuck ,i need you correct answer!"
            esac
        done
    else
        return $OVERWRITE_FILE
    fi
}
CREATE_NEW_FLIE=0
CREATE_NEW_FILE_ERROR=1
EXIST_FILE=2
INSERT_FILE_CON=""

get_c_init_context(){
#$1 path/filename.ext
#$2 filename
    INSERT_FILE_CON="/***************\n$1\n by luckystar\n ***************/\n"
    INSERT_FILE_CON+="static int $2_flag =0;\n"
    INSERT_FILE_CON+="\nvoid $2_init(void){\n"
    INSERT_FILE_CON+="\tif ($2_flag) {\n\t\t//log(\"module inited..\",X);\n\t\treturn;\n\t}\n"
    INSERT_FILE_CON+="\t$2_flag = 1;\n"
    INSERT_FILE_CON+="\t//todo:module init...\n\n}\n"
#up is create module_init func   
    INSERT_FILE_CON+="\nvoid $2_destory(void){\n"
    INSERT_FILE_CON+="\tif (!$2_flag) {\n\t\t//log(\"module not inited..\",X);\n\t\treturn;\n\t}\n"
    INSERT_FILE_CON+="\t$2_flag = 0;\n"   
    INSERT_FILE_CON+="\t//todo:module destory...\n\n}\n"
#up is create module_destory func
}

get_h_init_context(){
#$1 path/filename.ext
#$2 filename
    INSERT_FILE_CON="#ifndef _$2_H_\n#define _$2_H_\n"
    INSERT_FILE_CON+="\n//ins_inc_file\n"
    INSERT_FILE_CON+="\n//ins_typedef_def\n"
    INSERT_FILE_CON+="\n//ins_def\n"
    INSERT_FILE_CON+="\n//ins_func_declare\n"
    INSERT_FILE_CON+="\n\n"
    INSERT_FILE_CON+="#endif //_$2_H_\n"       
}
get_test_init_context(){
#$1 filename
#$2 libname
    INSERT_FILE_CON="#include \"$2.h\"\n"
    INSERT_FILE_CON+="\n\n"
    INSERT_FILE_CON+="int main(int argc,char *argv[])\n"
    INSERT_FILE_CON+="\t$2_init();\n"
    INSERT_FILE_CON+="\t$2_destrory();\n"
    INSERT_FILE_CON+="\treturn 0;\n"
    INSERT_FILE_CON+="}\n"       
}
insert_file_tmp(){
#$1 path/filename.ext
#$2 filename
#$3 ext mode
    case $3 in
    $C_FILE_SUFFIX)
    get_c_init_context $1 $2
    ;;
    $H_FILE_SUFFIX)
    get_h_init_context $1 $2
    ;;
    $TEST_FILE_SUFFIX)
    get_test_init_context $4 $2
    esac
    sed  -i "a\\$INSERT_FILE_CON" $1
   
}

create_file_in_sub_dir(){
   
    if [ -d $1 ];then
        if [ $3 = $TEST_FILE_SUFFIX ]; then
        NEW_FILENAME=$1/test_$4_main.c
        else
        NEW_FILENAME=$1/$2$3
        fi
        check_file_exist $NEW_FILENAME
        if [ $? = $OVERWRITE_FILE ];then
            echo > $NEW_FILENAME
            insert_file_tmp $NEW_FILENAME $2 $3 $4
            echo create /$MODULE_NAME/$NEW_FILENAME file
            return $CREATE_NEW_FILE
        else
            return $EXIST_FILE
        fi
    else
        echo  /$MODULE_NAME/$1 is not directory, create_file not continue...
        return $CREATE_NEW_FILE_ERROR
        #not exit , continue done the other cmd
    fi
}


check_other_cmd(){
while [ 2 -le $# ];do
    case $2 in
    $CREATE_FILE_FLAG)
        shift
        create_file_in_sub_dir $SRC_DIR_NAME $2 $C_FILE_SUFFIX #$C_FILE_TMP
        create_file_in_sub_dir $INC_DIR_NAME $2 $H_FILE_SUFFIX #$H_FILE_TMP
       
        #create_file_in_sub_dir $LOG_DIR_NAME $2 $LOG_FILE_SUFFIX
       
    ;;
    $CREATE_TEST_FILE_FLAG)
        shift
        create_file_in_sub_dir $SRC_DIR_NAME $2 $TEST_FILE_SUFFIX  $3
        shift
       
        ;;
    *)
       #    echo $2" test "
    esac
        shift
done
    exit
}
create_mkdir $MODULE_NAME
if [ -d $MODULE_NAME ];then
    cd $MODULE_NAME
    create_mkdir $SRC_DIR_NAME
    create_mkdir $INC_DIR_NAME
    create_mkdir $BIN_DIR_NAME
    create_mkdir $OBJ_DIR_NAME
    check_other_cmd $@
else
    echo $MODULE_NAME is not directory ,could not continue...   
    exit
fi
 这里需要有几个声明的:
    1、这个离理解configure的距离还差的很远。我尽可能的用函数调用,和简单的方式实现。当然有更精炼的操作方式。不过脚本语言一直有个悖论。高效的看不懂,看得懂的不高效。而我本身主业是搞算法优化的,包括从系统架构上做调整。所以我对脚本的设计,追求一点:但求好看,不求高效。
    估计又要被喷了,你做优化的还不要高效?我现在开始狡辩,如下:
    1、优化讲究目标。而不存在没有任何边界或者没有任何约束的优化。
    2、脚本的最大作用在于自动化的完成任务。但它是通过其他功能模块实现核心处理,脚本要什么都能做就不是脚本了。如果仅凭脚本自身就能做C都不能做的事情,那和汇编有什么区别,且不谈其他高级语言。
    3、用脚本的,不会只RUN一次。不会是个小事情,步骤单一的操作。一定是比较复杂的,或步骤繁琐的目标组合。
    4、现实中有两种脚本,一个是自己写的,一个是产品化发布中存在的。
    总结一下,轮到但凡自己写的,优化目标不是脚本自身运行的高效。同时,自己写的,不是给自己看的,就是给同事看的,而且会随项目的推进而做调整,因此,脚本本身优化的目标就是在于易读易改,而不是脚本自身的速度(不谈脚本所调用的其他模块的运行效率问题 )。
    我可没说我只做运行速度的优化。开发速度的优化也是优化。我自己写的代码足够快,也不可能是天下第一。我就是做了天下第一的一个软件,也不可能各个软件都天下第一。我更希望的去优化一个团队的组织行为,而不是工作目标本身。如同,美女值得调戏,但是你能调戏尽天下所有美女吗?因此,告诉新手组织化调戏的手段,比调戏本身更重要。
    对于那些非产品级发布的脚本,写的高效的,准确说,我连用都不用,更别提看了。因为有理解你脚本的功夫,不如我自己写了。不理解清楚脚本的目标和工作原理对我毫无价值。也希望新手保持个习惯,不要拿脚本设计来当作智力的体现,爱因斯坦成名那会也没有脚本这玩意啊。设计脚本的评价目标就是“易读,易改”。
    最后,建议新手:
    毕竟是linux下的C编程,基本的脚本命令和格式还是要会的。希望上述脚本作为模版,有利于你理解脚本的一些常用操作方式。同时记得ctrl+c ctrl+v保存为文件后,除了爱其什么名字就起什么名字,你得如下操作(如果你和我一样起名为create_moudule.sh)
    $chmod +x create_module.sh
    为什么这么做,记得gcc main.c 输出为什么是a.out吗?我们在linux下面,不是微软的win下。
    同时建议高手:
    能有空对我的脚本进行改动修正,前提是更易读,更易改。
    关于Makefile:
    C代码可不是弱智版的(后面会展开讨论),我自动生成没关系。Makefile现在是弱智版的,我自动生成,脑袋进水了。大家和外我一样慢慢码吧。
加载中
0
弦歌
弦歌
野鬼胸真的辛苦了。写得很好,必顶!
中山野鬼
中山野鬼
胸不辛苦,回头去游泳时才辛苦。
0
生命与幻觉
生命与幻觉
学习了!非常感谢!
0
iceberg
iceberg
虽然我现在工作是做java的,但是个人爱好还是C及linux系,相信也有很多人是这样的,非常敬仰博主啊。
0
中山野鬼
中山野鬼

引用来自“iceberg”的答案

虽然我现在工作是做java的,但是个人爱好还是C及linux系,相信也有很多人是这样的,非常敬仰博主啊。
我倒希望你能俯视。敬仰我,不是我高大,而是你自己心里渺小而已。我觉得到linux C这个层次,基本上搞开发得凭兴趣。如果只是为了钱,有些层次的东西不是自己想去做就能做好的。虽然linux C确实深层次的比较难,不过钱比其他平台和语言挣的都要多。为什么?不是做服务器,就是做底层的,便宜不了。都是高级货。前提是要能做好。到这个水平,你得凭爱好和你天生的特性才行。
0
中山野鬼
中山野鬼

SORRY ,脚本第 59行需要增加如下内容,否则 .c文件不会自动有#include

	INSERT_FILE_CON+="#include \"$2.h\"\n"

0
中山野鬼
中山野鬼

再sorry ,又一个错。91行需要将 destrory 改成 destory   ,如下

INSERT_FILE_CON+="\t$2_destory();\n"

可能是编辑器操作时,增加字符了。否则你生成的代码会找不到 ds_tree_destrory。今天把网站的内容COPY下来重新RUN一边,发现不少问题。昨天的东西都删除了。昨天好好的,今天就有问题。哈,所以我不相信我自己不会出BUG。

0
中山野鬼
中山野鬼

脚本增加了一个内容。可以通过 -h直接自动生成头文件。如下

 

#!/bin/bash 
MODULE_NAME=$1

SRC_DIR_NAME=src
INC_DIR_NAME=inc
BIN_DIR_NAME=bin
OBJ_DIR_NAME=obj
C_FILE_SUFFIX=.c
H_FILE_SUFFIX=.h
TEST_FILE_SUFFIX=.t
CREATE_FILE_FLAG=-f
CREATE_H_FILE_FLAG=-h
CREATE_TEST_FILE_FLAG=-t
OVERWRITE_FILE=0
NOT_OVERWRITE_FILE=1

create_mkdir(){
mkdir $1 > /dev/null 2>&1
if [ $? = 0 ];then	
echo /$1 had created
else
echo /$1 had exist
fi

}
check_file_exist(){
	if [ -e $1 ];then
		while :;do
			echo -n "the $1 had exist , do you want to overwrite?(y(Y) done:n(N) not:e(E) exit) : "
			read check_file_exist_ans
			case $check_file_exist_ans in
			y|Y)
				echo you answer y
				return $OVERWRITE_FILE
			;;
			n|N)
				echo you answer n
				return $NOT_OVERWRITE_FILE
			;;
			e|E)
				exit
			;;
			*)
				echo  "fuck ,i need you correct answer!"
			esac
		done
	else
		return $OVERWRITE_FILE
	fi
}
CREATE_NEW_FLIE=0
CREATE_NEW_FILE_ERROR=1
EXIST_FILE=2
INSERT_FILE_CON=""

get_c_init_context(){
#$1 path/filename.ext 
#$2 filename
	INSERT_FILE_CON="/***************\n$1\n by luckystar\n ***************/\n"
	INSERT_FILE_CON+="#include \"$2.h\"\n"
	INSERT_FILE_CON+="static int $2_flag =0;\n"
	INSERT_FILE_CON+="\nvoid $2_init(void){\n"
	INSERT_FILE_CON+="\tif ($2_flag) {\n\t\t//log(\"module inited..\",X);\n\t\treturn;\n\t}\n"
	INSERT_FILE_CON+="\t$2_flag = 1;\n"
	INSERT_FILE_CON+="\t//todo:module init...\n\n}\n"
#up is create module_init func	
	INSERT_FILE_CON+="\nvoid $2_destory(void){\n"
	INSERT_FILE_CON+="\tif (!$2_flag) {\n\t\t//log(\"module not inited..\",X);\n\t\treturn;\n\t}\n"
	INSERT_FILE_CON+="\t$2_flag = 0;\n"	
	INSERT_FILE_CON+="\t//todo:module destory...\n\n}\n"
#up is create module_destory func
}

get_h_init_context(){
#$1 path/filename.ext 
#$2 filename
	INSERT_FILE_CON="#ifndef _$2_H_\n#define _$2_H_\n"
	INSERT_FILE_CON+="\n//ins_inc_file\n"
	INSERT_FILE_CON+="\n//ins_typedef_def\n"
	INSERT_FILE_CON+="\n//ins_def\n"
	INSERT_FILE_CON+="\n//ins_func_declare\n"
	INSERT_FILE_CON+="\n\n"
	INSERT_FILE_CON+="#endif //_$2_H_\n"		
}
get_test_init_context(){
#$1 filename 
#$2 libname
	INSERT_FILE_CON="#include \"$2.h\"\n"
	INSERT_FILE_CON+="\n\n"
	INSERT_FILE_CON+="int main(int argc,char *argv[])\n"
	INSERT_FILE_CON+="\t$2_init();\n"
	INSERT_FILE_CON+="\t$2_destory();\n"
	INSERT_FILE_CON+="\treturn 0;\n"
	INSERT_FILE_CON+="}\n"		
}
insert_file_tmp(){
#$1 path/filename.ext 
#$2 filename
#$3 ext mode
	case $3 in
	$C_FILE_SUFFIX)
	get_c_init_context $1 $2
	;;
	$H_FILE_SUFFIX)
	get_h_init_context $1 $2
	;;
	$TEST_FILE_SUFFIX)
	get_test_init_context $4 $2
	esac
	sed  -i "a\\$INSERT_FILE_CON" $1
	
}

create_file_in_sub_dir(){
	
	if [ -d $1 ];then
		if [ $3 = $TEST_FILE_SUFFIX ]; then 
		NEW_FILENAME=$1/test_$4_main.c
		else
		NEW_FILENAME=$1/$2$3
		fi
		check_file_exist $NEW_FILENAME
		if [ $? = $OVERWRITE_FILE ];then
			echo > $NEW_FILENAME
			insert_file_tmp $NEW_FILENAME $2 $3 $4
			echo create /$MODULE_NAME/$NEW_FILENAME file
			return $CREATE_NEW_FILE
		else
			return $EXIST_FILE
		fi
	else
		echo  /$MODULE_NAME/$1 is not directory, create_file not continue...
		return $CREATE_NEW_FILE_ERROR
		#not exit , continue done the other cmd
	fi
}


check_other_cmd(){
while [ 2 -le $# ];do
	case $2 in
	$CREATE_FILE_FLAG) 
        shift
    	create_file_in_sub_dir $SRC_DIR_NAME $2 $C_FILE_SUFFIX #$C_FILE_TMP
    	create_file_in_sub_dir $INC_DIR_NAME $2 $H_FILE_SUFFIX #$H_FILE_TMP
    	
    	#create_file_in_sub_dir $LOG_DIR_NAME $2 $LOG_FILE_SUFFIX
    	
    ;;
    $CREATE_TEST_FILE_FLAG)
    	shift
    	create_file_in_sub_dir $SRC_DIR_NAME $2 $TEST_FILE_SUFFIX  $3
    	shift
    	
    	;;
    $CREATE_H_FILE_FLAG)
    	shift
    	create_file_in_sub_dir $INC_DIR_NAME $2 $H_FILE_SUFFIX #$H_FILE_TMP
    	;;	
    *) 
       #	echo $2" test "
    esac
        shift
done
	exit 
}
create_mkdir $MODULE_NAME 
if [ -d $MODULE_NAME ];then
	cd $MODULE_NAME
	create_mkdir $SRC_DIR_NAME
	create_mkdir $INC_DIR_NAME
	create_mkdir $BIN_DIR_NAME
	create_mkdir $OBJ_DIR_NAME
	check_other_cmd $@
else
	echo $MODULE_NAME is not directory ,could not continue...	
	exit
fi
0
中山野鬼
中山野鬼

SORRY,90行错了,少了{应该如下

	INSERT_FILE_CON+="int main(int argc,char *argv[]){\n"

奇怪了。自己的机器怎么玩都可以。抱怨一下ctrl + c /v呵呵

0
阿昭
阿昭
C的错误从来就不是一个屏幕能承受的,哈哈,所以我现在不写c了
0
中山野鬼
中山野鬼

引用来自“阿昭”的答案

C的错误从来就不是一个屏幕能承受的,哈哈,所以我现在不写c了
可是我还得写啊。所以得找方法,让错误尽可能一个屏幕承受下来。
返回顶部
顶部