字符串和数字的解析转换 纯C语言实现
灵感来源
很多脚本语言如python和js,都能做到字符串解析为整形或者小数型的变量,数字类型变量也能非常轻松的转化成字符串,今天突然想到用原始的C语言,设计算法自己手动实现一下这个功能。
主要功能
int类型0~9单个数字 <—相互转化—> 字符
int类型 <—相互转化—> 字符串
double类型 <—相互转化—> 字符串
源代码实现
直接新建一个main.c并将全部代码复制进去即可。调用对应的函数使用。
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
/**
* 获取一个数字的第d位数字
* @param number 数字
* @param d 如果是1,就表示个位数字
* @return 0~9之间的一个数字
*/
int getDig(int number, int d);
/**1
* 将数字转化成字符
* 3 --> '3'
* @param number 仅限 0 ~ 9
* @return '0' ~ '9'
*/
char numToChar(int number);
/**
* 将字符数字解析成数字整形
* @param chrNum '0' ~ '9'
* @return 0 ~ 9
*/
int charToInt(char chrNum);
/**
* 实现整形数字转字符串
* @param number int类型数字
* @return 转化成字符串后的数字,如 "-1657"
*/
char *intToStr(int number);
/**
* 将数字字符串解析成数字
* @param str 数字字符串,如 "-123", "2223"
* @return int 类型数字
*/
int strToInt(char *str);
/**
* 将小数字符串解析成小数
* @param str 如 "0.0" "-1.992"
* @return double 类型小数
*/
double strToDouble(char *str);
/**
* 将double类型小数转化为字符串
* @param number double类型小数
* @return "0.0" "-1.992"
*/
char *doubleToStr(double number);
// C99
int main() {
/// long -> int
/// int -> float
/// float -> int
/// int -> double, double -> int 同理
/// short, int, long, float, double 互相转化同理
// 直接强制转化即可
/// int --ASCII--> char
/// char --ASCII--> int
// 直接强制转化即可
/// int 0~9 --字符化--> char '0'~'9'
for (int i = 0; i < 10; i++) {
printf("%d -> '%c'\n", i, numToChar(i));
}
/// char '0'~'9' ---字符解析--> int
printf("%d\n", charToInt('9'));
/// int --> string
for (int i = -100; i < 100; i++) {
printf("string number is %d '%s'\n", i, intToStr(i));
}
/// string --> int
for (int i = -100; i < 100; i++) {
printf("%d -> '%s' -> %d\n", i, intToStr(i), strToInt(intToStr(i)));
}
/// string ---> double
printf("%s -> %lf\n", "12.3", strToDouble("12.3"));
/// double ---> string
printf("%s\n", doubleToStr(1.414));
printf("%s\n", doubleToStr(1.1));
printf("%s\n", doubleToStr(2005.23));
printf("%s\n", doubleToStr(-32.23));
printf("%s\n", doubleToStr(-55.244));
// printf("%s\n", doubleToStr(1.0));
return 0;
}
double strToDouble(char *str) {
int len = (int) strlen(str);
if (len == 0) {
return -0.0; // 解析错误
}
int flag = 1;
int di = 0; // 如果前面有负号占位,di=1
if (str[0] == '-') {
flag = -1;
di = 1;
}
// 先寻找小数点所在的位置
int dotIndex = -1; // 小数点所在的下标
for (int i = 0; i < len; i++) {
if (str[i] == '.') {
dotIndex = i;
break;
}
}
// 如果没有找到小数点,当成整形的算法处理
if (dotIndex == -1) {
return (double) strToInt(str);
}
double res = 0;
int w = 1;
// 先计算小数点前面的部分
for (int i = dotIndex - 1; i >= 0 + di; i--) {
res += charToInt(str[i]) * w;
w *= 10;
}
// 逐步累加计算小数点后面的部分
double dw = 0.1;
for (int i = dotIndex + 1; i < len; i++) {
res += charToInt(str[i]) * dw;
dw /= 10;
}
return res * flag;
}
char *doubleToStr(double number) {
// 先记录整数部分,负数负号包含在了整数字符串中
int integer = (int) number;
char *intStr = intToStr(integer);
int flag = 1;
if (number < 0) {
flag = -1;
}
double tile = (number - integer) * flag;
printf("intStr: %s, tile: %f\n", intStr, tile);
double n = tile * 10;
int tileLen = 0;
// char *tileStr = (char *) malloc(sizeof(char) * 2);
int *digList = (int *) malloc(sizeof(int) * 1);
int listLen = 1;
while (n > 0) {
int dig = (int) n;
digList[tileLen] = dig;
if (tileLen == listLen) {
// 数组扩容一位
digList = (int *) realloc(digList, sizeof(int) * listLen + 1);
}
listLen++;
n -= dig;
tileLen++;
n *= 10;
}
char *res = (char *) malloc(sizeof(char) * (strlen(intStr) + 1 + tileLen));
// 将整数部分写入
for (int i = 0; i < strlen(intStr); i++) {
res[i] = intStr[i];
}
// 写入小数点
res[strlen(intStr)] = '.';
// 写入小数部分
for (int j = 0; j < tileLen; j++) {
res[strlen(intStr) + 1 + j] = numToChar(digList[j]);
}
// free(digList);
// free(intStr);
return res;
}
int strToInt(char *str) {
int len = (int) strlen(str);
// printf("len: %d\n", len);
if (len == 0) {
return 0; // 解析异常
}
int flag = 1; // 这个数是否是负数,正数1,负数-1;
int res = 0;
if (str[0] == '-') {
flag = -1;
}
int w = 1; // 表示当前正在遍历个位状态
if (flag == 1) {
for (int i = len - 1; i >= 0; i--) {
res += charToInt(str[i]) * w;
// printf("%d\n", res);
w *= 10;
}
} else {
for (int i = len - 1; i >= 1; i--) {
res += charToInt(str[i]) * w;
w *= 10;
}
}
res *= flag;
return res;
}
char numToChar(int number) {
return (char) (48 + number);
}
int charToInt(char chrNum) {
return (int) (chrNum - 48);
}
char *intToStr(int number) {
// 首先获取这个数字有多少位
// 看这个数字是正还是负
// 根据字符串长度生成字符串
if (number == 0) {
return "0";
}
int flag = 0; // 0 表示是正数,1表示是负数
if (number < 0) {
number *= -1;
flag = 1;
}
int len = 1;
int n = 1;
while (n <= number) {
n *= 10;
len++;
}
len--;
char *res = (char *) malloc(sizeof(char) * (len + flag + 1)); // +1 是因为最后一个\0
if (flag) {
res[0] = '-';
for (int i = 1; i <= len; i++) {
res[len - i + 1] = numToChar(getDig(number, i));
}
} else {
for (int i = 1; i <= len; i++) {
res[len - i] = numToChar(getDig(number, i));
}
}
return res;
}
int getDig(int number, int d) {
return (number % (int) pow(10, d)) / (int) pow(10, d - 1);
}
不足
double转字符串(char*)类型,小数位会很长,会出很多问题
例如
1.414
会转化成 "1.41399999999999987920773492078296840190887451171875"
这是由于转化的方法设计的还不合理造成的。