十一、把字符串转换成整数
有两个任务:
1)为了支持把 C 风格的字符串转换成数字,C++提供了以下四个函数:
int atoi(const char *_String); // 把 C 风格字符串转换为 int 整数。
long atol(const char *_String); // 把 C 风格字符串转换为 long 整数。
long long atoll(const char *_String); // 把 C 风格字符串转换为 long long 整数。
double atof(const char *_String); // 把 C 风格字符串转换为 double 浮点数。
注意:a)如果字符串中间有非法字符,后面的内容将丢弃;b)如果字符串的第一个字符非法或字
符串为空,将返回 0。
2)从界面上输入一个 C 风格的字符串(二进制或十进制),把它转换成整数,类似 atoi()函数。
"4358" int result=0; // 转换的结果。
第一次:把字符4拿出来
result='4'-'0'; 4
第二次:把字符3拿出来
result=result*10; 40
result=40 + '3'-'0' 43
第三次:把字符5拿出来
result=result*10; 430
result=430 + '5'-'0' 435
第四次:把字符8拿出来
result=result*10; 4350
result=4350 + '8'-'0' 4358
循环结束
示例:
#include <iostream>
using namespace std;
int main()
{
// 从界面上输入一个 C 风格的字符串(二进制或十进制),把它转换成整数,类似 atoi()函数。
char str[21];
memset(str, 0, sizeof(str));
cout << "请输入一个由数字组成的字符串:"; cin >> str;
int radix;
cout << "请选择(2-二进制;10-十进制):"; cin >> radix;
int result = 0; // 转换后的结果。
for (int ii = 0,len= strlen(str); ii < len; ii++)
{
if (str[ii]<'0' || str[ii]>'9') { cout << "字符串非法(包含非数字字符)。\n"; break; }
if (radix==2 && str[ii] > '1') { cout << "字符串非法(只能是 0 和 1)。\n"; break; }
result = result * radix;
result = result + str[ii] - '0';
}
cout << "转换的结果是:" << result << endl;
}
十二、实现 strcpy()和 strncpy()函数
示例:
#define _CRT_SECURE_NO_WARNINGS // 使用 C 风格字符串操作的函数需要定义这个宏
#include <iostream>
using namespace std;
// 功 能 : 将参数 src 字符串拷贝至参数 dest 所指的地址。
// 返回值 : 返回参数 dest 的字符串起始地址。
// 复制完字符串后,会在 dest 后追加 0。
// 如果参数 dest 所指的内存空间不够大,会导致数组的越界。
char* mystrcpy1(char* dest, const char* src)
{
long long ii = 0, jj = 0; // 目标字符串和源字符串的下标计数器。
while (src[jj]) // 如果源字符串还没有结束。
dest[ii++] = src[jj++]; // 把源字符串中的字符一个一个的复制到目标字符串中。
dest[ii] = 0; // 把目标字符串加上结尾标志 0。
return dest; // 返回目标字符串。
}
char* mystrcpy2(char* dest, const char* src)
{
char* pdest = dest; // 指向目标字符串。
char* psrc = (char*)src; // 指向源字符串。
while (*psrc) // 如果目标字符串还没有结束。
*pdest++ = *psrc++; // 把源字符串中的字符一个一个的复制到目标字符串中。
*pdest = 0; // 把目标字符串加上结尾标志 0。
return dest; // 返回目标字符串。
}
char* mystrcpy3(char* dest, const char* src)
{
memcpy(dest, src, strlen(src) + 1); // 一次复制整块内存。
return dest; // 返回目标字符串。
}
// 功能:把 src 前 n 个字符的内容复制到 dest 中。
// 返回值:dest 字符串起始地址。
// 如果 src 字符串长度小于 n,则拷贝完字符串后,在 dest 后追加 0,直到 n 个。
// 如果 src 的长度大于等于 n,就截取 src 的前 n 个字符,不会在 dest 后追加 0。
// 如果参数 dest 所指的内存空间不够大,会导致数组的越界。
char* mystrncpy(char* dest, const char* src, const size_t n)
{
memcpy(dest, src, n); // 一次复制整块内存。
*(dest + n) = 0; // 加上字符串的结尾标志。
// dest[n]=0; // 加上字符串的结尾标志。
return dest; // 返回目标字符串。
}
#include <chrono> // 时间操作库的头文件。
int main()
{
//char str[51];
memset(str, 0, sizeof(str));
//mystrncpy(str, "aaaaaaaaa", 3);
//cout << str << "=" << endl;
//return 0;
std::chrono::steady_clock::time_point start, end; // start-计时开始,end-计时完成。
std::chrono::nanoseconds dt; // 时间差。
start = chrono::steady_clock::now(); // 开始计时。
char str1[51];
memset(str1, 0, sizeof(str1));
for (int ii = 0; ii < 10000000; ii++)
mystrcpy1(str1, "我是一只傻傻鸟,不是笨笨鸟,你才是笨笨鸟。1");
cout << str1 << endl;
end = chrono::steady_clock::now(); // 计时完成。
dt = end - start; // 计算时间差。
cout << "耗时: " << (double)dt.count() / (1000 * 1000 * 1000) << "秒。\n"; // 显示
消耗的时间。
start = chrono::steady_clock::now(); // 开始计时。
char str2[51];
memset(str2, 0, sizeof(str2));
for (int ii = 0; ii < 10000000; ii++)
mystrcpy2(str2, "我是一只傻傻鸟,不是笨笨鸟,你才是笨笨鸟。2");
cout << str2 << endl;
end = chrono::steady_clock::now(); // 计时完成。
dt = end - start; // 计算时间差。
cout << "耗时: " << (double)dt.count() / (1000 * 1000 * 1000) << "秒。\n"; // 显示
消耗的时间。
start = chrono::steady_clock::now(); // 开始计时。
char str3[51];
memset(str3, 0, sizeof(str3));
for (int ii = 0; ii < 10000000; ii++)
mystrcpy3(str3, "我是一只傻傻鸟,不是笨笨鸟,你才是笨笨鸟。3");
cout << str3 << endl;
end = chrono::steady_clock::now(); // 计时完成。
dt = end - start; // 计算时间差。
cout << "耗时: " << (double)dt.count() / (1000 * 1000 * 1000) << "秒。\n"; // 显示
消耗的时间。
}
十三、实现 strcat()和 strncat()函数
示例:
#define _CRT_SECURE_NO_WARNINGS // 使用 C 风格字符串操作的函数需要定义这个宏
#include <iostream>
using namespace std;
// 功能:将 src 字符串拼接到 dest 所指的字符串尾部。
// 返回值:返回 dest 字符串起始地址。
// dest 最后原有的结尾字符 0 会被覆盖掉,并在连接后的字符串的尾部再增加一个 0。
// 如果参数 dest 所指的内存空间不够大,会导致数组的越界。
char* mystrcat(char* dest, const char* src)
{
// abc0 // xyz0
memcpy(dest + strlen(dest), src, strlen(src)+1);
return dest;
}
// 功能:将 src 字符串的前 n 个字符拼接到 dest 所指的字符串尾部。
// 返回值:返回 dest 字符串的起始地址。
// 如果 n 大于等于字符串 src 的长度,那么将 src 全部追加到 dest 的尾部。
// 如果 n 小于字符串 src 的长度,只追加 src 的前 n 个字符。
// strncat 会将 dest 字符串最后的 0 覆盖掉,字符追加完成后,再追加 0。
// 如果参数 dest 所指的内存空间不够大,会导致数组的越界。
char* mystrncat(char* dest, const char* src, const size_t n)
{
size_t len = strlen(dest);
memcpy(dest + len, src, n);
// abc0 aaaaa0 3 abcaaa0
// abc0 a0 3 abca0 0
*(dest + len + n) = 0;
return dest;
}
int main()
{
char str[51];
strcpy(str, "abc");
cout << "str=" << str << endl; // 显示 str=abc
mystrcat(str, "abc");
cout << "str=" << str << endl; // 显示 str=abcabc
mystrncat(str, "aaaaaaaaaaaaa",3);
cout << "str=" << str << endl; // 显示 str=abcabcaaa
mystrncat(str, "b", 3);
cout << "str=" << str << endl; // 显示 str=abcabcaaab
}