String.c,RUN
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h> //atoi等函数
#include <string.h>
//不借助系统函数,实现字符串的相关功能
// 字符串和数组最大的差别:字符串自带结束标记'\0',不需要额外的字符串长度;数组需要知道数组长度。
//printf("%c", ch) 和 putchar(ch)等价
//printf("%s", str) 和 puts(str)等价
//遍历,通过'\0'停止循环
void TravelString(const char *str)
{
const char* p = str;
while (*p != '\0')
{
char ch = *p;
putchar(ch);
p++;
}
putchar('\n');
}
void TravelString2(const char* str)
{
//'\0'的ASCII码就是0。换一个写法
for(const char* p = str; *p != 0; p++)
{
putchar(*p);
}
putchar('\n');
}
//字符串长度,不包含结尾的'\0'
int StringLen(const char* str)
{
int len = 0;
for (; *str != '\0'; str++) len++;
return len;
}
//反转字符串,
void FlipString_0(char* str)
{
int len = StringLen(str);
//对称交换字符;
//len是奇数,如9,len/2是4, [0,4)一共4对字符要交换。独立第4个字符不需要交换;
//len是偶数,如8,len/2是4,[0,4)一共4对字符要交换。
for (int i = 0; i < len/2; i++)
{
char temp = str[i];
str[i] = str[len-1 - i];
str[len - 1 - i] = temp;
}
}
void FlipString_arry(char* str)
{
int len = StringLen(str);
//对称交换字符; 不需要考虑奇数偶数,两端出发,向中间靠齐
int left = 0, right = len - 1;
while(left < right)
{
char temp = str[left];
str[left] = str[right];
str[right] = temp;
left++, right--;
}
}
void FlipString_pointer(char* str)
{
int len = StringLen(str);
//对称交换字符; 不需要考虑奇数偶数,两端出发,向中间靠齐
char *left = str;
char *right = str + (len - 1);
while (left < right)
{
char temp = *left;
*left = *right;
*right = temp;
left++, right--;
}
}
//反转字符串。假定dst已经分配好内存
void FlipString2(const char* src, char* dst)
{
int len = StringLen(src); //len为内存中长度-1
for (int i = 0; i <= len; i++)
{
dst[i] = src[len - 1 - i];
}
//字符串结尾
dst[len] = '\0';
}
//字符串与数字的相互转换
void Test_NumberString()
{
//字符串转整数,
int num;
{
char str[] = "100";
num = atoi(str);
}
//字符串转小数或者整数
{
char str[] = "100 11.11";
int inum;
double dnum;
sscanf(str, "%d %lf", &inum, &dnum);
}
{
double dnum = atof("1.235");
}
//小数整数转字符串
{
char str[256];
double num = 12.34;
sprintf(str, "%lf", num);
}
return;
}
//单词分割。使用<string.h>提供函数strtok
//https://www.cplusplus.com/reference/cstring/strtok/
void WordSplit_strtok(char* str)
{
char deli[] = " .,?\n";//用字符' ''.'来分割,之一
char* p = strtok(str, deli);
while (p)
{
printf("%s\n", p);
p = strtok(NULL, deli); //继续查找
}
}
//c是否包含在strTemplate中
int IsOneOf(char c, const char* strTemplate)
{
for (const char* p = strTemplate; *p != '\0'; p++)
if (*p == c) return 1;
return 0;
}
int IsOneOf_(char c, const char* strTemplate)
{
for (const char* p = strTemplate; *p != '\0'; p++)
if (*p == c) return 1;
return 0;
}
//掠过包含在delimiter中的字符,直到出现新字符或者结尾空字符
const char* SkipDelimiter(const char* str, const char* delimiter)
{
const char* p = str;
while(*p && IsOneOf(*p, delimiter)) p++;
return p;
}
//提取单词,直到出现模板delimiter中的字符,单词存在word中
const char* ExtractWord(const char* str, const char* delimiter, char *word)
{
const char* src = str;
char* dst = word;
while (*src && !IsOneOf(*src, delimiter))
{
*dst = *src;
src++, dst++;
}
*dst = '\0'; //加上字符串结尾标记,封住word
return src;
}
//单词分割
void WordSplit(const char *str)
{
char delimiter[] = " .,?"; //用字符' ''.''?'来分割单词
const char* p = SkipDelimiter(str, delimiter);
while (*p)
{
char msg[128];
p = ExtractWord(p, delimiter, msg); //提取正常字符
puts(msg);
p = SkipDelimiter(p, delimiter); //掠过间隔字符
}
}
//单词分割(用字符' ''.''?'来分割单词),单个函数版本
//比较WordSplit_和WordSplit的难度
//如果需要扩充间隔符,代码的可读性和一致性会变得很差【多处出现比较的代码】
void WordSplit_(const char* str)
{
const char* p = str;
while (*p && (*p == ' ' || *p == '.' || *p == ',' || *p == '?')) p++; //掠过间隔字符
while (*p)
{
char word[128];
{//提取单词
char* dst = word;
while (*p && !(*p == ' ' || *p == '.' || *p == ',' || *p == '?'))
{
*dst = *p;
p++, dst++;
}
*dst = '\0'; //加上字符串结尾标记,封住字符串word
}
puts(word);
while (*p && (*p == ' ' || *p == '.' || *p == ',' || *p == '?')) p++; //掠过间隔字符
}
}
void Test_WordSplit()
{
char str[] = " I am just a word, and you?";
//WordSplit(str);
WordSplit_(str);
//WordSplit_strtok(str);
}
void Test_Travel()
{
char str[] = "I am a string.";
TravelString2(str);
printf("%s\n", str);
}
void Test_FilpString()
{
char str0[] = "012345678";
FlipString_pointer(str0);
printf("%s\n", str0);
char str2[256];
FlipString2(str0, str2);
printf("%s\n", str2);
}
int main()
{
Test_WordSplit();
//Test_FilpString();
return 0;
}