嵌入式成长轨迹16 【Linux应用编程强化阶段】【Linux下的C编程下】【Linux c基本应用】

一  字符串操作
应用程序按其功能可以分为数值计算、非数值计算以及输入输出操作等。非数值计算程序占相当大的比例,其核心就是字符串的处理。

1 字符测试
1).测试字符是否为英文字母

   int isalpha(int c)

 1 /* example1.c */
2 #include <stdio.h>
3 #include <ctype.h>
4 int main()
5 {
6 char str[] = "A13F+2c#D"; /* 定义字符数组 */
7 int i;
8 for (i=0; str[i]!=0; i++) /* 遍历数组中的每个字符 */
9 {
10 if (isalpha(str[i])) /* 测试字符是否为英文字母 */
11 {
12 printf("%d : %c \n", i, str[i]);
13 }
14 }
15 return 0;
16 }

 


2).测试字符是否为数字
   int isdigit(int c)

 1 /* example2.c */
2 #include <stdio.h>
3 #include <ctype.h>
4 int main()
5 {
6 int c;
7 printf("Input the characters :\n");
8 for(;;)
9 {
10 c = getchar(); /* 从键盘获取字符 */
11 printf("%c : %s digit\n", c, isdigit(c)?"is":"not"); /* 测试字符是否为数字 */
12 }
13 return 0;
14 }


2 字符串初始化
在C语言中,字符串被当作字符数组来处理,对应于内存中的一块连续区域。

   void *memset(void *buffer, int c, int count);

 1 /* example3.c */
2 #include <stdio.h>
3 #include <string.h>
4 int main()
5 {
6 char s[] = "Hello World";
7 printf("%s\n", s);
8 memset(s, 'H', 5); /* 将字符串的前5个字节设为字符H */
9 printf("%s\n", s);
10 return 0;
11 }

 

3 字符串复制
字符串复制的函数主要有strcpy、strdup、memcpy以及memmove等,下面分别进行介绍。

1).strcpy函数

   char *strcpy(char *dest,char *src);

2).strdup函数

   char *strdup(char *s);

3).memcpy函数

   void *memcpy(void *dest, void *src,unsigned int count);

 1 /* example4.c */
2 #include <stdio.h>
3 #include <string.h>
4 #define BUFFER_SIZE 128
5 int main()
6 {
7 char s[] = "Linux C Programming";
8 char d[BUFFER_SIZE]; /* 定义内存缓冲区 */
9 strcpy(d, s); /* 字符串拷贝 */
10 printf("%s\n", d);
11 return 0;
12 }

 


4).memmove函数

   void *memmove(void *dest, const void *src,size_t n);

 1 /* example5.c */
2 #include <stdio.h>
3 #include <string.h>
4 int main()
5 {
6 char s[] = "Linux C Programming";
7 printf("%s\n", s);
8 memmove(s, s+6, strlen(s)-6); /* 字符串拷贝,这里源指针和目标指针指向的内存区域有重叠 */
9 s[strlen(s)-6] = '\0'; /* 字符串结束符 */
10 printf("%s\n", s);
11 return 0;
12 }

 

4 字符串比较
字符串比较的函数主要有strcmp、strncmp、strcasecmp、strncasecmp以及memcmp等,下面分别进行介绍。

1).strcmp函数

   int strcmp(const char *s1, const char *s2);

 1 /* example6.c */
2 #include <stdio.h>
3 #include <string.h>
4 int main()
5 {
6 char s1[] = "Hello World";
7 char s2[] = "Hello world";
8 int ret;
9 printf("s1 : %s\n", s1);
10 printf("s2 : %s\n", s2);
11 ret = strcmp(s1, s2); /* 比较两个字符串 */
12 if(ret == 0)
13 printf("s1 and s2 are identical\n");
14 else if(ret < 0)
15 printf("s1 less than s2\n");
16 else
17 printf("s1 greater than s2\n");
18 return 0;
19 }



2).strncmp函数
   int strncmp(const char *s1, const char *s2,size_t n);

3).strcasecmp/strncasecmp函数 忽略大小写
   int strcasecmp(const char *s1, const char *s2);
   int strncasecmp(const char *s1, const char *s2,size_t n);


