程序设计II 第三讲 字符串处理.

Slides:



Advertisements
Similar presentations
1 第 3 章 C++ 中的条件与循环 第 3 次见面! acm.nefu.edu.cn/C++_03.ppt.
Advertisements

While 迴圈 - 不知重複執行次數
电子成绩单项目实现.
第 2 章 初探 C++.
程序设计实习 3月份练习解答
第九章 字串 (String).
補充: Input from a text file
C++程序设计 王希 图书馆三楼办公室.
第六讲 指针与字符串 —— 为什么指针 —— 持久动态内存分配 —— 字符串(字符数组).
第8章 字元與字串處理 8-1 C語言的字元檢查函數 8-2 C語言的字串 8-3 字串的輸入與輸出 8-4 指標與字串
第4章 串 串的基本概念和C语言的串函数 串的存储结构 动态数组实现的顺序串 串的模式匹配算法——BF算法 主要知识点.
第一章 程序设计入门.
函數 授課:ANT 日期:2009/3/24.
資料大樓 --談指標與陣列 綠園.
函數(一) 自訂函數、遞迴函數 綠園.
东北林业大学 陈宇 ACM程序设计 东北林业大学 陈宇
函數 授課:ANT 日期:2011/3/28.
If … else 選擇結構 P27.
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
计算概论 第十八讲 C语言高级编程 结构与习题课 北京大学信息学院.
Introduction to the C Programming Language
Object-Oriented Programming in C++ 第一章 C++的初步知识
程序设计期末复习 黎金宁
第12章 從C到C++語言 12-1 C++語言的基礎 12-2 C++語言的輸出與輸入 12-3 C++語言的動態記憶體配置
2 C++ 的基本語法和使用環境 親自撰寫和執行程式是學好程式語言的不二法門。本章藉由兩個簡單的程式,介紹C++ 程式的基本結構和開發環境,讓初學者能逐漸建立使用C++ 的信心。
程式撰寫流程.
Chap 8 指针 8.1 寻找保险箱密码 8.2 角色互换 8.3 冒泡排序 8.4 电码加密 8.5 任意个整数求和*
第5章 堆疊(Stacks) 5-1 堆疊的基礎 5-2 堆疊的表示法 5-3 堆疊的應用 - 運算式的計算與轉換
计算机网络讲义 第5章 批量数据处理—数组 一维数组 排序和查找 二维数组 字符串.
C语言 程序设计基础与试验 刘新国、2012年秋.
C++程序设计 string(字符串类) vector(容器类).
字符串和字符数组 字符串的输入和输出 字符串的基本操作
C++语言程序设计 第二章 C++简单程序设计.
2017 添加标题.
計數式重複敘述 for 迴圈 P
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
切換Dev c++顯示語言 工具->環境選項(V)->介面->language (Chinese TW)
数组 梁春燕 华电信息管理教研室.
2013年工作总结及14年计划 人力资源部 二〇一三年十二月.
C++大学基础教程 第5章 数组 北京科技大学 信息基础科学系.
C++ 程式設計 基礎篇 張啟中 Chang Chi-Chung.
C语言复习3----指针.
C++语言程序设计 C++语言程序设计 第三章 控制语句 第十一组 C++语言程序设计.
今天, AC 你 了吗? 2019/4/26.
函式庫補充資料.
C语言的特点 1. C程序由许多函数组成 2. C程序必须有且只有一个主函数main( ) 3. 函数用“{”和“}”表示起点和终点
物件導向程式設計 CH2.
第11章 從C到C++語言 11-1 C++語言的基礎 11-2 C++語言的資料型態與運算子 11-3 C++語言的輸出與輸入
字符串 (String) 字符串是 n (  0 ) 个字符的有限序列, 记作 S = “c1c2c3…cn” 其中,S 是串名字
C++语言程序设计 C++语言程序设计 第二章 基本数据类型与表达式 第十一组 C++语言程序设计.
C程序设计.
C++程式設計入門 變數與運算子 作者:黃建庭.
第九章 指针.
C/C++基礎程式設計班 C++: 物件的使用、參考、重載函式 講師:林業峻 CSIE, NTU 3/28, 2015.
第 8 章 标准模板库STL 陈哲 副教授 南京航空航天大学 计算机科学与技术学院.
#include <iostream.h>
C++语言程序设计 C++语言程序设计 第二章 基本数据类型与表达式 第十一组 C++语言程序设计.
C/C++基礎程式設計班 字元與字串 講師:林業峻 CSIE, NTU 3/14, 2015.
Oop7 字串 String.
Introduction to the C Programming Language
C++语言程序设计 C++语言程序设计 第十一章 异常处理 C++语言程序设计.
C 程式設計— 字元與字串 台大資訊工程學系 資訊系統訓練班.
字串 第10章 part I 8/30/2019.
變數與資料型態  綠園.
資料!你家住哪裏? --談指標 綠園.
第三章 流程控制 程序的运行流程 选择结构语句 循环结构语句 主讲:李祥 时间:2015年10月.
第11章 字符和内存处理 一、字符数组、指针和字符串的初始化作用 二、strlen函数确定字符串有效长度 三、strcpy函数拷贝字符串.
台大資訊工程學系 資料系統訓練班 第119期 吳晉賢
C++语言程序设计 C++语言程序设计 第二章 基本数据类型与表达式 第十一组 C++语言程序设计.
Presentation transcript:

