《程序员》杂志专家门诊C/C++问题

babysloth 2002-04-19 11:17:48
下面是《程序员》杂志第5期中专家门诊部分的C/C++问题,我整理了几个,大家能否看看有没有什么问题。

由于这次时间仓促,没有及时与大家商量,非常抱歉。以后希望大家多提建议,推荐您认为好的问题,共同学习。

----------------------------------------------

需要在 p = new xxx()之后检查NULL吗?

按现行标准,如果内存分配失败,则会抛出std::bad_alloc异常。但有些编译器仍遵循以前的方式:返回0,例如Microsoft Visual C++。不过从VC7开始,CRT仍采取这样的方式,但VC中的C++标准库则支持抛出异常之一标准方式。详细情况请见MSDN。

另外,标准委员会为了与以前保持一致性,也提供了不抛出异常的方式:

xxx *p = new (nothrow) xxx;

这时就不妨用assert(p)。

相关问题在Effective C++上有非常精彩的描述,请参考。


----------------------------------------------



如何安全地将多态指针放进STL容器?

class A{};
class C: public A{};
// 以vector为例,如果
vector<A*> vec;
vec.push_back(new C());

问题出现如何对容器中的指针进行管理上,假如直接把指针放到容器里,然后在进行删除元素操作和容器的析构器中释放元素指向的内存,听起来似乎井井有条,但是如果一个容器中有多个元素指向同一个对象或者多个指向同一个对象的元素被包含到多个容器中,就会带来一片混乱


那么用标准库中的auto_ptr来管理指针又会如何呢?情况可能会更糟,不但老问题不能解决,还带来了新问题,auto_ptr只是简单地将指针的管理权在对象之间转移,假如在对容器进行操作的算法中将元素的管理权交给了临时对象,那么当算法完成后临时对象将自动地释放该元素指向的内存,结果将不堪设想。毕竟,auto_ptr是典型的“一拷就坏(Copy Destructive)”。

有一种解决办法是专门用一个容器来保存所有的动态对象,只有该容器可以删除对象,其他容器只保留指向这些对象的指针。当然这种做法比较烦。另一种简单的方法是利用Boost库(介绍见《程序员》2002年3月号的《走进Boost》一文)中的shared_ptr。

#include <list>
#include <boost/shared_ptr.hpp>
class A{};
class C: public A{};

void g()
{
typedef boost::shared_ptr<A> element_type;
typedef std::list<element_type> list_type;

list_type ll;
ll.push_back(element_type(new C));
}

这个比auto_ptr复杂得多的东东管理的是对象的引用计数,当计数为0时自动释放内存,呵呵,真是个好管家。


----------------------------------------------


一个std::string对象,要把这个对象两端多余的空格去掉,怎么办?

可以利用string的成员函数find_first_not_of和find_last_not_of:

#include <iostream>
#include <string>

template <class T> void trim(std::basic_string<T>& s)
{
const char c = ' ';
s.erase(0, s.find_first_not_of(c));
s.erase(s.find_last_not_of(c) + 1);
}

void main()
{
using namespace std;
string str(" 123 456 789 ");
trim(str);
cout << str << '$' << endl;
return;
}

如果字符串非空部分很长的话,上面的find_last_not_of显然缺乏效率,我们可以把trim函数改写为:

template <class T> void trim(std::basic_string<T>& s)
{
const char c = ' ';
s.erase(0, s.find_first_not_of(c));
basic_string<T>::reverse_iterator i =
std::find_if(s.rbegin(), s.rend(),
std::bind2nd(std::not_equal_to<T>(), c));
s.erase(i.base(), s.end());
}

不知道是否还有更好的方法。

----------------------------------------------
...全文
75 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
Elminster 2002-04-23
  • 打赏
  • 举报
回复
关于问题二,Matt Austern 在 CUJ Forum 上专文讨论过,相当详细。
关于问题三,嗯 …… 我想能不能讨论一下扩展情况?比如 string 两头既有空格又有‘\t’制表符,怎么把它们去掉?或者更一般些,给定一个字符集,将 string 两头在这个字符集中的字符都去掉?
hcpp 2002-04-23
  • 打赏
  • 举报
