主頁 > 後端開發 > 前端學習C語言 - 函式和關鍵字

前端學習C語言 - 函式和關鍵字

2023-06-20 08:00:07 後端開發

函式和關鍵字

本篇主要介紹:自定義函式宏函式字串處理函式關鍵字

自定義函式

基本用法

實作一個 add() 函式,請看示例:

#include <stdio.h>

// 自定義函式,用于計算兩個整數的和
int add(int a, int b) { // a, b 叫形參
    int sum = a + b;
    return sum;
}

int main() {
    int num1 = 3;
    int num2 = 5;
    
    // 呼叫自定義函式計算兩個整數的和
    int result = add(num1, num2); // num1, num2 叫實參
    
    printf("兩個整數的和為:%d\n", result);
    
    return 0;
}

其中a, b 叫形參,num1, num2 叫實參

Tip:形參和實參的個數不同,筆者編譯器報錯如下(一個說給函式的引數少,一個說給函式的引數多了):

// 3個形參,2個實參
int add(int a, int b, int c) {}

//  error: too few arguments to function call, expected 3, have 2
int result = add(num1, num2);
// 2個形參,3個實參
int add(int a, int b) {}

// error: too many arguments to function call, expected 2, have 3
int result = add(num1, num2, num1);

函式呼叫程序

函式呼叫程序:

  1. 通過函式名找到函式的入口地址
  2. 給形參分配記憶體空間
  3. 傳參,包含值傳遞地址傳遞(比如js中的物件)
  4. 執行函式體
  5. 回傳資料
  6. 釋放空間,例如堆疊空間

請看示例:

#include <stdio.h>

// 2. 給形參分配記憶體空間
// 3. 傳參:值傳遞和地址傳遞(比如js中的物件)
// 4. 執行函式體
// 5. 回傳資料
// 6. 釋放空間,例如堆疊空間:區域變數 a,b,sum
int add(int a, int b) {
    int sum = a + b;
    return sum;
}

int main() {
    int num1 = 3;
    int num2 = 5;
    
    // 1. 通過函式名找到函式的入口地址
    int result = add(num1, num2); 
    
    printf("add() 的地址:%p\n", add);
    printf("%d\n", result);
    
    return 0;
}

輸出:

add() 的地址:0x401130
8

練習-sizeof

題目:以下兩次 sizeof 輸出的值相同嗎?

#include <stdio.h>

void printSize(int arr[]) {
    printf("Size of arr: %zu\n", sizeof(arr));
}

int main() {
    int nums[] = {1, 2, 3, 4, 5};
    
    printf("Size of nums: %zu\n", sizeof(nums));
    printSize(nums);
    
    return 0;
}

運行:

開始運行...
// sizeof(arr) 獲取的是指標型別 int * 的大小(在此例中是8位元組)
/workspace/CProject-test/main.c:4:40: warning: sizeof on array function parameter will return size of 'int *' instead of 'int[]' [-Wsizeof-array-argument]
    printf("Size of arr: %zu\n", sizeof(arr));
                                       ^
