C語言 進階指針學習筆記

文章目錄

    • 字符指針
    • 指針數組
    • 數組指針
      • 數組名
      • 數組傳參
    • 函數指針
    • 函數指針數組
      • 指向函數指針數組的指針
    • 回調函數
      • Qsort 的使用
      • 通過冒泡排序模擬實現 qsort

大部分的內容都寫在代碼注釋中
指針有類型,指針的類型決定了指針的±整數的步長,指針解引用操作的時候的權限

字符指針

#include <stdio.h>  int main(void)  
{  const char *str1 = "Hello, World!";  const char *str2 = "Hello, World!";  // 在這個寫法中,字符串放在表達式中("hello world" 視為一個表達式)  // 該表達式的值是一個指向字符串的指針  // *str2 = "Hello, C!"; // const 在 * 前面,不能修改指針指向的內容  char str3[] = "Hello, World!";  char str4[] = "Hello, World!";  // 在這個寫法中,字符串放在數組中,數組是一個變量,可以修改  char *str5 = "Hello, World!";  // 在這個寫法中,指針未被修飾,且其中存的為常量字符串  // *str5 = "Hello, C!"; // 會報錯,因為指針指向的是常量字符串,不能被修改  // 在前面加上 const 修飾符,即可在編譯階段報錯,避免運行時錯誤  // const char *str5 = "Hello, World!";  printf("str1: %s, address: %p\n", str1, str1);  printf("str2: %s, address: %p\n", str2, str2);  printf("str5: %s, address: %p\n", str5, str5);  // str1、str2 和 str5 的地址是相同的,因為它們指向的是常量字符串,在內存中只有一份  printf("str3: %s, address: %p\n", str3, str3);  printf("str4: %s, address: %p\n", str4, str4);  // str3 和 str4 的地址是不同的,因為它們是數組,每個數組都有自己的內存空間  return 0;  
}

C/C++會把常量字符串存儲到單獨的一個內存區域,當幾個常量指針指向同一個字符串時,他們實際會指向同一塊內存(全局區)
但是用相同的常量字符串去初始化不同的數組的時候就會開辟出不同的內存塊,因此 str1 和 str2 不同,str3 和 str4 不同

指針數組

指針數組是一個存放指針的數組

#include <stdio.h>  int main()  
{  int arr1[] = {1, 2, 3, 4, 5}; // 整形數組  // 指針數組  int *parr1[] = {arr1, arr1 + 1, arr1 + 2, arr1 + 3, arr1 + 4};  // parr1 是一個數組,數組中的每個元素都是一個 int*,指向 arr1 中的元素  for (int i = 0; i < 5; i++)  {  printf("arr1[%d]: %d, address: %p\n", i, arr1[i], &arr1[i]);  printf("parr1[%d]: %d, address: %p\n", i, *parr1[i], parr1[i]);  // 這里的 address 實際上就是 arr2[i] 的值,即 arr1 中元素的地址  }  // ----------------------------  int arr2[] = {1, 2, 3, 4, 5};  int arr3[] = {2, 3, 4, 5, 6};  int *parr2[] = {arr2, arr3}; // 利用指針數組,將多個獨立數組組合成類二維數組  for(int i = 0; i < 2; i++)  {  for(int j = 0; j < 5; j++)  {  printf("parr2[%d][%d]: %d, address: %p\n", i, j, parr2[i][j], &parr2[i][j]);  // parr2[i][j] 等價于 *(parr2[i] + j),即 arr2[i] 中的第 j 個元素  }  }  return 0;  
}

數組指針

數組指針指指向數組的指針

int main()  
{  int *arr1[5]; // 指針數組  // arr1 先是一個數組(先和方塊結合),數組中的每個元素都是一個 int*,指向 int 類型的變量  int (*arr2)[5]; // 數組指針  // arr2 是一個指針,指向一個 int 類型的數組  return 0;  
}

數組名

  1. 通常,數組名表示的都是首元素地址
  2. 存在兩個例外
    1. sizeof (數組名),這里的數組名表示整個數組
    2. &數組名,表示的依然是整個數組

類型(對 int arr[5]]):

  • arr -> int*
  • &arr -> int (*)[5]
