1. 程式人生 > >物聯網技術部&祕書部第一次軟體培訓總結

物聯網技術部&祕書部第一次軟體培訓總結

物聯網技術部&祕書部第一次軟體培訓總結

一、二維陣列

1.定義

型別說明符 陣列名 [常量表達式1] [常量表達式2]

float a[3][4];

陣列中的元素為:
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]

2.初始化

int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}; 
int a[3][4]={{1},{0,6},{0,0,11}}; 
int a[3][4]={1,2,3}; 
int a[ ][3]={{1},{2},{3,4,5}};      //即 a[3][3] 
int a[ ][3]={1,2,3,4,5};            //即 a[2][3]

注意: 下標不能越界!

3.引用

陣列名[常量表達式1][常量表達式2]

	//示例:
	b[1][2] = a[2][3]/2

4.應用

請設計一個程式,將一個4行4列的二維陣列中行和列元素互換,並存放到另一個數組中。

小程式碼示例

    //C語言

#include<stdio.h>
int main(){
	int a[4][4] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14};
	int t;
	for (int i=0; i < 4; i++) {
		for (int j = 0; j < 4; j++) 
			printf("%3d", a[i][j]);
		printf("\n");
	}
	for (int i = 0; i < 4; i++) 
		for (int j = i + 1; j < 4; j++) {
			t = a[i][j];
			a[i][j]=a[j][i] ;
			a[j][i] = t;
		}
	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 4; j++) 
			printf("%3d", a[i][j]);
		printf("\n");
	}
return 0;
}
  //  C++
  
#include<iostream>
#include<iomanip>
using namespace std;

int main(){
	int a[4][4] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14};     
	int t;
	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 4; j++) 
			cout << setw(3) << setfill(' ') << a[i][j];
		cout << endl;
	}
	for (int i = 0; i < 4; i++) 
		for (int j = i + 1; j < 4; j++) {
			t = a[i][j];
			a[i][j]=a[j][i] ;
			a[j][i] = t;
		}
	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 4; j++) 
			cout << setw(3) << setfill(' ') << a[i][j];
		cout << endl;
	}
	return 0;
}

二、指標

1.概念

變數的值: 變數所代表的記憶體單元中的內容
變數的地址: 該變數所佔儲存單元的首地址
指標: 一個變數的地址,一個記憶體單元的地址,通常是一個無符號整數
指標變數: 存放變數地址的變數

2.定義與使用

型別說明符 *變數名

int *i_pointer , i=10; 
i_pointer=&i; 
printf(“%d”,*i_pointer);

說明: * 解引用 & 取地址符

小程式碼示例:

int main(){
	int i = 10;
	int *p;
	*p = i;          //危險!
	printf("%d", *p);
	return 0;
}

注意: 指標變數必須先賦值,再使用!

3.指標與一維陣列

1)一維陣列的地址

在這裡插入圖片描述

2)關係

	int a[10], *pa; 
	pa=a; pa =&a[0];  //等價

引用一個數組元素,有3種方法:
1)下標法: a[ i ]
2)陣列名地址法: * (a+i )
3)指標法:
①指標地址法: * (pa+i )
②指標下標法: pa[ i ]

4.指標與多維陣列

1)多維陣列的地址

在這裡插入圖片描述
int a[3][4]={0};

a代表二維陣列首行的首地址,記作a[0]或&a[0][0](現在的首元素不是一個簡單的整型元素,而是由4個整型元素所組成的一維陣列)
同理a+1為序號為1的行的首地址,記作a[1]==&a[1][0]
那1行1列的元素的地址? a[1]+1

2)關係

指向陣列元素的指標變數

int a[3][4]={0};
int *p;
p = a[0];
p++;                    //p可以向下移動,依次指向下一個元素

指向陣列的行指標變數

int a[3][4]={0};
int (*p)[4];
p = a;
a[i][j] == *(*(p+i)+j)

5.多級指標

