C++投票计数程序
花了一个上午加一个下午写了个投票计数的小程序,用Python很快可以搞定的,决定挑战一下自己同时熟练一下C++。
首先我们是13个同学投票,每个同学投票不超过11票,然后计算被投票人获得的票数。(即有13个txt投票文件,每个txt投票文件中的名字用空格隔开)
思路
拿到这个实际的问题,首先得有个思路,我有两种思路:
①把所有的名字都存入一个新的txt文件中,然后进行计数;
②逐个读取文件,逐个名字进行累加票数;
最后我选择了第二种方式。
读取文件夹中文件名
要想读取txt文件中的数据or字符串,首先得知道文件名,手动输入非我所愿,所以我使用vector将所有的文件名保存为字符串存入vector变量files。使用以下函数:
vector<string> readfiledir(){
struct dirent *ptr;
DIR *dir;
string PATH="/home/gz/下载/calculateParty/data";
dir = opendir(PATH.c_str());
vector<string> files;
cout << "文件列表:" << endl;
while((ptr=readdir(dir)) != NULL){
if(ptr->d_name[0] == '.')
continue;
// cout << ptr->d_name << endl;
files.push_back(ptr->d_name);
}
return files;
}
读取txt文件中名字
13个txt文件使用for循环读取即可,实际上只需要编写读取一个文件的程序即可。
首先进行定义:
ifstream infile;//声明自己的ifstream对象
vector<string> files;
files = readfiledir();//存储文件名
unordered_map<string, int> people;//使用unordered_map作为存储数据的结构,key存人名,value存票数。
int count = 0;//计算总的票数
然后是for循环当中的程序。
首先判断文件是否被正确打开:
infile.open("data/"+ files[i]);
if(!infile.is_open()){
cout << "Can't open file. Bye.\n";
exit(EXIT_FAILURE);
}
定义一个string数组,存储人名。
string *line = new string[15];
int j = 0;
计算每个人的票数
用空格将人名分开,分别读取:
while(getline(infile, line[j], ' ')){
cout << line[j] << " : "<< line[j].size() << endl;//人名和人名长度
if (people.find(line[j]) == people.end())//hash表中没有该人名
people[line[j]] = 1;//初始化为1
else
people[line[j]]++;//票数累加
j++;
count++;//总票数
}
这些代码紧跟在循环后面,用于判断循环为何终止。eof()只能判断是否达到EOF,而fail()可用于检测EOF和类型不匹配。
if (infile.eof())
cout << "End of file reached.\n";
else if (infile.fail())
cout << "Input terminated by data mismatch.\n";
else
cout << "Input terminated for unknown reason.\n";
infile.close();
cout << "file: " << i << " heiheiheiheiheihei"<< endl;
infile.close();//关闭txt文件
打印hash表
输出hash表的所有数据,每个人对应的票数。
for(unordered_map<string, int>::iterator iter = people.begin(); iter != people.end(); iter++)
cout << iter->first << " : " << iter->second << endl;
cout << "总投票数" << count << endl;
问题来了
这时候发现输出有问题,问题出在文件末尾的那个字符串会带上换行符‘\n’,所以这个带换行符的人名和人名属于不同的key,问题大了,必须得解决,换行符删掉不就行了,嘿嘿!试了很多方法。
①重新定义一个char数组
while(getline(infile, line[j], ' ')){
char str[10] = line[j];
if (str[strlen(str) - 1] == '\n'){//最后一位为换行符,替换为‘\0’
str[strlen(str) - 1] = '\0';
line[j] = str[strlen(str) - 1] = '\0';
}
}
发现统计票数时会多13票不属于任何人,属于“空格”。这才发现C++不存在切片功能,字符串数组也不能赋值给字符串数组,除非是string类型的。
②截取子串(正确方法!!!)
while(getline(infile, line[j], ' ')){
string str = line[j];
if (str[str.size() - 1] == '\n'){
line[j] = str.substr(0, str.size()-1);
}
}
得到完美答案,具体代码请看计数程序