题目:
开发一个简单错误记录功能小模块,能够记录出错的代码所在的文件名称和行号。
处理:
1.记录最多8条错误记录,对相同的错误记录(即文件名称和行号完全匹配)只记录一条,错误计数增加;(文件所在的目录不同,文件名和行号相同也要合并)
2.超过16个字符的文件名称,只记录文件的最后有效16个字符;(如果文件名不同,而只是文件名的后16个字符和行号相同,也不要合并)
3.输入的文件可能带路径,记录文件名称不能带路径
数据范围:输入错误记录数量满足 1≤n≤1000 ,每条记录的长度满足 1≤len≤50
输入描述:
一行或多行字符串。每行包括带路径文件名称,行号,以空格隔开。
文件路径为windows格式
如:E:\V1R2\product\fpgadrive.c 1325
输出描述:
将所有的记录统计并将结果输出
格式:文件名 代码行数 数目,一个空格隔开,如: fpgadrive.c 1325 1
结果根据数目从多到少排序,数目相同的情况下,按照输入第一次出现顺序排序。
如果超过8条记录,则只输出前8条记录.
如果文件名的长度超过16个字符,则只输出后16个字符
输入例子:
E:\V1R2\product\fpgadrive.c 1325
输出例子:
fpgadrive.c 1325 1
#include <iostream>
#include <vector>
using namespace std;
//定义一个记录错误的结构
struct fileError {
string fileName; //文件名
int rowNum; //行数
int count; //错误数
};
fileError fileArr[1000];
int length = 0; //记录数组长度
bool flag; //标记
//从字符串中取得文件名的方法
int getFileNum (string FileName) {
int i = FileName.length() - 1;
char temp = FileName[i]; //当前元素
while(temp != '\\') {
i--;
temp = FileName[i];
}
return i;
}
//按照错误数大小排序的方法
void countSort(fileError f[]) {
for (int i = length - 1; i > 0; i--) {
for ( int j = 0; j < i; j++) {
if (fileArr[j].count < fileArr[j + 1].count) {
fileError temp = fileArr[j];
fileArr[j] = fileArr[j + 1];
fileArr[j+1] = temp;
}
}
}
}
int main() {
string name, fName; //输入文件地址,文件名
int row, iName; //输入错误行数,从第i为开始截取文件名
while (cin >> name >> row) { // 注意 while 处理多个 case
iName = getFileNum(name) + 1;
fName = name.substr(iName, name.length() - iName);
int i = 0;
flag = true;
//遍历vector,如果有相等字符串,且错误行数相同,则count++
for(; i < length; i++) {
if (fileArr[i].fileName == fName && fileArr[i].rowNum == row) {
fileArr[i].count++;
flag = false;
break;
}
}
//若没有相同错误,则pushback,令count为1
if (flag) {
fileArr[i].fileName = fName;
fileArr[i].rowNum = row;
fileArr[i].count = 1;
length++;
}
}
//输出
countSort(fileArr);
for ( int j = 0; j < 8; j++) { //最多记录8条错误记录
if (fileArr[j].fileName.length() > 16) {
cout << fileArr[j].fileName.substr(fileArr[j].fileName.length() - 16, 16) << " " << fileArr[j].rowNum << " " << fileArr[j].count << endl;
} else {
cout << fileArr[j].fileName << " " << fileArr[j].rowNum << " " << fileArr[j].count << endl;
}
}
return 0;
}
知识点1
c++对字符串的操作
(9条消息) C++字符串常见操作函数最全总结_c++字符串操作函数_Cyril_KI的博客-CSDN博客
(9条消息) C++中的string类用法简介_c++ string_liitdar的博客-CSDN博客
1. 构造函数:
string str; ——空串
string s(str);——将str复制到s
string s(num,c); ——生成由num个c字符构成的字符串
2. 插入函数:
有两种:push_back()和insert(),后者比较常用。
push_back():尾部插入一个字符,例如s.push_back(‘p’);
insert():例如s=“abcddss”,执行s.insert(s.begin(),‘i’)后在位置0前插入’i’变成"iabcddss"。
3. 遍历:
借助迭代器或者下标,下标比较常用,下标即字符串数组。
迭代器分两种:正向和反向。
正向:string::iterator it=s.begin();it!=s.end();it++;
反向:string::reverse_iterator it=s.rebegin();it!=s.rend();it++;
其中*it表示该位置的字符。
4. 查找:
1)查找一个字符串:s.find(ss),找到返回ss在s中的起始位置,否则返回-1;
2)从某一个位置开始查找某个字符:s.find(‘t’,6),从s的位置6开始查找字符’t’,找到则返回位置,否则返回-1;注意1)和2)都是返回第一次找到的位置;
3)从末尾开始查找某个字符:s.rfind(‘t’);
4)从某个位置开始查找第一个不属于s1的字符位置,例如s=“cdcdscds”,s1=“cdcdfff”,s.find_first_not_of(s1)=4,s的位置4字符不属于s1,类似的还有查找第一个属于s1的字符的位置,去掉not就好。
5. 排序:sort(s.bgein(),s.end());
6. 分割截取:
有两个函数:substr()与strtok()。
s.substr(2,5)为s从2位置开始的5个字符组成的子串。
strtok()函数原型:char *strtok(char *s,const char *delim)
函数功能:分解字符串为一组字符串,s为要分解的字符串,delim为分隔字符串。
7. 删除:erase()函数,例如s=“12345678”,s.erase(s.begin()+3)后变为"1235678",即把位置3的字符删掉。
8. 替换:
repalce()函数:s.replace(pos,len,ss),将s从pos开始的len个字符替换成ss,
s.replace(pos,n1,n2,c),将s从pos开始的n1个字符替换成n2个字符c。
9. 大小写转换:
tolower()和toupper()。循环遍历字符串的每一个位置s[i]=tolower(s[i]),大写转小写,或者s[i]=toupper(s[i]),小写转大写。
这里其实推荐用STL中的transform()函数,具体用法如下:
transform(s.begin(),s.end(),s.begin(),::tolower)大写转小写,小写转大写类似。
10. 比较函数:
string支持<,>,<=, >=, ==, != 等操作。
compare()函数专门用做string的比较函数,s.compare(ss)=0说明ss == s,返回1表明s>ss,返回-1表明s<ss。
11. 拼接函数:
c++的string支持直接相加,“cdd”+“sss”=“cddsss”。
另外s.append(ss)表示在s最后加上ss,等同于s+=ss
12. 计算字符串长度:length( ),计算结果为字符串的实际长度
13. 判空:empty( )
14. string转换为char*
使用c_str( )方法
#include <string>
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
string strOutput = "Hello World";
cout << "[cout] strOutput is: " << strOutput << endl;
// string 转换为 char*
const char* pszOutput = strOutput.c_str();
printf("[printf] strOutput is: %s\n", pszOutput);
return 0;
}
输出:
cout 可直接输出 string 类的对象的内容;
使用 c_str() 方法转换 string 类型到 char* 类型时,需要为char*添加 const 关键字;
printf() 函数不能直接打印 string 类的对象的内容,可以通过将 string 转换为 char* 类型,再使用 printf() 函数打印。
data( )方法和c_str( )方法:
两者都返回const char*类型,但在c++98版本中,data( ) 返回的字符串不以空字符结尾
15. char* char[ ] 转换为string
直接进行赋值操作,将 char*、char[] 的变量赋值给 string 对象即可。
实际上是将 char*、char[] 定义的字符串的首地址赋值给 string 对象了。
#include <string>
#include <iostream>
using namespace std;
int main()
{
const char* pszName = "liitdar";
char pszCamp[] = "alliance";
string strName;
string strCamp;
strName = pszName;
strCamp = pszCamp;
cout << "strName is: " << strName << endl;
cout << "strCamp is: " << strCamp << endl;
return 0;
}
16. int类型转换为string类型
常用to_string( )来转换
#include <string>
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
// 方法1
int nNum1 = 123;
stringstream ss;
ss << nNum1;
string strTest1 = ss.str();
cout << "strTest1 is: " << strTest1 << endl;
/*
string strTest2;
strTest2 << ss; // stringstream 未定义 << 操作符,故此句报错
cout << "strTest2 is: " << strTest2 << endl;
*/
string strTest3;
ss >> strTest3;
cout << "strTest3 is: " << strTest3 << endl;
// 方法2
int nNum2 = 456;
string strTest4;
strTest4 = to_string(nNum2); // C++11 标准
cout << "strTest4 is: " << strTest4 << endl;
return 0;
}
知识点2
排序方法
//单独写一篇