4).memcmp函数

    int memcmp(const void *s1, const void *s2,size_t n);

5 字符/字符串查找
字符/字符串查找的函数主要有index、rindex、strchr、strrchr以及strstr等,下面分别进行介绍。

1).index/rindex函数 返回找到字符的指针(此时输出就会输出它和它后面的各个字符,直至到'\0')
   char *index(const char *s, int c);
   char *rindex(const char *s, int c); 从后面找起

 1 /* example7.c */
2 #include <stdio.h>
3 #include <string.h>
4 int main()
5 {
6 char s[] = "Hello World";
7 char *p;
8 p = index(s, 'W'); /* 在字符串s中查找字符W */
9 printf("%s\n", p);
10 return 0;
11 }

 

2).strchr/strrchr函数

   char *strchr(const char *s, int c);
   char *strrchr(const char *s, int c);


3).strstr函数
   char *strstr(const char *haystack,const char *needle);

 1 /* example8.c */
2 #include <stdio.h>
3 #include <string.h>
4 int main()
5 {
6 char haystack[] = "Linux C Programming";
7 char needle[] = "Pro";
8 char *p;
9 p = strstr(haystack, needle); /* 查找字符串 */
10 if(p != NULL)
11 printf("%s\n", p);
12 else
13 printf("Not Found!\n");
14 return 0;
15 }

 

6 字符串连接与分割
实现字符串连接与分割的函数为strcat、strncat和strtok,下面分别进行介绍。

1).strcat函数
   char *strcat(char *dest, const char *src);

 1 /* example9.c */
2 #include <stdio.h>
3 #include <string.h>
4 #define BUFFER_SIZE 64
5 int main()
6 {
7 char s[BUFFER_SIZE] = "orld";
8 char d[BUFFER_SIZE] = "Hello W";
9 strcat(d, s); /* 连接字符串 */
10 printf("%s\n", s); /* 输出源字符串 */
11 printf("%s\n", d); /* 输出目标字符串 */
12 return 0;
13 }

 


2).strncat函数

   char *strncat(char *dest, const char *src,size_t n);
3).strtok函数

   char *strtok(char *str, const char *delim);

在str中找出以delim中的字符为分隔的字符串,即是源串中除去了含有分隔串中的所有字符后余下的一段段的字符串,每调用一次找到一串,找不到则返回空串。第一次调用必须传给它有效的字符串,第二次传NULL就可以了,每次调用返回找到的子串的时候都会把源串中该子串的尾部字符(原来是搜索串中的某一字符)修改成'/0'字符返回值为每次调用得到的字串。

 1 /* example10.c */
2 #include <stdio.h>
3 #include <string.h>
4 int main()
5 {
6 char str[] = "Linux C Programming";
7 char *p;
8 p = strtok(str, " "); /* 以空格对字符串进行分割 */
9 while(p != NULL)
10 {
11 printf("%s\n", p); /* 输出分割后的子串 */
12 p = strtok(NULL, " ");
13 }
14 printf("str : %s\n", str);
15 return 0;
16 }

 

二  数据转换
数据转换包括英文字母大小写之间的转换、字符串与整数、浮点数之间的转换,下面分别进行介绍。

1 字母大小写转换
int toupper(int c);
int tolower(int c);

 1 /* example11.c */
2 #include <stdio.h>
3 #include <ctype.h>
4 int main()
5 {
6 char s[] = "Hello World!";
7 int i;
8 printf("%s\n", s); /* 输出原来的字符串 */
9 for(i=0; i<sizeof(s); i++)
10 {
11 s[i] = toupper(s[i]); /* 全部转换为大写字母 */
12 }
13 printf("%s\n", s); /* 输出转换后的字符串 */
14 for(i=0; i<sizeof(s); i++)
15 {
16 s[i] = tolower(s[i]); /* 全部转换为小写字母 */
17 }
18 printf("%s\n", s); /* 输出转换后的字符串 */
19 return 0;
20 }

 

 

二 字符串转换
实现字符串与整数、浮点数之间转换的函数有atoi、atol、strtol、atof、strtod以及gcvt等,下面分别进行介绍

1.将字符串转换为整数

   int atoi(const char *nptr);

   long atol(const char *nptr);

 1 /* example12.c */