回复
领教领教。
babysloth 2002-04-23
  • 打赏
  • 举报
回复
谢谢大家的参与。
cber 2002-04-23
  • 打赏
  • 举报
回复
Elminster() :
对于问题三,在我上面给出的CppTips中已经由James Kanze搞定了,你可以去看看上面那一长串代码
>KANZE: James Kanze <kanze@gabi-soft.de>

>Not really. It doesn't consider other types of white space, nor
>other types of char.

Winner_Li 2002-04-22
  • 打赏
  • 举报
回复
Good!!
maoliao 2002-04-22
  • 打赏
  • 举报
回复
save!
xjl930 2002-04-22
  • 打赏
  • 举报
回复
STL的东西还是很值得探讨的,谢谢小懒虫虫精彩的帖子,收藏!!
jjyin7806 2002-04-22
  • 打赏
  • 举报
回复
GOOD
招RD和QA 2002-04-22
  • 打赏
  • 举报
回复
gzer
nicholas_87 2002-04-21
  • 打赏
  • 举报
回复
saved...
挺拔的劲松 2002-04-21
  • 打赏
  • 举报
回复
sc
vcmfc 2002-04-20
  • 打赏
  • 举报
回复
我的思跟是这样的,C中有个函数,名给忘了,也就是在一个char*上拷贝指定东东,估计没出异常安全,所以就是*p++加入API,不过代码还是比你多,你的最精练,对于string,你运用的好熟练,看来得闭关。
cber 2002-04-20
  • 打赏
  • 举报
回复
TITLE: trimming a standard string

(Source: comp.lang.c++.moderated, 18 Sep 2001)

WILSON: Bryan Wilson

> > I am new to C++ using MS Visual C++ 6.0 and trying to create a dll
> > to parse chunks from a flat .ASC file into a tab delimited .txt
> > file with leading and trailing spaces trimed off. Could someone
> > please show me an example of how to write the trim functionality??

FRITZSCHE: Albrecht Fritzsche <albrecht.fritzsche@alfabet.de>

> The std::string class already offers you enough functionality:
>
> std::string shortenString(const std::string& str) // untested code!!
> {
> std::string::size_type first = str.find_first_not_of(" ");
> std::string::size_type last = str.find_last_not_of(" ");
> return str.substr(first, last-first+1);
> }
>
> should give you a trimmed string

KANZE: James Kanze <kanze@gabi-soft.de>

Not really. It doesn't consider other types of white space, nor
other types of char.

There is a function in std::ctype that you'd expect to give you what
you need: scan_is. Regretfully, it doesn't work with iterators, only
charT*, so we are a bit handicapped. However, we can use std::find_if
by simply defining an appropriate predicate:

template< std::ctype_base::mask type , typename charT = char >
class Is : public std::unary_function< charT , bool >
{
public:
explicit Is( std::locale const& l )
: m_ctype( std::use_facet< std::ctype< charT > >( l ) )
{
}
bool operator()( charT ch ) const
{
return m_ctype.is( type , ch ) ;
}
private:
std::ctype< charT > const&
m_ctype ;
} ;

Given this, trim becomes just a simple return statement:

template< typename stringT >
stringT
trim( stringT const& s , std::locale const& l = std::locale() )
{
return
std::find_if(
s.begin() , s.end() ,
std::not1( Is< std::ctype_base::space ,
typename stringT::value_type >( l ) ) )
== s.end()
? stringT()
: stringT(
std::find_if(
s.begin() , s.end() ,
std::not1( Is< std::ctype_base::space ,
typename stringT::value_type >( l )
) ) ,
std::find_if(
s.rbegin() , s.rend() ,
std::not1( Is< std::ctype_base::space ,
typename stringT::value_type >( l )
) ).base() ) ;
}

OK, so the statement's a bit long. But the logic in it is actually
very simple, once you get through the cruft due to namespaces and the
template syntax. (Welcome to the wonderful world of generic
programming:-).)
x_zj 2002-04-20
  • 打赏
  • 举报
回复
to vcmfc:
那个函数是: strdup。
vcmfc 2002-04-19
  • 打赏
  • 举报
回复
最后一期,我是热衷于使用*p++的C方式来处理,高效安全。


