本笔记记录自 Coursera课程 《计算机程式设计》 台湾大学 刘邦锋老师

Week6 String

6-1 Character and ASCII

字符变量的声明

  1. char c;

C语言使用一个位元组来储存一个字符,所以一个字符能存一个-128到127之间的整数。

例子:(char-size.c)一个char所占的位元组数

  1. #include <stdio.h>
  2. int main(void)
  3. {
  4. char c;
  5. printf("%d\n", sizeof(c));
  6. return 0;
  7. }

输出

  1. 1

字符的输出

  1. printf("%c", c);
  • 字符最大的用处就是以ASCII码的形式将文字讯息显示出来。
  • ASCII码(American Standard Code for Information Interchange),就是将0到127的整数对应到我们常用的英文大小写字母,0到9的数字,以及标点符号等。

例子:(ascii.c)印出部分ASCII码

  1. #include <stdio.h>
  2. int main(void)
  3. {
  4. char c;
  5. int i, j;
  6. printf("0123456789abcdef\n");
  7. for (i = 2; i <= 7; i++){
  8. for (j = 0; j <= 15; j++){
  9. c = i * 16 + j;
  10. printf("%c", c);
  11. }
  12. printf("\n");
  13. }
  14. return 0;
  15. }

输出

  1. 0123456789abcdef
  2. !"#$%&'()*+,-./
  3. 0123456789:;<=>?
  4. @ABCDEFGHIJKLMNO
  5. PQRSTUVWXYZ[\]^_
  6. 'abcdefghijklmno
  7. pqrstuvwxyz{|}~-
  • 这个程序印出由32到127的ASCII码。对应到的16进位数字是20到7F,我们选这个范围是因为32之前的都是特殊字符。
  • 输出是16个字符一行,而且在第一行加上0到f的16进位。

6-2 Character Constant and Integer

  • 字符常数将字符串的ASCII值和它所代表的符号连接起来。
  • C中字符常数是用一对单引号将一个符号括起来,代表它的ASCII值。

例子:(char-assignment.c)将字符常数指定给字符串变量

  1. #include <stdio.h>
  2. int main(void)
  3. {
  4. char c;
  5. c = 'm';
  6. printf("%c", c);
  7. c = 'a';
  8. printf("%c", c);
  9. c = 'i';
  10. printf("%c", c);
  11. c = 'n';
  12. printf("%c", c);
  13. c = '(';
  14. printf("%c", c);
  15. c = ')';
  16. printf("%c", c);
  17. c = '\n';
  18. printf("%c", c);
  19. c = '{';
  20. printf("%c", c);
  21. c = '\n';
  22. printf("%c", c);
  23. c = '}';
  24. printf("%c", c);
  25. return 0;
  26. }

输出结果

  1. main()
  2. {
  3. }

6-3 Character Input and C-type Functions

字符的输入

  1. scanf("%c", &c);

例子:(char-io.c)输入一个字符分别用字符或整数输出

  1. #include <stdio.h>
  2. int main(void)
  3. {
  4. char c;
  5. scanf("%c", c);
  6. printf("%c\n", c);
  7. printf("%d\n", c);
  8. return 0;
  9. }

输入

  1. a

输出

  1. a
  2. 97

借由scanf的返回值判定是否还有数据

  1. while (scanf("%c", &c) != EOF){
  2. ...
  3. process character c;
  4. }

使用字符分类函数

  1. #include <ctype.h>
  2. ...
  3. char c;
  4. ...
  5. if (isxxxxx(c))
  • 系统的<ctype.h>中定义了一些好用的字符处理函数。

    • 字符分类函数
    • 字符转换函数
  • 字符分类函数决定传进来字符是否属于某一类字符。
    • isalpha(c)会判断c是否为英文字母

字符串分类函数表

函数名称 分类
isalnum 英文字母或数字
isalpha 英文字母
islower 小写英文字母
isupper 大写英文字母
isdigit 数字
isxdigit 16进位数字
isprint 可显示字符(包含空白)
isgraph 可显示字符串(不包含空白)
isspace 空白
ispunct 标点符号
iscntrl 控制字符

6-4 Character Input EOF

在命令行形式下可以打CTRL+D来结束程序。

6-5 ASCII Table in Decimal Format

