您的位置:首页 > 编程语言

类型转换与字符串赋值、分割、合并、复制、比较、查询、翻转详解 (完整代码)

2013-08-24 20:44 597 查看
一、类型转换

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()函数把读出的数据放回到缓冲区,缓冲区这个容器就为这些数据分配相应的大小空间,之后这个空间是不变的,直到你把缓冲区的数据读出去,所以你在没有释放缓冲区时,再次想往缓冲区装数据是装不进去的。

****转载请注明出处:/article/2673925.html****
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