2 #include <stdlib.h>
3 #include <stdio.h>
4 int main()
5 {
6 char a[] = "-100";
7 char b[] = "0x20"; /* 转换后结果为0,因此只转换到字符x */
8 int c;
9 c = atoi(a) + atoi(b);
10 printf("c = %d\n", c);
11 return 0;
12 }

 

2.将字符串转换为浮点数

   double atof(const char *nptr);

3.将浮点数转换为字符串
   char *gcvt(double number, size_t ndigits,char *buf);

 1 /* example14.c */
2 #include <stdlib.h>
3 #include <stdio.h>
4 #define BUFFER_SIZE 64
5 int main()
6 {
7 double a=123.456;
8 char str[BUFFER_SIZE]; /* 定义缓冲区 */
9 gcvt(a, 5, str); /* 将浮点数转换为字符串,显示5位 */
10 printf("%s\n",str);
11 gcvt(a, 6, str); /* 将浮点数转换为字符串,显示6位 */
12 printf("%s\n",str);
13 return 0;
14 }

 

4.将字符串根据参数base来转换成长整型数
   long int strtol(const char *nptr,char **endptr,int base);

 1 /* example13.c */
2 #include <stdlib.h>
3 #include <stdio.h>
4 int main()
5 {
6 char a[] = "10000";
7 char b[] = "20000";
8 char c[] = "FFFF";
9 printf("a = %ld\n", strtol(a, NULL, 2)); /* 二进制 */
10 printf("b = %ld\n", strtol(b, NULL, 10)); /* 十进制 */
11 printf("c = %ld\n", strtol(c, NULL, 16)); /* 十六进制 */
12 return 0;
13 }



三  内存分配与释放
1 内存空间的分配

   void *alloca(unsigned size);
 
   void *malloc(unsigned size);
   void *calloc(size_t nmemb, size_t size);

2 内存空间的释放
 
   void free(void *ptr);

 1 /* example15.c */
2 #include <stdlib.h>
3 #include <stdio.h>
4 #define SIZE 10
5 int main()
6 {
7 int *p;
8 int i, sum;
9 p = (int *)malloc(SIZE*sizeof(int)); /* 分配内存空间 */
10 if(p == NULL) /* 如果内存空间分配失败,输出错误信息 */
11 {
12 printf("malloc error\n");
13 }
14 else
15 {
16 sum = 0;
17 for(i=0; i<SIZE; i++)
18 {
19 *(p+i) = i; /* 对内存单元的引用*(p+i)等价于p[i] */
20 sum += p[i];
21 }
22 free(p); /* 释放内存空间 */
23 }
24 printf("sum = %d\n", sum);
25 return 0;
26 }

 

3 更改已分配的内存空间
 
   void *realloc(void *ptr, size_t size);

四  时间和日期
Linux系统下的应用程序设计过程中,经常会涉及时间和日期的处理

1 时间和日期的获取
time和gettimeofday用来获取系统当前的时间和日期,下面分别进行介绍。

1).time函数
   time_t time(time_t *t);2).gettimeofday函数

   int gettimeofday(struct timeval *tv,struct timezone *tz);


 struct timeval
 {

 long tv_sec;
 long tv_usec;
 };

 1 /* example16.c */
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <unistd.h>
5 #include <sys/time.h>
6 int main()
7 {
8 struct timeval tv;
9 struct timezone tz;
10 gettimeofday(&tv, &tz); /* 获取当前的时间 */
11 printf("tv_sec : %ld\n", tv.tv_sec);
12 printf("tv_usec : %ld\n", tv.tv_usec);
13 printf("tz_minuteswest : %d\n", tz.tz_minuteswest);
14 printf("tz_dsttime : %d\n", tz.tz_dsttime);
15 return 0;
16 }

 

2 时间和日期的显示
ctime、gmtime、asctime函数用来将时间和日期转换为字符串格式,下面分别进行介绍。

1).ctime函数

   char *ctime(const time_t *timep);

 1 /* example17.c */
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <time.h>
5 int main()
6 {
7 time_t timep;
8 time(&timep); /* 获取当前的时间 */
9 printf("%s", ctime(&timep)); /* 转换为字符串格式并输出 */
10 return 0;
11 }

 

