20160217.CCPP體系詳解(0027天)

尹成發表於2016-03-15

程式片段(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");
}

相關文章