前言
每次写这种稍微复杂一点的题,总是小错误不断,而且说实话,感觉写的很烂...一点代码的优美感都没有
题目
实现一个selfString
类,构造函数从文件中读取一个以空格为分隔符的英文句子。实现一个函数(不一定是成员函数)来找出两个句子的最长公共单词。
分析
要从文件读取句子创建一个文件输入流就可以了,然后因为是一行,所以借助getline()
更好实现一些,再加上getline()
函数会自动在输入结束后加上一个终止符,简直不能更棒。
因为涉及到对两个对象进行操作,所以声明为友元类外函数更合适。
总的来的说思路是先通过strtok将两个字符串切片为单个单词,并将每个单词的首地址分别保存在两个字符指针数组中,然后用双重循环遍历的方式进行验证是否有公共单词,如果公共单词再将其首地址保存在一个字符指针数组中,最后再比较出最长的单词即可。
实现
代码
#include<fstream>
#pragma warning(disable:4996)
using namespace std;
const int char_MaxSize = 1000;
const int word_MaxSize = 100;
class selfString{
public:
selfString(const char c[]) {
ifstream inf(c);
inf.getline(myStr, 100); //分割符可省,这个不可省,getline会自动插终止符
}
friend void findMax(selfString str1, selfString str2); //未曾设想的道路,友元函数是否可以是用私有成员作为实参呢,看来不行,因为在主函数里就调用不了
private:
char myStr[char_MaxSize];
};
void findMax(selfString str1, selfString str2) {
//用来保存单词首地址的指针数组
char *word1[word_MaxSize] = { 0, };
char *word2[word_MaxSize] = { 0, };
//复制两个字符串,因为strtok函数会对原字符串进行更改
char sent1[char_MaxSize];
char sent2[char_MaxSize];
strcpy(sent1, str1.myStr);
strcpy(sent2, str2.myStr);
//进行切片处理并保存单词首地址
char *p = strtok(sent1, " ");
for (int i = 0; p != NULL; i++) {
word1[i] = p;
p = strtok(NULL, " ");
}
p = strtok(sent2, " ");
for (int i = 0; p != NULL; i++) {
word2[i] = p;
p = strtok(NULL, " ");
}
//开始寻找公共单词并保存其首地址
char *same[word_MaxSize] = {0, }; //用来保存公共单词的头指针
int k = 0;
for (int i = 0; word1[i] != NULL; i++) { //遍历word1中的单词,终止条件为遍历到单词数组没有内容
for (int j = 0; word2[j] != NULL; j++) { //遍历word2中的单词看是否有与word1的当前单词相同的
char *p = word1[i]; //应该接下来的判断语句中都会对p,q进行更改,所以每次循环都要重置一次
char *q = word2[j];
while (*p != 0 && *q != 0) { //strtok函数会将分割符变为'\0',所以指向此说明这个单词结束了
if (*p != *q)
break; //有一个不同即说明不是公共单词,跳出这个while
p++;
q++;
}
if (*p == 0 && *q == 0) { //只要能完成判定,那就是同一个,不然早就退出了,指针也就没机会指向终止符
same[k++] = word1[i];
break; //如果已经确定是公共单词了,就不用继续判断了
}
}
}
//如果没有公共单词,直接返回即可
if (same[0] == NULL) {
cout << "没有公共单词" << endl;
return;
}
//检查出公共单词中最长的那个
int max = 0; //保存长度最大值
int temp; //保存最大值的下标
for (int i = 0; same[i] != NULL; i++) {
int wlen = 0;
char *p = same[i];
while (*p != 0) {
p++;
wlen++;
}
if (wlen > max) {
max = wlen;
temp = i;
}
}
cout << same[temp]; //输出最长公共单词
}
int main() {
selfString str1("test1.txt");
selfString str2("test2.txt");
findMax(str1, str2);
return 0;
}
输入
"test1.txt":welcome1 to newyork city hhhh
"test2.txt":nowelcome to newyork citty
输出
newyork
总结
- 对
strtok()
理解更深了 - 在循环中,一定要记得重置变量
- 友元函数不能使用私有数据成员作为实参,因为在主函数调用友元函数时还没有权限访问类的私有数据成员作为实参