简单的C ++函数 - 这段代码“好”吗?

时间:2008-10-17 17:20:01

标签: c++

以下代码是由为我的小组工作的顾问制作的。我不是一个C ++开发人员(虽然工作在很多语言中)但是想对以下代码有一些独立的意见。这是在Visual Studio C ++ 6.0中。我有一个直觉反应(显然不是一个很好的反应),但我想要那些来自经验丰富(甚至不是那么没有经验)的C ++开发人员的“直觉反应”。提前谢谢!

// Example call
strColHeader = insert_escape(strColHeader, ',', '\\'); //Get rid of the commas and make it an escape character

...略...

CString insert_escape ( CString originalString, char charFind, char charInsert ) {
    bool continueLoop = true;   
    int currentInd   = 0;

    do {
        int occurenceInd = originalString.Find(charFind, currentInd);

        if(occurenceInd>0) {
            originalString.Insert(occurenceInd, charInsert);
            currentInd = occurenceInd + 2; 
        }
        else {
            continueLoop = false;   
        }
    } while(continueLoop);
    return(originalString);
}

14 个答案:

答案 0 :(得分:17)

HMM。我想

CString strColHeader;
strColHeader.Replace(",", "\\,") 

也会这样做。

我不喜欢代码,我倾向于从while循环中断,而不是有一个不必要的bool'continin'标志。当他可以使用while (occurenceInd != 0)作为他的循环控制变量而不是布尔值时,它会变成两倍。

增加计数器还依赖于“+2”,这似乎不能立即理解(不是一瞥),最后(最重要的是)他似乎没有做评论。

答案 1 :(得分:11)

中间有一个一个一个一个的错误: 看一下如果第一个字符是逗号会发生什么:“,abc,def,ghi”:我假设所需的输出将是“\,abc \,def \,ghi”,但是你会得到原始的回来了:

int occurenceInd = originalString.Find(charFind, currentInd);

OccurrenceInd返回0,因为它在第一个字符处找到了charFind。

if(occurenceInd>0) 

0不大于0,所以取else分支并返回原始字符串。 CString::Find在无法找到某些内容时返回-1,因此至少该比较应为:

if(occurrenceInd >= 0)

最好的方法是使用Replace函数,但是如果你想手动完成,更好的实现可能看起来像这样:

CString insert_escape ( const CString &originalString, char charFind, char charInsert ) {
    std::string escaped;
    // Reserve enough space for each character to be escaped
    escaped.reserve(originalString.GetLength() * 2); 
    for (int iOriginal = 0; iOriginal < originalString.GetLength(); ++iOriginal) {
        if (originalString[iOriginal] == charFind)
            escaped += charInsert;
        escaped += originalString[iOriginal];
    }
    return CString(escaped.c_str());
}

答案 2 :(得分:5)

已经提到了错误。但是,他们认为任何人都可能遇到的问题很快就会被快速破解,而且还没有经过适当的测试,特别是如果他们不熟悉CString的话。

我更担心风格的东西,因为他们建议有人不熟悉C ++。使用bool continueLoop只是简单的C ++。它代表函数代码的三分之一,可以通过使用简单的if ... break构造来消除,使代码更容易在过程中遵循。

此外,变量名称“originalString”非常具有误导性。因为它们是按值传递的,所以它不是原始字符串,而是它的副本!然后他们无论如何都要修改字符串,因此它不再是与原始文本相同的对象或相同的文本字符串。这种双重谎言暗示了混乱的思维模式。

答案 3 :(得分:3)

CString有一个Replace()方法......(这是我的第一反应)

我看到了很多不好的代码,而且比这更糟糕。但是,如果没有明显的理由,那么就不要使用内置功能......不好。

答案 4 :(得分:3)

我的直觉反应是: WTF 。最初是如何格式化代码(有许多我不喜欢格式化的东西),然后检查代码实际上在做什么。

这个开发人员对C ++中对象复制的理解存在严重问题。这个例子本身就是一个WTF(如果该函数的开发人员真的使用了他/她自己的函数):

// Example call
strColHeader = insert_escape(strColHeader, ',', '\\'); //Get rid of the commas and make it an escape character

