iOS開發系列--C語言之數組和字符串

概覽

數組在C語言中有着特殊的地位,它有不少特性,例如它的存儲是連續的,數組的名稱就是數組的地址等。而在C語言中是沒有String類型的,那麼若是要表示一個字符串,就必須使用字符數組。今天主要就介紹以下三個方面:數組

  1. 一維數組
  2. 多維數組
  3. 字符串

一維數組

一維數組操做比較簡單,可是須要注意,數組長度必須是固定的,長度不能使用變量進行初始化;若是聲明的同時進行賦值則數組長度能夠省略,編譯器會自動計算數組長度;同時數組不能先聲明再一次性賦值(固然能夠對每一個元素一一賦值)。安全

#include <stdio.h>

int main(){
    int len = 2;
    //int a[len] = { 1, 2};//錯誤,不能使變量
    int a[2];//正確
    a[0] = 1;
    a[1] = 2;
    //a[2] = 3;//超過數組長度,可是編譯器並不會檢查,運行報錯
    int b['a'] = {1,2,3};//'a'=97,因此能夠做爲數組長度,可是後面的元素沒有初始化,其值默認爲0
    for (int i = 0; i < 97; ++i){
        printf("b[%d]=%d\n",i,b[i]);
    }
    int c[2 * 3];//2*3是固定值能夠做爲數組長度
    int d[] = { 1, 2, 3 };//若是初始化的同時賦值則數組長度能夠省略,當前個數爲3
}

擴展--數組的存儲

數組在內存中存儲在一塊連續的空間中,若是知道數組類型(int、float等)和初始地址就能夠知道其餘元素的地址,同時因爲數組名等於數組第一個元素的地址,因此當數組做爲參數(做爲參數時形參能夠省略)實際上是引用傳遞。函數

#include <stdio.h>

int main(){
    int const l = 3;
    int a[l] = { 1, 2,3 };
    for (int i = 0; i < l; ++i){
        //因爲當前在32位編譯器下,int型長度爲4個字節,能夠判斷出三個地址兩兩相差都是4
        printf("a[%d]=%d,address=%x\n", i, a[i], &a[i]);
    }
    /*當前輸出結果:
    a[0] = 1, address = c9f95c
    a[1] = 2, address = c9f960
    a[2] = 3, address = c9f964*/
}

咱們看一下上面定義的數組在內存中存儲結構ui

arrayAddress1.2

再來看一下數組做爲參數傳遞的狀況,數組做爲參數傳遞的是數組的地址spa

#include <stdio.h>

void changeValue(int a[]){ a[0] = 10;
}

int main(){ int a[2] = {1,2};
    changeValue(a); for (int i = 0; i < 2; ++i){
        printf("a[%d]=%d\n",i,a[i]);
    } /*打印結果
    a[0]=10
    a[1]=2
    */
}

多維數組

多維數組其實能夠當作是一個特殊的一維數組,只是每一個元素又是一個一維數組,下面簡單看一下多維數組的初始化和賦值 code

#include <stdio.h>

