IOS開發系列--C語言之數組和字串,ios開發--c數組

來源:互聯網
上載者:User

IOS開發系列--C語言之數組和字串,ios開發--c數組
概覽

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

一維數組

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

#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*/}

我們看一下上面定義的數組在記憶體中儲存結構

再來看一下數組(注意不是數組的元素,是數組)作為參數傳遞的情況

#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    */}
多維陣列

多維陣列其實可以看成是一個特殊的一維數組,只是每個元素又是一個一維數組,下面簡單看一下多維陣列的初始化和賦值

#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數組為例,它在記憶體中的結構如

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

關於多維陣列,其實可以以此類推,在此不再贅述。

字串

在C語言中是沒有字串類型的,如果要表示字串需要使用char類型的數組,因為字串本身就是多個字元的組合。但是需要注意的是字串是一個特殊的數組,在它的結束位置必須要加一個”\0”(ASCII中0是空操作符,表示什麼也不做)來表示字串結束,否則編譯器是不知道什麼時候字串已經結束的。當直接使用字串賦值的時候程式會自動加上”\0”作為結束符。

////  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在記憶體中的儲存。

我們不難發現由於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;}

注意在Xcode中會提示gets是不安全的,因為Xcode使用的是gcc編譯器,在gcc編譯器中已經不能正確編譯gets()函數,推薦使用fgets()。


C語言字元數組,輸入輸出字串格式(各位指教)

%s表示輸出一個字串,給出的字元指標變數名是str,那麼系統先輸出它所指向的第一個字元資料,然後自動使str加1,使之指向下一個字元,然後再輸出一個字元。。。。如此直到遇到結束標誌‘\0’為止(\0是最後被自動加上的,因此能夠在輸出時確定字串的終止位置)~
 
c語言中指標數組與字串數組的不同 ,進

#include "stdio.h"
#include "string.h"
void shellsort(char v[][10], int n);
void writeline(char linp[][10],int n);
main()
{
char line[][10]={"C++","Fortran","Basic","Pascal","Foxbase"};
int n=5;
shellsort(line,n);
writeline(line,n);
}

shellsort(char v[][10], int n)
{
char *temp,*t[5];
int i,j;

for(i=0;i<n;i++)
t[i]=&v[i];

for(i=0;i<n-2;i++)
for(j=n-1;j>i;j--)
if(strcmp(t[j-1],t[j])>0)
{
temp=t[j];
t[j]=t[j-1];
t[j-1]=temp;}
}

writeline(char linp[][10],int n)
{
int i;
for(i=0;i<n;i++)
printf("%s\n",linp[i]);
}
上面是修改過的程式;
關鍵在於
if(strcmp(v[j-1],v[j])>0)
{t=v[j];v[j]=v[j-1];v[j-1]=t;}
這裡面的v[j]=v[j-1];這句不對,因為這是兩個地址,也是兩個數組,不能賦值
我用了另外的一組指標來指向這個數組

你的函數的定義很奇怪,更奇怪這樣的定義也能編譯
建議象我這樣定義吧,不然別人看程式很困難的.
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.