天天看點

C語言從入門到精通——字元串和記憶體

求非空字元串元素個數:

“ni chou sha chou ni za di”      

字元串逆置: str_inverse

hello -- olleh      

void str_inserse(char *str)

{

char *start = str; // 記錄首元素位址

char *end = str + strlen(str) - 1; // 記錄最後一個元素位址。

while (start < end)      // 首元素位址是否 < 最後一個元素位址
{
  char tmp = *start;    // 三杯水 char 元素交換
  *start = *end;
  *end = tmp;
  start++;      // 首元素對應指針後移
  end--;        // 尾元素對應指針前移
}      

}

判斷字元串是回文:

int str_abcbb(char *str)

{

char *start = str; // 記錄首元素位址

char *end = str + strlen(str) - 1; // 記錄最後一個元素位址。

while (start < end)      // 首元素位址是否 < 最後一個元素位址
{
  if (*start != *end)   // 判斷字元是否一緻。
  {
    return 0;     // 0 表示非 回文
  }
  start++;
  end--;
}
return 1;       // 1 表示 回文      

}

字元串處理函數: #include <string.h>

字元串拷貝:

  strcpy:

    将 src 的内容,拷貝給 dest。 傳回 dest。 保證dest空間足夠大。【不安全】

    char *strcpy(char *dest, const char *src);

    函數調用結束 傳回值和 dest參數結果一緻。

  strncpy:

    将 src 的内容,拷貝給 dest。隻拷貝 n 個位元組。 通常 n 與dest對應的空間一緻。

    預設 不添加 ‘\0’

    char *strncpy(char *dest, const char *src, size_t n);

    特性: n > src: 隻拷貝 src 的大小

           n < src: 隻拷貝 n 位元組大小。 不添加 ‘\0’

字元串拼接:

  strcat:

    将 src 的内容,拼接到 dest 後。 傳回拼接後的字元串。  保證 dest 空間足夠大。

    char *strcat(char *dest, const char *src);

  strncat:

    将 src 的前 n 個字元,拼接到 dest 後。 形成一個新的字元串。保證 dest 空間足夠大。

    char *strncat(char *dest, const char *src, size_t n);

    函數調用結束 傳回值和 dest 參數結果一緻。


字元串比較:  不能使用 > < >= <= == !=

  strcmp:

    比較s1和s2兩個字元串,如果相等 傳回0.如果不相等,進一步表 s1 和 s2 對應位 ASCII碼值。

    s1 > s2 傳回1

    s1 < s2 傳回-1

    int strcmp(const char *s1, const char *s2);

  strncmp:

    int strncmp(const char *s1, const char *s2, size_t n);

    比較s1和s2兩個字元串的前n個字元,

    如果相等 傳回0。如果不相等,進一步表 s1 和 s2 對應位 ASCII碼值。(不比字元串ASCII碼的和)

    s1 > s2 傳回1

    s1 < s2 傳回-1



字元串格式化輸入、輸出:

  sprintf():  s -- string

    int sprintf(char *str, const char *format, ...);

    對應printf,将原來寫到螢幕的“格式化字元串”,寫到 參數1 str中。

    printf("%d+%d=%d\n", 10, 24, 10+24);

    ---》
    char str[100];

    sprintf(str, "%d+%d=%d\n", 10, 24, 10+24);  格式串寫入str數組中。

  sscanf():

    int sscanf(const char *str, const char *format, ...);

    對應scanf, 将原來從螢幕擷取的“格式化字元串”, 從 參數1 str中 擷取。

    scanf("%d+%d=%d", &a, &b, &c);

    ---》

    char str[]= "10+24=45";

    sscanf(str, "%d+%d=%d", &a, &b, &c);  a --> 10, b --> 24, c --> 45


字元串查找字元、子串:

  strchr():

    在字元串str中 找一個字元出現的位置。 傳回字元在字元串中的位址。

    char *strchr(const char *s, int c);

    printf("%s\n" strchr("hehehahahoho", 'a'));  --> "ahahoho"

  strrchr():

    自右向左,在字元串str中 找一個字元出現的位置。 傳回字元在字元串中的位址。

    char *strrchr(const char *s, int c);

    printf("%s\n" strrchr("hehehahahoho", 'a'));  --> "ahoho"

  strstr():

    在字元串str中,找子串substr第一次出現的位置。傳回位址。

    char *strstr(const char *str, const char *substr);

    在字元串中找子串的位置。

    printf("%s\n" strrchr("hehehahahoho", "ho"));  --> "hoho"

    printf("%s\n" strrchr("hehehahahoho", "xixi"));  --> NULL      