程序设计II 第三讲 字符串处理

内容提要 字符串的存储、字符串处理函数 将数组传递给函数 例题:ai2767 Caesar密码 (P115) 例题:单词排序 例题:ai2744 子串 (P112) 例题:POJ1936 All in All

字符串 每个字符串是一个特殊的数组,满足两个条件 元素的类型为char 最后一个元素的值为‘\0’ ,Ascii码就是 0 以字符型数组存储 从0号元素开始存储 最大可以存储长度为N-1的字符串,N是数组的大小。 字符串“hello”在长度为10的字符串数组中的存储 h e l l o \0

字符串处理函数 将格式化数据写入字符串:sprintf 字符串长度查询函数: strlen 字符串复制函数:strcpy、strncpy 字符串连接函数: strcat 字符串比较函数: strcmp、strncmp、stricmp、strnicmp 字符串搜索函数: strcspn、strspn、strstr、strtok、strchr 字符串大小写转换函数: strlwr、strupr 这些函数都要求 #include <string.h>

字符串拷贝和求字符串长度 char *strcpy(char *dest, const char *src); int strlen(const char *s); 查询str1中字符串的长度 #include <stdio.h> #include <string.h> void main() { char str1[10]="hello", str2[12]; strcpy(str2,"hello world"); printf("length:%d(str1); %d(str2)\n", strlen(str1), strlen(str2)); strcpy(str1, str2); printf("length:%d(str1); %d(str2)\n", strlen(str1), strlen(str2)); printf("%s\n", str1); return; } 把”hello world”复制到str2 把str2复制到str1

输出结果: length:5(str1); 11(str2) length:11(str1); 11(str2) hello world str1存储了11个非’\0’字符? strcpy在复制字符串str2到str1时,不检查str2是否超出了str1的存储容量,而是直接将str2中存储的字符串复制到从str1开始的一段连续区域 在程序中要特别注意这种情况所引发的程序运行 不确定性

strcpy(str2,“hello world"); main() str1 h e l l o \0 str2 strcpy(str2,“hello world"); str1 h e l l o \0 str2 h e l l o w o r l d \0 strcpy(str1,str2); str1 h e l l o w o r l d \0 str2 h e l l o w o r l d \0

用strlen时常犯的错误 int MyStrchr(char * s, char c) //看s中是否包含 c { for( int i = 0; i < strlen(s); i ++ ) if( s[i] == c) return 1; return 0; } 哪里不好?这个函数执行时间和 s 的长度是什么关系? strlen 是一个o(N)的函数,每次判断 i < strlen(s) – 1 都要执行,太浪费时间了