这东东用STL,感觉就像用大炮打蚊子。
twist 2002-04-19
  • 打赏
  • 举报
回复
收藏
cber 2002-04-19
  • 打赏
  • 举报
回复
不错,不过我记得最后那个问题在CppTips上面有一个更据弹性的做法,但很复杂。你给出的那个做法差不多可以在大部分情况下使用了。
babysloth 2002-04-19
  • 打赏
  • 举报
回复
不用这样啊,老哥,呵呵。
就算是char*,恐怕也不容易,因为还涉及内存管理的问题。
vcmfc 2002-04-19
  • 打赏
  • 举报
回复
上面我说错了,是去掉string,而我以为是char*,真没长眼睛,收回我的话。

babysloth还是厉害,不得不佩服。
ljf1107 2002-04-19
  • 打赏
  • 举报
回复
不错!
加载更多回复(2)
内容概要:本文研究了一种应用于太阳能发电系统的多级逆变器,旨在通过采用正弦脉宽调制(SPWM)技术有效降低输出电压的总谐波失真(THD),从而提升电能质量。研究基于Simulink平台构建了完整的仿真模型,系统地实现了SPWM信号生成、驱动逻辑控制以及多电平输出波形合成等关键环节,验证了该多级逆变器在不同运行工况下具备优异的动态响应能力和稳定性。仿真结果表明,所设计的逆变器能够输出接近理想正弦波的电压波形,显著抑制高次谐波,满足可再生能源并网对电能质量的严苛要求,体现出多级逆变拓扑在光伏发电系统中的技术先进性与工程应用价值。; 适合人群:电气工程、自动化、新能源科学与工程及相关专业的本科生、研究生,以及从事光伏逆变器设计、电力电子变换技术和可再生能源并网系统研发的工程技术人员。; 使用场景及目标:①深入理解多级逆变器的工作原理及其在太阳能发电系统中的关键作用;②掌握SPWM调制技术的理论基础与实现方法,并分析其对改善THD的核心机制;③借助Simulink仿真平台开展电力电子电路的建模、参数调试与性能评估,服务于课程设计、毕业设计、科研课题或实际工程项目开发。; 阅读建议:建议读者结合提供的Simulink仿真模型进行同步操作与验证,细致调整调制比、载波频率等关键参数,观察其对输出波形和THD指标的影响,以深化对系统动态特性的理解,并尝试优化控制策略以进一步提升系统性能。
VCF 生成器 Lite v6.0.0:批量导入与功能拓展 VCF 生成器 Lite v6.0.0 正式版已发布,此次更新带来了批量导入手机通讯录这一重要功能,极大地方便了用户整理和管理联系人信息。同时,新增了多项功能,如翻译所有 CLI 内容,让不同语言背景的用户都能更好地使用;verbose 模式新增更多日志信息,有助于用户更详细地了解操作过程。 此外,还添加了多地区号码格式支持,包括中国港澳台地区电话号码格式,满足了不同地区用户的需求。当未捕获异常时,系统会自动保存错误日志,并引导用户反馈给开发者,这体现了产品团队对用户体验 的重视,有助于及时发现和解决问题。 修复痛点:引号清理与进度条显示问题 在修复方面,此次更新解决了引号清理功能在包含换行符时的错误行为,以及自 `v4.3.0` 版本以来的进度条显示问题。这些问题虽然看似微小,但却影响了用户的使用体验,修复后能让用户更加顺畅地使用 VCF 生成器 Lite。 代码与文档重构:提升可维护性与易用性 在变更方面,将翻译框架迁移到 gettext,提升了 `LANGUAGE` 环境变量 优先级,方便用户根据自己的语言偏好进行设置。在 AI 的指导下重构项目,使得各层次职责更加清晰,代码更加模块化,可维护性更高,这为产品的后续发展奠定了良好的基础。 同时,按 Diataxis 框架重构用户文档,按开发生命周期 重组开发者文档,让用户和开发者都能更方便地获取所需信息,提高了产品的易用性。 编辑观点:VCF 生成器 Lite v6.0.0 的更新在功能、修复和代码文档方面都有显著提升,满足了用户的实际需求,增强了产品的竞争力,未来有望在市场上取得更好的成绩。

70,039

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