2).gmtime函数

   struct tm*gmtime(const time_t *timep);
struct tm {  int tm_sec;
  int tm_min;
  int tm_hour;
 
 int tm_mday;
  int tm_mon;
  int tm_year;
  int tm_wday;
  int tm_yday;
  int tm_isdst;

};

 1 /* example18.c */
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <time.h>
5 int main()
6 {
7 time_t timep;
8 struct tm *p;
9 char *wday[]={"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
10 time(&timep); /* 获取当前的时间 */
11 p = gmtime(&timep); /* 转换为tm结构 */
12 printf("%d/%d/%d\n", (1900+p->tm_year), (1+p->tm_mon), p->tm_mday); /* 输出日期 */
13 printf("%s\n", wday[p->tm_wday]); /* 输出星期 */
14 printf("%d:%d:%d\n", p->tm_hour, p->tm_min, p->tm_sec); /* 输出时间 */
15 return 0;
16 }

 

3).asctime函数

   char *asctime(const struct tm *timeptr);

3 时间的计算
double difftime(time_t time1, time_t time0);

 1 /* example19.c */
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <unistd.h>
5 #include <time.h>
6 #define SIZE 100000
7 int main()
8 {
9 time_t time0;
10 time_t time1;
11 int i, j;
12 int *p;
13 double d;
14 time(&time0); /* 获取循环运行前的时间 */
15 for(i=0; i<10000; i++)
16 {
17 p = (int *)malloc(SIZE*sizeof(int)); /* 分配内存空间 */
18 for(j=0; j<SIZE; j++)
19 {
20 *(p+j) = j; /* 初始化 */
21 }
22 free(p); /* 释放内存空间 */
23 }
24 time(&time1); /* 获取循环运行后的时间 */
25 d = difftime(time1, time0); /* 计算时间差 */
26 printf("%f\n", d);
27 return 0;
28 }

 

 

五 其他应用
其他应用包括命令行参数分析、用户和用户组操作以及环境变量设置等,下面分别进行介绍。

1 命令行参数分析
main函数
   int main(int argc, char **argv)
或:

   int main(int argc, char *argv[])

 1 /* example20.c */
2 #include <stdlib.h>
3 #include <stdio.h>
4 int main(int argc, char ** argv)
5 {
6 int i;
7 for (i=0; i<argc; i++)
8 {
9 printf("Argument %d is %s.\n", i, argv[i]); /* 输出传入main函数的各个参数 */
10 }
11 return 0;
12 }

 

getopt函数可以用来分析传入的各命令行参数

   int getopt(int argc, char *const argv[], const char *optstring);
单个字符,表示选项;
单个字符后面跟一个冒号:
表示该选项后面必须跟一个参数,参数紧跟在选项后面,或者以空格隔开;

单个字符后面跟两个冒号:表示该选项后面必须跟一个参数,参数必须紧跟在选项后面,不能以空格隔开。

 1 /* example21.c */
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <unistd.h>
5 int main(int argc, char * argv[])
6 {
7 int ch;
8 if(argc < 2)
9 {
10 printf("no arguments\n");
11 }
12 while ((ch = getopt(argc, argv, "ab:c")) != -1) /* 分析各选项 */
13 {
14 printf("optind : %d\n", optind); /* 输出全局变量optind的值 */
15 switch (ch)
16 {
17 case 'a': /* 选项a */
18 printf("option : a\n");
19 break;
20 case 'b': /* 选项b,该选项必须带参数 */
21 printf("option : b\n");
22 printf("argument of -b : %s\n", optarg);
23 break;
24 case 'c': /* 选项c */
25 printf("option : c");
26 break;
27 case '?': /* 其他选项 */
28 printf("unknown option : %c\n", (char)optopt);
29 break;
30 default:
31 ;
32 }
33 }
34 return 0;
35 }

 

2 用户和用户组操作
用户和用户组操作的函数有getuid、getgid、getlogin、getpwent、getpwnam以及getutent等。

1).getuid函数
   uid_t getuid(void);

2).getgid函数
   gid_t getgid(void);