scanf(“%s”, str);

scanf(“%[^\n]”, str);

字元串分割:

  strtok(): 按照既定的分割符,來拆分字元串。“www.baidu.com”  --> "www\0baidu.com"

  char *strtok(char *str, const char *delim);

    參1: 待拆分字元串

    參2: 分割符組成的“分割串”

  傳回:字元串拆分後的首位址。 “拆分”:将分割字元用 '\0'替換。

特性:
  1)strtok拆分字元串是直接在 原串 上操作,是以要求參1必須,可讀可寫(char *str = "www.baidu.com" 不行!!!)

  2)第一次拆分,參1 傳待拆分的原串。 第1+ 次拆分時,參1傳 NULL.


練習: 拆分 ".itcast.cn$This is a strtok$test"

  char str[] = "www.itcast.cn$This is a strtok$test";

  char *p = strtok(str, "$ .");

  while (p != NULL)
  {
    p = strtok(NULL, " .$");
    printf("p = %s\n", p);
  }

atoi/atof/atol:

  使用這類函數進行轉換,要求,原串必須是可轉換的字元串。

  錯誤使用:"abc123" --> 0; "12abc345" ---> 12;  "123xyz" -->123

  atoi:字元串 轉 整數。

  int atoi(const char *nptr);

  atof:字元串 轉 浮點數

  atol:字元串 轉 長整數      

局部變量:

概念:定義在函數 内 部的變量。

作用域:從定義位置開始,到包裹該變量的第一個右大括号結束。      

全局變量:

概念:定義在函數 外 部的變量。

作用域:從定義位置開始,預設到本檔案内部。 其他檔案如果想使用,可以通過聲明方式将作用域導出。      

static全局變量:

定義文法: 在全局變量定義之前添加 static 關鍵字。   static int a = 10;

作用域:被限制在本檔案内部,不允許通過聲明導出到其他檔案。      

static局部變量:

定義文法: 在局部變量定義之前添加 static 關鍵字。

特性: 靜态局部變量隻定義一次。在全局位置。 通常用來做計數器。

作用域:從定義位置開始,到包裹該變量的第一個右大括号結束。      

全局函數: 函數

定義文法: 函數原型 + 函數體      

static函數:

定義文法:static + 函數原型 + 函數體

static 函數 隻能在 本檔案内部使用。 其他檔案即使聲明也無效。      

生命周期:

局部變量:從變量定義開始,函數調用完成。 --- 函數内部。

全局變量:程式啟動開始,程式終止結束。  --- 程式執行期間。

static局部變量:程式啟動開始,程式終止結束。  --- 程式執行期間。

static全局變量:程式啟動開始,程式終止結束。  --- 程式執行期間。

全局函數:程式啟動開始,程式終止結束。  --- 程式執行期間。

static函數:程式啟動開始,程式終止結束。  --- 程式執行期間。      

記憶體4區模型:

代碼段:.text段。 程式源代碼(二進制形式)。

資料段:隻讀資料段 .rodata段。初始化資料段 .data段。 未初始化資料段 .bss 段。

stack:棧。 在其之上開辟 棧幀。 windows 1M --- 10M  Linux: 8M --- 16M

heap:堆。 給使用者自定義資料提供空間。 約 1.3G+      

開辟釋放 heap 空間:

void *malloc(size_t size);  申請 size 大小的空間

  傳回實際申請到的記憶體空間首位址。 【我們通常拿來當數組用】

void free(void *ptr); 釋放申請的空間

  參數: malloc傳回的位址值。      

使用 heap 空間:

空間時連續。 當成數組使用。

free後的空間,不會立即失效。 通常将free後的 位址置為NULL。

free 位址必須 是 malloc申請位址。否則出錯。

如果malloc之後的位址一定會變化,那麼使用臨時變量tmp 儲存。      

二級指針對應的 heap空間:

申請外層指針: char **p = (char **)malloc(sizeof(char *) * 5);

申請内層指針: for(i = 0; i < 5; i++)
    {
      p[i] = (char *)malloc(sizeof(char) *10);
    }

使用: 不能修改 p 的值。

   for(i = 0; i < 5; i++)
  {
    strcpy(p[i], "helloheap");
  }

釋放内層:

   for(i = 0; i < 5; i++)
  {
    free(p[i]);
  }

釋放外層:

  free(p);      

棧的存儲特性:

局部變量:

形參:      
memset:

memmove:

memcmp:      
1) 申請 0 位元組空間

2)free空指針

3)越界通路

4)free ++後的位址

5)子函數malloc空間,main中用      

繼續閱讀