#include <stdio.h>  int main()  
{  int arr1[] = {1, 2, 3, 4, 5};  printf("%p\n", arr1);  printf("%p\n", &arr1);  // 在這里,&arr1 表示整個數組的地址,即 arr1 的地址  printf("----------------\n");  int sz = sizeof(arr1);    printf("%d\n", sz);    // sizeof(arr1) 是整個數組的大小,單位是字節  // 在這里,數組名表示整個數組  printf("----------------\n");  printf("%p\n", arr1 + 1);    printf("%p\n", &arr1 + 1);    // arr1 + 1 表示數組中第二個元素的地址  // &arr1 + 1 表示整個數組后面的地址  printf("----------------\n");  int (*parr)[5] = &arr1;    // parr 是一個指針,指向一個 int 類型的數組  // 需要寫清楚有幾個元素// 此時,parr 的類型為 int(*)[5]int *p = &arr1;  // warning:'int(*)[5]' 類型的表達式被隱式轉換為不兼容的指針類型  return 0;  
}

數組傳參

#include <stdio.h>  /**  * @brief 打印數組內容,參數直接傳數組  ** @param arr 傳入數組  * @param line 數組行數  * @param length 數組列數  */void print1(int arr[3][5], int line, int length)  
{  for (int i = 0; i < line; i++)  {  for (int j = 0; j < length; j++)  {  printf("%d ", arr[i][j]);  }  printf("\n");  }  
}  /**  * @brief 打印數組內容,傳參傳數組指針  * * @param p   * @param line   * @param length   */  
void print2(int (*p)[5], int line, int length)  
{  for(int i = 0; i < line; i++)  {  for(int j = 0; j < length; j++)  {  printf("%d ", *(*(p + i) + j));  // printf("%d ", (*(p + i))[j]); // 等價于上面的寫法  // 如果寫成 *(p + i)[j],輸出會報錯,因為 [] 的優先級高于 *            printf("%d ", p[i][j]); // 也可以這樣寫  }  printf("\n");  }  
}  int main()  
{  int arr[3][5] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};  // 二維數組的首元素是第一行,在這里為含有 5 個元素的一維數組  print1(arr, 3, 5);  print2(arr, 3, 5); // 將二維數組的首元素傳入函數  return 0;  
}
int *parr1[10];
// 指針數組int(*parr)[10];
// 數組指針int(*parr[5])[10];
// 存放數組指針的數組

一維指針數組傳參
指針數組元素為 指針
指針數組的數組名相當于一個 指針
指針指向存放一個指針的位置 -> 二級指針
因此指針數組傳參可以為二級指針

void test(int **parr);void test1(int *parr[20]);

二維數組通過指針傳參
二維數組的首元素是一維數組,不能用一級/二級指針接收
形參應該是一個一維數組的指針

void test(int *arr);
// errvoid test1(int (*arr)[5]);
// 參數為一個一維數組void test2(int **arr);
// err,二級指針指向存放一級指針的地址,不能是指向一個一維數組的指針

函數指針

指向函數的指針

#include <stdio.h>  int func1(int x, int y)  
{  return x + y;  
}  int main()  
{  printf("%p\n", &func1); // 取地址符得到函數的地址  printf("%p\n", func1); // 對函數來說,&func1 和 func1 是一樣的  int (*p)(int, int) = func1; // 定義一個函數指針  // 返回值類型 (*指針變量名)(參數類型1, 參數類型2, ...);  int ret = (*p)(1, 2); // 通過函數指針調用函數  int ret2 = p(1, 2); // *p 和 p 是一樣的,如果要寫 *p,必須加括號(如果不加括號,p 先和后面結合,* 會被當成解引用操作符對 p(1, 2) 解引用)  // 等價于 int ret = func1(1, 2);    printf("%d\n", ret);    printf("%d\n", ret2);  return 0;  
}

案例

(*(void (*)())0)();
// void (*p)() -> p 是函數指針
// void (*)() -> 函數指針類型
// (void (*)())0 -> 把 0(0x00000000) 強制轉換為函數指針類型(此時把 0 看作一個地址)
// (*(void (*)())0)() -> 調用 0 地址對應的函數
// 即這行代碼為一次函數調用,調用 0 地址的函數
void (*signal(int, void(*)(int)))(int);
// 一次函數聲明
// 聲明的 signal 函數參數 1 類型為 int,參數 2 類型為函數指針,該函數指針指向的函數參數是 int 類型,返回類型為 void
// signal 函數的返回類型為函數指針,該函數指針參數是 int 類型,返回類型為 void// ----------typedef void (*pf_t)(int); // 把 void(*)(int) 類型重命名為 pf_t  
int main()  
{  void (*signal(int, void (*)(int)))(int);  pf_t signal(int, pf_t); // 使用 pf_t 重命名后的類型  return 0;  
}

函數指針的用途

#include <stdio.h>  void menu()  
{  printf("Please select:\n");  printf("1. Add\n");  printf("2. Sub\n");  printf("3. Mul\n");  printf("4. Div\n");  printf("0. Exit\n");  
}  int Add(int x, int y)  
{  return x + y;  
}  int Sub(int x, int y)  
{  return x - y;  
}  int Mul(int x, int y)  
{  return x * y;  
}  int Div(int x, int y)  
{  return x / y;  
}  // 方法 2:將輸入代碼塊放在一個函數中,通過函數指針傳遞給 Calculate 函數(回調函數)
/**
/**  * @brief 接收一個函數指針,通過函數指針調用函數  * * @param pf 函數指針  */void Calculate(int (*pf)(int, int))  
{  printf("Please input two numbers: ");  int num1 = 0;  int num2 = 0;  scanf("%d %d", &num1, &num2);  int ret = pf(num1, num2);  printf("Result: %d\n", ret);  
}  int main()  
{  int choice = 0;  do  {  menu();  printf("Please select: ");  scanf("%d", &choice);  // printf("Please input two numbers: ");  // int num1 = 0;        // int num2 = 0;        // scanf("%d %d", &num1, &num2);        // int ret = 0;        // 輸入代碼塊放在外面,無論選擇什么都要輸入兩個數,不符合邏輯  switch (choice)  {  case 1:  // printf("Please input two numbers: ");  // int num1 = 0;            // int num2 = 0;            // scanf("%d %d", &num1, &num2);            // int ret = 0;            // 方法 1:將每一個輸入涉及的代碼塊放在一個 case 語句中,造成代碼冗余  // ret = Add(num1, num2);  Calculate(Add);  break;  case 2:  // ret = Sub(num1, num2);  Calculate(Sub);  break;  case 3:  // ret = Mul(num1, num2);  Calculate(Mul);  break;  case 4:  // ret = Div(num1, num2);  Calculate(Div);  break;  case 0:  printf("Exit!\n");  break;  default:  printf("Error input!\n");  break;  }  // printf("Result: %d\n", ret);  } while (choice);  return 0;  
}

函數指針數組

把函數指針放在數組中

#include <stdio.h>  int Add(int x, int y)  
{  return x + y;  
}  int Sub(int x, int y)  
{  return x - y;  
}  int Mul(int x, int y)  
{  return x * y;  
}  int Div(int x, int y)  
{  return x / y;  
}  void menu()  
{  printf("Please select:\n");  printf("1. Add\n");  printf("2. Sub\n");  printf("3. Mul\n");  printf("4. Div\n");  printf("0. Exit\n");  
}  int main()  
{  int choice = 0;  // 實現函數跳轉(轉移表)  int(*pfArr[4])(int, int) = {Add, Sub, Mul, Div};  do  {  menu();  scanf("%d", &choice);  if(choice < 0 || choice > 4)  {  printf("Error input!\n");  continue;  }  else if (choice == 0)  {  break;  }  else  {  printf("Please input two numbers: ");  int num1 = 0;  int num2 = 0;  scanf("%d %d", &num1, &num2);  printf("Result: %d\n", pfArr[choice - 1](num1, num2));  }  } while (choice);  printf("Exit!\n");  return 0;  
}

指向函數指針數組的指針

int (*pfarr[])(int, int) = {add, sub, mul, div};  // 指向函數指針數組的指針  
int (*(*pfarr)[5])(int, int)

回調函數

通過函數指針調用的函數(把 A 函數的指針作為參數傳遞給 B 函數,當特定的事件或條件滿足時,由 B 函數調用 A 函數,此時 A 為回調函數)

Qsort 的使用

/**  * @brief 快速排序(庫函數),可以對任意類型的數據進行排序  ** @param base 排序的數據起始位置  * @param nmemb 待排序元素個數  * @param size 待排序元素大小(字節)  * @param compar 函數指針,指向比較函數,e1、e2分別指向待比較的兩個元素,當e1 < e2時,返回負數;當e1 = e2時,返回0;當e1 > e2時,返回正數*/void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void * e1, const void *e2));

