如何找到std :: strings数组的长度?

时间:2014-05-13 02:53:35

标签: c++

我有一些与我的代码部分相关的问题。

第一个问题与我如何找到string s数组数组的长度有关。我正在使用以下作为我正在使用的微积分工具的地图。

std::string dMap[][10] = {{"x", "1"}, {"log(x)", "1/x"}, {"e^x", "e^x"}};

我想知道如何做相同的

int arr[] = {1, 69, 2};
int arrlen = sizeof(arr)/sizeof(int);

带有std::string.类型的元素数组另外,是否有更好的方法来存储(f(x),f'(x))对的符号表示?我试图不使用C ++ 11。

我的下一个问题与我写的不起作用的程序有关。这是:

std::string CalculusWizard::composeFunction(const std::string & fx, const char & x, const std::string & gx)
{
    /* Return fx compose gx, i.e. return a string that is gx with every instance of the character x replaced 
       by the equation gx. 
       E.g. fx="x^2", x="x", gx="sin(x)" ---> composeFunction(fx, x, gx) = "(sin(x))^2"
    */
    std::string hx(""); // equation to return 

    std::string lastString("");
    for (std::string::const_iterator it(fx.begin()), offend(fx.end()); it != offend; ++it)
    {
        if (*it == x)
        {
            hx += "(" + gx + ")";
            lastString.erase(lastString.begin(), lastString.end());
        }
        else
        {
            lastString.push_back(*it);
        }
    }

    return hx;
}

首先,程序中的错误在哪里?当我测试它时它不起作用。

其次,当尝试再次将字符串设为空时,执行

会更快
lastString.erase(lastString.begin(), lastString.end());

lastString = ""; 

???

感谢您的时间。

4 个答案:

答案 0 :(得分:1)

问题1)了解您不能,也不需要以这种方式计算String的大小。只要问它有多大,就会告诉你。

// comparing size, length, capacity and max_size
#include <iostream>
#include <string>

int main ()
{
  std::string str ("Test string");
  std::cout << "size: " << str.size() << "\n";
  std::cout << "length: " << str.length() << "\n";
  std::cout << "capacity: " << str.capacity() << "\n";
  std::cout << "max_size: " << str.max_size() << "\n";
  return 0;
}

http://www.cplusplus.com/reference/string/string/capacity/

至于字符串数组,请仔细阅读: How to determine the size of an array of strings in C++?

查看DavidRodríguez的回答。

问题2)更好的方法可能是根据您对它们的处理来定义FunctionPair类。 Vector<FunctionPair>可能派上用场。

如果FunctionPair没有与之关联的任何行为(函数),那么结构可能就足够了:std::pair<std::string, std::string>也可以被推入一个向量中。

除非您要使用一个函数字符串来查找另一个函数字符串,否则您不需要映射。 http://www.cplusplus.com/reference/map/map/

问题3)更好地描述什么不起作用会有所帮助。我注意到lastString根本不会影响hx

问题4)“第二个”最快速度在这一点上无需担心。写出最容易看到的内容,直到所有错误都消失为止。 “过早的优化是所有邪恶的根源”,唐纳德克努特。

提示:了解replace函数如何帮助您进行合成替换: http://www.cplusplus.com/reference/string/string/replace/

答案 1 :(得分:1)

正如上述评论者所说,即使你只是想让事情变得“容易”,也不应该使用c风格的数组。

实际上做这样的事情会让事情变得更难。

c样式数组没有检查边界。这意味着它们是由于内存不安全而导致的错误来源,并且当您从不相关的内存块中读取随机数据时甚至会更糟糕地写入它们时,可能会导致各种问题,从分割到破坏数据。

#include <iostream>

int main() {
  int nums[] = {1, 2, 3};
  std::cout << nums[3] << std::endl;
}

# ./a.out 
4196544

