一,本章学习内容有:
1,串的类型定义,存储结构及其运算
记录的一些知识点:
(1)C语言,求串的长度
char a[100];
strlen();
(头文件为
而C++中
string a;
a.length();
(2)串的模式匹配算法
对比 BF算法和KMP算法
难点:KMP算法中的next[ ]函数
作业题的第一题可以应用这两种方法来解题
但是由于next函数的一些问题还没解决,所以我的代码只是部分正确
1 #include2 #include <string.h> 3 using namespace std; 4 5 //计算next函数 6 int* get_next(string T)//通过相等的两条模式串得出next的规律 7 { 8 int* next = new int[T.length()];//为next数组动态 分配空间 9 int i = 1; 10 next[1] = 0; 11 int j = 0; 12 while(i //未到达队尾 13 { 14 if(j == 0 || T[i] == T[j])//如果j为0 或者 两个对应字符相等 15 {++i;++j;next[i]=j;}//后移一位,把j的位置记到next函数中 16 else j = next[j];//否则,下面的模式根据next函数右移 17 } 18 return next;//因为是指针函数,所以返回next数组首地址 19 } 20 21 //KMP算法 22 int Index_KMP(string S,string T) 23 { 24 int j = 1; 25 int i = 1; //位置? 26 int m = S.length(); 27 int n = T.length(); 28 int *next=get_next(T);//用next指针接受指针函数传来的数组地址 29 30 while(i<=m && j<=n)//l两串均未到达队尾 31 { 32 if(j==0 || S[i] == T[i]) 33 { ++i;++j; }//若模式串为0 或 两对应字符相等,后移一位 34 else j = next[j];//若不匹配且j不为0,则模式串右移,通过next[]函数 35 if(j>n) return i-n;//若匹配,则j=j+1,会比模式串大1 36 else return 0; } 37 } 38 int main() 39 { 40 string S, T; 41 getline(cin,S); 42 getline(cin,T); 43 get_next(T); 44 cout << Index_KMP(S,T); 45 return 0; 46 }
还有一个没解决的问题,不知道i,j表示的是下标还是位置,以及用下标或是位置的话,在代码中有什么不能解决的地方。
2,数组:
特殊矩阵中的对称矩阵,稀疏矩阵
因为课本中没有例题,PPT中关于这部分的代码也很少,所以在做实践题的第一题的时候有点不知道怎么下手,
参考了一些同学的博客后才有了一点想法,但是对于利用三元组表压缩和用十字链表压缩的实现,虽然知道想法,但我不知道怎么打这个代码。
1 #include2 using namespace std; 3 typedef struct{ 4 int q; 5 int p; 6 int val; 7 }node; 8 typedef struct{ 9 int m, n, N; 10 node a[100]; 11 }Matrix; 12 13 int main() 14 { 15 Matrix K; 16 node a[100]; 17 int P; 18 int m, n, N; 19 cin >> K.m; 20 cin >> K.n; 21 cin >> K.N;//输入矩阵的行数,列数,非0个数N,N可在下面用作输入的限制 22 for(int i=0; i //输入每个元素的行,列,值到数组里 23 cin >> K.a[i].q; 24 cin >> K.a[i].p; 25 cin >> K.a[i].val; 26 } 27 cin >> P;//输入待匹配的值P 28 int i = 0; 29 int flag = 0;//设定标志 30 while(i < K.N) { 31 if(P == K.a[i].val){//对比看是否相等 32 cout << K.a[i].q << ' ' < //如果相等,则输出该元素的行,列 33 flag = 1;//修改标志值 34 } 35 ++i; 36 } 37 if(flag == 0) 38 cout << "ERROR" <<endl; 39 return 0; 40 }
3,本周老师带着我们一起打了一道关于AI的题,感觉学到的东西很多,并且根据上课的代码,也能自己推出由“can you"换为”I can"的方法
1 #include2 #include 3 #include 4 #include <string>//用string 的头文件 5 using namespace std; 6 7 bool isDependent(char ch) 8 { 9 //判断ch是否分隔符 10 //字母数字空格标点杠铃 11 ch = tolower(ch); 12 if((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')) 13 return false; 14 else 15 return true; 16 } 17 18 19 void go(string s){ 20 //根据S输出AI的回答 21 char t[3001]; 22 // 1234 789 23 //1234 789 24 int i,j;//i为输入串的下标,j为输出串的下标 25 for(i=0;s[i]!='\0' && s[i]==' ';++i);//\0 当i定位到S的第一个非空,跳出循环 26 j = 0; 27 28 29 //下面搞空格问题 30 while(s[i]!= '\0'){//i变化不规律,用while 不用if(i++)//把s串copy到t,连续空格只copy一个 31 32 if(s[i]==' ' && s[i-1]==' '){//空格前还是空格时,i加1跳过该空格 33 ++i; 34 continue;} 35 36 if(s[i]=='?'){//当为问号时,改问号为感叹号 ,并下标都加一 37 t[j++] = '!'; 38 i++; 39 continue;//回到循环开头 ,回到判断是s[i]是否为结尾符 40 } 41 42 if(s[i]!='I'){//除I以外的大写转小写 43 t[j]= tolower(s[i]); 44 ++j,++i; 45 continue;//回到循环开头 ,回到判断是s[i]是否为结尾符 46 } 47 t[j++] = s[i++];//因为前面的函数都有continue,进入了就退出,不读此句,所以该语句是用于第一句的空格处理 48 //如果是非空字符后第一个空格,就写入t,然后i++,j++ 49 //不能copy连续的空格 ,先读变量值,为下一轮循环做准备 50 //此时t没有处理'\0' 后面读出字符串会出错 51 } 52 53 t[j]='\0';// 字符串结尾标志;完全读完后,因为前面的while语句读不到、0,需要手动在t字符结尾附上\0 54 //s完全读入了t 55 j=0;//开始全部输出t并进行修改 56 while(t[j]!='\0'){ 57 if(t[j]=='I'&&(j==0||isDependent(t[j-1])&&isDependent(t[j+1])))//有j+1-1要考虑是否越界 58 { 59 cout<<"you"; 60 ++j; 61 continue; 62 } 63 //下面搞me,考虑独立和不独立 64 if(t[j]=='m' && t[j+1]=='e' && (j==0||isDependent(t[j-1])&&isDependent(t[j+2])))//j+2不会越界,因为与的特性,前面的对了就不看后面的 65 { 66 cout<<"you"; 67 j=j+2; 68 continue; 69 } 70 71 if(t[j]==' ' && isDependent(t[j+1])){ 72 ++j; 73 continue; 74 } 75 76 //搞canyou 77 if(t[j]=='c' && t[j+1]=='a' && t[j+2]=='n' && t[j+3]==' '&& t[j+4]=='y' && t[j+5]=='o' && t[j+6]=='u' && isDependent(t[j-1])&&isDependent(t[j+7]))//can you待搞 78 { 79 cout << "I can"; 80 j = j+7; 81 continue; 82 } 83 84 cout << t[j]; //如果不是上述情况,不用修改,直接输出 85 ++j;//这种情况不会自动加1, 86 } 87 //t串全部输出 88 cout << endl;//输出空行 89 } 90 91 92 int main() 93 { 94 int n; 95 string s; 96 cin >> n; 97 getchar();//吸收回车,头文件 98 for(int i=1; i<=n; i++){ 99 //读一个字符串 100 getline(cin,s);//与string s,对应 101 cout< endl; 102 cout<<"AI: "; 103 go(s); 104 } 105 106 }
但回来之后发现有一些细节没处理好
比如说(1)括号的范围很乱,
(2)不知道为什么要用这些头文件
最后,进行本周学习小结:
(1)上周的目标实现了吗?
这周打代码的时间较多,特别是周四实践课之后,对那道题非常地想弄明白,但是由于我上学期C++学的不是很好,很多地方不知道要这样写就不行,要纠结很久,比如单引号和双引号的区别,参数里面有的未知数,在主函数中是否还要重新定义一遍等等。
但是因为这周题有点难,纠结的时间更久,有些地方还没有纠结出来,希望下周可以解决掉这些问题。
(2)本周做题不足和收获
a)比如说括号很乱的问题,我发现,只要标清楚了注释,很容易就可以找出是哪里少了或多了括号。
b)双引号和单引号的区别:双引号是字符串型,单引号是字符型。
c) 参数在函数中是否需要定义:
不需要,函数里面只需定义在这个函数里需要用到的一些辅助量,其他引用的量一般在主函数中定义
d)定义一个函数时用void 还是int /char.
如果不需要返回一些值到主函数中,或返回的是数组或指针,就用void
返回的是数值,用int之类
返回的是字符,用char之类
e) 原型声明怎么写
当调用在前,运用在后时,需要原型声明
格式:【数据类型】 <函数名>(形参列表)
从我总结的问题就知道了我上学期真的没学好C++嘤嘤嘤
本周学习目标:
(1)单日课程单日总结
(2)解决一些还没解决的问题
(3)同时温习一些C++书上的内容,一些基础知识要掌握。