20160217.CCPP体系详解(0027天)
程序片段(01):TestCmd.c
内容概要:管道_字符串
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//01.管道:Windows应用程序与DOS系统之间的通信桥梁
// 1.用于进程之间的通信(两个进程:窗体进程+cmd进程)
// 2.窗体进程发送指令到cmd进程进行执行;
// 然后将cmd进程执行之后的结果反馈到当前窗体进程
//注:C语言将所有的设备都可以当做文件进行处理!(很重要)
int exeShell(char * cmd, char * result)
{//通过管道让cmd进程执行窗体进程向cmd进程发送的指令,并通过管道返回指令执行结果到窗体进程
FILE * pf = _popen(cmd, "r");//以读取的模式打开一个管道,用管道的另一端执行一个cmd指令并反馈执行结果
//1.打开进程之间通信的管道,进程管道用于进程之间的信息传递,可以向进程管道的另外一端(cmd进程)发送一个指令
// 等待该指令的执行结果反馈,然后再做对指令执行结果的信息处理(窗体进程)
//2.在Windows系统当中,操作各种设备的时候,都可以将各种设备当做文件系统进行处理(设备概念-->文件概念)
// C语言的文件概念模拟设备要点!(操作文件就等同于操作设备)-->需要_popen();函数进行文件模拟!
if (NULL == pf)
{
printf("窗体进程和cmd进程之间的通信管道创建失败! \n");
return 0;
}
while (!feof(pf))//到达文件结尾返回1,没有到达文件结尾返回0
{
char str[256] = { 0 };//信息读取字符缓冲区
if (fgets(str, 256, pf))//fgets();函数的返回值就是通过管道进行进程通信所读取到的字符个数
{//进行进程通信信息的拼接:通过strcat函数不断的进行拼接动作,每次拼接都是采取替换字符串标识'\0'的方式进行拼接
strcat(result, str);//拼接字符串信息,构成完整信息体(逐步读取文件,构建完整文件体)
}
}
_pclose(pf);//关闭进程之间的通信管道,避免过度占用资源
return 1;
}
int main01(void)
{
char str[1024];
gets(str);//获取键盘录入的字符串,并存储到参数所指定的字符串当中特点:只以回车作为录入结束标识符!
puts(str);
system("pause");
}
int main02(void)
{
char result[1024 * 8] = { 0 };//8M尺寸的字符串缓冲区
if (exeShell("tasklist", result))
{//如果执行脚本成功,就输出脚本的执行结果信息
printf("%s \n", result);
}
//判断某个进程是否正在操作系统之上运行
//char * p = strstr(result, "QQ.exe");
//if (NULL != p)
//{
// printf("QQ正在执行当中! \n");
//}
//else
//{
// printf("QQ未在执行当中! \n");
//}
int i = 0;
//统计QQ进程的执行个数,找到返回地址,未找到返回NULL
for (char * p = strstr(result, "QQ.exe"); NULL != p; strstr(p + 6, "QQ.exe"))
{
++i;
printf("QQ运行了%d个! \n", i);
}
system("pause");
}
int main03(void)
{
char cmd[128] = { 0 };
char result[1024 * 8] = { 0 };
//gets(cmd);//只以\n作为录入状态结束标识符!
scanf("%[^\n]", cmd);//%[^\n]正则表达式+scanf();函数-->只以\n作为扫描结束标识符
puts(cmd);
if (0 != exeShell(cmd, result))
{
printf("%s \n", result);
}
system("pause");
}
//1.tree Directory:用于将某个目录以树状形式进行显示,以及用于扫描某个地址(搜索文件的最佳方式!)-->避免使用递归遍历!
//2.netstat -a:用于显示所有的TCP/UDP协议信息,用于显示网络链接状态,本地客户端与服务器之间的联系
//3.ftp:都可以用命令行进行操作,这个操作的特点就是可以用于进行WiFi密码的破解,因为匹配密码的时候都会通过命令行发送一系列密码字典,我们可以采用密码字典进行密码的破解
//4.管道的特点:进程之间的通信桥梁,Windows操作设备都是将设备看做为文件系统进行的操作;管道既可以用于操作文件也可以用于操作系统设备
//5.strstr();的读取特点,会从首地址不断的进行数据的比对,只要检索到一个就停止检索状态
//6.scanf();和gets();的不同点:scanf();不会处理空格,Tab键盘,gets();会进行空格的处理读取
程序片段(02):PrintF.c
内容概要:PrintF可变参数
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>//可变参数使用头文件
//01.可变参数的使用特点:
// 1.包含可变参数头文件:
// #include <stdarg.h>
// 2.可变参数列表描述符:
// ...-->代表可变参数列表
// 3.可变参数列表的特点:
// 类型可以不一致,个数可以不确定
// 4.几大标识符的使用:
// va_list:可变列表
// va_start:初始化列表
// va_arg:列表获取
// va_end:结束读取
void myPrintf(char * pStr, ...)//...代表可变参数列表,类型可以不一致,个数也可以不一致
{
va_list vl;//可变参数列表起点
va_start(vl, pStr);//通过pStr指向字符串的指针来初始化可变列表
char flag;
while (*pStr)//*pStar<=>*pStr!=NULL
{//循环遍历每一个字符(字符指针特点)
flag = *pStr;//取出字符
if ('%' != flag)
{
putchar(flag);//打印字符
++pStr;
}
else
{
++pStr;//跳过格式控制符前缀:%c->%s->%d->%f->%%(标识前缀'%')
flag = *pStr;
switch (flag)
{
case 'c':
{
char chr = va_arg(vl, char);//按照指定类型从可变列表当中进行数据解析
printf("%c", chr);
break;
}
case 's':
{
char *str = va_arg(vl, char *);
printf("%s", str);
break;
}
case 'd':
{
int num = va_arg(vl, int);
printf("%d", num);//printf();函数的底层实现就依赖于putchar();这个函数进行的实现
break;//将一个整数转化成为字符串,并且按照字符串的显示方式最简单方式就是调用printf();函数实现
}
case 'f':
{
double db = va_arg(vl, double);
printf("%lf", db);
break;
}
case '%':
{
putchar('%');
break;
}
default:
break;
}
++pStr;
}
}
va_end(vl);//结束可变参数列表的数据读取操作
}
int main01(void)
{
myPrintf("1234abc \n");
myPrintf("1234abc%d \n", 10);
myPrintf("1234abc%d%s \n", 10, "tytyuytu");
myPrintf("1234abc%d%s%c \n", 10, "tytyuytu", 'A');
myPrintf("1234abc%d%s%c%% \n", 10, "tytyuytu", 'A');
myPrintf("1234abc%d%s%c%%%f \n", 10, "tytyuytu", 'A', 1234.78);
system("pause");
}
程序片段(03):01.StrCpyStrCat.c+02.StrChr.c+03.StrSet.c
内容概要:Str函数学习与实现
///01.StrCpyStrCat.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//01.strcpy();和strcat();区别:
// strcpy();从目标字符串的首地址开始拷贝
// strcat();从目标字符串的末尾字符串结束标识符'\0'开始拷贝
void myStrCpy(char * dest, const char * src)
{//无法正确的记录目标首地址+目标地址默认有结束标识符!
if ('\0' == *src)
{//递归的标准形式
return;
}
*dest = *src;//按照指针变量方式进行内存拷贝(一个指针映射一块儿内存)
myStrCpy(++dest, ++src);//指针变量当中的指针往前递进
}
//02.递归传参的几种方式:
// 1.全局变量
// 2.静态变量
// 3.函数传参
// 4.函数返回
char * myStrCpyWithReturn(char * dest, const char * src, char * destS)
{//采用函数传参的方式进行所需内存首地址的保存传递
if ('\0' == *src)
{//递归结束条件+健壮性判断
return destS;
}
*dest = *src;
myStrCpyWithReturn(++dest, ++src, destS);
}
//03.三种修改数据方式所需传递的内容:
// 1.普通变量:(1种)
// 修改普通变量的数据,需要传递普通变量的地址
// 2.指针变量:(2种)
// 修改指针变量所指向的数据,传递指针变量本身
// 修改指针变量所存储的指向,传递指针变量的地址
void myStrCpyWithPoint(char * dest, const char * src)
{
dest = (char *)malloc(100);//内存不一致,跨内存修改无效!
while (*dest++ = *src++);
//过程详解:
// 1.运算符优先级:递变运算符的优先级高于取值运算符的优先级
// *dest++=*src++<=>*(dest++)=*(src++);
// 2.后递变运算符的运算特点,先赋值再进行运算(这个先后指的是整体表达式)
// *(desc++)=*(src++);<=>
// *desc=*src;
// ++src;
// ++desc
}
void myStrCpyWithPointPlus(char ** dest, const char * src)
{
*dest = (char *)malloc(100);//跨函数修改指针变量所存储的指针
char * tmpDest = *dest;//指针类型,需要匹配-->防止修改了指针变量本身所存储的内存首地址
while (*tmpDest++ = *src++);
}
char * myStrCat(char * dest, const char * src)
{
while ('\0' != *dest)
{
++dest;
}
while (*dest++ = *src++);
}
int main01(void)
{
char str1[10] = "task";
char str2[10] = "list";
strcat(str1, str2);
//printf("%s \n", str1);
char str[50] = { 0 };
//myStrCpy(str, str1);
//printf("%s \n", str);
//printf("%s \n", myStrCpyWithReturn(str, str1, str));
char * str3 = NULL;
myStrCpyWithPointPlus(&str3, str1);
printf("%s \n", str3);
system("pause");
}
///02.StrChr.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * myStrChr(const char * str, const char c)
{
//for (int i = 0; i < strlen(str); ++i)
//{//索引法
// if (c == *(str + i))
// {
// return str + i;
// }
//}
for (const char * p = str; '\0' != *p; ++p)
{//指针法
if (c == *p)
{
return p;
}
}
}
char * myStrChrRecursion(const char * str, const char c)
{//递归法
if ('\0' == *str)
{
return NULL;
}
if (c == *str)
{
return str;
}
myStrChrRecursion(++str, c);
}
int main02(void)
{
char * p = myStrChrRecursion("calc", 'c');
if (NULL == p)
{
printf("can't find!!! \n");
}
else
{
printf("can find %p, %c!!! \n", p, *p);
}
system("pause");
}
///03.StrSet.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//01.strset函数详解:
// 函数名:strset
// 功能:将一个字符串当中的所有字符都设置为指定字符
// 用法:char * strset(char * str, char c);
void * myStrSet(char * str, char c)
{
//for (int i = 0; i < strlen(str); ++i)
//{//索引法
// *(str + i) = c;
//}
//for (char * p = str; '\0' != *p; ++p)
//{//指针法
// *p = c;
//}
}
void * myStrSetRecursion(char * str, char c)
{//递归法
if ('\0' == *str)
{
return;
}
*str = c;
myStrSetRecursion(++str, c);
}
int main03(void)
{
char * p = (char[10]) { 0 };
strcpy(p, "123456");
printf("%s \n", p);
myStrSetRecursion(p, 'a');
printf("%s \n", p);
system("pause");
}
程序片段(04):宽字符.c
内容概要:宽字符实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
int myWcsLen(wchar_t * wstr)
{
int i = 0;
while (L'\0' != *wstr)
{
++i;
++wstr;
}
return i;
}
//01.宽字符问题处理流程:
// 1.设置本地化:
// setlocale(生效范围, "语言-国籍");
// 2.宽字符使用:
// wchar_t+wcslen+wprintf(L"%ls", 宽字符指针);
int main01(void)
{
setlocale(LC_ALL, "zh-CN");//设置本地化
wchar_t wstr[10] = L"我是男神爱女神!\n";
wprintf(L"%ls", wstr);//宽字符格式输出字符串L"%ls"
system("pause");
}
int main02(void)
{
setlocale(LC_ALL, "zh-CN");
wchar_t wstr[12] = L"a我是男神爱女神12 ";
//strlen-->wcslen
//int length = wcslen(wstr);
int length = myWcsLen(wstr);
printf("%d \n", length);
system("pause");
}
int main03(void)
{
setlocale(LC_ALL, "zh-CN");
wchar_t wch = L'我';
putwchar(wch);
system("pause");
}
wchar_t * myWcsCpy(wchar_t * dest, const wchar_t * src)
{
if (NULL == dest || NULL == src)
{
return NULL;
}
wchar_t * tmpDest = dest;
while (*tmpDest++ = *src++);
return dest;
}
int main04(void)
{
setlocale(LC_ALL, "zh-CN");
wchar_t * p = (wchar_t[100]) { 0 };//栈上分配一个数组
wchar_t wstr[10] = L"我是男神爱女神";
myWcsCpy(p, wstr);
wprintf(L"%ls", p);
system("pause");
}
程序片段(05):01.StrCmpi.c+02.StrNICmp.c
内容概要:StrCmpi
///01.StrCmpi.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void turnUpperToLower(char * pChr)
{
if ('A' <= *pChr && *pChr <= 'Z')
*pChr += 32;
}
int myStrCmpI(char * str1, char * str2)
{
char chr1 = *str1;
char chr2 = *str2;
turnUpperToLower(&chr1);
turnUpperToLower(&chr2);
while (chr1 == chr2 && '\0' != *str1)
{
++str1;
++str2;
turnUpperToLower(&chr1);
turnUpperToLower(&chr2);
}
if ('\0' == *str1 && '\0' == *str2)
{
return 0;
}
else
{
if (0 < chr1 - chr2)
{
return 1;
}
else
{
return -1;
}
}
}
//01.根据排序数组决定:
// 需要待排序数组元素的地址
int comp(void * p1, void * p2)
{
char ** pStr1 = (char **)p1;
char ** pStr2 = (char **)p2;
return myStrCmpI(*pStr1, *pStr2);
}
//02.strcmpi:
// 1.忽略大小写
// 2.比较全字符
int main01(void)
{
//strcmpi
//char str1[10] = "calc";
//char str2[10] = "Calc";
//printf("%d \n", _strcmpi(str1, str2));
char * strs[5] = { "calc", "ali", "A3", "Bt", "BH" };
qsort(strs, 5, 4, comp);
for (int i = 0; i < 5; ++i)
{
printf("%s \n", *(strs + i));
}
system("pause");
}
///02.StrNICmp.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//01.大写转小写:
// 大写+32<=>小写
//02.C语言static:
// 限定作用域
static void turnUpperToLower(char * pchr)
{
if ('A' <= *pchr && *pchr <= 'Z')
*pchr += 32;
}
int myStrNICmp(const char * str1,const char * str2, unsigned int maxCount)
{
char * bakStr = (char *)str1;
char chr1 = *str1;
char chr2 = *str2;
turnUpperToLower(&chr1);
turnUpperToLower(&chr2);
int i = 0;
while (chr1 == chr2 && '\0' != (*str1) && i < maxCount)
{//注意顺序
++str1;
++str2;
++i;
chr1 = *str1;
chr2 = *str2;
turnUpperToLower(&chr1);
turnUpperToLower(&chr2);
}
if (maxCount == i)
{
return 0;
}
else
{
int length = strlen(bakStr);
if (maxCount <= length)
{//最大个数和有效长度
if (chr1 - chr2 > 0)
{
return 1;
}
else
{
return -1;
}
}
else
{//有效长度范围之外!
if ('\0' == *str1 && '\0' == *str2)
{
return 1;
}
else
{
if (chr1 - chr2 > 0)
{
return 1;
}
else
{
return -1;
}
}
}
}
}
//03.strnicmp:
// 1.忽略大小写
// 2.比较前N项
int main02(void)
{
//strnicmp;
//char str1[20] = "wangfangshandong";
//char str2[20] = "wangfangshandong";
//printf("%d \n", _strnicmp(str1, str2, 8));
//printf("%d \n", myStrNICmp(str1, str2, 8));
char str1[24] = "A2341231A";
str1[6] = 'A';
char str2[24] = "a2341231a";
printf("%d \n", myStrNICmp(str1, str2, 8));
system("pause");
}