回調函數的使用

#include <stdio.h>  
#include <stdlib.h>  /**  * @brief 整形比較函數  ** @param e1 比較的元素1  * @param e2 比較的元素2  * @return int 當e1 < e2時,返回負數;當e1 = e2時,返回0;當e1 > e2時,返回正數  */int compareInt(const void *e1, const void *e2)  
{  return *(int *)e1 - *(int *)e2;  // void *可以接收任意類型的數據,不能解引用,也不能進行運算,需要轉換為具體類型  // 也可以寫成降序排序,return *(int *)e2 - *(int *)e1;  
}  void testFunc()  
{  int arr[] = {9, 8, 7, 6, 5, 4, 3, 2, 1};  int sz = sizeof(arr) / sizeof(arr[0]);  qsort(arr, sz, sizeof(arr[0]), compareInt);  for(int i = 0; i < sz; i++)  {  printf("%d ", arr[i]);  }  
}  struct Stu  
{  char name[20];  int age;  
};  int compareStu(const void *e1, const void *e2)  
{  return ((struct Stu *)e1)->age - ((struct Stu *)e2)->age;  
}  void testFunc2()  
{  struct Stu s[3] = {{"zhangsan", 20}, {"lisi", 30}, {"wangwu", 10}};  int sz = sizeof(s) / sizeof(s[0]);  qsort(s, sz, sizeof(s[0]), compareStu);  for(int i = 0; i < sz; i++)  {  printf("%s %d\n", s[i].name, s[i].age);  }  
}  int main()  
{  testFunc(); // int 類型排序  printf("\n");  testFunc2(); // 結構體類型排序  return 0;  
}