CString insert_escape ( CString originalString, char charFind, char charInsert )
  1. strColHeader副本作为originalString传递(请注意,没有&
  2. 该功能修改了此副本(精)
  3. 该函数返回副本的副本,然后替换原始strColHeader。编译器可能会将其优化为单个副本,但仍然像这样传递对象副本对C ++不起作用。人们应该知道参考文献。
  4. 一位经验丰富的开发人员会将此功能设计为:

    void insert_escape(CString &originalString, char charFind, char charInsert)
    

    或:

    CString insert_escape(const CString &originalString, char charFind, char charInsert)
    

    (可能会对参数命名有点不同)

    正如许多人所指出的那样,开发人员可以做的理智是检查API文档以查看CString是否已经有Replace方法......

答案 5 :(得分:2)

如果您想要评估此开发人员的C ++技能水平,我会说这证明了中间人的低端。

代码完成工作,并且不包含任何明显的“咆哮者”,但正如其他人所写,有更好的方法可以做到这一点。

答案 6 :(得分:2)

我不会提供替代代码,因为它只会添加到已提供的代码中。

但是,我的直觉是代码有问题。

为了证明这一点,我将列举原始函数中的一些要点,表明它的开发人员不是一位经验丰富的C ++开发人员,如果你需要一个干净的实现,你应该调查一下:

  • copy :参数作为副本而不是const-reference传递。在考虑对象时,这在C ++中是一个很大的NO NO。
  • 错误我猜“if(occurenceInd&gt; 0)”部分中存在错误。通过在MSDN上读取CString的文档,CString :: Find方法返回-1,而在查找失败时不返回0。这段代码告诉我,如果一个逗号是第一个字符,它就不会被转义,这可能不是函数的重点
  • 不需要的变量:不需要“continueLoop”。将代码“continueLoop = false”替换为“continue”,将“while(continueLoop)”替换为“while(true)”就足够了。请注意,继续这种推理使编码人员能够更改内部功能(在一段时间内替换do ...)
  • 更改返回类型:可能会选择详细信息,但我会提供一个替代函数,它不会返回结果字符串,而是接受作为参考(返回时减少一个副本),原始函数被内联并调用替代。
  • 再次添加const ,再次详细说明:两个“char”参数应该是const,只是为了避免意外修改它们。
  • 可能的多次重新分配该函数依赖于CString数据的潜在多次重新分配。 Josh使用std :: string保留的解决方案很好。
  • 使用完全CString API :但与Josh不同,因为你似乎使用CString,我会避免使用std :: string并使用CString :: GetBufferSetLength和CString :: ReleaseBuffer,这使我能够具有相同的代码,少一个对象分配。
  • 神秘的插入方法?是我,还是没有CString :: Insert ??? (见http://msdn.microsoft.com/en-us/library/aa252634(VS.60).aspx)。事实上,我甚至未能在Visual C ++ 2008和2005的相同MSDN中找到CString ......这可能是因为我应该真的进入睡眠状态,但我仍然认为这值得研究< / LI>

答案 7 :(得分:1)

这位顾问是否按照代码行付款?有几个人指出CString类已经提供了这个功能,所以即使你不是程序员,你也知道:

  • 该功能是不必要的。它增加了程序的复杂性,大小和可能的执行时间。
  • CString函数可能有效并且可能有效;这个可能会也可能不会。
  • CString函数已记录在案,因此是可支持的。
  • 顾问要么不熟悉标准CString功能,要么认为他/她可以通过写一个新功能做得更好。
    • 有人可能会得出结论,顾问不熟悉其他标准功能和最佳实践。
    • 选择为基本功能编写新代码,而不考虑可能存在标准版本,这是一种公认​​的不良做法。

也许是最重要的,最红的标志:你的直觉促使你从StackOverflow社区获得意见。

相信你的直觉。

答案 8 :(得分:0)

编写的代码确实有效,因为它返回了新字符串。它只是强制执行额外步骤,然后将旧string =设置为返回的字符串。

正如其他人所说,字符串的内置功能比重新发明轮子更有效,更不容易出错。

答案 9 :(得分:0)

看起来没问题,如果有点,我不知道,黑客攻击。最好使用该库,但我不会去重写这个例程。

答案 10 :(得分:0)

  

这是在Visual Studio C ++ 6.0中。

肠道反应: blech 。认真! VC ++ 6附带的C ++编译器已知存在问题,并且通常表现非常糟糕且已有10年历史。

@Downvoters:考虑一下!我非常认真地说这个。 VC6只是相对无效的,不应该再被使用了!特别是自微软停止支持该软件以来。有些情况下这是无法避免的,但很少见。在大多数情况下,代码库的升级可以节省资金。 VC ++ 6不允许利用C ++的潜力,这使得客观上较差的工具。

答案 11 :(得分:0)

看起来人们已经为你解决了这段代码的一些功能方面,但是我建议你不要像你在这里使用的那样改变命名。

除了UI控件之外,通常不赞成使用匈牙利表示法。这对于数字来说更为重要......例如:

我宣布:

float fMyNumber = 0.00;

然后我在整个应用程序中使用它。但后来,我将其改为双,因为我意识到我需要更高的精度。现在我有:

double fMyNumber = 0.00;

大多数优秀的重构工具都可以为您解决这个问题,但最好不要附加这些前缀。它们在某些语言中比其他语言更常见,但从一般的风格角度来看,你应该尽量避免使用它们。除非你使用记事本,否则你可能有类似Intellisense的东西,所以你真的不需要查看变量名来确定它是什么类型。

答案 12 :(得分:0)

始终有更好的实施方式。如果您使用该功能作为顾问不是很好的示例,您可能还需要考虑,虽然他们不知道已经存在的功能,但他们可能有项目构建的经验和理解。

软件开发不仅仅是完美的功能,还包括整个架构的结构。

答案 13 :(得分:0)

当我看到一个do ... while循环时,我总是担心; IMO他们总是很难理解。