int main(){
    int a[2][3];//2行3列,二維數組能夠當作是一個特殊的一維數組,只是它的每個元素又是一個一維數組
    a[0][0] = 1;
    a[0][1] = 2;
    a[0][2] = 3;
    a[1][0] = 4;
    a[1][1] = 5;
    a[1][2] = 6;
    for (int i = 0; i < 2; ++i){
        for (int j = 0; j < 3; ++j){
            printf("a[%d][%d]=%d,address=%x\n", i, j, a[i][j], &a[i][j]);
        }
    }
    /*打印結果
    a[0][0]=1,address=f8fb24
    a[0][1]=2,address=f8fb28
    a[0][2]=3,address=f8fb2c
    a[1][0]=4,address=f8fb30
    a[1][1]=5,address=f8fb34
    a[1][2]=6,address=f8fb38
    */
    //初始化並直接賦值
    int b[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
    //因爲數組的賦值順序是先從第一行第一列,再第一行第二列...而後第二行第一列...,因此咱們也能夠寫成以下形式
    int c[2][3] = { 1, 2, 3, 4, 5, 6 };
    //也能夠只初始化部分數據,其他元素默認爲0
    int d[2][3] = { 1, 2, 3, 4 };
    for (int i = 0; i < 2; ++i){
        for (int j = 0; j < 3; ++j){
            printf("d[%d][%d]=%d\n", i, j, d[i][j]);
        }
    }
    /*打印結果
    d[0][0]=1
    d[0][1]=2
    d[0][2]=3
    d[1][0]=4
    d[1][1]=0
    d[1][2]=0
    */
    //固然下面賦值也能夠
    int e[2][3] = { {}, { 4, 5, 6 } };
    //能夠省略行號,可是絕對不能夠省略列號,由於按照上面說的賦值順序,它沒法判斷有多少行
    int f[][3] = { {1,2,3},{4,5,6} };
}

擴展--多維數組的存儲

以上面a數組爲例,它在內存中的結構以下圖blog

arrayAddress2.1

根據上圖和一維數組的存儲,對於二維數組能夠得出以下結論:數組名就是整個二維數組的地址,也等於第一行數組名的地址,還等於第一個元素的地址;第二行數組名等於第二行第一個元素的地址。用表達式表示:內存

  1. a=a[0]=&a[0][0]
  2. a[1]=&a[1][0]

一樣能夠得出a[i][j]=a[i]+j。關於三維數組、四維數組等多維數組,其實能夠以此類推,在此再也不贅述。字符串

字符串

在C語言中是沒有字符串類型的,若是要表示字符串須要使用char類型的數組,由於字符串自己就是多個字符的組合。可是須要注意的是字符串是一個特殊的數組,在它的結束位置必需要加一個」\0」(ASCII中0是空操做符,表示什麼也不作)來表示字符串結束,不然編譯器是不知道何時字符串已經結束的。當直接使用字符串賦值的時候程序會自動加上」\0」做爲結束符。get

//
//  main.c
//  ArrayAndString
//
//  Created by KenshinCui on 14-7-06.
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#include <stdio.h>

int main(int argc, const char * argv[])
{

    char a[] = {'K','e','n','s','h','i','n','\0'};
    printf("%s",a); //結果:Kenshin,注意使用%s輸出字符串內容,若是換成整形輸出格式其實輸出的是a的地址
    printf("\n");
    printf("address=%x", a); //結果:address=5fbff890
    printf("\n");
    //後面的\0絕對不能省略,若是沒有\0則會出現以下狀況
    char b[] = { 'I', 'a', 'm'};
    printf("%s",b); //沒有按照指望輸出,多了一些垃圾數據,在當前環境打印結果:IamKenshin
    printf("\n");
    printf("address=%x",b); //結果:address=5fbff88d
    printf("\n");
    //直接賦值爲字符串,此時不須要手動添加\0,編譯器會自動添加
    char c[] = "Kenshin";
    printf("c=%s",c); //結果:c=Kenshin
    printf("\n");
    
    //二維數組存儲多個字符串
    char d[2][3]={"Kenshin","Kaoru","Rose","Jack","Tom","Jerry"};
    
    
    return 0;
}

從上面代碼註釋中能夠看到打印b的時候不是直接打印出來「Iam」而是打印出了「IamKenshin」,緣由就是編譯器沒法判斷字符串是否結束,要解釋爲何打印出「IamKenshin」咱們須要瞭解a和b在內存中的存儲。

arrayAddress3.1

從圖中咱們不難發現因爲a佔用8個字節,而定義完a後直接定義了b,此時分配的空間連續,b佔用3個字節,這樣當輸出b的時候因爲輸出完「Iam」以後並未遇到」\0」標記,程序繼續輸出直到遇到數組a中的「\0」才結束,所以輸出內容爲「IamKenshin」。

擴展--字符串操做經常使用函數

下面簡單看一下和字符和字符串相關的經常使用的幾個函數

//
//  main.c
//  ArrayAndString
//
//  Created by Kenshin Cui on 14-7-04.
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#include <stdio.h>

int main(int argc, const char * argv[])
{
    /*字符操做*/
    putchar('a'); //結果:a,putchar一次只能輸出一個字符
    printf("\n");
    putchar(97);//結果:a
    printf("\n");
    char a;
    a=getchar();//getchar()一次只能接收一個字符,能夠接收空格、tab、回車
    printf("a=%c",a);
    printf("\n");

    /*字符串操做*/
    char b[]="Kenshin";
    printf("b=%s",b);
    printf("\n");
    puts(b); //puts用於輸出單個字符串,不能像printf格式化輸出,會自動添加換行
    printf("\n");
    
    char c[10];
    scanf("%s",c);//注意c不必寫成&c,由於c自己就表明了數組的地址
    printf("c=%s\n",c);//注意即便你輸入的內容大於10,也能正確輸出,可是下面的gets()函數卻不行
    printf("\n");
    
    //gets()函數,注意它是不安全的,由於接收的時候不知道它的大小容易形成溢出,建議不要使用
    char d[10];
    gets(d); //gets一次只能接收一個字符串,可是scanf可接收多個;scanf不能接收空格、tab,gets則能夠
    printf("d=%s",d);
    printf("\n");
    
    char e[]={'K','s','\0'};
    printf("%lu",strlen(e)); //結果是:2,不是3,由於\0不計入長度
    printf("\n");
    char f[]={"Kenshin"};
    printf("%lu",strlen(f)); //結果是:7
    printf("\n");
    
    char g[5];
    strcpy(g,"hello,world!");
    printf("%s",g); //結果是:hello,即便定義的g長度爲5,可是也能徹底拷貝進去
    printf("\n");
    char h[5];
    char i[]={'a','b','c','\0','d','e','f','\0'};
    strcpy(h,i);
    printf("%s",h); //結果是:abc,遇到第一個\0則結束
    printf("\n");
    
    strcat(i,"ghi");
    printf("%s",i); //結果是:abcghi,注意不是abcdefghi,strcat,從i第一\0開始使用「ghi」覆蓋,覆蓋完以後加上一個\0,在內存中目前應該是:{'a','b','c','g','h','i','\0','f','\0'}
    printf("\n");
    
    char j[]="abc";
    char k[]="aBc";
    char l[]="acb";
    char m[]={'a','\0'};
    printf("%d,%d,%d",strcmp(j,k),strcmp(k,l),strcmp(l,m));//遇到第一個不相同的字符或\0則返回二者先後之差,結果:32,-33,99
    printf("\n");

    return 0;
}

 

注意:

1.在Xcode中會提示gets是不安全的,推薦使用fgets()。

2.strlen()只用於計算字符串長度,因爲在C語言中字符串使用字符數組長度表示,因此它能夠計算帶有’\0’結尾的字符數組長度,可是它並不能計算其餘類型的數組長度。

相關文章
相關標籤/搜索