例子:(ascii-dec.c)用十进位印ASCII表

  1. #include <stdio.h>
  2. int main(void)
  3. {
  4. int c;
  5. printf(" 0123456789\n");
  6. for (c = 30; c <= 127; c++){
  7. if (c % 10 == 0)
  8. printf("%2d ", c / 10);
  9. if (isprint(c))
  10. printf("%c", c);
  11. else
  12. printf(" ");
  13. if (c % 10 == 9)
  14. printf("\n");
  15. }
  16. return 0;
  17. }

输出结果

  1. 0123456789
  2. 3 !"#$%&'
  3. 4 ()*+,-./01
  4. 5 23456789:;
  5. 6 <=>?@ABCDE
  6. 7 FGHIJKLMNO
  7. 8 PQRSTUVWXY
  8. 9 Z[\]^_'abc
  9. 10 defghijklm
  10. 11 nopqrstuvw
  11. 12 xyz{|}~
  • 想输出的范围是32到127可印出的部分。
  • 用isprint()检查是否列印,或是用空白代替。
  • 每一行的开始会印出十进位的前两位。为了对齐,这前两位指定用两位数字印出。方法是在%及d中放一个2。

6-6 Toupper and Tolower Functions

字符转换函数

函数名称 动作
tolower 转成小写英文字母
touppper 转成大写英文字母

6-7 String Declaration

字符串的声明

  1. char s[80];
  • 字符是专门用来处理文字资料的。而文字资料一般都是成批出现的。单独使用字符来处理成批的文字资料很麻烦,所以我们可以使用字符串来处理。
  • C语言以字符数组代表字符串。
  • 字符串的声明就必须制定足够的数组长度,也就是字符串的长度,来储存字符串中的字符。

例子:(string-size.c)字符串所占的记忆体位元组数

  1. #include <stdio.h>
  2. int main(void)
  3. {
  4. char s[80];
  5. printf("%D\n", sizeof(s));
  6. return 0;
  7. }

输出

  1. 80

例子:(string-init.c)使用数组的方式初始化一个字符串

  1. #include <stdio.h>
  2. int main(void)
  3. {
  4. char s[80] = {'m', 'a', 'i', 'n', '(', ')', '\n', '{', '\n', '}', '\n'};
  5. int i;
  6. for (i = 0; i < 11; i++)
  7. printf("%c", s[i]);
  8. return 0;
  9. }
  • C语言字符串处理的管理是字符串范围到'\0'这个特殊字符为止。这个特殊字符位元组中所有的位元皆为0。

用printf印出字符串

  1. printf("%S", string);

6-8 Empty String

  • 字符串常数和字符常数很类似,只不过字符串常数是用双引号,而字串常数是用单引号
  • printf输出一个整数的参数"%d"就是字符串常数。

例子:(string-init-double-quote.c)使用字符串常数的方式初始化

  1. #include <stdio.h>
  2. int main(void)
  3. {
  4. char s[80] = "main()\n{\n}\n";
  5. printf("%s", s);
  6. return 0;
  7. }
  • 空字符串写成“”
  • 空字符串的第一个字符就是'\0',所以它只占1个位元组。

6-9 String Input

例子:(string-io.c)字符串的输入

  1. #include <stdio.h>
  2. int main(void)
  3. {
  4. int i;
  5. char string[10];
  6. while (scanf("%s", string) != EOF){
  7. printf("%s\n", string);
  8. for (i = 0; i < 10 && string[i] != '\0'; i++)
  9. printf("%c ", string[i]);
  10. printf("\n");
  11. }
  12. return 0;
  13. }
  • scanf读字符串遇到空格就会断开,而不是读整行。

6-10 Character Pointer

指向一个字符数组的字符指针也能当字符串

  1. char string[80];
  2. char *ptr = string;

例子:(char-pointer.c)指向一个字符数组的字符指针

  1. #include <stdio.h>
  2. #include <string.h>
  3. int main(void)
  4. {
  5. char string[80];
  6. char *ptr = string;
  7. int i;
  8. scanf("%s", ptr);
  9. printf("%s\n", ptr);
  10. for (i = 0; i < strlen(ptr); i++)
  11. printf("%c ", ptr[i]);
  12. return 0;
  13. }

输入

  1. programming

输出

  1. programming
  2. p r o g r a m m i n g

字符指针类别的字符串也可以有初始值

  1. char *string = "programming";

6-11 Strien Usage

  • <string.h>标头档中定义了许多好用的函数,用之前记得要引入。