/workspace/CProject-test/main.c:3:20: note: declared here
void printSize(int arr[]) {
                   ^
1 warning generated.
Size of nums: 20
Size of arr: 8

運行結束,

結果:輸出不相同,一個是陣列的大小,一個卻是指標型別的大小,

結果分析:將一個陣列作為函式的引數傳遞時,它會被隱式地轉換為指向陣列首元素的指標,然后在函式中使用 sizeof 運算子獲取陣列大小時,實際上回傳的是指標型別的大小((通常為4或8位元組,取決于系統架構)),而不是整個陣列的大小,

宏函式

宏函式是C語言中的一種預處理指令,用于在編譯之前將代碼片段進行替換

之前我們用 #define 定義了常量:#define MAX_NUM 100,定義宏函式就是將常量改為函式,就像這樣

#include <stdio.h>
// 無參
#define PRINT printf("hello\n")

// 有參
#define PRINT2(n) printf("%d\n", n)

int main() {

    // 無參呼叫
    PRINT;
    // 有參呼叫
    PRINT2(10);    
    return 0;
}

輸出:hello 10

編譯流程

宏函式發生在編譯的第一步,

編譯可以分為以下幾個步驟:

  • 預處理(Preprocessing):在這一步中,前處理器將對源代碼進行處理,它會展開宏定義、處理條件編譯指令(如 #if、#ifdef 等)、包含頭檔案等操作,處理后的代碼會生成一個被稱為預處理檔案(通常以 .i 或 .ii 為擴展名),
  • 編譯(Compilation):在這一步中,編譯器將預處理后的代碼翻譯成匯編語言,它會進行詞法分析、語法分析、語意分析和優化等操作,將高級語言的代碼轉化為低級機器可以理解的形式,輸出的檔案通常以 .s 為擴展名,是一個匯編語言檔案,
  • 匯編(Assembly):匯編器將匯編語言代碼轉換為機器語言指令,它將每潭訓編陳述句映射到對應的機器語言指令,并生成一個目標檔案(通常以 .o 或 .obj 為擴展名),其中包含已匯編的機器指令和符號表資訊,
  • 鏈接(Linking):如果程式涉及多個源檔案,以及使用了外部庫函式或共享的代碼模塊,聯結器將合并和決議這些檔案和模塊,它會將目標檔案與庫檔案進行鏈接,決議符號參考、處理重定位等,最終生成可執行檔案(或共享庫),其中包含了完整的機器指令,

這些步驟并非一成不變,具體的編譯程序可能因為編譯器工具鏈和目標平臺的不同而有所差異,但是大致上,這是一個常見的編譯流程,

宏函式 vs 普通函式

用普通函式和宏函式實作平方的功能,代碼分別如下:

int square(int x) {
    return x * x;
}
#define SQUARE(x) ((x)*(x))

宏函式在編譯程序中被簡單地替換為相應的代碼片段,它沒有函式呼叫的開銷,可以直接插入到呼叫的位置,這樣可以提高代碼執行效率

這發生在預處理階段,不會進行型別檢查錯誤檢查,可能導致意外的行為或結果,例如:宏函式中需列印字串,而引數傳遞數字1:

#include <stdio.h>

#define PRINT2(n) printf("%s\n", n)

int main() {

    PRINT2(1);    
    return 0;
}

編譯有告警,執行檔案還是生成了:

pjl@pjl-pc:~/ph$ gcc demo-3.c -o demo-3
demo-3.c: In function ‘main’:
demo-3.c:3:26: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
    3 | #define PRINT2(n) printf("%s\n", n)
      |                          ^~~~~~
......
    7 |     PRINT2(1);
      |            ~
      |            |
      |            int
demo-3.c:7:5: note: in expansion of macro ‘PRINT2’
    7 |     PRINT2(1);
      |     ^~~~~~
demo-3.c:3:28: note: format string is defined here
    3 | #define PRINT2(n) printf("%s\n", n)
      |                           ~^
      |                            |
      |                            char *
      |                           %d

但運行還是報錯:

pjl@pjl-pc:~/ph$ ./demo-3
段錯誤 (核心已轉儲)

普通函式具備了型別檢查作用域錯誤檢查等功能,可以更加安全可靠地使用,但是函式呼叫需要一定的開銷,涉及保存現場、跳轉等操作,例如:

#define ADD(a, b) (a + b)

int result = ADD(3, 5);

編譯器會將宏函式展開為 (3 + 5),并直接插入到 ADD(3, 5) 的位置,避免了函式呼叫的開銷,

練習

題目:請問以下輸出什么?

#include <stdio.h>

#define SQUARE(x) x * x

int main() {
    int result = SQUARE(1 + 2); 
    printf("%d\n", result);

    return 0;
}

輸出:5,

分析:

// 1 + 2 * 1 + 2
#define SQUARE(x) x * x

如果希望輸出 9 可以用括號,就像這樣:

//(1 + 2) * (1 + 2)
#define SQUARE(x) (x) * (x)

字串處理函式

以下幾個字串處理函式都來自 <string.h> 庫函式,

strlen()

strlen() - 用于獲取字串的長度,即字串中字符的個數(不包括結尾的空字符'\0')

語法:

#include <string.h>

size_t strlen(const char *str);

示例:

#include <stdio.h>
#include <string.h>

int main() {
    char str[] = "Hello, world!";
    size_t length = strlen(str);
    // Length of the string: 13
    printf("Length of the string: %zu\n", length);

    return 0;
}

Tip: %zu只用于格式化輸出 size_t 型別的格式控制符

size_t

size_t是無符號整數型別,unsigned int 也是無符號整數,兩者還是有區別的,

size_t 被定義為足夠大以容納系統中最大可能的物件大小的無符號整數型別,可以處理比 unsigned int更大的值,

在涉及到記憶體分配、陣列索引、回圈迭代等需要表示大小的場景中,建議使用size_t型別,以保證代碼的可移植性和兼容性,盡管許多編譯器將size_t 定義為 unsigned int,但不依賴于它與unsigned int之間的精確關系是一個好的編程實踐,

strcpy()

strcpy - 將源字串(src)復制到目標字串(dest)中,包括字串的結束符\0,語法:

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

示例:

#include <stdio.h>
#include <string.h>

int main() {
    char source[] = "Hello, world!";
    char destination[20];
    strcpy(destination, source);
    // Destination: Hello, world!
    printf("Destination: %s\n", destination);

    return 0;
}

比如destination之前有字串,而且比source要長,你說最后輸出什么?

char source[] = "Hello, world!";
char destination[20] = "world, Hello!XXXXXXX";
strcpy(destination, source);

輸出不變,source 拷貝的時候會將結束符\0也復制到目標,destination 最后是Hello, world!\0XXXXXX,如果不需要拷貝結束符,可以使用 strncpy()

strncpy()

strncpy - 將源字串的指定長度復制到目標字串中,比如不拷貝源字符的結束符:

示例:

#include <stdio.h>
#include <string.h>

int main() {
    char source[] = "Hello, world!";
    char destination[20] = "world, Hello!XXXXXXX";
    
    // 將源字串的指定長度復制到目標字串中,不要source的結束符
    strncpy(destination, source, sizeof(source)-1);
    // Destination: Hello, world!XXXXXXX
    printf("Destination: %s\n", destination);

    return 0;
}

最后輸出:Destination: Hello, world!XXXXXXX

strcat()

strcat - 將源字串(src)連接到目標字串(dest)的末尾,形成一個新的字串,語法:

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

示例:

#include <stdio.h>
#include <string.h>

int main() {
    char destination[20] = "Hello";
    char source[] = ", world!";
    
    strcat(destination, source);
    // Destination: Hello, world!
    printf("Destination: %s\n", destination);

    return 0;
}
strncat()

strncat - 將源字串連接到目標字串的末尾,并限制連接的字符數量,

示例:

#include <stdio.h>
#include <string.h>

int main() {
    char destination[20] = "Hello";
    char source[] = ", world!";
    
    strncat(destination, source, 3);
    // Destination: Hello, w
    printf("Destination: %s\n", destination);

    return 0;
}

strcmp()

strcmp - 用于比較兩個字串的大小,

  • 字串的比較是按照字典順序進行的,根據每個字符的 ASCII 值進行比較,
  • 比如 apple 和 applea比較,第一次是 a 等于 a,繼續比較,直到第六次 \0 和 a 比較,\0 的 ASCII 是0,而a 是97(可列印字符的ASCII值通常位于32-126之間),所以 applea 更大
  • 大小寫敏感,例如 A 的 ASCII 是 65,

例如:比較字串 str1 和字串 str2 的大小

  • 如果 str1 小于 str2,則回傳一個負整數(通常是 -1),
  • 如果 str1 大于 str2,則回傳一個正整數(通常是 1),
  • 如果 str1 等于 str2,則回傳 0,

示例:

#include <stdio.h>
#include <string.h>

int main() {
    char str1[] = "apple";
    char str2[] = "applea";

    int result = strcmp(str1, str2);

    if (result < 0) {
        printf("str1 is less than str2\n");
    } else if (result > 0) {
        printf("str1 is greater than str2\n");
    } else {
        printf("str1 is equal to str2\n");
    }

    return 0;
}

輸出:str1 is less than str2

strncmp()

strncmp - 比較兩個字串的前n個字符是否相等

示例:

#include <stdio.h>
#include <string.h>

int main() {
    char str1[] = "apple";
    char str2[] = "applea";

    // int result = strcmp(str1, str2);
    int result = strncmp(str1, str2, strlen(str1));

    if (result < 0) {
        printf("str1 is less than str2\n");
    } else if (result > 0) {
        printf("str1 is greater than str2\n");
    } else {
        printf("str1 is equal to str2\n");
    }

    
    return 0;
}

輸出:str1 is equal to str2

strchr()

strchr - 在一個字串中查找指定字符第一次出現的位置,語法:

// str是要搜索的字串;
// c是要查找的字符,
char* strchr(const char* str, int c);

函式回傳值:

  • 如果找到指定字符,則回傳該字符在字串中的地址(指標),
  • 如果未找到指定字符,則回傳NULL,

Tip:可以通過地址相級訓傳字符在字串中出現的索引值,請看示例:

#include <stdio.h>
#include <string.h>

int main() {
    char str[] = "Hello, world!";
    char* result = strchr(str, 'o');
    
    if (result != NULL) {
        // 回傳字符'o'的位置,并輸出字符 'o' 到結尾的字串
        printf("找到了字符'o',位置為:%s\n", result);
        // 地址相減,回傳字符第一次出現的索引
        printf("找到了字符'o',位置為:%ld\n", result - str);
    }
    else {
        printf("未找到字符'o'\n");
    }
    
    return 0;
}

輸出:

開始運行...

找到了字符'o',位置為:o, world!
找到了字符'o',位置為:4

運行結束,
strrchr

strrchr - 相對strchr()逆序查找,

修改上述示例(strchr)一行代碼:

- char* result = strchr(str, 'o');
+ char* result = strrchr(str, 'o');

運行:

開始運行...

找到了字符'o',位置為:orld!
找到了字符'o',位置為:8

運行結束,

strstr

strstr - 用于在一個字串中查找指定子字串的第一次出現位置,語法:

char* strstr(const char* str1, const char* str2);

示例:

#include <stdio.h>
#include <string.h>

int main() {
    char str[] = "Hello, World!";
    char *subStr = "World";
    char *result = strstr(str, subStr);

    if (result != NULL) {
        printf("找到子字串:%s\n", result);
    } else {
        printf("未找到子字串,\n");
    }

    return 0;
}

關鍵字

C 語言有如下關鍵字:

關鍵字 描述 關鍵字 描述
auto 宣告自動變數 enum 宣告列舉型別
break 跳出當前回圈或開關陳述句 extern 宣告外部變數或函式
case 開關陳述句分支標簽 float 宣告單精度浮點型變數或函式回傳值型別
char 宣告字符型變數或函式回傳值型別 for 回圈陳述句
const 宣告只讀變數 goto 無條件跳轉陳述句
continue 結束當前回圈的迭代,并開始下一次迭代 if 條件陳述句
default 開關陳述句的默認分支 int 宣告整型變數或函式回傳值型別
do 回圈陳述句的回圈體 long 宣告長整型變數或函式回傳值型別
double 宣告雙精度浮點型變數或函式回傳值型別 register 宣告暫存器變數
else 條件陳述句中否定條件的執行體 return 從函式回傳值
short 宣告短整型變數或函式回傳值型別 signed 宣告有符號數型別
sizeof 獲取某個資料型別或變數的大小 static 宣告靜態變數
struct 宣告結構體型別 switch 開關陳述句
typedef 宣告型別別名 union 宣告聯合體型別
unsigned 宣告無符號數型別 void 宣告無型別
volatile 說明變數可以被意外修改,應立即從記憶體中讀取或寫入而不進行優化 while 回圈陳述句

重點說一下:static、const(已講過)、extern,

auto

在C語言中,auto 關鍵字并不是必需的,因為所有在函式內部宣告的變數默認都是自動變數,所以在實際編碼中,很少使用 auto 關鍵字進行變數宣告

#include <stdio.h>

int main() {
    auto int x = 10; // 等于 int x = 10;
    
    printf("The value of x is: %d\n", x); // 輸出:The value of x is: 10
    
    return 0;
}

在現代的C語言標準中(C99及以上),auto 關鍵字的使用已經不常見,并且很少被推薦使用,因為它已經成為了默認行為

register

比如 for(int i = 0; i< 1000; i++),每次i都會自增1,如果編譯器沒有任何優化,有可能會導致暫存器記憶體之間的資料互動發生一千次,如果將 i 宣告成暫存器變數(register int count;),可能就無需互動這么多次,但這也只是給編譯器提供一個建議,指示它將變數存盤在暫存器中,實際上,編譯器可以選擇忽略這個建議,根據自身的優化策略和限制來決定是否將變數存盤在暫存器中,

Tip: 暫存器是不能被直接取地址,C 語言標準已經從 C99 開始將 register 關鍵字標記為過時(deprecated)

extern

extern - 用于宣告變數或函式的外部鏈接性,

通俗點說,比如我在b.c中定義了一個方法,在另一個檔案中想使用,無需重復撰寫,通過 extern 宣告后可直接使用,編譯時需要將多個檔案一起編譯成可執行檔案,

定義b.c和main.c兩個檔案:

  • b.c 中通過 extern int number 宣告 number 變數在外部已定義,不會分配記憶體空間
  • main.c 先宣告 show() 函式已在外部定義,然后使用
  • 最后通過 gcc 將這兩個檔案編譯成 main 可執行函式

完整代碼如下:

b.c:

#include <stdio.h>
extern int number;  // 宣告外部變數 number 已存在,不會分配記憶體空間

void show() {
    printf("x = %d\n", number);  // 使用外部變數 number
}

main.c:

#include <stdio.h>

extern void show();  // 宣告函式 show 的存在

// 全域變數
int number = 101;
int main() {
    show();  // 呼叫 b.c 中的函式,列印外部變數 number
    return 0;
}

兩兩個檔案一起編譯,運行輸出 x = 101

pjl@pjl-pc:~/$ gcc main.c b.c -o main && ./main
x = 101

static

static 有3個作用:

  • static int number = 101;, 指明 number 只能在本檔案中使用,其他檔案即使使用了 extern 也不能訪問
  • static void show(), 指明 show 只能在本檔案中使用,其他檔案即使使用了 extern 也不能訪問
  • static 修飾區域變數,會改變變數的宣告周期,直到程式結束才釋放

通過三個示例一一說明,

:在 extern 示例基礎上進行,

示例1:修改 main.c:

- int number = 101;
+ static int number = 101;

編譯報錯如下:

pjl@pjl-pc:~/$ gcc main.c b.c -o main
/usr/bin/ld: /tmp/ccEOKXoI.o: in function `show':
b.c:(.text+0xa): undefined reference to `number'
collect2: error: ld returned 1 exit status

示例2:修改 b.c:

- void show() {
+ static void show() {

編譯報錯:

pjl@pjl-pc:~/$ gcc main.c b.c -o main
/usr/bin/ld: /tmp/cc8XfhVS.o: in function `main':
main.c:(.text+0xe): undefined reference to `show'
collect2: error: ld returned 1 exit status

示例3:請問下面這段代碼輸出什么?

#include <stdio.h>
void show(); 

void fn1(){
    int i = 1;
    printf("%d\n", ++i);
}

int main() {
    for(int i = 0; i < 3; i++){
        fn1();
    }
    return 0;
}

輸出三個2,因為 fn1() 每次執行完,存放在堆疊中的變數 i 就被釋放,

如果給 i 增加 static 會輸出什么:

- int i = 1;
+ static int i = 1;

輸出2 3 4

Tip:在C語言中,全域變數靜態變數都屬于靜態存盤類別,默認情況下會被分配到靜態資料區,靜態資料區在程式啟動時被分配,在程式結束時釋放,

練習

Tip:以下4個都是字串相關的編程練習

練習1

題目:查找字符陣列中字符的位置,例如 hello e,輸出1,

實作:

#include <stdio.h>
#include <string.h>

int findIndex(char array[], char target) {
    int length = strlen(array);
    for (int i = 0; i < length; i++) {
        if (array[i] == target) {
            return i;
        }
    }
    return -1; // 字符不在陣列中
}

int main() {
    char array[] = "hello";
    char target = 'e';
    int index = findIndex(array, target);

    if (index != -1) {
        printf("字符 %c 的位置是:%d\n", target, index);
    } else {
        printf("字符 %c 不在陣列中\n", target);
    }

    return 0;
}

輸出:字符 e 的位置是:1

練習2

題目:查找字符陣列中字符的位置,例如 hello ll,輸出2,

實作:

#include <stdio.h>
#include <string.h>

int findIndex(char array[], char substring[]) {
    char *result = strstr(array, substring);
    if (result != NULL) {
        return result - array;
    }
    return -1; // 字串不在陣列中
}

int main() {
    char array[] = "hello";
    char substring[] = "ll";
    int index = findIndex(array, substring);

    if (index != -1) {
        printf("字串 \"%s\" 的位置是:%d\n", substring, index);
    } else {
        printf("字串 \"%s\" 不在陣列中\n", substring);
    }

    return 0;
}

輸出:字串 "ll" 的位置是:2

練習3

題目:在字串指定位置插入字串

實作

#include <stdio.h>
#include <string.h>

void insertString(char str[], int pos, const char insert_str[]) {
    int len1 = strlen(str);
    int len2 = strlen(insert_str);

    if (pos < 0 || pos > len1)
        return;  // 無效的插入位置
    
    // 創建臨時陣列,用于存盤插入后的新字串
    char temp[len1 + len2 + 1];
  
    // 將原字串中插入位置之前的部分復制到臨時陣列
    strncpy(temp, str, pos);
    
    // 將要插入的字串復制到臨時陣列的合適位置
    strcpy(&temp[pos], insert_str);

    // 追加原字串中插入位置之后的部分
    strcat(temp, &str[pos]);

    // 將新字串復制回原字串
    strcpy(str, temp);
}

int main() {
    char original_str[100] = "Hello, world!";
    int pos = 7;
    char insert_str[100] = "beautiful ";

    insertString(original_str, pos, insert_str);
    printf("%s\n", original_str);

    return 0;
}

輸出:Hello, beautiful world!

練習4

題目:計算字串中子串的次數,例如 "helloworldhelloworldhelloworld hello" 中 hello 出現4次

#include <stdio.h>
#include <string.h>

int countSubstringOccurrences(const char* str, const char* substring) {
    int count = 0;
    int substring_length = strlen(substring);
    const char* ptr = strstr(str, substring);

    while (ptr != NULL) {
        count++;
        ptr += substring_length;
        ptr = strstr(ptr, substring);
    }

    return count;
}

int main() {
    const char* str = "helloworldhelloworldhelloworld hello";
    const char* substring = "hello";

    int count = countSubstringOccurrences(str, substring);
    // 4
    printf("%d\n", count);

    return 0;
}
作者:彭加李
出處:https://www.cnblogs.com/pengjiali/p/17492014.html
本文著作權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連接,

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/555553.html

標籤:其他

上一篇:Rust語言 - 介面設計的建議之顯而易見(Obvious)

下一篇:返回列表

標籤雲
其他(161274) Python(38242) JavaScript(25505) Java(18249) C(15237) 區塊鏈(8271) C#(7972) AI(7469) 爪哇(7425) MySQL(7258) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5875) 数组(5741) R(5409) Linux(5347) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4603) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2436) ASP.NET(2404) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1984) HtmlCss(1968) 功能(1967) Web開發(1951) C++(1942) python-3.x(1918) 弹簧靴(1913) xml(1889) PostgreSQL(1881) .NETCore(1863) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • 前端學習C語言 - 函式和關鍵字

    ## 函式和關鍵字 本篇主要介紹:`自定義函式`、`宏函式`、`字串處理函式`和`關鍵字`。 ### 自定義函式 #### 基本用法 實作一個 add() 函式。請看示例: ```c #include // 自定義函式,用于計算兩個整數的和 int add(int a, int b) { // a ......

    uj5u.com 2023-06-20 08:00:07 more
  • Rust語言 - 介面設計的建議之顯而易見(Obvious)

    # Rust語言 - 介面設計的建議之顯而易見(Obvious) - [Rust API 指南 GitHub](https://github.com/rust-lang/api-guidelines): - [Rust API 指南 中文](https://rust-chinese-translat ......

    uj5u.com 2023-06-20 08:00:02 more
  • java后端接入微信小程式登錄功能

    # 前言 此文章是Java后端接入微信登錄功能,由于專案需要,舍棄了解密用戶資訊的`session_key`,只保留`openid`用于檢索用戶資訊 后端框架:spring boot 小程式框架:uniapp # 流程概括 - 官方流程:通過自定義登錄態與openid,session_key關聯,之 ......

    uj5u.com 2023-06-20 07:59:54 more
  • 一種實作Spring動態資料源切換的方法

    ## 1 目標 不在現有查詢代碼邏輯上做任何改動,實作dao維度的資料源切換(即表維度) ## 2 使用場景 節約bdp的集群資源。接入新的寬表時,通常uat驗證后就會停止集群釋放資源,在對應的查詢服務器uat環境時需要查詢的是生產庫的表資料(uat庫表因為bdp實時任務停止,沒有資料落入),只進行 ......

    uj5u.com 2023-06-20 07:59:44 more
  • java~搞懂Comparable介面的compareTo方法

    `Comparable` 介面的 `compareTo` 方法的升序或降序取決于實作該介面的類的具體實作。按照慣例,`compareTo` 方法應該回傳負數、零或正數來指示當前物件是小于、等于還是大于傳入的物件。具體來說: - 如果 `this` 物件小于傳入的物件,則 `compareTo` 應該 ......

    uj5u.com 2023-06-20 07:59:36 more
  • ElasticSearch的使用和介紹

    # 1、概述 ## 功能 Elasticsearch 是一個分布式的 RESTful 搜索和分析引擎,可用來集中存盤您的資料,以便您對形形色色、規模不一的資料進行搜索、索引和分析。 例如: - 在電商網站搜索商品 ![image](https://img2023.cnblogs.com/blog/3 ......

    uj5u.com 2023-06-20 07:54:11 more
  • Java 運算子的使用

    # Java 運算子的使用 # 1.算術運算子 ## 算術運算子包括: +, -, *, /, %, ++, --,其中需要注意的是%,++,--; ## % 取模運算也叫做取余,在 Java 中取余的規則: a % b = a - a / b * b,如果是小數的話是這樣:a % b = a- ( ......

    uj5u.com 2023-06-20 07:48:58 more
  • 【python基礎】函式-值傳遞

    為了更好的認識函式,我們還要研究值傳遞問題,再研究這個問題之前,我們已經知道了函式之間的值傳遞,是實參變數值傳遞給形參變數,然后讓形參變數在函式內完成相應的功能。但是因為資料型別的不同,這里的值傳遞產生的對實參變數的效果是不同的 # 1.傳遞資料本質 引數傳遞之間傳遞的肯定是資料,而這種資料本質上是 ......

    uj5u.com 2023-06-20 07:43:39 more
  • Spring Boot 優雅實作多租戶架構,so easy~!

    ## 一、概述 ### 1.什么是多租戶架構? 多租戶架構是指在一個應用中支持多個租戶(Tenant)同時訪問,每個租戶擁有獨立的資源和資料,并且彼此之間完全隔離。通俗來說,多租戶就是把一個應用按照客戶的需求“分割”成多個獨立的實體,每個實體互不干擾。 ### 2. 多租戶架構的優勢 - 更好地滿足 ......

    uj5u.com 2023-06-20 07:43:30 more
  • Scala高階語法

    # 高階函式 ## 函式可以作為引數進行傳遞和回傳值進行回傳 ```Scala //傳一個a乘b 就回傳一個函式,邏輯是實作兩數相乘 //傳一個a*b 回傳一個函式,邏輯是實作兩數相乘 //傳一個axb 回傳一個函式,邏輯是實作兩數相乘 def funTest6(str:String,fun:(St ......

    uj5u.com 2023-06-20 07:43:05 more