尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

C++入门教程:数组、字符串与指针入门

C++入门教程:数组、字符串与指针入门 本文是 C 系列教程的第 4 篇。上一篇讲解了函数与作用域本篇深入讲解数组、字符串和指针一维/多维数组、C 风格字符串与 std::string、指针基础、指针与数组的关系、引用与 const 限定。一、数组1.1 一维数组数组是同类型元素的集合内存中连续存储#includeiostreamusingnamespacestd;intmain(){// 声明与初始化intscores[5];// 未初始化含垃圾值intnums[5]{1,2,3,4,5};// 列表初始化intpartial[5]{1,2};// 其余补 0intautoSize[]{10,20,30};// 自动推导大小为 3// 访问与修改coutnums[0] nums[0]endl;// 1nums[2]100;// 修改第三个元素cout修改后 nums[2] nums[2]endl;// 100// 遍历for(inti0;i5;i){coutnums[i] ;}coutendl;return0;}1.2 数组越界危险#includeiostreamusingnamespacestd;intmain(){intarr[3]{1,2,3};// arr[3] 越界访问编译不报错但行为未定义// 可能读到垃圾值甚至修改其他内存导致崩溃cout越界访问 arr[3] arr[3]未定义行为endl;return0;}数组下标从 0 开始合法范围是 0 ~ 大小-1。C 不检查越界这是很多 bug 的根源。1.3 多维数组#includeiostreamusingnamespacestd;intmain(){// 3x4 二维数组3 行 4 列intmatrix[3][4]{{1,2,3,4},{5,6,7,8},{9,10,11,12}};// 遍历for(inti0;i3;i){for(intj0;j4;j){coutmatrix[i][j]\t;}coutendl;}return0;}1.4 数组与范围 forC11 起可用范围 for 遍历数组#includeiostreamusingnamespacestd;intmain(){intnums[]{5,10,15,20};// 范围 for只读for(intn:nums){coutn ;}coutendl;// 用引用修改元素for(intn:nums){n*2;}for(intn:nums){coutn ;}coutendl;// 10 20 30 40return0;}二、字符串2.1 C 风格字符串#includeiostream#includecstringusingnamespacestd;intmain(){// C 风格字符串以 \0 结尾的字符数组charstr1[]Hello;// 自动加 \0charstr2[]{H,i,\0};// 手动加 \0charstr3[20];// 常用函数strcpy(str3,World);// 复制strcat(str3, C);// 拼接coutstr3 str3endl;// World Ccoutstrlen(str1) strlen(str1)endl;// 5不含\0// 比较if(strcmp(str1,Hello)0){cout相等endl;}return0;}2.2 std::string推荐#includeiostream#includestringusingnamespacestd;intmain(){string s1Hello;string s2 C;// 拼接string s3s1s2;couts3 s3endl;// Hello C// 长度与访问cout长度: s3.length()endl;// 9cout首字符: s3[0]endl;// H// 查找size_t poss3.find(C);if(pos!string::npos){cout找到 C 在位置 posendl;// 6}// 截取子串string subs3.substr(6,3);cout子串: subendl;// C// 比较if(s1s2){couts1 字典序小于 s2endl;}return0;}2.3 string 与 C 字符串互转#includeiostream#includestringusingnamespacestd;intmain(){// string - const char*string sHello;constchar*cstrs.c_str();coutC 字符串: cstrendl;// const char* - stringconstchar*pWorld;string s2p;coutstring: s2endl;return0;}三、指针基础3.1 指针的概念指针是存储地址的变量#includeiostreamusingnamespacestd;intmain(){intnum42;// 声明指针并取地址int*ptrnum;// 取地址* 声明指针coutnum 的值: numendl;// 42coutnum 的地址: numendl;// 如 0x61ff08coutptr 的值: ptrendl;// 同 num 地址coutptr 解引用: *ptrendl;// 42// 通过指针修改值*ptr100;cout修改后 num numendl;// 100return0;}3.2 空指针与野指针#includeiostreamusingnamespacestd;intmain(){int*p1nullptr;// C11 空指针推荐int*p2NULL;// C 风格不推荐int*p30;// 等价于空指针if(p1nullptr){coutp1 是空指针endl;}// 野指针未初始化的指针指向未知地址int*wild;// 未初始化// *wild 10; // 危险解引用野指针是未定义行为// 正确做法使用前必须指向有效内存intvalue5;int*safevalue;cout*safeendl;// 5return0;}3.3 指针的运算#includeiostreamusingnamespacestd;intmain(){intarr[]{10,20,30,40};int*parr;// 数组名退化为首元素地址cout*p *pendl;// 10cout*(p1) *(p1)endl;// 20指针1 跳过 1 个 intcout*(p2) *(p2)endl;// 30// 指针算术与下标等价coutp[1] p[1]endl;// 20cout*(arr1) *(arr1)endl;// 20// 遍历for(int*qarr;qarr4;q){cout*q ;}coutendl;// 10 20 30 40return0;}四、指针与数组的关系4.1 数组名与指针#includeiostreamusingnamespacestd;intmain(){intarr[3]{1,2,3};// 数组名 arr 可视为指向首元素的常量指针coutarr arrendl;// 首地址coutarr[0] arr[0]endl;// 同首地址couta[i] *(ai): (arr[1]*(arr1))endl;// 1相等// 数组名不可被赋值不是真正的变量指针// arr arr[1]; // 错误// 但可以用指针指向数组并移动int*parr;p;// 合法指针可以移动cout*p *pendl;// 2return0;}4.2 指针作为函数参数传数组#includeiostreamusingnamespacestd;// 数组参数退化为指针需要同时传大小intsumArray(intarr[],intsize){intsum0;for(inti0;isize;i){sumarr[i];}returnsum;}// 等价写法int *arrintsumArrayPtr(int*arr,intsize){intsum0;for(inti0;isize;i){sum*(arri);}returnsum;}intmain(){intscores[]{85,90,78,92};cout总分 sumArray(scores,4)endl;// 345cout总分 sumArrayPtr(scores,4)endl;// 345return0;}五、引用5.1 引用基础#includeiostreamusingnamespacestd;intmain(){intnum10;// 引用变量的别名必须初始化且不能改绑intrefnum;ref20;// 通过引用修改原变量coutnum numendl;// 20coutref refendl;// 20// 引用不是独立变量修改引用就是修改原变量intother50;refother;// 这是把 other 的值赋给 num不是让 ref 绑定 othercoutnum numendl;// 50return0;}5.2 指针 vs 引用维度指针引用定义存储地址的变量变量的别名初始化可以不初始化野指针必须初始化重新绑定可以指向其他对象不可改变空值可以为 nullptr不能为空语法需要 * 解引用直接使用适用动态分配、可选对象、数组遍历函数参数、运算符重载六、const 限定6.1 顶层 const 与底层 const#includeiostreamusingnamespacestd;intmain(){intnum10;// 顶层 const指针本身不可变int*constpTopnum;// pTop 不能指向别处*pTop20;// 但可以修改指向的值coutnum numendl;// 20// 底层 const指向的对象不可变constint*pLownum;// 不能通过 pLow 修改值// *pLow 30; // 错误pLownullptr;// 但 pLow 可以指向别处// 同时 constconstint*constpBothnum;// pBoth nullptr; // 错误// *pBoth 30; // 错误return0;}6.2 const 指针传参惯例#includeiostreamusingnamespacestd;// const int* 表示只读访问不修改数组voidprintArray(constintarr[],intsize){for(inti0;isize;i){coutarr[i] ;}coutendl;// arr[0] 99; // 错误const 数组不可修改}intmain(){intdata[]{1,2,3,4};printArray(data,4);// 1 2 3 4return0;}七、实战字符串反转与回文判断综合本篇知识实现字符串处理和回文判断#includeiostream#includestringusingnamespacestd;// 反转字符串用指针实现voidreverseStr(char*str){intlen0;while(str[len]!\0)len;// 求长度char*leftstr;char*rightstrlen-1;while(leftright){chartemp*left;*left*right;*righttemp;left;right--;}}// 判断回文用 std::stringboolisPalindrome(conststrings){intleft0,rights.length()-1;while(leftright){if(s[left]!s[right])returnfalse;left;right--;}returntrue;}intmain(){// 1. 字符数组反转chartext[]HelloWorld;reverseStr(text);cout反转后: textendl;// dlroWolleH// 2. 回文判断string words[]{level,hello,上海自来水来自海上};for(conststringw:words){cout\w\ (isPalindrome(w)?是回文:不是回文)endl;}return0;}运行示例反转后: dlroWolleH level 是回文 hello 不是回文 上海自来水来自海上 是回文总结本篇讲解了数组一维/多维/范围 for、字符串C 风格与 std::string、指针基础地址/解引用/运算/野指针、指针与数组的关系、引用与指针的区别、const 限定顶层/底层并用字符串反转和回文判断串联实战。重点掌握数组越界的危害、std::string 的常用操作、指针算术、引用与指针的选择。下一篇将讲解结构体、枚举与类初探正式进入面向对象世界敬请期待
返回列表