通過冒泡排序模擬實現 qsort

#include <stdio.h>  struct Stu    
{    char name[20];    int age;    
};    int compareStu(const void *e1, const void *e2)    
{    return ((struct Stu *)e1)->age - ((struct Stu *)e2)->age;    
}    int compareInt(const void *e1, const void *e2)  
{  return *(int *)e1 - *(int *)e2;  
}  void swapMem(void *e1, void *e2, size_t width)  
{  char tmp;  for(int i = 0; i < width; i++)  {  tmp = *((char *)e1 + i);  *((char *)e1 + i) = *((char *)e2 + i);  *((char *)e2 + i) = tmp;  }  
}  /**  * @brief 模擬實現 qsort 函數  ** @param arr 待排序數組  * @param sz 待排序元素個數  * @param width 待排序元素大小(字節),由于傳入的是 void * 類型,無法得知具體類型,需要傳入元素大小  * @param compare 比較函數  */void bubbleSort(void *arr, size_t sz, size_t width, int (*compare)(const void *e1, const void *e2))  
{  sz = (int)sz;  width = (int)width;  for(int i = 0; i < sz - 1; i++)  {  for(int j = 0; j < sz - 1 - i; j++)  {  if(compare((char *)arr + j * width, (char *)arr + (j + 1) * width) > 0) // 通過起始位置 + 偏移量來訪問元素  {  swapMem((char *)arr + j * width, (char *)arr + (j + 1) * width, width); // 交換兩個元素  }  }  }  
}  int main()  
{  int arr[] = {9, 8, 7, 6, 5, 4, 3, 2, 1};  int sz = sizeof(arr) / sizeof(arr[0]);  bubbleSort(arr, sz, sizeof(arr[0]), compareInt);  for(int i = 0; i < sz; i++)  {  printf("%d ", arr[i]);  }  printf("\n");  struct Stu s[3] = {{"zhangsan", 20}, {"lisi", 30}, {"wangwu", 10}};  sz = sizeof(s) / sizeof(s[0]);  bubbleSort(s, sz, sizeof(s[0]), compareStu);  for(int i = 0; i < sz; i++)  {  printf("%s %d\n", s[i].name, s[i].age);  }  return 0;  
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/71834.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/71834.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/71834.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

李沐《動手學深度學習》——14.9. 用于預訓練BERT的數據集——wiki數據集問題以及存在的其他問題

問題1&#xff1a;出現"file is not a zip file" 原因是鏈接已經失效。 解決方法&#xff1a;打開下面鏈接自行下載&#xff0c;需要魔法。下載完解壓到特定位置。 下載鏈接&#xff1a;項目首頁 - Wikitext-2-v1數據包下載:Wikitext-2-v1 數據包下載本倉庫提供了一…

【芯片驗證】verificationguide上的36道UVM面試題

跟上一篇一樣,verificationguide上的36到UVM面試題,通義回答ds判卷。 1. What is uvm_transaction, uvm_seq_item, uvm_object, uvm_component? uvm_transaction、uvm_seq_item、uvm_object、uvm_component是什么? uvm_transaction是UVM中所有事務的基礎類,用于表示仿真…

Python 動態規劃(DP)套路總結

Python 動態規劃&#xff08;DP&#xff09;套路總結 在解決算法問題時&#xff0c;動態規劃&#xff08;DP&#xff09; 是一種非常常見的優化技巧&#xff0c;它可以通過保存子問題的結果來避免重復計算&#xff0c;從而減少時間復雜度。Python 提供了非常方便的語法特性&am…

ESP32驅動OV3660攝像頭實現yoloV5物體分類(攝像頭支持紅外夜視、邊緣AI計算)

目錄 1、傳感器特性 2、硬件原理圖 3、驅動程序 ESP32-S3 AI智能攝像頭模塊是一款專為智能家居和物聯網應用打造的高性能邊緣AI開發模組。它集成了攝像頭、麥克風、音頻功放、環境光傳感器和夜視補光燈,無需依賴云端即可實現本地化AI推理。 憑借TensorFlow Lite、YOLO和O…

RReadWriteLock讀寫鎖應用場景

背景 操作涉及一批數據&#xff0c;如訂單&#xff0c;可能存在多個場景下操作&#xff0c;先使用讀鎖&#xff0c;從redis緩存中獲取操作中數據 比如 關閉賬單&#xff0c; 發起調賬&#xff0c; 線下結算&#xff0c; 合并支付 先判斷當前操作的數據&#xff0c;是否在…

網絡安全高級軟件編程技術 網絡安全 軟件開發

安全軟件開發入門 軟件安全問題 有趣的《黑客帝國》終極解釋&#xff1a; 《黑客帝國》故事里面的人物關系&#xff0c;就像電腦里面的各種程序的關系一樣&#xff1a; 電腦里面的系統程序&#xff1a;Matrix&#xff1b; 病毒程序&#xff1a;以Neo為首的人類&#xff1b; 防病…

蘋果商店上架流程,app上架發布流程

蘋果商店地址 https://appstoreconnect.apple.com/login 其他地址:開發 - Apple Developer 1.更新代碼 將項目的代碼更新到最新,更新成功后右下角會給出提示 2.打開模擬器 鼠標右鍵可以選擇設備(Device) 3.測試運行 如下圖可以看到已經識別到設備了,點擊運行即可,運行到模…

正點原子[第三期]Arm(iMX6U)Linux移植學習筆記-2.1 uboot簡介

前言&#xff1a; 本文是根據嗶哩嗶哩網站上“Arm(iMX6U)Linux系統移植和根文件系統構鍵篇”視頻的學習筆記&#xff0c;在這里會記錄下正點原子 I.MX6ULL 開發板的配套視頻教程所作的實驗和學習筆記內容。本文大量引用了正點原子教學視頻和鏈接中的內容。 引用&#xff1a; …

Better-SQLite3 參數綁定詳解

Better-SQLite3 參數綁定詳解 在使用 better-sqlite3 進行數據庫操作時&#xff0c;參數綁定是一個非常重要的概念。它不僅提高了代碼的可讀性和安全性&#xff0c;還能有效防止 SQL 注入攻擊。本文將詳細介紹如何在 better-sqlite3 中使用匿名參數和命名參數&#xff0c;并展…

C++編程:進階階段—4.1封裝

C面向對象的三大特性&#xff1a;封裝、繼承、多態 具有相同性質的對象&#xff0c;抽象為類 4.1 封裝 封裝的意義&#xff1a;將屬性和行為作為一個整體&#xff0c;表現生活中的事物&#xff0c;并將屬性和行為加以權限控制。 4.1.1 類的定義及實例化對象 語法&#xff…

運行OpenManus項目(使用Conda)

部署本項目需要具備一定的基礎&#xff1a;Linux基礎、需要安裝好Anaconda/Miniforge&#xff08;Python可以不裝好&#xff0c;直接新建虛擬環境的時候裝好即可&#xff09;&#xff0c;如果不裝Anaconda或者Miniforge&#xff0c;只裝過Python&#xff0c;需要確保Python是3.…

spring boot + vue 搭建環境

參考文檔&#xff1a;https://blog.csdn.net/weixin_44215249/article/details/117376417?fromshareblogdetail&sharetypeblogdetail&sharerId117376417&sharereferPC&sharesourceqxpapt&sharefromfrom_link. spring boot vue 搭建環境 一、瀏覽器二、jd…

MPPT與PWM充電原理及區別詳解

MPPT&#xff08;最大功率點跟蹤&#xff09;和PWM&#xff08;脈寬調制&#xff09;是太陽能充電控制器中常用的兩種技術&#xff0c;它們在原理、效率和適用場景上有顯著區別。以下是兩者的詳細對比&#xff1a; 1. 工作原理 PWM&#xff08;脈寬調制&#xff09; 核心機制…

slam學習筆記9---ubuntu2004部署interactive_slam踩坑記錄

背景&#xff1a;interactive_slam是一款可用于離線優化點云地圖算法。部署安裝容易出問題&#xff0c;這里記錄一下。 一、安裝基本流程 絕大部分跟著readme走&#xff0c;g2o安裝使用apt安裝 interactive_slam depends on the following libraries:GL3W GLFW Dear ImGui p…

視覺圖像處理

在MATLAB中進行視覺圖像處理仿真通常涉及圖像增強、濾波、分割、特征提取等操作。以下是一個分步指南和示例代碼,幫助您快速入門: 1. MATLAB圖像處理基礎步驟 1.1 讀取和顯示圖像 % 讀取圖像(替換為實際文件路徑) img = imread(lena.jpg); % 顯示原圖 figure; subplot(2…

用java如何利用jieba進行分詞

在Java中使用jieba進行分詞&#xff0c;可以借助jieba的Java版本——jieba-analysis。jieba-analysis是一個基于jieba分詞算法的Java實現&#xff0c;支持精確模式、全模式和搜索引擎模式等多種分詞方式。 以下是使用jieba-analysis進行分詞的詳細步驟和示例代碼&#xff1a; …

【含文檔+PPT+源碼】Python爬蟲人口老齡化大數據分析平臺的設計與實現

項目介紹 本課程演示的是一款Python爬蟲人口老齡化大數據分析平臺的設計與實現&#xff0c;主要針對計算機相關專業的正在做畢設的學生與需要項目實戰練習的 Python學習者。 1.包含&#xff1a;項目源碼、項目文檔、數據庫腳本、軟件工具等所有資料 2.帶你從零開始部署運行本…

【A2DP】SBC 編解碼器互操作性要求詳解

目錄 一、SBC編解碼器互操作性概述 二、編解碼器特定信息元素(Codec Specific Information Elements) 2.1 采樣頻率(Sampling Frequency) 2.2 聲道模式(Channel Mode) 2.3 塊長度(Block Length) 2.4 子帶數量(Subbands) 2.5 分配方法(Allocation Method) 2…

Android雙親委派

下面是一份 Android 類加載器雙親委派機制的時序圖示例&#xff0c;描述了當應用調用 loadClass() 時&#xff0c;各個加載器之間的委派過程。 #mermaid-svg-rBdlhpD2uRjBPiG8 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mer…