using namespace std的使用(转载)

本文探讨了C++中命名空间的概念及其重要性,并详细解释了<iostream>与<iostream.h>的区别。此外,还通过一个具体的例子说明了如何避免命名冲突。

所谓namespace,是指标识符的各种可见范围。C++标准程序库中的所有标识符都被定义于一个名为std的namespace中。
一 :
<iostream>和<iostream.h>是不一样,前者没有后缀,实际上,在你的编译器include文件夹里面可以看到,二者是两个文件,打开文件就会发现,里面的代码是不一样的。

后缀为.h的头文件c++标准已经明确提出不支持了,早些的实现将标准库功能定义在全局空间里,声明在带.h后缀的头文件里,c++标准为了和C区别开,也为了正确使用命名空间,规定头文件不使用后缀.h。

因 此,当使用<iostream.h>时,相当于在c中调用库函数,使用的是全局命名空间,也就是早期的c++实现;当使用< iostream>的时候,该头文件没有定义全局命名空间,必须使用namespace std;这样才能正确使用cout。
二:
所谓namespace,是指标识符的各种可见范围。
C++标准程序库中的所有标识符都被定义于一个名为std的namespace中。
由于namespace的概念,使用C++标准程序库的任何标识符时,可以有三种选择:
1、直接指定标识符。例如std::ostream而不是ostream。完整语句如下:

std::cout << std::hex << 3.4 << std::endl;

2、使用using关键字。

using std::cout;
using std::endl;
using std::cin;


以上程序可以写成

cout << std::hex << 3.4 << endl;

3、最方便的就是使用using namespace std;
例如:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
这样命名空间std内定义的所有标识符都有效(曝光)。就好像它们被声明为全局变量一样。那么以上语句可以如下写:

cout << hex << 3.4 << endl;
因为标准库非常的庞大,所程序员在选择的类的名称或函数名时就很有可能和标准库中的某个名字相同。所以为了避免这种情况所造成的名字冲突,就把标准 库中的一切都被放在名字空间std中。但这又会带来了一个新问题。无数原有的C++代码都依赖于使用了多年的伪标准库中的功能,他们都是在全局空间下的。  

         所以就有了<iostream.h>和<iostream>等等这样的头文件,一个是为了兼容以前的C++代码,一个是为了支持新的标准。
命名空间std封装的是标准程序库的名称,标准程序库为了和以前的头文件区别,一般不加".h"




今天用了VISUAL C++写了个小程序(VS2005),很简单很简单的,但是就是编译不通过
出现一个奇怪的问题:错误 1 error C2668: “max”: 对重载函数的调用不明确

最初代码如下
#include <iostream>
using namespace std;

template <typename T>
T max (T a,T b)
{
return ((a>b)?a:b);
}
void main()
{
double x,y;
cin>>x>>y;
cout<<"Max number is "<<(max(x,y))<<endl;
cin>>x;
}


     我将这段代码放到VC++ 6.0下竟然通过了,程序运行也正常。这让我百思不得其解。后来终于弄明白了!
     其实在std命名空间下还有一个MAX函数,而且实现的功能也是一样的……我昏。利用转到定义功能可以看到微软是怎么写MAX函数的。这里为了不被鄙视就不贴微软的代码了。
     明白了为什么出现这个错误我们就改写代码如下:
#include <iostream>
using std::cin;
using std::cout;
using std::endl;

template <typename T>
T max (T a,T b)
{
return ((a>b)?a:b);
}
int main()
{
double x,y;
cin>>x>>y;
cout<<"Max number is "<<(max(x,y))<<endl;
cin>>x;
}

     这是我比较推荐的做法,因为C++ PRIMER, EFFECTIVE C++上都是用这种方式的,但是谭浩强的书上都是一句using namespace std;就搞定,我觉得蛮简洁的就一直用了,没想到带来那么多的问题,以前在友元函数上还碰到莫名的错误呢。
     其实还有两个简单的解决方案,那就是把自己定义的函数改成其他的名字,或者直接用微软提供的函数。相信微软提供的效率绝对不会比我们写的低~
     好了,就写到这了。希望大家养成良好的编程习惯,^-^

