我正在阅读每行上有几个不同字段的大文件。通过类比,您可以将文件的每一行视为代表员工,其中一个字段包含它们所在的部门名称。但是,部门名称可以由任意一组4-5个ASCII字符组成(例如, " 1234"," ABCD"," P + 0 $ i"。
目前,我(天真地)将字符存储为std :: string,但我注意到我已经进行了大量耗时的字符串比较。因此,我想从文件中读取字段,将字符串转换为数字(可能是unsigned int?),然后进行许多数字比较(并避免字符串比较)。当然,我需要一种方法将数字转换回字符串以便输出。
我的大多数在线搜索都会显示"将字符串转换为数字"讨论了使用stringstream将数字字符串转换为某种类型的int的用法。这不是特别有用,我似乎无法找到合适的搜索查询来找到解决方案。有人可以请我指向相关来源或提供执行此转换的方法吗?
答案 0 :(得分:1)
好吧,如果你有最多5个ASCII字符,那么最简单的方法是用你喜欢的任何字符将其填充到8,然后*reinterpret_cast<uint64_t*>(the_id.data())
。
如果要将字符表示拟合为32位int,则需要做更多的工作:简单地丢弃高位(可能因为ASCII码为0-127)仍然留下7 * 5 = 35位 - 对于32位类型来说太多了。假设id不包含任何控制代码(即ASCII代码0-31),您可以使用 base-96 encoding 来实现打包:
unsigned base = 128 - 32;
// pad c out to 5 characters if necessary.
unsigned idnum = (((((c[0] - 32) * base + (c[1] - 32)) * base + (c[2] - 32)) * base + (c[3] - 32)) * base + (c[4] - 32)) * base + c[5] - 32;
您可能会发现使用循环更容易阅读:
unsigned idnum = 0;
for (size_t i = 0; i < 5; ++i)
{
idnum *= base;
idnum += c[i] - ' ';
}
使用% base
将数字打包回字符串值以获取最后一位数字,然后/ base
准备获取下一位数字....
答案 1 :(得分:0)
答案 2 :(得分:0)
鉴于std :: string相等操作对于任意长度的数据实际上是有效的,并且您需要保留实际的字符串值,我觉得您可能希望在别处寻找性能改进。查看您的要求,您似乎只需要为对象提供更好的搜索效率。 std::unordered_map
容器可能是一个很好的候选者。它是一个关联容器,具有通过密钥查找的恒定时间。您可以将其他数据集存储为unordered_map的值类型,并将关联键设置为您想要查找的内容。以下是一些类型的示例,这些类型可以通过字符串查找数据的匹配子集。
struct Employee;
typedef std::vector<std::shared_ptr<Employee>> Employees;
typedef std::unordered_map<std::string, Employees> EmployeeByLookup;
然后,您可以查找匹配给定键值的所有员工。
static EmployeeByLookup byDepartment;
Employees& GetDepartmentList(const std::string& department)
{
return byDepartment[department];
}
如果您需要按值而不是通过关联键查找对象,那么我建议您查看std::unordered_set
。它还具有查找的恒定时间的平均复杂度。如果需要优化内部哈希性能,可以为对象创建自己的哈希函数。
我使用unordered_map
示例创建了simple application。看看你是否感兴趣。
答案 3 :(得分:-1)
C ++ 11有std::stoi
。除此之外,您可以使用字符串流进行转换:
std::istringstream iss("1234");
int x;
if ( iss >> x )
std::cout << "Got " << x << "\n";
else
std::cout << "String did not contain a number\n";
您可以像iss
一样从cin
进行其他流提取。
我不确定为什么你认为stringstream建议“不是很有用”?