As we know, we can display a colorful string on linux terminal with bash shell,
but what about c program?

In this post, I’ll talk about howto print a colorful string on linux terminal with c program.

At first, I’ll give you an introduction about foregroud and background colors, which are as following:

Foreground Colors        Background Colors
-----------------------------------------
Value        Color        Value    Color 
-----------------------------------------
30            Black        40        Black
31            Red            41        Red
32            Green        42        Green
33            Yellow      43      Yellow
34            Blue        44      Blue
35            Purple      45        Purple
36            Cyan        46      Cyan
37            White       47      White

I want to display a colorful string on the terminal, and the bash shell command as follows:

1
$ echo -e “\033[41;33mHello, this is a colorful characters string example.\033[0m”

shell colors

Now, I do it with c program colors.c, which content is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <stdio.h>
enum Foreground
{
FG_BLACK = 30,
FG_RED,
FG_GREEN,
FG_YELLOW,
FG_BLUE,
FG_PURPLE,
FG_CYAN,
FG_WHITE
};
enum Background
{
BG_BLACK = 40,
BG_RED,
BG_GREEN,
BG_YELLOW,
BG_BLUE,
BG_PURPLE,
BG_CYAN,
BG_WHITE
};
void set_color_str(const char *str, int fgcolor, int bgcolor);
int main()
{
enum Background backcolor = BG_YELLOW;
enum Foreground forecolor = FG_RED;
set_color_str("Here are the color words!", forecolor, backcolor);
return 0;
}
void set_color_str(const char *str, int fgcolor, int bgcolor)
{
if ((FG_BLACK > fgcolor) || (FG_WHITE < fgcolor)
|| (BG_BLACK > bgcolor) || (BG_WHITE < bgcolor))
{
printf("%s\n", str);
}
else
{
printf("\033[%d;%dm%s\n\033[0m", bgcolor, fgcolor, str);
}
}

Save it as colors.c and compile with gcc as following:

1
$ gcc colors.c -o colors

Then run it, and what happens?

1
$ ./colors

c colors

Yes, as you know, there is a colorful string printed on the terminal.

是夜,温故 shell, 偶有所得,遂作 post 以记之。

问:此乃何物?对曰:debian 打包利器也。

shell 脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#!/bin/bash
#
# File: mkdeb.sh
# Version: 0.11.03
# Description: this bash shell script shows how
# to generate a debian package.
#
# Created date: March 20th, 2011
# Author: mutse <yyhoo2.young@gmail.com>
# (C) 2011 Chin Foundry. All Rights Reserved.
#
echo
echo "mkdeb (chin foundry utility) 0.11.03"
echo "(C) 2011 Chin Foundry. All Rights Reserved."
echo
if [ ! -e /usr/bin/dh_make ]
then
sudo apt-get install dh-make
fi
echo "Plese choose a directory name which you want to package:"
read -p " >> " DIRNAME
echo "Please input the version of your package:"
read -p " >> " VERSION
SRCDIRNAME=$DIRNAME"-"$VERSION
if [ ! -d $DIRNAME ]
then
if [ ! -d $SRCDIRNAME ]
then
echo "$DIRNAME or $SRCDIRNAME is not exist."
exit 1
fi
fi
if [ ! -d $SRCDIRNAME ]
then
mv "$DIRNAME" "$SRCDIRNAME"
fi
TARNAME=$DIRNAME"_"$VERSION".orig.tar.gz"
tar -czvf $TARNAME $SRCDIRNAME
echo "Please input your email:"
read -p " >> " EMAIL
cd $SRCDIRNAME
USER=`id -un`
dh_make -s -e $EMAIL -f ../$TARNAME
sudo dpkg-buildpackage -rfakeroot
cd ..
sudo chown -R $USER:$USER *.deb
echo "Your debian package is generated."

芘絲者,善工文,曾作詩《無題》,詩曰:

日思縴綿三色堇,

夢尋雄蕩錢塘濱。

怎知吳越高良玉,

不食楚邑喑啞音?

芘絲少時,痴文,願從文。予問之,何解?答曰:小女子閱《明史》而作,君自解耳。

Objective-C 简介

1980年代初布莱德·确斯在其公司Stepstone发明Objective-C。Objective-C是在C语言的基础上,增加了面向对象的特征而扩充的编程语言。目前主要应用于Mac OS X和iPhone Os这两个以OpenStep为标准的系统。Objective-C可以在任何运行GCC的系统中编译和执行,因为GCC本身就包含了Objective-C的编译器。

安装 Objective-C

很多朋友知道,进行Objective-C开发需要Apple Mac 机器(不是咱无产阶级兄弟玩得起的!)。买台苹果本本,有些不太现实(如果读者的经济能力允许的话,那就另当别论了),怎么办?Ubuntu 10.04下可以使用GNUStep进行Objective-C开发·[2]。请使用新得立软件包管理器安装,启动后输入gnustep-devel,右键标记安装,会提示安装相关的依赖软件包(很省事),然后选中标记下,最后点击应用,即可进行安装。

编写示例

安装完毕后,自然是要编写一个实例[来自维基百科]来验证下,例子如下所示:

1
2
3
4
5
6
7
8
9
10
11
#import<Foundation/Foundation.h>
int main(int argc, char *argv[]){
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSLog(@"Hello World!");
[pool drain];
return 0;
}

使用gedit或vi编辑器编辑上述内容,并保存为hello.m。

然后打开终端,进入到hello.m目录中,使用如下所示命令编辑程序:

1
$ gcc hello.m `gnustep-config --objc-flags` -lgnustep-base -o hello

当前目录下生成了两个文件,一个是hello.d,另外一个是hello(可执行文件)。

运行可执行程序:

1
2
$ hello
2010-09-12 11:37:39.917 hello[5170] Hello World!

Objective-C 资料

参考资料:

Please use an editor that you like to write a matlab script as following:

a=3;
b=2;
c=a+b

Save as num.m (a matlab script).

Then, use the editor vi or gedit to write a shell script as following:

1
2
3
4
5
6
7
8
9
10
#!/bin/sh
#
# File: num.sh
# Description:
# running a matlab script from within a shell script.
#
# Created Date: August 1st,2010
# Author: Mutse Young <yyhoo2.young@gmail.com>
#
matlab -nodesktop -nosplash -r “num;quit”

Save as a shell script num.sh.

Now, you can run the matlab script from within a shell script as follows:

1
2
$ chmod a+x num.sh
$ num.sh

There is a result string information printed on the terminal, showed as following:

Warning: Could not access OpenGL library 

                          < M A T L A B > 
              Copyright 1984-2004 The MathWorks, Inc. 
                     Version 7.0.0.19901 (R14) 
                            May 06, 2004 


  To get started, type one of these: helpwin, helpdesk, or demo. 
  For product information, visit www.mathworks.com. 

c = 

    5

字符串内容相同,也就是忽略字符串中的空格符和不可见的控制符号,其它字符是否相同。那么如何判断两个字符串的内容是否相同?

下面以一个例子来说明:

1
2
char *str1 = “Hello, World!”;
char *str2 = “ Hello World!”;

要比较上述例子中两个字符串内容是否相同,应分为两种情况来讨论:

  • 忽略标点字符;
  • 不忽略标点字符。

若忽略标点字符,则字符串str1和字符串str2的内容相同;若不忽略标点字符,则两字符串的内容不相同。

弄清楚了什么是字符串内容相同的概念后,开始剖析如何实现这一功能。

算法思路:

  • 使用两指针分别同时遍历两个字符串;
  • 在遍历的过程中,每遍历一个字符,应先判断该字符是否是字母或数字。若是,则设置相应的标记为TRUE;若不是,再判断是否是空格符或控制符;
  • 若该字符是空格符或控制符,指针向后移动一位;若不是,再判断是否是标点字符;
  • 若是标点字符,且忽略,指针向后移动一位;若不忽略,则设置相应的标记为TRUE;
  • 若两字符串的标记都为TRUE,则进行字符比较。若相同,则返回步骤2,继续遍历;若不同,则返回1(内容不相同);
  • 遍历直至其中一个字符串到结束符的位置,停止循环;
  • 然后判断另一个字符串中未遍历的字符是否是字母或数字;若是,则返回1;若不是,再判断是否是标点字符;
  • 若是标点字符,且忽略,继续遍历,直至该字符串遍历完毕;若不忽略,则返回1;当两字符串都遍历完毕,则两字符串的内容相同。

函数原型:

1
int strccmp(const char *str1, const char *str2, int flag);

参数说明:

str1: 字符串
str2: 字符串
flag: 是否忽略标点字符标记
返回值:若返回值为1,则两字符串内容不相同;若返回值为0,则内容相同。

源码

附:strccmp.c 程序实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
* 文件名: strccmp.c
* 描述:
* 比较两字符串的内容是否相同,其中忽略空格字符和控制符,
* 是否忽略标点符,依标记flag的值而定。若flag为TRUE,
* 则忽略;若flag为FALSE,则不忽略。
*
* 日期: 2010年3月11日
* 作者: 默之 <yyhoo2.young@gmail.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define TRUE 1
#define FALSE 0
int isnonaln(int c, int flag);
int strccmp(const char *s1, const char *s2, int flag);
int main()
{
char s1[] = "hello 55,6, oworld !!";
char s2[] = " hello 5 56 o world!";
printf("strccmp(s1,s2) = %d\n", strccmp(s1, s2, TRUE));
return 0;
}
/* checks for an alphanumeric character, not a black character
* or a control character
*
*/
int isnonaln(int c, int flag)
{
if (isalnum(c) == 0)
{
if (isblank(c) != 0 || iscntrl(c) != 0)
{
return 0;
}
if (ispunct(c) != 0)
{
if (flag == TRUE)
{
return 0;
}
else
{
return 1;
} // if flag
}
}
return 1;
}
/* compare the two strings s1 & s2 by their contents. the value returned is one
* if the two string are equal by their contents, and a zero if not.
*
*/
int strccmp(const char *s1, const char *s2, int flag)
{
const char *p1 = s1;
const char *p2 = s2;
int ischar1 = FALSE;
int ischar2 = FALSE;
while (*p1 != '\0' && *p2 != '\0')
{
if (isnonaln(*p1, flag) == 0)
{
p1++;
}
else
{
ischar1 = TRUE;
}
if (isnonaln(*p2, flag) == 0)
{
p2++;
}
else
{
ischar2 = TRUE;
}
if (ischar1 == TRUE && ischar2 == TRUE)
{
if (*p1 == *p2)
{
ischar1 = FALSE;
ischar2 = FALSE;
p1++;
p2++;
}
else
{
return 1;
}
}
} // while p1
while (*p1 != '\0' || *p2 != '\0')
{
if (*p1 != '\0')
{
if (isnonaln(*p1, flag) != 0)
{
return 1;
}
else
{
p1++;
}
}
if (*p2 != '\0')
{
if (isnonaln(*p2, flag) != 0)
{
return 1;
}
else
{
p2++;
}
}
}
return 0;
}

首先,不免俗地编写一个简单的GTK+程序gtkhello.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/*
* gtkhello.c
*
* Created on: 2010-1-28
* Author: young
*/
#include <gtk/gtk.h>
int main(int argc, char *argv[])
{
GtkWidget *wnd;
GtkWidget *label;
gtk_init(&argc, &argv);
wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(wnd), "Hello GTK+!");
gtk_window_set_default_size(GTK_WINDOW(wnd), 300, 200);
label = gtk_label_new("Hello, welcome to the GTK+ world in Ubuntu 9.10\n\n(C) 2010 Chinsoft Studio");
gtk_container_add(GTK_CONTAINER(wnd), label);
g_signal_connect(GTK_OBJECT(wnd), "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all(wnd);
gtk_main();
return 0;
}

接下来,我们开始使用automake等命令编写Makefile文件。

(1) 在终端中运行autoscan命令;

1
$ ls -l
总计 8
-rw-r--r-- 1 young young   0 2010-01-28 21:35 autoscan.log
-rw-r--r-- 1 young young 470 2010-01-28 21:35 configure.scan
-rw-r--r-- 1 young young 720 2010-01-28 21:35 gtkhello.c

(2) 使用mv命令将onfigure.scan重命名为configure.ac或configure.in并修改文件内容:

修改前文件:

#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.64])
AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])
AC_CONFIG_SRCDIR([gtkhello.c])
AC_CONFIG_HEADERS([config.h])