<think> 我们被要求将之前提供的C++代码修改为使用`using namespace std;`,这样可以省略标准库名称前的`std::`前缀。同时,我们需要保持代码功能不变:从输入字符串中找出最长的数字串(连续的数字序列)。 原始代码(未使用`using namespace std;`): ```cpp #include<iostream> #include <regex> #include <string> #include <iostream> int main() { std::string s; std::getline(std::cin, s); // 输入字符串 std::string pattern = "[+-]?\\d+(\\.\\d+)?"; // 匹配数字串的正则表达式 std::string resS = ""; // 最长的数字串 for (int i = 0; i < s.length(); i++) { std::string temp = s.substr(i); // 从第i个字符开始的子字符串 std::regex regex(pattern); std::smatch match; if (std::regex_search(temp, match, regex)) { std::string matchStr = match.str(); if (matchStr.length() >= resS.length()) { resS = matchStr; // 更新最长的数字串 } } } std::cout << resS << std::endl; // 输出最长的数字串 return 0; } ``` 修改后的代码(使用`using namespace std;`): 注意:我们将所有`std::`去掉,并在全局作用域使用`using namespace std;`。同时,注意避免重复包含头文件(原代码有两个`#include<iostream>`,我们保留一个)。 ```cpp #include <iostream> #include <regex> #include <string> using namespace std; // 使用标准命名空间 int main() { string s; getline(cin, s); // 输入字符串 string pattern = "[+-]?\\d+(\\.\\d+)?"; // 匹配数字串的正则表达式 string resS = ""; // 最长的数字串 for (int i = 0; i < s.length(); i++) { string temp = s.substr(i); // 从第i个字符开始的子字符串 regex regex(pattern); // 定义正则表达式对象 smatch match; // 存储匹配结果 if (regex_search(temp, match, regex)) { // 在子字符串中搜索匹配 string matchStr = match.str(); // 获取匹配的字符串 if (matchStr.length() >= resS.length()) { resS = matchStr; // 更新最长的数字串 } } } cout << resS << endl; // 输出最长的数字串 return 0; } ``` ### 代码逐行解释(使用`using namespace std;`后): 1. `#include <iostream>`:包含输入输出流库,用于`cin`和`cout`。 2. `#include <regex>`:包含正则表达式库,用于`regex`、`smatch`和`regex_search`。 3. `#include <string>`:包含字符串库,用于`string`类型及其操作。 4. `using namespace std;`:使用标准命名空间,这样我们就可以直接使用`string`、`cout`等,而不需要写`std::`。 5. `int main() {`:程序的主函数。 6. `string s;`:声明一个字符串变量`s`,用于存储输入的字符串。 7. `getline(cin, s);`:从标准输入读取一行字符串,存入`s`中。 8. `string pattern = "[+-]?\\d+(\\.\\d+)?";`:定义正则表达式模式字符串。该模式用于匹配整数或浮点数(可选的符号、整数部分、可选的小数部分)。注意:在C++字符串中,反斜杠需要转义,所以`\\d`表示`\d`(匹配数字),`\\.`表示`\.`(匹配点号)。 9. `string resS = "";`:初始化一个空字符串,用于存储找到的最长数字串。 10. `for (int i = 0; i < s.length(); i++) {`:循环遍历字符串的每个字符位置。 11. `string temp = s.substr(i);`:从位置`i`开始截取子字符串(直到字符串末尾)。 12. `regex regex(pattern);`:创建一个正则表达式对象,使用之前定义的模式。注意:这里变量名`regex`与类型`regex`同名,在某些编译器下可能产生警告,但通常可以编译通过。为了避免歧义,可以修改变量名(例如`re`),但原代码如此,我们保持不变。 13. `smatch match;`:创建一个`smatch`对象,用于存储匹配结果。 14. `if (regex_search(temp, match, regex)) {`:在子字符串`temp`中搜索与正则表达式匹配的内容,如果有匹配,则结果存储在`match`中,并进入条件体。 15. `string matchStr = match.str();`:从匹配结果中提取匹配的整个字符串。 16. `if (matchStr.length() >= resS.length()) {`:比较当前匹配的字符串长度与当前最长字符串`resS`的长度。 17. `resS = matchStr;`:如果当前匹配的字符串更长或等长(取等长是为了在同样长时更新,但题目要求最长,所以等长时更新为后面出现的),则更新`resS`。 18. `}`:结束内层条件语句。 19. `}`:结束循环体。 20. `cout << resS << endl;`:输出最长数字串,并换行。 21. `return 0;`:程序正常退出。 ### 代码功能说明: 该程序通过遍历输入字符串的每一个位置,从该位置开始截取剩余子串,然后在子串中搜索匹配正则表达式的数字串(整数或浮点数)。每次匹配到数字串后,将其长度与当前保存的最长数字串长度比较,更新最长数字串。最后输出找到的最长数字串。 ### 注意事项: 1. 正则表达式模式解释: - `[+-]?`:可选的正负号(0个或1个)。 - `\\d+`:1个或多个数字。 - `(\\.\\d+)?`:可选的小数部分,包括一个小数点和至少一个数字。 2. 该程序在匹配时,如果存在多个同样长度的最长数字串,它会保留最后一个遇到的(因为当长度相等时更新)。如果想保留第一个,可以将条件改为`>`(大于),但原代码是`>=`(大于等于),所以会更新为后面遇到的等长字符串。 ### 相关问题 1. 如何使用C++正则表达式匹配整数? 2. 在C++中,`using namespace std;`的使用有什么优缺点? 3. 如何处理正则表达式匹配中的性能问题,特别是长字符串? 4. 如何修改代码以匹配所有数字串并输出所有结果(而不仅仅是最长的一个)? </think> ### 修改后的代码(使用 `using namespace std`) ```cpp #include <iostream> #include <regex> #include <string> using namespace std; int main() { string s; getline(cin, s); // 输入完整字符串 string pattern = "[+-]?\\d+(\\.\\d+)?"; // 匹配数字序列的正则表达式 string resS = ""; // 存储最长的数字串 for (int i = 0; i < s.length(); i++) { string temp = s.substr(i); // 提取当前位置开始的子串 regex regex(pattern); // 创建正则表达式对象 smatch match; // 存储匹配结果 if (regex_search(temp, match, regex)) { // 在子串中搜索匹配 string matchStr = match.str(); // 获取匹配的字符串 if (matchStr.length() >= resS.length()) { // 比较长度 resS = matchStr; // 更新最长数字串 } } } cout << resS << endl; // 输出结果 return 0; } ``` ### 详细代码解释(使用 `using namespace std`) 1. **头文件引入** ```cpp #include <iostream> // 提供输入输出功能(cin, cout) #include <regex> // 提供正则表达式支持 #include <string> // 提供字符串操作 using namespace std; // 使用标准命名空间 ``` - 使用 `using namespace std` 后,所有标准库组件无需 `std::` 前缀 - 例如 `string` 代替 `std::string`,`cout` 代替 `std::cout` 2. **输入处理** ```cpp string s; getline(cin, s); // 读取整行输入(包括空格) ``` - `getline()` 完整读取用户输入到字符串 `s` - 处理包含空格的输入(如 `abc 123.45 def`) 3. **正则表达式定义** ```cpp string pattern = "[+-]?\\d+(\\.\\d+)?"; // 匹配数字序列 ``` - 模式解析: - `[+-]?`:可选正负号($+$ 或 $-$) - `\\d+`:1个或多个数字($\d+$) - `(\\.\\d+)?`:可选小数部分($.123$) - 可匹配:`123`, `-45.67`, `+0.5` 等格式 4. **遍历与匹配** ```cpp for (int i = 0; i < s.length(); i++) { string temp = s.substr(i); // 截取子串 regex regex(pattern); // 编译正则表达式 smatch match; // 存储匹配结果 if (regex_search(temp, match, regex)) { // 执行搜索 string matchStr = match.str(); // 提取匹配文本 ``` - 遍历每个字符位置 $i$(时间复杂度 $O(n)$) - `substr(i)`:获取从位置 $i$ 到结尾的子串 - `regex_search()`:查找第一个匹配项[^4] 5. **更新最长数字串** ```cpp if (matchStr.length() >= resS.length()) { resS = matchStr; // 保留更长的匹配结果 } ``` - 使用 `>=` 保证多个等长时取最后出现的 - 例如输入 `a12 b345 c67` 会取 `345` 6. **结果输出** ```cpp cout << resS << endl; // 输出最长数字串 ``` - 若未找到数字串,输出空字符串 - 例如输入 `hello world` 输出空行 ### 关键改进说明 1. **命名空间简化**: - 移除所有 `std::` 前缀,代码更简洁 - 保持与原代码完全相同的功能逻辑 2. **正则表达式优化**: - 模式 `[+-]?\d+(\.\d+)?` 覆盖整数和浮点数 - 支持科学计数法需扩展为:`[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?` 3. **性能考虑**: - 最坏时间复杂度 $O(n^2)$(嵌套循环 + 正则匹配) - 大数据量时可优化为单次遍历(不使用正则) ### 相关问题 1. 如何修改正则表达式以匹配科学计数法(如 `1.23e-4`)? 2. 当存在多个等长的数字串时,如何修改代码返回第一个匹配项? 3. 对于超大输入字符串,如何优化该算法的时间复杂度? 4. C++ 正则表达式中的 `smatch` 和 `cmatch` 有何区别? 5. 如果输入包含货币符号(如 `$123.45`),如何调整正则表达式?[^1][^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值