函数strlen

  1. int strlen(char *string);
  • strlen(string length)计算一个字符串的长度
  • strlen接受一个字符指针参数,这个指针指向要算长度的字串,算出字符串长度并返回。

6-12 Strcpy Strcat

函数strcpy与函数strcat

  1. char *strcpy(char *destination, char *source);
  2. char *strcat(char *destination, char *source);
  • strcpy(string copy)将source参数字符串复制到destination参数字符串,并返回destination的位址。
  • source字符串的结束字符'\0'也会被复制到destination字串。
  • strcat与strcpy类似,但strcat会将第二个字符串参数复制并接到第一个字符串参数的后面。

6-13 Strncpy Strncat

缓冲区覆盖

  • 在使用strcpy及strcat时我们有可能尝试将太长的字符串复制进目的字符串,以致超过目的字符串的长度。
  • 如果目的字符串的后面还有重要的数据,这些数据就会被破坏。这个现象称为缓冲区覆盖(buffer overrun)

函数strncpy与函数strncat

  1. char *strncpy(char *dest, char *source, int i);
  2. char *strncat(char *dest, char *source, int i);
  • strncpy可由第三个参数i控制“至多”要覆盖几个字符,避免缓冲区覆盖。
  • strncpy不会帮你补结束字符'\0',而是要自己加。

例子:(buffer-no-overrun.c)strncpy避免超过长度

  1. #include <stdio.h>
  2. #include <string.h>
  3. int main(void)
  4. {
  5. char destination[16];
  6. char source[80];
  7. printf("destination at %p\n", destination);
  8. printf("%s", source);
  9. scanf("%s", source);
  10. printf("source = %s\n", source);
  11. strncpy(destination, source, 15);
  12. destination[15] = '\0';
  13. printf("source = %s\n", source);
  14. printf("destination = %s\n", destination);
  15. reutrn 0;
  16. }

6-14 Strcmp and String Sorting

函数strcmp与函数strncmp

  1. int strcmp(char *string1, *string2);
  2. int strncmp(char *string1, *string2, int n);
  • strcmp比较两个字符串string1及string2的大小。strncmp只比较到n个字符。

    • 如果第一个字符串string1比较小则返回一个负数。
    • 如果第一个字符串string1比较大则返回一个正数。
    • 如果一样大则返回0。
  • 两个字符串的大小比法是由第一个字符开始按ASCII码的大小开始比,如果相同则比第二个字符,直到比出大小或是最后一个字符结束为止。

字符串排序

  • 十二生肖的字符串放在一个二维字符串数组里,第一维代表十二生肖,第二维代表字符串。
  • 使用两层for循环操作泡沫排序法。
    • 第一层循环决定两两交换的范围。
    • 第二层循环实际作两两交换。
  • 使用strcmp比较两个生肖字符串。

例子:(string-sort.c)将字符串排序

  1. #include <stdio.h>
  2. #include <string.h>
  3. int main(void)
  4. {
  5. char zodiac[12][40];
  6. int i, j;
  7. char temp[40];
  8. for (i = 0; i < 12; i++)
  9. scanf("%s", zodiac[i]);
  10. for (i = 10; i >= 1; i--)
  11. for (j = 0; j <= i; j++)
  12. if (strcmp(zodiac[j], zodiac[j + 1]) > 0){
  13. strcpy(temp, zodiac[j]);
  14. strcpy(zodiac[j], zodiac[j + 1]);
  15. strcpy(zodiac[j + 1], temp);
  16. }
  17. for (i = 0; i < 12; i++)
  18. printf("%s\n", zodiac[i]);
  19. return 0;
  20. }

输入

  1. rat
  2. ox
  3. tiger
  4. hare
  5. dragon
  6. snake
  7. horse
  8. sheep
  9. monkey
  10. rooster
  11. dog
  12. pig

输出

  1. dog
  2. dragon
  3. hare
  4. horse
  5. monkey
  6. ox
  7. pig
  8. rat
  9. rooster
  10. sheep
  11. snake
  12. tiger

例子:(string-pointer-sort.c)使用指针数组将字符串排序

  1. #include <stdio.h>
  2. #include <string.h>
  3. int main(void)
  4. {
  5. char zodiac[12][40];
  6. char *zptr[12];
  7. int i;
  8. int j;
  9. char *temp;
  10. for (i = 0; i < 12; i++){
  11. scanf("%s", zodiac[i]);
  12. zptr[i] = zodiac[i];
  13. }
  14. for (i = 10; i >= 1; i--)
  15. for (j = 0; j<= i; j++)
  16. if (strcmp(zptr[j], zptr[j + 1]) > 0){
  17. temp = zptr[j];
  18. zptr[j] = zptr[j + 1];
  19. zptr[j + 1] = temp;
  20. }
  21. for (i = 0; i < 12; i++)
  22. printf("%s\n", zptr[i]);
  23. return 0;
  24. }