如果指標變數中存放的是另一個指標變數的地址,就稱該指標變數為指向指標的指標變數,也稱為二級指標。

資料型別 **變數名

	int i=10,*ptrch=&i; 
	int **pp=&ptrch; 

6.malloc動態分配

void *malloc(unsigned int size);

int a[n];   !錯誤

int *a=(int *)malloc(n*sizeof(int));
//或
#define N 100
int a[N]

7.指標小應用

用指標改寫二維陣列中的矩陣轉置

int *p=a;
int (*q)[4]=a;
a[i][j] = p[i*n+j] = *(p+(i*n+j));
a[i][j] = q[i][j] = *(*(q+i)+j);

三、函式

1.定義與宣告

定義
型別名 函式名(形參表)
{
宣告部分
執行語句
}

宣告
型別名 函式名(形參表);

2.遞迴函式

如果一個函式在其函式體中直接或者間接地呼叫了自己,則該函式稱為遞迴函式。
直接呼叫自己為直接遞迴;間接呼叫自己為間接遞迴

圖解如下:
在這裡插入圖片描述

1)從數學角度看遞迴

例如
等差數列:
首項,即第一項的值a1;
遞推公式,即連續項間的關係(an = an-1 +9)

當呼叫a(n)即執行a(n-1)+9,同時呼叫a(n-1)即a(n-2)+9……這樣一直下去,最後到首項時,不再呼叫函式,直接返回數值。此時一路反向加回去,結束遞迴。

圖解如下:
在這裡插入圖片描述

2)遞迴的注意點

1)結束條件:遞迴需要有明確的終止條件(首項)
2)逼近過程:處理好問題和子問題之間的關係,使得每次遞迴呼叫都要逼近終止條件
3)初始引數:呼叫遞迴函式的引數

3)遞迴的應用

1.請設計一個程式,利用遞迴求n!

小程式碼示例:

    // C語言
    
#include<stdio.h>
int multiple(int n) {
    if (n == 1) 
        return 1;
    else 
        return n*multiple(n - 1);
}

int main() {
    int n,m;
    scanf("%d", &n);
    m = multiple(n);
    printf("%d", m);
    return 0;
}
  //  C++
  
#include<iostream>
using namespace std;
int multiple(int n) {
	if (n == 1) {
		return 1;
	}else {
		return n*multiple(n - 1);
	}
}
int main() {
	int n,m;
	cin >> n;
	m = multiple(n);
	cout << m;
	return 0;
}

2.有一對兔子,從出生後第三個月起每個月都生一對兔子,小兔子長到第三個月後,每個月又生一對兔子。假設兔子都不死,問第20個月的兔子的對數為多少

小程式碼示例

    //	C語言

#include<stdio.h>

int birth(int n) {
	int result;
	if (n == 1)
		result = 1;
	else if (n == 2)
		result = 1;
	else if (n == 3)
		result = 2;
	else
		result = birth(n-1)+birth(n-3);
	return result;
}

int main()
{
	int n,x;
    scanf(“%d”,&n);
    x=birth(n);
    printf(“%d”,x);
    return 0;
}
      //  C++

#include<iostream>
using namespace std;

int birth(int n) {
	int result;
	if (n == 1)
		result = 1;
	else if (n == 2)
		result = 1;
	else if (n == 3)
		result = 2;
	else
		result = birth(n-1)+birth(n-3);
	return result;
}

int main()
{
	int n,x;
	cin >> n;
	x=birth(n);
	cout << x;
	return 0;
}

3.函式的優缺點

函式用於包裝一些程式碼片段,使得他能夠方便的被重複使用。
函式主要有以下的幾個優點:
1)函式是實現程式碼重用的一種方式
2)友好的函式名字便於傳達程式碼的含義
3)函式會簡化程式碼的實現,使思路更清晰
同時,函式主要也有以下的幾個缺點:
1)呼叫函式會時間和空間的消耗
2)遞迴函式擁有棧溢位的風險