字符串添加 strcat char *strcat(char *dest, const char *src); 把src内容加到dest后面,同样不会考虑 dest是否够长 #include <stdio.h> #include <string.h> void main() { char str1[100]="hello", str2[10]="^_^"; strcat(str1," world "); printf("%s\n", str1); strcat(str1, str2); return; } 把”world”添加到str1中原字符串的末尾 把str2中的字符串添加到str1中原字符串的末尾 输出: hello world hello world ^_^

字符串比较函数strcmp(分大小写)、stricmp(不分大小写) int strcmp(const char *s1, const char *s2); Return Value If s1 is... return value is... less than s2 < 0 the same as s2 == 0 greater than s2 > 0 int stricmp(const char *s1, const char *s2); Compares one string to another, without case sensitivity. Return Value If s1 is... return value is... less than s2 < 0 the same as s2 == 0 greater than s2 > 0

关于 stricmp 的注意事项 stricmp 不是严格意义上的C++标准库函数,所以不同编译器的实现有所不同。 比如在POJ上交题,编译器选C++时,该函数应写为: _stricmp 不同编译器的 _stricmp 库函数执行过程也可能不一样,有的是把小写转换成大写后比较,有的是把大写转换成小写后比较,所以,在待比较字符串里面有非字母字符,比如标点符号时,不同编译器的 _stricmp执行的结果有可能不同

字符串比较函数strcmp、stricmp #include <string.h> #include <stdio.h> char string1[] = "The quick brown dog jumps over the lazy fox"; char string2[] = "The QUICK brown dog jumps over the lazy fox"; void main( void ) { int result; printf( "Compare strings:\n\t%s\n\t%s\n\n", string1, string2 ); result = strcmp( string1, string2 ); printf( "strcmp: result=%d\n", result); result = stricmp( string1, string2 ); printf( "stricmp: result=%d\n", result); return; }

输出: Compare strings: The quick brown dog jumps over the lazy fox The QUICK brown dog jumps over the lazy fox strcmp: result=1 stricmp: result=0

查找子串strstr char *strstr(char *s1, char *s2); Scans a string for the occurrence of a given substring. 查找给定字符串在字符串中第一次出现的位置,返回位置指针 strstr scans s1 for the first occurrence of the substring s2. Return Value strstr returns a pointer to the element in s1, where s2 begins (points to s2 in s1). If s2 does not occur in s1, strstr returns null. 如果找到,返回指针,指向s1中第一次出现s2的位置 如果找不到,返回 NULL

在string中搜索str,返回str在string中第一次出现的位置 #include <string.h> #include <stdio.h> char str[] = "lazy"; char string[] = "The quick brown dog jumps over the lazy fox"; void main( void ) { char *pdest; int result; pdest = strstr( string, str ); result = pdest - string + 1; if( pdest != NULL ) printf( "%s found at position %d\n\n", str, result ); else printf( "%s not found\n", str ); } 输出: lazy found at position 36 在string中搜索str,返回str在string中第一次出现的位置

在字符串中查找字符 strchr char *strchr(char *s, int c); Scans a string for the first occurrence of a given character. 查找给定字符在字符串中第一次出现的位置,返回位置指针 strchr scans a string in the forward direction, looking for a specific character. strchr finds the first occurrence of the character c in the string s. Return Value strchr returns a pointer to the first occurrence of the character c in s; if c does not occur in s, strchr returns null.

在string中搜索ch,返回str在string中第一次出现的位置 在字符串中查找字符 strchr #include <string.h> #include <stdio.h> int ch = 'r'; char string[] = "The quick brown dog jumps over the lazy fox"; void main( void ) { char *pdest; int result; pdest = strchr( string, ch ); result = pdest - string + 1; if( pdest != NULL ) printf( "Result:\tfirst %c found at position %d\n\n", ch, result ); else printf( "Result:\t%c not found\n" ); } 输出: Result: first r found at position 12 在string中搜索ch,返回str在string中第一次出现的位置