没有程序员是完美的,每次你实现类似的东西,你有一定几率的机会,你将在你的界限或其他东西。即使你是一些编程神,大多数人都必须与一个没有编程的人一起工作。在许多情况下,没有人会注意到,因为不是每次都会引起任何明显的事情。内存可以随机损坏而不会导致任何可怕的崩溃。直到你做出一个完全无关的改变,导致内存处于不同的顺序。

但是当你注意到它会经常产生一些完全不相关的东西,你可以在以后的某个时间编码。鉴于您可能在编程生命周期中实现许多此类数组,您可能会使自己的事情变得更糟,每个项目节省10分钟,但最终花费数小时追踪一个错误。

如果你真的不想要C ++ 11,那么请使用std::vector<std::vector<std::string>>。它将使用更多的内存,因此你可能松散某些性能,但大多数时候,当人们担心性能时,他们不应该这样做。你是否每秒呼叫这个功能10,000次?即使这样,您也可以通过线程化代码或预先分配内存来获得更高的性能。大多数时候,人们认为某些东西的性能不好,但实际上计算机正在优化它,或者CPU正在优化它。内存分配的性能是否比每次运行时找到数组大小更糟糕?

原始指针vs std::unique_ptrstd::shared_ptr也是如此。

如果键入所有这些名称看起来很痛苦,请使用typedef使其变得更好。

您还可以查看使用Boost的数组类型boost::array。或者掀起你自己的自定义课程。

这并不是说你永远不应该使用那些东西。但是你应该只在你能够证明它的时候使用它。默认值应该是'纯'C ++样式代码。

  • 表现(只有当你测量并看到你需要它时)。
  • C兼容性(但大部分时间你都可以将这些东西包装在std类中)。

如果你确实觉得你需要它。确保您对代码进行单元测试。并查看使用当前版本gccclang中提供的地址和内存清理程序。并尽可能地隔离代码(即在classe中)。

这听起来像是很多工作,但是一旦你学会了这样做,它就成了一种习惯,并将它构建到你的构建系统中,然后它只是开发过程的一部分。就像make test一样简单。一旦你在一个构建系统中拥有它,你就可以将其剪切并粘贴到你永远做的其他事情中。您已经扩展了程序员工具包。即使你不这样做,这也是良好的习惯。

但这是你的数组大小问题的实际答案:

  std::string arr[][10] = {
    {"xxx", "111"},
    {"y", "222"},
    {"hello", "goodbye"},
    {"I like candy", "mmmm"},
    {"Math goes here", "this is math"},
    {"More random stuff", "adsfdsfasf"},
  };
  int size = sizeof(arr) / 10 / sizeof(std::string);
  std::cout << size << endl; // Prints 6, as in 6 pairs of strings

答案 2 :(得分:0)

由于语义类似于Map(你将函数映射到它的差分),我猜最合适的数据结构是std::map,当你可以使用函数作为索引轻松获得差异时。

关于该功能,您不附加lastString。

return hx+lastString;

答案 3 :(得分:0)

问题1实际上非常简单:

std::string dMap[][10] = {{"x", "1"}, {"log(x)", "1/x"}, {"e^x", "e^x"}};
size_t tupleCount = sizeof(dMap)/sizeof(dMap[0]);
size_t maxTupleSize = sizeof(dMap[0])/sizeof(dMap[0][0]);

assert(tupleCount == 3);
assert(maxTupleSize == 10);

请注意,您不会以这种方式获取元组中字符串的实际数量。您只能获得适合每个元组的std::string个数量。当然,您可以在元组中搜索它包含的第一个默认构造std::string。但是整个设置都是对bug的邀请,所以你不想再使用它(见下文)。


问题2也可以非常清楚地回答。你应该使用std::unordered_map<>。为什么呢?

  1. usecase是将一个类的字符串映射到另一个类。这是std::map<>std::unordered_map<>

  2. 的语义
  3. 从你的问题我收集到你不需要下一个或上一个映射的概念,你的映射对本质上是不相关的。在这种情况下,std::unordered_map<>std::map<>快,因为它在内部使用哈希表。无论你的std::unordered_map<>有多大,查找其元素需要花费一定的时间。 std::map<>

  4. 不适用