6-15 Strtok

函数strtok

  1. char *strtok(char *string, char *delimeters);
  • strtok(string to token)把第一个字符串参数string切成一段一段的token。
  • token是第一个字符串中被第二个字符串参数delimeters中的任何字符所隔开的部分。

例子:(strtok.c)使用strtok将字串切成token

  1. #include <stdio.h>
  2. #include <string.h>
  3. int main(void)
  4. {
  5. char delimeters[] = "/";
  6. char pathname[40];
  7. char file[40][40];
  8. int file_count = 0;
  9. char *start = pathname;
  10. int copy_length;
  11. int i;
  12. scanf("%s", pathname);
  13. start = strtok(start, delimeters);
  14. while (start != NULL){
  15. strcpy(file[file_count], start);
  16. file_count++;
  17. start = strtok(NULL, delimeters);
  18. }
  19. for (i = 0; i < file_count; i++)
  20. printf("%s\n", file[i]);
  21. printf("After strtok pathname becomes %s\n", pathname);
  22. return 0;
  23. }

输入

  1. /usr/local/bin/emacs

输出

  1. usr
  2. local
  3. bin
  4. emacs
  5. After strtok pathname becomes /usr

测验代码

自己写的

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <ctype.h>
  4. int main(void)
  5. {
  6. char sentence[100][40];
  7. int i = 0;
  8. int j;
  9. int n;
  10. int start_num = 0;
  11. int end_num = 0;
  12. int k;
  13. int p = 0;
  14. char output[40];
  15. //输入字符串
  16. while (scanf("%s", sentence[i]) != EOF)
  17. i++;
  18. //分割词组,并打印
  19. for (j = 0; j < i; j++){
  20. n = strlen(sentence[j])-1;
  21. if (isalpha(sentence[j][n]))
  22. end_num++;
  23. else{
  24. end_num = j;
  25. for (k = start_num; k <= end_num; k++)
  26. if ((strcmp(sentence[k], "of") != 0) && (strcmp(sentence[k], "and") != 0) && (strcmp(sentence[k], "the") != 0) && (strcmp(sentence[k], "at") != 0)){
  27. output[p]=toupper(sentence[k][0]);
  28. p++;
  29. }
  30. printf("%s ", output);
  31. strncpy(output, "",p);
  32. p = 0;
  33. start_num = j + 1;
  34. end_num = j + 1;
  35. }
  36. }
  37. return 0;
  38. }

老师写的

  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #include <string.h>
  4. int main ()
  5. {
  6. char str[128];
  7. int flag = 0;
  8. while ( scanf ( "%s", str ) != EOF ) {
  9. if ( flag ) {
  10. printf ( " " );
  11. flag = 0;
  12. }
  13. if ( strchr ( str, '.' ) )
  14. flag = 1;
  15. if ( !strcmp ( str, "and" ) || !strcmp ( str, "at" ) ||
  16. !strcmp ( str, "of" ) || !strcmp ( str, "the" ) )
  17. continue;
  18. printf ( "%c", toupper ( str[0] ) );
  19. }
  20. return 0;
  21. }

以及安利一个C的在线编译器,比老师推荐的ideone速度快些,也更清爽些。

C语言在线编译器