四、OJ小技巧

1.關於輸入問題

1)做題的時候儘量使用scanf printf。cin cout比scanf printf慢20倍左右,一旦遇到大資料量,光是讀入就有可能跪掉。
2)scanf和cin混用可能就會造成一些奇怪的錯誤。
3)關於輸入多組資料

#include <stdio.h>
int main(){   
	int input;    
	while(scanf("%d",&input) != EOF) {   
		//在此處理資料        
		printf("%d\n",input);    
	}    
	return 0;
}

還可以:
while( ( scanf(“%d”,&a) ) != -1 )
while( ( scanf(“%d”,&a) ) == 1 )
while( ~( scanf(“%d”,&a) ) )
while(cin>>a) //C++

讀到一個0時,程式結束,可用:
while( scanf(“%d”,&a) ,a)
while( scanf(“%d”,&a) &&a!=0)
while (cin>>i,i) //C++

2.關於輸出格式(presentation error)

1)行末空格:比如我輸出需要列印多個數需要使用空格分隔的時候,我們迴圈使用printf(“%d “,x);這種會很方便,但是這樣會導致行末多一個空格,後臺系統會嚴格比對你的輸出和.out檔案,這樣也會被判錯誤
2)換行問題:對於每個樣例,建議輸出完全之後都換行一下。對於一些題目,可能就是不換行就導致了後面輸入資料錯位,那就肯定不可能過了。
3)大部分題處理一組資料後可直接輸出,不需要用陣列儲存每一個Case的資料。

3.關於陣列問題

1)陣列定義int a[10]={0};可以對其全部元素賦值為0;但是陣列太大不要這樣。
2)定義陣列時,陣列大小最好比告訴的最大範圍大一點。
3)字元陣列大小必須比字串最大長度大1。
4)處理字元陣列時不要忘了在最後加’/0’或者0。

4.關於Runtime error

1)下標越界
2)要表示的數值太大,超出了定義型別數的範圍。
3)未賦值的變數就直接使用
4)在無限遞迴或函式裡使用了太大的陣列變數
!一定要好好排查,不仔細一般找不出來。

5.關於字串

1)純字串用puts()輸出,會增快速度。
2)先用scanf(),再用gets()會讀入回車。要使用getchar()吸收空格和回車的錄入。
!使用c語言讀字元和字串一定要十分小心。儘量寫好就自己輸出一下看看是否是自己需要的值被讀入。

6.總結

1)輸入輸出是不是按照題意進行的。
2)是不是有些步驟沒有完成。
3)對於邊界輸入的檢查
4)演算法的複雜度是不是過高
牢記:
程式碼不通過肯定是自己哪裡出了什麼問題,檢查程式碼!再三看題讀懂題意!!!

7.OJ小例題

輸入
輸入包含多個測試用例。每個測試用例以數字N開始(0 < N <= 1000)——分佈的氣球總數。接下來的N行每一行都包含一種顏色。氣球的顏色是由15個小寫字母組成的字串。
輸出
對於每一種情況,列印氣球顏色最流行的問題在一行。保證每個測試用例都有唯一的解決方案。
sample input:
orange
orange
pink
red
blue
sample
output:
orange

程式碼小示例:

#include <stdio.h>
#include <string.h>
main(){
    int n, i, j, t, max, num[1000];
    char color[1000][16];
    while(scanf("%d", &n) != EOF){
        if(n){
            num[0]=0;
            scanf("%s", color[0]);
            for(i=1; i <n; i++){
                num[i]=0;
                scanf("%s", color[i]);
                for(j=0; j <i-1; j++)
                    if(strcmp(color[i], color[j])==0) num[i] +=1;
            }
            max=num[0];
            t=0;
            for(i=1; i <n; i++)
               if(max <num[i]) {max =num[i]; t=i;}
            printf("%s\n",color[t]);
        }
    }
}