字符串部分拷贝 strncpy char *strncpy(char *dest, char *src, int maxlen); 将前 maxlen 个字符从src拷贝到dest 1)如果src中字符不足 maxlen 个,则连’\0’一起拷贝,’\0’后面的不拷贝 2) 如果src中字符大于等于maxlen个,则拷贝 maxlen个字符

字符串部分拷贝 strncpy 输出: abcd abcd567890 #include <iostream> using namespace std; #include <stdio.h> int main(void) { char s1[20] = "1234567890"; char s2[] = "abcd" ; strncpy( s1,s2,5); cout << s1 << endl; strcpy( s1,"1234567890"); strncpy( s1,s2,4); return ; } 输出: abcd abcd567890

数组作为函数的参数 #include <iostream> using namespace std; char str1[200] = "Hello,World"; char str2[100] = "Computer"; void swap( char s1[ ], char * s2) //交换两个字符串的内容 { char c; for( int i = 0; s1[i] || s2[i]; i ++ ){ // ‘\0’的Ascii 码就是 0 c = s2[i]; s2[i] = s1[i]; s1[i] = c; } s1[i+1] = s2[i+1] = 0; int main() swap(str1,str2); cout << str1 << endl << str2; return 0; 输出: Computer Hello,World

例题:ai2767 Caesar密码 (P115) 问题描述 Julius Caesar 生活在充满危险和阴谋的年代。为了生存,他首次发明了密码,用于军队的消息传递 假设你是Caesar 军团中的一名军官,需要把Caesar 发送的消息破译出来、并提供给你的将军。消息加密的办法是:对消息原文中的每个字母,分别用该字母之后的第5个字母替换(例如:消息原文中的每个字母A都分别替换成字母F,V替换成A,W替换成B…),其他字符不 变,并且消息原文的所有字母都是大写的。

密码消息:由1到200个字符组成一行,表示Caesar发出的一条消息 结束行:END 密码字母:A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 原文字母:V W X Y Z A B C D E F G H I J K L M N O P Q R S T U 输入 最多不超过100个数据集组成。每个数据集由3部分组成 起始行:START 密码消息:由1到200个字符组成一行,表示Caesar发出的一条消息 结束行:END 在最后一个数据集之后,是另一行:ENDOFINPUT 输出 每个数据集对应一行,是Caesar 的原始消息。

样例输入 START NS BFW, JAJSYX TK NRUTWYFSHJ FWJ YMJ WJXZQY TK YWNANFQ HFZXJX END N BTZQI WFYMJW GJ KNWXY NS F QNYYQJ NGJWNFS ANQQFLJ YMFS XJHTSI NS WTRJ IFSLJW PSTBX KZQQ BJQQ YMFY HFJXFW NX RTWJ IFSLJWTZX YMFS MJ ENDOFINPUT 样例输出 IN WAR, EVENTS OF IMPORTANCE ARE THE RESULT OF TRIVIAL CAUSES I WOULD RATHER BE FIRST IN A LITTLE IBERIAN VILLAGE THAN SECOND IN ROME DANGER KNOWS FULL WELL THAT CAESAR IS MORE DANGEROUS THAN HE

#include <iostream> #include <string.h> using namespace std; int main() { char szLine[300]; while( cin.getline(szLine,210) ) { //可用此方式判断数据是否读完 /*cin.getline 读取一行,第一个参数是缓冲区地址;第二个参数是缓冲区大小,为了防止越界用的。缓冲区不够大,就自动截断。它会自动往缓冲区末尾添加 ‘\0’。*/ if( strcmp( szLine,"ENDOFINPUT") == 0) break; cin.getline(szLine,210); //读取密文 for( int i = 0; szLine[i]; i ++ ) if( szLine[i] >= 'A' && szLine[i] <= 'Z' ) { szLine[i] -= 5; if( szLine[i] < 'A' ) szLine[i] = 'Z' - ('A' - szLine[i]) + 1; } cout << szLine; cout << endl; cin.getline(szLine,210); //读取 END } return 0;

例题:单词排序 输入若干行单词(不含空格),请按字典序排序输出。大小写有区别。单词一共不超过100行,每个单词不超过20字符 Sample input: What man Tell About back Sample output: About Tell What back man

例题:单词排序 用什么保存多个单词? 答:用二维字符数组 char Word[100][30]; 则表达式 Word[i] 的类型就是 char * Word[i] 就是数组中的一行,就是一个字符串 Word[i][0] 就是Word[i] 这个字符串的头一个字符 二维字符数组也能初始化,例如: char week[7][10]={"Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday"};

例题:单词排序 #include <stdlib.h> #include <stdio.h> #include <string.h> char Word[100][30]; int MyCompare( const void * e1, const void * e2 ) { return strcmp( (char * ) e1, (char * ) e2 ); } int main() int n = 0; //单词个数 while(scanf("%s",Word[n]) != EOF && Word[n][0]) n ++; qsort(Word, n,sizeof(Word[0]),MyCompare); for( int i = 0; i < n; i ++ ) printf(“%s\n”,Word[i]); // ‘\n’表示换行 return 0; 为了对付有可能最后一行读入的是空行

例题:ai2744 子串 (P112) 问题描述:给出一些由英文字符组成的大小写敏感的字符串的集合s,请找到一个最长的字符串x,使得对于s中任意字符串y,x或者是y的子串,或者x中的字符反序之后得到的新字符串是y的子串。 输入:输入的第一行是一个整数t (1 <= t <= 10),t表示测试数据的数目。对于每一组测试数据,第一行是一个整数n (1 <= n <= 100),表示已经给出n个字符串。接下来n行,每行给出一个长度在1和100之间的字符串。

例题:ai2744 子串 (P112) 输出:对于每一组测试数据,输出一行,给出题目中要求的字符串x的长度。 Sample Input: 2 3 ABCD BCDFF BRCD rose orchid Sample Output 2 2

例题:ai2744 子串 (P112) 思路: 随便拿出输入数据中的一个字符串,从长到短找出它的所有子串,直到找到否符合题目要求的。 改进: 不要随便拿,要拿输入数据中最短的那个。从长到短找出它的所有子串,直到找到否符合题目要求的。

#include <stdio.h> #include <string.h> int t, n; char str[100][101]; int searchMaxSubString(char* source); int main() { int i, minStrLen, subStrLen; char minStr[101]; scanf("%d", &t); while(t--) { scanf("%d", &n); minStrLen = 100; //记录输入数据中最短字符串的长度 for (i = 0; i < n; i++) {//输入一组字符串 scanf("%s", str[i]); if ( strlen(str[i]) < minStrLen ) {//找其中最短字符串 strcpy(minStr, str[i]); minStrLen = strlen(minStr); } subStrLen = searchMaxSubString(minStr);//找答案 printf("%d\n", subStrLen); } return 0;

int searchMaxSubString(char* source) { int subStrLen = strlen(source), sourceStrLen = strlen(source); int i, j; bool foundMaxSubStr; char subStr[101], revSubStr[101]; while ( subStrLen > 0 ) {//搜索不同长度的子串,从最长的子串开始搜索 for (i = 0; i <= sourceStrLen - subStrLen; i++) { //搜索长度为subStrLen的全部子串 strncpy(subStr, source+i, subStrLen); strncpy(revSubStr, source+i, subStrLen); subStr[subStrLen] = revSubStr[subStrLen] = '\0'; _strrev(revSubStr); foundMaxSubStr = true; for( j = 0; j < n; j++) //遍历所有输入的字符串 if ( strstr(str[j], subStr) == NULL && strstr(str[j], revSubStr) == NULL ) { foundMaxSubStr = false; break; } if (foundMaxSubStr) return subStrLen; subStrLen--; return(0); _strrev (char * s) 将字符串 s 颠倒