我已经实现了以下的程序,为一个练习的STL模板和算法的作业。我所做的就是实现用于打印空文件、非空文件等的代码。我想知道是否有任何方法使代码更加优化。
注:根据本校的要求(必须遵守):
empty_check(),split()和print_filename()。int main(). (成员访问)-> (通过指针进行成员访问)* (去引用)for、while、do while)或选择(if、switch、?:)语句或运算符。auto。std::cout、std::cerr或执行文本打印的任何其他函数。我将不得不使用提供的助手函数来完成它。#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <algorithm>
#include <functional>
#include <utility>
using name_file = std::string;
using sizeFile = size_t;
using record_in_file = std::pair<name_file, sizeFile>;
using file_datas = std::map<name_file, sizeFile>;
bool empty_check( //helper function
const record_in_file& dataRecord,
bool true_if_its_not
)
{
sizeFile size;
std::tie(std::ignore, size) = dataRecord;
bool result = (size == 0);
if (true_if_its_not)
{
result = !result;
}
return result;
}
name_file split(const record_in_file& dataRecord) //helper function
{
name_file name;
std::tie(name, std::ignore) = dataRecord;
return name;
}
void print_filename(const name_file& name1) //helper function
{
std::cout << " * " << name1 << std::endl;
}
void file_names_print(const file_datas& map1) //can modify
{
std::vector<name_file> files;
std::transform(std::begin(map1), std::end(map1), std::back_inserter(files), split);
std::for_each(std::begin(files), std::end(files), print_filename);
}
size_t files_un_empty_print(const file_datas& map1) //can modify
{
std::vector<record_in_file> files;
std::copy_if(std::begin(map1), std::end(map1), std::back_inserter(files),
std::bind(empty_check, std::placeholders::_1, true));
std::vector<name_file> file_names;
std::transform(std::begin(files), std::end(files), std::back_inserter(file_names),
split);
std::for_each(std::begin(file_names), std::end(file_names), print_filename);
return std::count_if(std::begin(map1), std::end(map1),
std::bind(empty_check, std::placeholders::_1, true));
}
size_t files_empty_print(const file_datas& map1) //can modify
{
std::vector<record_in_file> files;
std::copy_if(std::begin(map1), std::end(map1), std::back_inserter(files),
std::bind(empty_check, std::placeholders::_1, false));
std::vector<name_file> file_names;
std::transform(std::begin(files), std::end(files), std::back_inserter(file_names),
split);
std::for_each(std::begin(file_names), std::end(file_names), print_filename);
return std::count_if(std::begin(map1), std::end(map1),
std::bind(empty_check, std::placeholders::_1, false));
}
std::tuple<file_datas&> get_param(file_datas& map1) //can modify
{
return std::forward_as_tuple<file_datas&>(map1);
}
void empty_removal(file_datas& map1) //can modify
{
std::vector<record_in_file> files;
std::copy_if(std::begin(map1), std::end(map1), std::back_inserter(files),
std::bind(empty_check, std::placeholders::_1, true));
file_datas n_map{ std::begin(files),std::end(files) };
std::swap(map1, n_map);
}
int main()
{
file_datas map = {
{"readme.txt", 2000},
{"main.exe", 10000},
{"save.bak", 0},
{"library.dll", 1243},
{"0.res", 121100},
{"1.res", 121100},
{"2.res", 115600},
{"errors.log", 0}
};
std::cout << "Files:" << std::endl;
file_names_print(map);
std::cout << std::endl;
std::cout << "Files that are not empty:" << std::endl;
size_t Count_of_unemptyFiles = files_un_empty_print(map);
std::cout
<< " There are "
<< Count_of_unemptyFiles
<< " non-empty files.\n"
<< std::endl;
std::cout << "Files that are empty:" << std::endl;
size_t Count_of_emptyFiles = files_empty_print(map);
std::cout
<< " There are "
<< Count_of_emptyFiles
<< " empty files.\n"
<< std::endl;
std::cout << "Files after removing the empty ones:" << std::endl;
auto parameters = get_param(map);
std::apply(empty_removal, parameters);
file_names_print(map);
}
```发布于 2020-08-10 19:45:48
您应该避免创建不必要的临时向量。例如,在file_names_print()中,可以使用嵌套的std::bind()来避免向量files:
void file_names_print(const file_datas& map1) //can modify
{
std::for_each(std::begin(map1), std::end(map1),
std::bind(print_filename, std::bind(split, std::placeholders::_1)));
}这可以用所有的std::transform() + std::for_each()组合来完成。考虑到您的限制,我看不出如何避免std::copy_if的临时向量。
在使用std::copy_if()的情况下,不再需要调用std::count_if()来计数原始输入中的匹配元素,只需获得临时向量的std::size()即可。例如:
size_t files_un_empty_print(const file_datas& map1) //can modify
{
std::vector<record_in_file> files;
std::copy_if(std::begin(map1), std::end(map1), std::back_inserter(files), std::bind(empty_check, std::placeholders::_1, true));
std::for_each(std::begin(files), std::end(files), std::bind(print_filename, std::bind(split, std::placeholders::_1)));
return std::size(files);
}中删除元素
如果您可以使用C++20,那么只需编写:
void empty_removal(file_datas& map1) //can modify
{
std::erase_if(map1, std::bind(empty_check, std::placeholders::_1, true));
}如果您不能使用C++20,那么典型的方法是使用for-loop对匹配的元素调用erase()。当然,你被限制不能这样做,然后你确实必须复制。
std::map中
在empty_removal()中,首先创建文件的std::vector,然后将其转换为映射。可以通过创建一个空的std::map并插入以下内容来避免这种情况:
void empty_removal(file_datas& map1) //can modify
{
file_datas files;
std::copy_if(std::begin(map1), std::end(map1),
std::inserter(files, std::end(files)),
std::bind(empty_check, std::placeholders::_1, true));
std::swap(map1, files);
}关于这些限制的
这可能是一种强迫您使用STL算法的方法,但是有几个缺点。不幸的是,由于您必须将多个迭代器传递给STL算法,并且永远不会将容器作为返回值,因此很难组合多个STL算法。然后,您必须使用中间副本,这是非常低效的。然后,射程基础for循环播放通常更清晰、更高效。在现实世界中,您将能够使用C++提供的所有工具,并选择最适合该任务的工具。您可能会将for-loops、算法和lambda结合在一起。
发布于 2020-08-10 20:07:04
很抱歉,我的评论有点简短,但是,我今天的时间有限。我的评论不像G.Sliepen的那么技术性,而是更多地关注代码风格。
查看列表后的前两行,包括:
using name_file = std::string;
using sizeFile = size_t;
...选择一种风格(two_words,twoWords,TwoWords等)在你的代码中坚持使用它。
的名称
size_t files_un_empty_print(const file_datas& map1); // what does "files_un_empty" mean?
void file_names_print(const file_datas& map1); // what is "map_1"?
bool empty_check(
const record_in_file& dataRecord,
bool true_if_its_not // "is_empty" is concise and better communicates the intent
);
void empty_removal(file_datas& map1); // "remove" or "delete_empty_files" are clearer关于正确语法的第二点,我认为这可能是无关紧要的挑剔之处,但是,如果您在选择名称时可以使用适当的英语语法,请这样做:
using name_file = std::string; // "file_name" is a more natural and familiar way to say the same thing
using file_datas = std::map<name_file, sizeFile>; // the word "data" is plural您的代码中可能有其他示例,但这应该说明这一点。
您创建了一个别名:
using sizeFile = size_t;然后返回到使用size_t:
size_t files_un_empty_print(const file_datas& map1);https://codereview.stackexchange.com/questions/247705
复制相似问题