3).getlogin函数

   char *getlogin(void);

 1 /* example22.c */
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <unistd.h>
5 #include <sys/types.h>
6 int main()
7 {
8 uid_t uid;
9 gid_t gid;
10 uid = getuid(); /* 获取当前用户的标识符 */
11 gid = getgid(); /* 获取当前组的标识符 */
12 printf("user name : %s\n", getlogin()); /* 输出当前用户的账号名称 */
13 printf("uid = %d\n", uid);
14 printf("gid = %d\n", gid);
15 return 0;
16 }

 

4).getpwent函数

   struct passwd *getpwent(void);struct passwd {
 
 char *pw_name;
 char *pw_passwd;
 uid_t pw_uid;
 gid_t pw_gid;
 char *pw_gecos;
 char *pw_dir;
 char *pw_shell;
};

 1 /* example23.c */
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include<pwd.h>
5 #include<sys/types.h>
6 int main()
7 {
8 struct passwd *user;
9 user = getpwent();
10 while(user != NULL) /* 读取用户账号信息 */
11 {
12 printf("%s:%d:%d:%s:%s:%s\n", user->pw_name, user->pw_uid, user->pw_gid,
13 user->pw_gecos, user->pw_dir, user->pw_shell);
14 user = getpwent();
15 }
16 endpwent(); /* 关闭文件 */
17 return 0;
18 }


5).getpwnam函数

   struct passwd getpwnam(const char * name);

6).getutent函数

   struct utmp *getutent(void);struct utmp {

    short int ut_type;
    pid_t ut_pid;
     char ut_line[UT_LINESIZE];
  
  char ut_id[4];
    char ut_user[UT_NAMESIZE];
  
  char ut_host[UT_HOSTSIZE];
 
   struct exit_status ut_exit;
  
  long int ut_session;
 
   struct timeval ut_tv;
    int32_t ut_addr_v6[4];
     char __unused[20];

};

 1 /* example24.c */
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <utmp.h>
5 int main()
6 {
7 struct utmp *u;
8 while((u = getutent()) != NULL)
9 {
10 if(u->ut_type == USER_PROCESS) /* 判断是否为普通用户进程 */
11 printf("%s\t%s \n", u->ut_user, u->ut_line);
12 }
13 endutent(); /* 关闭文件 */
14 return 0;
15 }


3 环境变量操作
环境变量是包含系统环境信息的字符串,可以作用于用户的整个工作空间。这一小节将介绍环境变量操作相关的三个函数:getenv、putenv和setenv,他们分别用来获取环境变量、更改或增加环境变量。

1).getenv函数
   char *getenv(const char *name);

 1 /* example25.c */
2 #include <stdlib.h>
3 #include <stdio.h>
4 int main()
5 {
6 char *p;
7 p = getenv("SHELL"); /* 获取环境变量 */
8 if(p == NULL) /* 如果环境变量获取失败,输出错误信息并退出 */
9 {
10 printf("getenv error\n");
11 exit(1);
12 }
13 else
14 printf("SHELL=%s\n", p); /* 输出环境变量的内容 */
15 return 0;
16 }

 

 1 /* example26.c */
2 #include <stdlib.h>
3 #include <stdio.h>
4 int main(int argc, char * argv[])
5 {
6 char * p;
7 if(argc != 3) /* 检查命令行参数个数 */
8 {
9 printf("no arguments\n");
10 exit(1);
11 }
12 if((p=getenv(argv[1])) == NULL) /* 获取并输出环境变量 */
13 printf("%s does not exist\n", argv[1]);
14 else
15 printf("%s=%s\n", argv[1], p);
16 setenv(argv[1], argv[2], 1); /* 设置环境变量 */
17 if((p=getenv(argv[1])) != NULL) /* 重新获取并输出环境变量 */
18 {
19 printf("%s=%s\n", argv[1], p);
20 }
21 return 0;
22 }



2).putenv函数

   int putenv(const char *string);

3).setenv函数
   int setenv(const char *name,const char * value, int overwrite);

 

六 常见面试题
常见面试题1:memcpy函数与strcpy函数的主要差别是什么?

常见面试题2:编写一个函数,求两个给定字符串的最大公共子串。

 

 

posted @ 2012-03-09 16:58  MooreZHENG  阅读(236)  评论(0编辑  收藏  举报