【C语言】Coursera课程《计算机程式设计》台湾大学刘邦锋——Week6 String课堂笔记的更多相关文章

  1. Coursera课程《Machine Learning》吴恩达课堂笔记

    强烈安利吴恩达老师的<Machine Learning>课程,讲得非常好懂,基本上算是无基础就可以学习的课程. 课程地址 强烈建议在线学习,而不是把视频下载下来看.视频中间可能会有一些问题 ...

  2. 【Python学习笔记】Coursera课程《Python Data Structures》 密歇根大学 Charles Severance——Week6 Tuple课堂笔记

    Coursera课程<Python Data Structures> 密歇根大学 Charles Severance Week6 Tuple 10 Tuples 10.1 Tuples A ...

  3. 《计算机程式设计》Week5 课堂笔记

    本笔记记录自 Coursera课程 <计算机程式设计> 台湾大学 刘邦锋老师 Week5 Pointer 5-1 Pointer Definition and Declaration 指针 ...

  4. 《计算机程式设计》Week3 课堂笔记

    本笔记记录自 Coursera课程 <计算机程式设计> 台湾大学 刘邦锋老师 Week3 Array 3-1 Array Usage 例子:使用数组一次申明10个整数变量 int a[10 ...

  5. 《计算机程式设计》Week4 课堂笔记

    本笔记记录自 Coursera课程 <计算机程式设计> 台湾大学 刘邦锋老师 Week4 Functions 4-1 System Function 函数主要分为两大类系统定义函数与使用者 ...

  6. 《计算机程式设计》Week2 课堂笔记

    本笔记记录自 Coursera课程 <计算机程式设计> 台湾大学 刘邦锋老师 Week2 Control Structure 2-1 If-then-else if then 判断 if ...

  7. 【DeepLearning学习笔记】Coursera课程《Neural Networks and Deep Learning》——Week2 Neural Networks Basics课堂笔记

    Coursera课程<Neural Networks and Deep Learning> deeplearning.ai Week2 Neural Networks Basics 2.1 ...

  8. C语言程序设计课程总结

    第一次教授C语言程序设计课程,相比计算机组成原理.arm体系结构等偏向硬件的课程,C的教学方式要灵活一些.计算机组成原理课程偏向理论,哈尔滨工业大学的计算机组成原理是国家精品课,增加了mooc+spo ...

  9. 第一次使用博客及Coursera课程体验

    前言: 第一天的学习目标有三个 开设博客园账户 开设Github账号 进行第一次coursera课程学习:Internet History, Technology, and Security  (网址 ...

随机推荐

  1. BZOJ 1055 玩具取名(区间DP)

    很显然的区间DP,定义dp[i][j][k], 如果dp[i][j][k]=1表示字符串[i,j]可以组成k字符. # include <cstdio> # include <cst ...

  2. JS面向对象基础讲解(工厂模式、构造函数模式、原型模式、混合模式、动态原型模式)

    什么是面向对象?面向对象是一种思想. 面向对象可以把程序中的关键模块都视为对象, 而模块拥有属性及方法. 这样如果我们把一些属性及方法封装起来,日后使用将非常方便,也可以避免繁琐重复的工作.   工厂 ...

  3. chrome源码之恢复上次打开的标签页的学习

    startup_browser_creator_impl.cc ————————>打开任何页面或浏览器的入口函数bool StartupBrowserCreatorImpl::ProcessSt ...

  4. [COGS2652]秘术「天文密葬法」

    description 题面 给个树,第\(i\)个点有两个权值\(a_i\)和\(b_i\),现在求一条长度为\(m\)的路径,使得\(\frac{\sum a_i}{\sum b_i}\)最小 d ...

  5. CF359D:Pair of Numbers——题解

    https://vjudge.net/problem/CodeForces-359D http://codeforces.com/problemset/problem/359/D 题目大意: 给一串数 ...

  6. HDOJ.1113 Word Amalgamation(map)

    Word Amalgamation 点我挑战题目 点我一起学习STL-MAP 题意分析 给出字典.之后给出一系列======乱序======单词,要求你查字典,如过这个乱序单词对用有多个有序单词可以输 ...

  7. [zz]【整理】Python中Cookie的处理:自动处理Cookie,保存为Cookie文件,从文件载入Cookie

    http://www.crifan.com/python_auto_handle_cookie_and_save_to_from_cookie_file/ #!/usr/bin/python # -* ...

  8. C# 枚举的初始化

    3.2 枚举类型(Enum types)的默认值 对于枚举类型(Enum types),.NET会自动将字面值0(literal 0)隐式地转换为对应的枚举类型. 3.2.1 有一个0值成员 如果枚举 ...

  9. B树及其变种

    B树是为磁盘或其他直接存取的辅助存储设备而设计的一种平衡搜索树.B树类似于红黑树,但它们在降低磁盘I/O操场数方面要更好一些.许多数据库系统使用B树或B树的变种来存储信息. 介绍 常见的动态查找树包括 ...

  10. linux下输出查看进程及杀进程

    1.查找有关tomcat的进程 ps -ef | grep tomcat 2.查看某端口占用情况 netstat -tulpn | grep 9009 3.杀进程 普通:kill 进程id 强制:ki ...