# Checks for programs.
AC_PROG_CC

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

AC_OUTPUT

修改后文件:

#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.64])
AC_INIT(gtkhello, 1.10.01, yyhoo2.young@gmail.com)
AC_CONFIG_SRCDIR([gtkhello.c])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE(gtkhello,1.10.01)

# Checks for programs.
AC_PROG_CC

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.
AM_PATH_GTK_2_0(2.2.0,,AC_MSG_ERROR(gtkhello 0.1 needs GTK+ 2.2.0))

AC_OUTPUT(Makefile)

(3) 在当前目录下新建Makefile.am文件,文件内容如下:

bin_PROGRAMS = gtkhello
gtkhello_SOURCES = gtkhello.c
AM_CPPFLAGS  = @GTK_CFLAGS@
LDADD = @GTK_LIBS@

(4) 在当前目录下使用touch命令新建NEWS、 README、 ChangeLog 、AUTHORS 四个文件,否则运行automake –add-missing命令时将会报错;

(5) 在终端中依次运行以下命令:

1
2
3
4
$ aclocal
$ autoheader
$ autoconf
$ automake --add-missing

(6)如果没有任何错误,继续运行./configure命令:

1
$ ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... no
checking for mawk... mawk
checking whether make sets $(MAKE)... yes
checking for gcc... gcc
checking for C compiler default output file name... a.out
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables... 
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking for style of include used by make... GNU
checking dependency style of gcc... gcc3
checking for pkg-config... /usr/bin/pkg-config
checking for GTK+ - version >= 2.2.0... yes (version 2.18.3)
configure: creating ./config.status
config.status: creating Makefile
config.status: creating config.h
config.status: executing depfiles commands

即生成Makefile文件。

(7) 使用make命令即可编译gtkhello.c程序。

参考资料: