chapter 4 數組


C語言程序設計

chapter 4 數組

1. 數組的概念

數組:同類數據的集合

定義方式:類型 數組名[數組大小];
數組中的變量稱為為數組元素,由於數組中每個元素都有下標,因此數組元素也稱為下標變量。
數組下標取值從0開始,使用數組時下標不能越界,同一數組的所有數組元素在內存中占用一片連續的存儲單元。

例如:int num[10]; //表示定義一個數組num,最多能存放10個int類型的元素。
解析:定義了一個名字為 num 的數組,它有10個元素,每個元素都是一個int型變量,下標變量為num[0]~num[9],num數組占用了一片連續的、大小為10*sizeof(int)字節的空間。

例如:int num[10][10];//表示定義一個數組num,最多能存放10*10個int類型的元素。
像這樣的用兩個 [] 的定義的數組,我們稱之為二維數組,同樣還有三維數組,多維數組,但是需要注意的時,電腦內存分配是有限的,數組所占空間大小也是有限的。

2. 數組元素的引用

每個數組元素都是一個變量,數組元素可以表示為:數組名[下標]
其中,下標可以是任何值為整型的表達式,該表達式里可以包含變量和函數調用。引用時,下標值應在數組定義的下標值范圍內。
例如:若i、j都是int型變量,則 num[5]、num[i+j]、num[i++] 都是合法的元素。

在定義一個一維數組的同時,可以給數組中的元素賦初值。
格式:類型名 數組名[元素個數]={值1,值2,……};

例如:int a[10]={0,1,2,3,4,5,6,7,8,9};
相當於:a[0]=0  a[1]=1  a[2]=2  a[3]=3  a[4]=4  ……  a[8]=8  a[9]=9

使用數組時,要注意:
(1)數組下標為正整數
(2)在定義元素個數的下標范圍內使用
當在程序中把下標寫成負數或者大於元素個數時,程序編譯不會出錯,當然結果也是錯的。
(3)定義數組時使用的容量大小必須使用常數,且需要注意:
在 C語言中常量的定義為:#define N 10000
在C++中還支持:const int N=1000;但是這個方式在C語言中表示只讀變量,不能等同於為常量。

3. 作用域

根據數組定義的位置,我們將數組分為全局變量和局部變量
全局變量:是指不被{}包裹起來的變量;
局部變量:是指被{}包裹起來的變量。

並且編譯器會給這些數組變量初始化不同的值,具體如下:
全局變量,默認初始化為 0.
局部變量,隨機初始化一個值.
局部變量,部分賦值,則未賦值部分初始化為 0.

#include<stdio.h>
#define N 100
int a[N];   //全局變量,默認初始化為 0
int b[N]={1,2,3,4,5}; //全局變量,部分賦值,其余默認初始化為 0

int main() {
    int c[N];//局部變量,隨機初始化一個值
    int d[N]= {1,2,3,4,5};//局部變量,部分賦值,則未賦值部分初始化為 0
    int n=10;

    printf("a[i]:"); for(int i=0; i<=n; i++) printf("%d ", a[i]); printf("\n");
    printf("b[i]:"); for(int i=0; i<=n; i++) printf("%d ", b[i]); printf("\n");
    printf("c[i]:"); for(int i=0; i<=n; i++) printf("%d ", c[i]); printf("\n");
    printf("d[i]:"); for(int i=0; i<=n; i++) printf("%d ", d[i]); printf("\n");

    return 0;
}

輸出結果:
a[i]:0 0 0 0 0 0 0 0 0 0 0
b[i]:1 2 3 4 5 0 0 0 0 0 0
c[i]:7603456 0 75 0 0 3 12260288 0 0 0 1
d[i]:1 2 3 4 5 0 0 0 0 0 0

4. 數組案例學習

【題目描述】現有 10 個數據 {0,1,2,3,4,5,6,7,8,9},將他們存儲到內存中,並逆序輸出。

#include<stdio.h>
int main(){
    int n=10;
    int a[10]={0,1,2,3,4,5,6,7,8,9};
    for(int i=n-1; i>=0; i--){
        printf("%d ", a[i]);
    }
    return 0;
}

【題目描述】現有 n 個整數數據,將他們存儲到內存中,並逆序輸出(n<=10000)。

輸入樣例:
5
45 12 34 89 21
輸出樣例:
21 89 34 12 45
#include<stdio.h>
#define N 10000
int a[N];
int main(){
    int n; scanf("%d", &n);
    for(int i=0; i<n; i++){ // [0, n-1]
        scanf("%d", &a[i]);
    }
    for(int i=n-1; i>=0; i--){// [n-1, 0]
        printf("%d ", a[i]);
    }
    return 0;
}

5. 最大值所在位置

【題目描述】輸入 n 個正整數,存放在 a[1]~a[n] 中,輸出最大值所在位置(n<=10000)。

輸入樣例:
5
1 2 6 4 5
輸出樣例:
3
#include<stdio.h>
#define N 10010
int a[N];
int main(){
    int n, max_a=-1, max_i=-1; scanf("%d", &n);
    for(int i=1; i<=n; i++){
        scanf("%d", &a[i]);
        if(max_a<a[i]){
            max_a=a[i];
            max_i=i;
        }
    }
    printf("%d", max_i);
    return 0;
}

6. 斐波那契數列

【題目描述】斐波那契數列指的是這樣一個數列:0,1,1,2,3,5,8,13,21...
求數列的前 50 項,並按照從大到小的順序輸出。

無輸入,輸出樣例部分如下:
50 : 7778742049
49 : 4807526976
48 : 2971215073
47 : 1836311903
46 : 1134903170
45 : 701408733
...
5 : 3
4 : 2
3 : 1
2 : 1
1 : 0
#include<stdio.h>
#define N 100
long long a[N]={0,0,1};
int main(){
    int n=50;
    for(int i=3; i<=n; i++){
        a[i] = a[i-1]+a[i-2];
    }
    for(int i=n; i>=1; i--){
        printf("%d : %lld\n", i, a[i]);
    }
    return 0;
}

7. 第幾天

【題目描述】輸入年、月、日,輸出該天是這一年的第幾天。

輸入樣例:2021 8 24
輸出樣例:236

#include<stdio.h>
int main(){
    int a[12]={31,28,31,30,31,30,31,31,30,31,30,31};
    int year,month,day; scanf("%d%d%d", &year, &month, &day);
    int ans=day;
    if(month>2){
        if(year%400==0 || year%4==0&&year%100!=0) ans++;
    }
    for(int i=0; i<month-1; i++){
        ans += a[i];
    }
    printf("%d", ans);
    return 0;
}

8. 起立與坐下

【題目描述】有n個人,編號為 1~n。
開始時,所有人都站着,接着第2個人和2的倍數的人坐下,
然后,第3個人及3的倍數的人按相反的操作(坐的人站起來,站着的人坐下),
依次類推,一共操作到第k人及k的倍數。
問最后有哪些人站着。輸入n和k,輸出站着的人的編號。

輸入樣例:7 3
輸出樣例:1 5 6 7

#include<stdio.h>
#define N 10010
int a[N];//0表示站着,1表示坐着
int main(){
    int n,k; scanf("%d%d", &n, &k);
    for(int i=2; i<=k; i++){
        for(int j=1; j<=n; j++){
            if(j%i==0) a[j]=!a[j];
        }
    }
    for(int i=1; i<=n; i++){
        if(a[i]==0) printf("%d ", i);
    }
    return 0;
}

9. 排序

【題目描述】輸入n個數,存在數組a中,每個數都是介於0~k之間的整數,
此處k為某個整數(n<=100000,k<=1000),按從小到大的順序,輸出a數組中的數據。

輸入樣例:
10
2 3 1 2 4 55 3 55 3 2
輸出樣例:
1 2 2 2 3 3 3 4 55 55
#include<stdio.h>
#define N 1010
int a[N];
int main(){
    int n, k=1000; scanf("%d", &n);
    for(int i=1; i<=n; i++){
        int x; scanf("%d", &x);
        a[x]++; //計數思想
    }
    for(int i=0; i<=k; i++){
        for(int j=1; j<=a[i]; j++){
            printf("%d ", i);
        }
    }
    return 0;
}

10 . 二維數組

二維數組的定義格式:類型說明符 數組名[常量表達式1][常量表達式2]
例如:int a[3][4], b[5][6];
解釋:定義 a為一個 3*4(3行4列)的數組,b為一個 5*6 (5行6列)的數組,且均為int類型。
用矩陣形式是在邏輯上的概念,可以形象的表示出行列關系。
在內存中,各元素是連續存放的,並不是二維的,而是線性的。

a[0][0] a[0][1] a[0][2] a[0][3]
a[1][0] a[1][1] a[1][2] a[1][3]
a[2][0] a[2][1] a[2][2] a[2][3]

b[0][0] b[0][1] b[0][2] b[0][3] b[0][4] b[0][5]
b[1][0] b[1][1] b[1][2] b[1][3] b[1][4] b[1][5]
b[2][0] b[2][1] b[2][2] b[2][3] b[2][4] b[2][5]
b[3][0] b[3][1] b[3][2] b[3][3] b[3][4] b[3][5]
b[4][0] b[4][1] b[4][2] b[4][3] b[4][4] b[4][5]

二維數組的初始化
1.分行賦值:int a[3][4]={{1,2,3,4}, {5,6,7,8}, {9,10,11,12}};
2.同行賦值:int b[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
上述兩種賦值方式均是可行的,且結果是相同的。

a,b均為:
1 2 3 4
5 6 7 8
9 10 11 12

但是,如果按照如下方式賦值會出現不同的結果:
1.分行賦值:int a[3][4]={{1,2,3,4}, {5}, {9,10,11,12}};
2.同行賦值:int b[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};

a:
1 2 3 4
5 0 0 0
9 10 11 12

b:
1 2 3 4
5 6 7 8
9 10 11 12

二維數組的賦值特性與一維數組相同,全局默認為0;局部部分賦值,未賦值部分為0;局部未賦值,則隨機。

11. 二維數組案例學習

【題目描述】給定正整數 n, m,以及一個 n*m 的矩陣,請按原矩陣保存並輸出,
同時輸出該矩陣順時針旋轉 90度后的新矩陣,
輸出的原矩陣以及新矩陣之間換行,且每個數據占 5個寬度。

輸入樣例:
2 4
1 2 3 4
5 6 7 8
輸出樣例:
    1    2    3    4
    5    6    7    8

    5    1
    6    2
    7    3
    8    4
#include<stdio.h>
#define N 100
int a[N][N];
int main(){
    int n, m; scanf("%d%d", &n, &m);
    for(int i=1; i<=n; i++){
        for(int j=1; j<=m; j++){
            scanf("%d", &a[i][j]);
        }
    }

    for(int i=1; i<=n; i++){
        for(int j=1; j<=m; j++){
            printf("%5d", a[i][j]);
        }printf("\n");
    }
    printf("\n");
    for(int i=1; i<=m; i++){
        for(int j=n; j>=1; j--){
            printf("%5d", a[j][i]);
        }printf("\n");
    }
    return 0;
}

12. 楊輝三角

【題目描述】給出 n(n≤20),輸出楊輝三角的前 n行。
如果你不知道什么是楊輝三角,可以觀察樣例找找規律
輸入樣例:6
輸出樣例:

1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
#include<stdio.h>
#define N 110
int a[N][N];
int main(){
    int n=10; scanf("%d", &n);
    a[1][1]=1;
    for(int i=2; i<=n; i++){
        for(int j=1; j<=i; j++){
            a[i][j]= a[i-1][j-1]+a[i-1][j];
        }
    }
    for(int i=1; i<=n; i++){
        for(int j=1; j<=i; j++){
            printf("%d ", a[i][j]);
        }printf("\n");
    }
    return 0;
}

13. 蛇形方陣

【題目描述】給出一個不大於 9 的正整數 n,輸出 n×n 的蛇形方陣。
從左上角填上 1 開始,順時針方向依次填入數字,如同樣例所示。
注意每個數字有都會占用 3 個字符,前面使用空格補齊。

輸入樣例:4
輸出樣例:

  1  2  3  4
 12 13 14  5
 11 16 15  6
 10  9  8  7
#include<stdio.h>
int a[10][10];
int main(){
    int n; scanf("%d", &n);
    a[1][1]=1;
    int i=1, j=1, cnt=1;
    while(cnt<n*n){
        while(j+1<=n && a[i][j+1]==0){//右
            a[i][++j] = ++cnt;
        }
        while(i+1<=n && a[i+1][j]==0){//下
            a[++i][j] = ++cnt;
        }
        while(j-1>0 && a[i][j-1]==0){//左
            a[i][--j] = ++cnt;
        }
        while(i-1>0 && a[i-1][j]==0){//上
            a[--i][j] = ++cnt;
        }
    }
    for(int i=1; i<=n; i++){
        for(int j=1; j<=n; j++){
            printf("%3d",a[i][j]);
        }printf("\n");
    }
    return 0;
}

14. 字符數組

我們已經知道字符型數據是以字符的ASCII代碼存儲在存儲單元的,一般占一個字節,由於ASCII代碼也屬於整數形式,因此在 C99標准中,把字符類型歸納為整型類型中的一種。
C語言中沒有字符串類型,也沒有字符串變量,字符串是存放在字符數組中的。

char c[11];// 定義一個大小為 11的字符數組 c
c[0]='H'; c[1]='e'; c[2]='l'; c[3]='l'; c[4]='o'; c[5]=' ';
c[6]='W'; c[7]='o'; c[8]='r'; c[9]='l'; c[10]='d';

int c[11]; //char類型本身就是以ASCII代碼存儲的,所以用 int也可以,但是浪費空間
c[0]='H'; c[1]='e'; c[2]='l'; c[3]='l'; c[4]='o'; c[5]=' ';
c[6]='W'; c[7]='o'; c[8]='r'; c[9]='l'; c[10]='d';

字符數組的初始化

列表初始化

char c[11]={'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd'};
把11個字符依次賦值給 c[0]~c[10]這 11個元素。

char c[]={'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd'};
如果沒有給出數組長度,系統會自動根據初值個數確定數組長度,如上數組 c的長度會自動定位 11.

字符串常量初始化

char c[]={"c program"};
char c[]="c program"; //可以省略 {}

字符串結束標志 : '\0'
C系統在用字符數組存儲字符串常量時會自動加一個 '\0' 作為結束符。
例如:"c program" 共 9個字符,字符串時存儲在一維數組中的,在數組中它占 10字節,最后一個字節 '\0'是由系統自動加上去的。
字符數組並不要求它的最后一個字符為 '\0',甚至可以不包含 '\0',比如像如下寫法也是合法的:

char c[9]={"c program"};

字符數組的輸入輸出
1.逐個輸入輸出:用格式符 "%c"
2.將整個字符串一次輸入輸出:用格式符 "%s"

char str[100];
scanf("%s", str); //不加 &, 在 C語言中 數組名代表該數組的第一個元素的地址,也就是該數組的起始地址。
printf("%s", str);
printf("%o", str); //以8進制形式輸出數組的起始地址。

當然,字符數組也可以構建二維數組,甚至三維,多維,不過這一點就不多贅述了,有興趣可以自己測試一下。

15. 字符串處理函數

注意:字符串處理函數的頭文件:#include<string.h>

char str[10]="Hello World!";
puts(str); //輸出字符串,puts()輸出時會將 '\0'轉換為 '\n'即輸出完字符數組后換行
gets(str); //輸入字符串,gets()返回字符數組的首地址,但是由於溢出問題在 C11已被移除

char str1[100]="Hello ", str2[]="World!";
strcat(str1, str2);//連接字符串,將 str2連接到 str1之后, 並返回 str1的首地址。(str1必須足夠大)
注意:strcat連接前兩個字符串都有 '\0', 連接時將 字符串 str1后的 '\0'取消,只在新串最后保留 '\0'.

strcpy(str1, str2);//復制字符串,將 str2復制到 str1中
注意:不能直接: str1="Hello "; str1=str2; 這兩條語句都是不合法的。

strncpy(str1, str2, n);//復制前n個字符,將 str2的前 n個字符復制到 str1中

strcmp(str1, str2);//字符串比較,從左至右,按 單個字符的ASCII代碼比較。
如果 str1 與 str2相等, return 0;
如果 str1 大於 str2, return 正整數;
如果 str1 小於 str2, return 負整數;

strlen(str);//返回字符串的實際長度

strlwr(str);//字符串大寫轉小寫
strupr(str);//字符串小寫轉大寫

char ch = tolower(ch);//單個字符轉小寫,頭文件 <ctype.h>
char ch = toupper(ch);//單個字符轉大寫,頭文件 <ctype.h>

16. 字符計數

【題目描述】給定一個字符串(長度不超過100)以及單個字符,
求該字符在字符串中出現的次數,不區分大小寫。
輸入格式:兩行,第一行一個字符串,第二行單個字符。
輸出格式:一個整數,表示該字符在字符串中出現的次數。
輸入樣例:

ABCabcA
a

輸出樣例:

3

題解:

#include<stdio.h>
#include<string.h>
#include<ctype.h>
char a[101], b;
int main(){
    scanf("%s\n%c", a, &b);
    int len=strlen(a), ans=0;
    b=tolower(b);
    for(int i=0; i<len; i++){
        a[i] = tolower(a[i]);
        if(a[i]==b) ans++;
    }
    printf("%d\n", ans);
    return 0;
}

17. 尋找字符串

【題目描述】給定兩個字符串 a, b,尋找字符串 b 在字符串 a 中出現的次數,字符可重疊。
如:a="abababa", b="aba",則 b 在 a中出現的次數為 3 次。

輸入格式:兩行,第一行為字符串 a,第二行為字符串 b,字符串長度不大於 1000。
輸出格式:一個整數,表示字符串 b 在 a 中出現的次數。

題解:

#include<stdio.h>
#include<string.h>
#define N 1010
char a[N], b[N];
int main(){
    fgets(a, 1001, stdin);//會讀入\n, 也可以使用scanf("%s", a);
    fgets(b, 1001, stdin);
    int len1=strlen(a)-1, len2=strlen(b)-1;
    int ans=0;
    for(int i=0; i<len1; i++){
        bool flag=1;
        for(int j=0; j<=len2/2; j++){
            if(a[i+j]!=b[j]){
                flag=false; break;
            }
        }
        if(flag) ans++;
    }
    printf("%d\n", ans);
    return 0;
}

18. 對稱字符串

題目描述:對於給定的正整數 N(N<=20), 有如下對應的對稱字符串。

A[1]:A
A[2]:ABA
A[3]:ABACABA
A[4]:ABACABADABACABA
...
A[N]:...

輸入格式:一個正整數 N。
輸出格式:一行字符串A[N]。

題解:

#include<stdio.h>
#include<string.h>
#define N 1000000
char a[N];
int main(){
    int n, len=0; scanf("%d",&n);
    for(int i=1; i<=n; i++){
        strcat(a+len+1, a);
        a[len]='A'+i-1;
        len = strlen(a);
    }
    printf("%s\n", a);
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM