类型转换与字符串赋值、分割、合并、复制、比较、查询、翻转详解 (完整代码)_合并字符串函数
阿里云国际版折扣https://www.yundadi.com |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
一、类型转换
char数组转int, long long, double:
#include<cstring>
#include<cstdio>
#include<cctype>
#include<cstdlib>
char str[100];
int main(void)
{
gets(str);
if (!strchr(str, '.'))
{
if (strlen(str) < 10)
printf("%d\n", atoi(str)); // 转int
else
printf("%lld\n", atoll(str)); // 转long long,或者用strtoll(str, NULL, 10)
}
else
printf("%.4f\n", atof(str)); // 转double并保留4位小数
return 0;
}
int, long long, double转char数组:
#include<cstring>
#include<cstdio>
#include<cctype>
#include<cstdlib>
#include<cmath>
char str[100];
int main(void)
{
int num = 666;
__int64 num2 = (__int64)1 << 55;
double num3 = acos(-1.0);
sprintf(str, "%d", num);
puts(str);
sprintf(str, "%lld", num2);
puts(str);
sprintf(str, "%.16f", num3); // 16位有效数字
puts(str);
return 0;
}
PS:模10除10的方法更快
PS2:进制转换见这篇文章。
二、字符串赋值
PS:我们不讨论scanf()和gets()这种从键盘输入的方法。
#include<cstdio>
#include<cstring>
char str[20];
int main(void)
{
char *p = str;
///尝试A
p = "Minecraft";//不可取的做法
/*
双引号做了3件事:
1. 申请了空间,存放了字符串
2. 在字符串尾加上了'\0'
3. 返回地址,准确地说是指针常量
*/
printf("%s %p\n\n", p, p);//output:Minecraft 00403024
///尝试B
//*p = "Minecraft";
/*
照样不行,因为右边返回的是一个指针常量
这和str = "Minecraft";是一样的
*/
///尝试C
p = "Minecraft";
strcpy(str, p);
puts(str);
//成功,详见下方解释
///尝试D
p = "Minecraft";
sprintf(str, "%s", p);
puts(str);
//成功
return 0;
}
先看看strcpy()的实现代码:
char *strcpy(char *strDest, const char *strSrc)
{
char *strDestCopy = strDest;
if ((strDest == NULL) || (strSrc == NULL))//两边指针都为空
throw "Invalid argument(s)";
while (*strDest++ = *strSrc++);//先赋值,在递增,最后判断返回值是否为空指针(NULL)
return strDestCopy;
}
这相当于把char数组一个一个地赋给str。
三、字符串分割、合并、复制、比较、查询、翻转及自定义字符串函数
先放上C风格的代码:
/*请务必运行本程序以便对照阅读*/
#include<cstring>
#include<cstdio>
#include<cctype>
#include<cstdlib>
///没有换行的puts()函数
void puts1(const char *str)
{
while (*str) //*str != '\0'
putchar(*str++);
}
///前后换行的puts()函数
void puts2(const char *str)
{
putchar('\n');
while (*str) //*str != '\0'
putchar(*str++);
putchar('\n');
}
///连换两行的puts()函数
void puts3(const char *str)
{
while (*str) //*str != '\0'
putchar(*str++);
putchar('\n');
putchar('\n');
}
int main(void)
{
///1. 分割与复制
char str[] = "num = 666", str2[20], str3[20], key[20];
int val;
strcpy(str2, strtok(str, " ="));
puts(str2);
val = atoi(strtok(NULL, " ="));///分割一个元组后,要继续分割后面的元组,请将参数改为NULL
///2. 比较与合并
printf("%d\n\n请输入两个字符串:\n", val);
memset(str2, 0, sizeof(str2));
scanf("%s%s", str2, str3);
getchar();
puts3(strcmp(str2, str3) < 0 ? strcat(str2, str3) : strcat(str3, str2));
///3.1 查询
const char NAME[] = "Takanashi Rikka";
puts(strchr(NAME, 'k') ? "YES" : "NO");
puts(strchr(NAME, 'b') ? "YES" : "NO");
puts3(strstr(NAME, "Rikka") ? "YES" : "NO");
///3.2 替换
strcpy(str2, "he put his book on the table.");
strcpy(key, "book");
char *p = strstr(str2, key), *p2 = key;
for (int i = 0; i < strlen(key); ++i) key[i] = toupper(key[i]);
while (*p2) *p++ = *p2++;
puts(str2);
///4.1 翻转
strcpy(str2, "eca");///请勿翻转中文字符
puts(strrev(str2));
///4.2 检查一个字符串是否为回文字符串
strcpy(str2, "TAT");
strcpy(str3, str2);
puts(strcmp(str2, strrev(str3)) ? "NO" : "YES");///注意strrev会修改传入的字符串
///5. 当读到一个空行就结束,否则输出
char ch;
while (true)
{
ch = getchar();
if (ch == '\n')
break;
ungetc(ch, stdin); ///放回到标准输入流(键盘)
memset(str2, 0, sizeof(str2));
gets(str2);
puts(str2);
getchar();
}
return 0;
}
C++STL:
#include<cstdio>
#include<iostream>
#include<string>
using namespace std;
string str, str2, str3;
int main(void)
{
///1. 条件读入
///PS: 在处理前后空格时,依旧没scanf("%s",str);强大
puts("请输入一行含有若干'#'的话:");
while (getline(cin, str, '#'))
{
if (str == "") continue;///遇到连续的'#'
if (~str.find("\n", 0))
str.erase(str.size() - 1);///去掉输入最后的换行(不写的话会多出一个换行)
cout << str << endl;
}
cout << endl;
///2. 比较与合并
str = "ace", str2 = "ab";
cout << (str < str2 ? str + str2 : str2 + str) << endl;
cout << endl;
///3. 查询
str = "Takanashi Rikka";
puts(~str.find("a", 0) ? "YES" : "NO");
puts(~str.find("S", 0) ? "YES" : "NO");///未找到就返回-1(string::npos)
cout << endl;
///4. 插入
str.insert(3, "OOOO");
cout << str << endl;
cout << endl;
///5. 片段截取与删除
str2 = ("Now is the time to get AC.");
str3.assign(str2, 11, 4);///4指要截取的长度
//等价的做法:str3 = str2.substr(11, 4);
cout << str3 << endl;
str2.erase(3, 6);
cout << str2 << endl;
cout << endl;
return 0;
}
四、补充
Q:使用ungetc()如果把读出的数据放回到缓冲区去后,没有将缓冲区的数据读出来,就再次试图把读出的数据放回到缓冲区,会发生什么?
A:数据是放不进去的。我们可以把缓冲区看做一个可变化的容器,当你把试图用ungetc()函数把读出的数据放回到缓冲区,缓冲区这个容器就为这些数据分配相应的大小空间,之后这个空间是不变的,直到你把缓冲区的数据读出去,所以你在没有释放缓冲区时,再次想往缓冲区装数据是装不进去的。
阿里云国际版折扣https://www.yundadi.com |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |