字节跳动笔试题——万万没想到之聪明的编辑
转载请注明链接,有问题请及时联系博主:Alliswell_WP
题目描述:
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32M,其他语言64M
我叫王大锤,是一家出版社的编辑。我负责校对投稿来的英文稿件,这份工作非常烦人,因为每天都要去修正无数的拼写错误。但是,优秀的人总能在平凡的工作中发现真理。我发现一个发现拼写错误的捷径:
1. 三个同样的字母连在一起,一定是拼写错误,去掉一个的就好啦:比如 helllo -> hello
2. 两对一样的字母(AABB型)连在一起,一定是拼写错误,去掉第二对的一个字母就好啦:比如 helloo -> hello
3. 上面的规则优先“从左到右”匹配,即如果是AABBCC,虽然AABB和BBCC都是错误拼写,应该优先考虑修复AABB,结果为AABCC
我特喵是个天才!我在蓝翔学过挖掘机和程序设计,按照这个原理写了一个自动校对器,工作效率从此起飞。用不了多久,我就会出任CEO,当上董事长,迎娶白富美,走上人生巅峰,想想都有点小激动呢!
……
万万没想到,我被开除了,临走时老板对我说: “做人做事要兢兢业业、勤勤恳恳、本本分分,人要是行,干一行行一行。一行行行行行;要是不行,干一行不行一行,一行不行行行不行。” 我现在整个人红红火火恍恍惚惚的……
请听题:请实现大锤的自动校对程序
输入描述:
第一行包括一个数字N,表示本次用例包括多少个待校验的字符串。
后面跟随N行,每行为一个待校验的字符串。
输出描述:
N行,每行包括一个被修复后的字符串。
输入例子1: 2 helloo wooooooow 输出例子1: hello woow
>vi main.c
#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<string> #include <algorithm> using namespace std; // 初始化,获取数据 int getFileContent(char *pFileName/*in*/, char ***p, int *nLine) { cout << "请输入待检测的行数N: " << endl; cin >> *nLine; cout << "请依次输入待检测的数据: " << endl; getchar(); char **tmpP = NULL; tmpP = (char **)malloc(sizeof(char *) * *nLine); if (tmpP == NULL) { cout << "func getFileContent() err: " << endl; return -1; } // 依次输入n行内容 for (int i = 0; i < *nLine; i++) { tmpP[i] = (char *)malloc(20); cin.getline(tmpP[i], 20); } //间接赋值 *p = tmpP; return 0; } int getFileContent_Free(char **p, int iLine) { int i = 0; if (p == NULL) { return 0; } for (i = 0; i < iLine; i++) { free(p[i]); } free(p); //p = NULL; return 0; } // 既可以把指针所指向的内存空间给释放掉 并且把实参重新赋值成NULL int getFileContent_Free2(char ***p, int iLine) { getFileContent_Free(*p, iLine); *p = NULL; return 0; } // 依次检测每行 int checkFileContent(char **p, int iLine) { if ((p == NULL)&&(iLine == 0)) { return -1; } for (int i = 0; i < iLine; i++) { string sString = p[i]; transform(sString.begin(), sString.end(), sString.begin(), ::tolower); string sonString; // 规则:检测小写字母 for (int j = 0; j < 26; j++) { char ch = (char)(j + 'a'); sonString.clear(); // 规则1:检测3个相邻的字母 sonString.append(3, ch); int pos = sString.find(sonString); // 找到 while (pos != -1) { sString.erase(pos, 1); pos = sString.find(sonString, pos); strcpy(p[i], sString.c_str()); } // 规则2:检测aabb相邻的字母 sonString.clear(); sonString.append(2, ch); for (int k = 0; k < 26; k++) { char ch2 = (char)(k + 'a'); sonString.erase(2, 2); sonString.append(2, ch2); int pos2 = sString.find(sonString); // 找到 while (pos2 != -1) { sString.erase(pos2+2, 1); pos2 = sString.find(sonString, pos2); strcpy(p[i], sString.c_str()); break; } } } } return 0; } // 依次打印每行 void printFileContend(char **p, int iLine) { for (int i = 0; i < iLine; i++) { cout << p[i] << endl; } } int main() { int ret = 0, i = 0; char *myFileName = NULL; char **myP = NULL; int myLine = 0; cout << "程序开始..." << endl; //获取文件内容 ret = getFileContent(myFileName, &myP, &myLine); if (ret != 0) { cout << "func getFileContent() err" << endl; return ret; } // 依次检测每行 ret = checkFileContent(myP, myLine); if (ret != 0) { cout << "func getFileContent() err" << endl; return ret; } //打印文件内容 按照行 printFileContend(myP, myLine); getFileContent_Free2(&myP, myLine); system("pause"); return 0; }
编程问题总结:
1)动态分配内存?如何输入n行字符串?
思路:用数组先整体分配空间(存储结点),然后为每行的每个变量再分配空间,指向每行字符串的首地址的位置。
注意:释放内存的时候,顺序相反,先释放每行字符串的首地址指向的空间,后释放存储结点。
C++的istream中的类(如cin)提供了一些面向行的类成员函数:getline()和get()。这两个函数都读取一行输入,直到到达换行符。然而,随后getline()将丢弃换行符,而get()将换行符保留在输入队列中。
(1)getline()
getline()函数读取整行,它使用通过回车键输入的换行符来确定输入结尾。要调用这种方法,可以使用cin.getline()。该函数有两个参数。第一个参数是用来存储输入行的数组名称,第二个参数是要读取的字符数。如果这个参数为20,则函数最多读取19个字符,余下的空间用于存储自动在结尾处添加的空字符。getline()成员函数在读取指定数目的字符或遇到换行符时停止读取。
例如:假设要使用getline()将姓名读入到一个包含20个元素的name数组中,可以用这样的函数调用:
cin.getline(name,20);
这将一行读入到name数组中——如果这行包含的字符不超过19个。
getline()函数每次读取一行。它通过换行符来确定行尾,但不保存换行符。相反,在存储字符串时,它用空字符来替换换行符。
(2)get()
istream类有另一个名为get()的成员函数,该函数有几种变体。其中一种变体的工作方式与getline()类似,它们接受的参数相同,解释参数的方式也相同,并且都读取到行尾。但get()并不再读取并丢弃换行符,而是将其留在输入队列中。假设连续两次调用get():
cin.get(name,ArSize); cin.get(name,ArSize); //a problem
由于第一次调用后,换行符将留在输入队列中,因此第二次调用时看到的第一个 字符便是换行符。因此get()认为已经到达行尾,而没有发现任何可读取的内容。如果不借助于帮助,get()将不能跨过该换行符。
get()有另一种变体。使用不带任何参数的cin.get()调用可读取下一个字符(即使是换行符),因此可以用它来处理换行符,为读取下一行输入做准备:
cin.get(name,ArSize); //read first line cin.get(); //read newline cin.get(name,ArSize); //read second line
get()相比于getline()可以使得输入更仔细。例如,假设用get()将一行读入数组。如何知道停止原因是由于已经读取了整行,而不是由于数组已经填满了呢?查看下一个字符,如果是换行符,说明已经读取了整行;否则,说明该行中还有其他输入。
getline()使用起来简单一些,但get()使得检查错误更简单些。
2)函数设计,如何使代码分块更好处理?
// 获取数据内容 getFileContent(); // 依次检测每行 checkFileContent(); //打印文件内容 按照行 printFileContend(); // 释放内存 getFileContent_Free();
3)C/C++如何整行读入字符串?
方法一:scanf()读入char[]
使用方法:
char str[1024]; scanf("%[^\n]",&str); getchar();
说明:在scanf函数中,可以使用%c来读取一个字符,使用%s读取一个字符串, 但是读取字符串时不忽略空格,读字符串时忽略开始的空格,并且读到空格为止,因此只能读取一个单词,而不是整行字符串。
其实scanf函数也可完成这样的功能,而且还更强大。这里主要介绍一个参数,%[ ],这个参数的意义是读入一个字符集合。[ ]是个集合的标志,因此%[ ]特指读入此集合所限定的那些字符,比如%[A-Z]是输入大写字母,一旦遇到不在此集合的字符便停止。如果集合的第一个字符是"^",这说明读取不在"^"后面集合的字符,既遇到"^"后面集合的字符便停止。注意此时读入的字符串是可以含有空格的,而且会把开头的空格也读进来。
注意:如果要循环的多次从屏幕上读取一行的话,就要在读取一行后,在用%c读取一个字符,将输入缓冲区中的换行符给读出来。否则的话,在下一次读取一行的时候,第一个就遇到'\n',匹配不成功就直接返回了。这里可以用scanf()或者getchar()函数读取换行符。
方法二:getchar()读入char[]
使用方法:
char str[1024]; int i=0; while((str[i]=getchar())!='\n') i++; getchar();
说明:这样一个一个读也可以,也会把开头的空格读进来。最后也需要考虑换行符,使用getchar()读出来。
方法三:gets()读入char[]
使用方法:
char str[1024]; gets(str);
说明:感觉这个就是多个getchar的集合函数,很好用。功能是从标准输入键盘上读入一个完整的行(从标准输入读,一直读到遇到换行符),把读到的内容存入括号中指定的字符数组里,并用空字符'\0'取代行尾的换行符'\n'。读入时不需要考虑换行符。
方法四:getline()读入string或char[]
使用方法:
string str; getline(cin,str);//读入string char str2[1024]; cin.getline(str2,1024);//读入char数组
说明:这是比较常用的方法,cin.getline第三个参数表示间隔符,默认为换行符'\n'。读入不需要考虑最后的换行符。
方法五:get()读入char[]
使用方法:
char str3[1024]; cin.get(str3,1024);//读入char数组
说明:get函数读入时需要考虑最后的换行符,也就是说,如果用get读入多行数据,要把'\n'另外读出来,一般使用cin.get(str,1024).get();来读入多组数据。
参考——https://www.cnblogs.com/AlvinZH/p/6798023.html
4)每次输入3后,但只能输入两行数据?
思路:读取了之前在缓冲区中的换行符(“\n”),所以读取之前先getchar();把缓冲区中的数据清空。
5)如何实现依次检测每行,实现规则1,实现查找相同3个字母的字符串?
思路:先实现子串“aaa”的子串在字符串的查找,然后实现字符‘a’到‘z’的遍历,拼接完成子串的过程,然后遍历在(每行的)字符串中查找。
6)c++ 如何获取输出26个字母?
#include <iostream> using namespace std; void main() { int i; cout<<"输出小写字母:"; for (i=0;i<26;i++) cout << (char) (i+'a'); //小写 cout << endl; cout<<"输出大写字母:"; for (i=0;i<26;i++) cout << (char) (i+'A'); // 大写 cout << endl; }
7)如何实现依次检测每行,实现规则2,实现查找AABBCC得到AABCC?
思路:先实现子串“aaa”的子串在字符串的查找,然后实现字符‘a’到‘z’的遍历,拼接完成子串的过程,然后遍历在(每行的)字符串中查找。
8)如果输入的字符串中有大小写,大小写字母如何处理?
思路:由于大写字母AAa或AABBcc,这样的存在,为避免出错,所以统一使用C++自带的算法(transform(s.begin(), s.end(), s.begin(), ::tolower);
),转为小写。
注意:添加头文件#include<algorithm>
9)c++ strcpy放到程序中报错?
思路:这段代码放到VS2015没有问题,但是在自测程序报错,查了资料,添加头文件#include<cstring>
转载请注明链接,有问题请及时联系博主:Alliswell_WP
posted on 2020-08-12 11:44 Alliswell_WP 阅读(427) 评论(0) 编辑 收藏 举报