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

资讯详情

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

C++零基础入门:从Hello World到函数与数组的编程核心

C++零基础入门:从Hello World到函数与数组的编程核心 1. 从“Hello World”到理解程序骨架如果你刚打开电脑面对一个空白的代码编辑器心里琢磨着“C到底是个啥我该怎么开始”那咱们就从这里聊起。别被“零基础”吓到也别被“万字解析”唬住编程本质上就是和计算机对话而C是其中一种非常强大但也相对严谨的语言。咱们不扯那些“面向对象”、“编译原理”的复杂概念先来点最实在的让屏幕对你“说”句话。打开你的代码编辑器比如VS Code新建一个文件就叫hello.cpp。然后一字不差地输入下面这几行#include iostream int main() { std::cout Hello, World! std::endl; return 0; }敲完保存。现在你有了人生中第一个C程序。但先别急着运行咱们得掰开揉碎了看看这几行代码到底在干嘛。这比你直接看到黑窗口里蹦出几个字重要得多。第一行#include iostream。你可以把它想象成“搬救兵”。iostream是“输入输出流”的缩写它就像一个工具箱里面装着cout用来输出和cin用来输入这些工具。#include就是告诉编译器“嘿去把那个叫iostream的工具箱给我拿过来我等会儿要用里面的工具。” 没有这行下面的std::cout编译器就不认识会报错。接下来是int main() { ... }。这是每个C程序的心脏是程序开始执行的起点。你可以把它理解为一个固定的仪式入口。int表示这个“仪式”函数执行完后会返回一个整数通常是0表示一切正常。main是它的名字这个名字是固定的不能改成别的。后面的一对花括号{ }就像一个大口袋里面装着这个仪式要做的所有具体事情。口袋里装了两条指令。第一条是std::cout Hello, World! std::endl;。std::cout是那个从iostream工具箱里拿出来的“输出工具”。这个符号很像箭头意思是“把右边的东西送到左边去”。所以std::cout Hello, World!就是把双引号里的字符串“Hello, World!”送到标准输出通常是你的电脑屏幕。后面的 std::endl是再送一个“换行符”相当于你在键盘上按了一下回车这样光标会跳到下一行让输出看起来更整洁。最后的分号;是C语句的结束标志就像我们写句子要打句号一样必不可少。第二条指令是return 0;。这对应着int main()开头说的要返回一个整数。返回0是约定俗成的表示“程序正常结束没出岔子”。如果程序中途崩溃或者遇到严重错误可能会返回其他非零值。现在你可以尝试运行它了。怎么运行这涉及到“编译”和“运行”两个步骤。简单理解你刚写的hello.cpp是“源代码”是人类你能看懂的文本。但计算机CPU只认识0和1组成的机器码。所以需要一个“翻译官”编译器把你的源代码翻译成计算机能直接执行的“可执行文件”。对于新手最省事的方法是使用集成开发环境IDE比如Code::Blocks、Dev-C或者Visual Studio社区版免费。它们通常有一个大大的“运行”或“编译并运行”按钮一键搞定所有事。如果你用的是VS Code则需要稍微配置一下。你需要先安装一个C编译器比如MinGW-w64Windows或GCCLinux/macOS通常自带。然后在VS Code里安装“C/C”扩展。之后你可以打开终端Terminal进入到hello.cpp所在的文件夹输入命令g hello.cpp -o hello进行编译。这条命令的意思是调用g编译器把hello.cpp这个源文件编译-o指定输出文件名成一个叫helloWindows下是hello.exe的可执行文件。编译成功后再输入./helloLinux/macOS或hello.exeWindows来运行它。当你第一次在屏幕上看到“Hello, World!”时恭喜你你不仅完成了一个仪式更重要的是你理解了构成C程序最基础的几个要素包含头文件、主函数、输入输出语句、编译运行流程。这个简单的程序就是所有复杂程序的雏形。注意很多新手会在这里卡住问题往往出在“环境配置”。如果编译报错“g不是内部或外部命令”说明你的编译器没有正确安装或者它的路径没有添加到系统的环境变量PATH中。这是入门的第一道坎耐心搜索“如何安装配置MinGW”或“VS Code配置C环境”照着图文教程一步步做一定能解决。2. 变量与数据类型给信息一个“家”和“形状”程序不能只会说“Hello World”它得能处理信息比如计算你的游戏得分、存储用户的名字、判断一个开关的状态。这就需要用到变量和数据类型。你可以把变量想象成一个带标签的盒子标签就是变量名盒子里装的就是数据。而数据类型则规定了盒子的“形状”和“容量”——这个盒子是专门装整数的还是装小数的还是装单个字符的C提供了几种基础的数据类型咱们先认识最常用的几个int(整型)用来存放整数比如-10,0,100。它就像一个小号收纳盒能装的整数范围有限通常是-2^31到2^31-1。float/double(浮点型)用来存放小数。float是单精度浮点数double是双精度浮点数后者能表示的范围更大、精度更高。一般用double就够了比如3.14159,-0.5。char(字符型)用来存放单个字符比如A,b,9,#。注意字符必须用单引号括起来。bool(布尔型)只有两个值true(真) 和false(假)。用于逻辑判断。string(字符串型)这不是基础类型但极其常用。它来自string这个“工具箱”用来存放一串文本比如Hello,张三。字符串用双引号括起来。声明和初始化变量就是创建盒子并往里放东西的过程。语法是数据类型 变量名 初始值;。看几个例子#include iostream #include string // 使用string类型需要包含这个头文件 int main() { // 声明并初始化变量 int age 25; // 一个叫age的盒子里面装了整数25 double price 99.8; // 价格小数 char grade A; // 等级单个字符 bool isPassed true; // 是否通过布尔值 std::string name Alice; // 名字字符串。注意前面的std:: // 使用变量可以直接用变量名来访问盒子里的值 std::cout Name: name std::endl; std::cout Age: age std::endl; std::cout Price: $ price std::endl; std::cout Grade: grade std::endl; std::cout Passed? (isPassed ? Yes : No) std::endl; // 三目运算符后面会讲 // 也可以先声明后赋值 int score; score 95; // 赋值 std::cout Score: score std::endl; // 变量的值可以改变 age 26; // 过了一年age盒子里的值更新为26 std::cout Next year, age will be: age std::endl; return 0; }这里有几个关键点需要注意命名规则变量名只能包含字母、数字和下划线且不能以数字开头。区分大小写age和Age是两个不同的变量。最好起有意义的英文名字比如userAge而不是a。作用域变量在哪个花括号{}内声明一般就只能在这个范围内使用。在main函数开头声明的变量可以在整个main函数里使用。std::前缀cout、endl、string这些标准库里的东西通常都住在std这个“命名空间”里。std::就像是它们的姓氏用来避免重名。你也可以在文件开头加一行using namespace std;这样后面就可以直接写cout、string而不用加std::了。但对于新手我建议初期还是加上std::这能让你更清楚代码的来源是好习惯。常量顾名思义就是值不能改变的“盒子”。用const关键字来声明。一旦初始化再试图修改就会编译报错。const double PI 3.1415926; // 圆周率常量 // PI 3.14; // 错误不能修改常量的值理解变量和数据类型是编写任何有实际功能程序的基础。接下来我们就要让这些数据“动”起来进行运算和判断。3. 运算符与流程控制让程序“思考”和“选择”程序如果只能按顺序一行行执行那也太笨了。我们需要让它能进行计算、能根据条件走不同的路、能重复做某些事情。这就是运算符和流程控制语句的作用。3.1 运算符数据的加工厂运算符就是对数据进行操作的符号。C提供了丰富的运算符算术运算符加,-减,*乘,/除,%取模求余数。注意整数相除结果还是整数会舍弃小数部分。5 / 2结果是2不是2.5。想得到小数至少有一个操作数是小数如5.0 / 2。关系运算符用于比较结果是bool类型true或false。包括等于,!不等于,大于,小于,大于等于,小于等于。特别注意判断相等是双等号单个等号是赋值这是新手最容易犯的错误之一。逻辑运算符用于组合多个条件。逻辑与两个条件都为真才为真||逻辑或至少一个为真就为真!逻辑非取反。赋值运算符最基本的。还有复合赋值运算符如,-,*,/它们更简洁。a 5;等价于a a 5;。自增自减运算符和--。i后置自增表示先使用i的值然后i加1i前置自增表示先给i加1然后使用新的i值。自减同理。int a 10, b 3; int sum a b; // 13 int quotient a / b; // 3 (整数除法) double accurateQuotient static_castdouble(a) / b; // 3.33333... 强制类型转换 bool isEqual (a 10); // true bool isGreater (a b); // true bool logicTest (a 5) (b 5); // true true true int count 0; count; // count 变为 1 count; // count 变为 2 int x count; // x 2, 然后 count 变为 3 (后置) int y count; // count 先变为 4, 然后 y 4 (前置)3.2 条件判断if-else 与 switch程序需要根据不同的情况做出选择这就需要条件判断语句。if-else 语句是最常用的。它的逻辑非常直白“如果……那么……否则……”。#include iostream int main() { int score; std::cout 请输入你的分数 (0-100): ; std::cin score; // 从键盘读取一个整数到score变量 if (score 90) { std::cout 优秀 std::endl; } else if (score 80) { // 注意是 else if不是 elseif std::cout 良好。 std::endl; } else if (score 60) { std::cout 及格。 std::endl; } else { std::cout 不及格需要努力。 std::endl; } // 简单的if语句 if (score 100) { std::cout 满分太棒了 std::endl; } return 0; }switch 语句适用于对一个变量的多个离散值进行判断比一连串的if-else if更清晰。#include iostream int main() { char grade; std::cout 请输入等级 (A, B, C, D, F): ; std::cin grade; switch (grade) { case A: case a: // case可以穿透A和a执行同样的代码 std::cout 优秀 std::endl; break; // break非常重要用来跳出switch否则会继续执行后面的case case B: case b: std::cout 良好。 std::endl; break; case C: case c: std::cout 中等。 std::endl; break; case D: case d: std::cout 及格。 std::endl; break; case F: case f: std::cout 不及格。 std::endl; break; default: // 所有case都不匹配时执行 std::cout 无效的等级输入。 std::endl; break; } return 0; }提示switch只能用于整型int,char等或枚举类型不能用于string或float。break语句在switch中至关重要漏写break会导致“case穿透”这是一个常见的错误来源。3.3 循环让重复劳动自动化当我们需要重复执行某段代码时循环就派上用场了。C主要有三种循环for,while,do-while。for 循环当你明确知道要循环多少次时用for最合适。它的结构很清晰for (初始化; 循环条件; 更新) { 循环体 }。// 计算1到100的和 int sum 0; for (int i 1; i 100; i) { // i从1开始只要i100就执行循环每次循环后i加1 sum i; // 等价于 sum sum i; } std::cout 1到100的和是: sum std::endl; // 输出5050 // 嵌套循环打印九九乘法表 for (int i 1; i 9; i) { for (int j 1; j i; j) { // 内层循环j最大到i std::cout j x i i*j \t; // \t是制表符用于对齐 } std::cout std::endl; // 每行结束后换行 }while 循环当循环次数不确定取决于某个条件是否满足时用while。先判断条件再执行循环体。// 猜数字游戏 #include iostream #include cstdlib // 用于rand()和srand() #include ctime // 用于time() int main() { srand(time(0)); // 用当前时间设置随机数种子确保每次运行结果不同 int secretNumber rand() % 100 1; // 生成1-100的随机数 int guess 0; int attempts 0; std::cout 我已经想好了一个1到100之间的数字猜猜看 std::endl; while (guess ! secretNumber) { std::cout 请输入你的猜测: ; std::cin guess; attempts; if (guess secretNumber) { std::cout 太大了 std::endl; } else if (guess secretNumber) { std::cout 太小了 std::endl; } } std::cout 恭喜你猜对了你用了 attempts 次。 std::endl; return 0; }do-while 循环和while类似但它是先执行一次循环体再判断条件。所以循环体至少会执行一次。// 至少执行一次的菜单选择 char choice; do { std::cout \n 菜单 std::endl; std::cout 1. 开始游戏 std::endl; std::cout 2. 加载存档 std::endl; std::cout 3. 退出 std::endl; std::cout 请选择 (1-3): ; std::cin choice; switch (choice) { case 1: /* 开始游戏 */ break; case 2: /* 加载存档 */ break; case 3: std::cout 再见 std::endl; break; default: std::cout 无效选择请重试。 std::endl; } } while (choice ! 3); // 只要不选3就继续显示菜单 return 0;循环控制语句break用于立即跳出整个循环。continue用于跳过本次循环剩余的语句直接进入下一次循环的条件判断。// 找1-100中第一个能被7整除的数 for (int i 1; i 100; i) { if (i % 7 0) { std::cout 找到了: i std::endl; break; // 找到第一个就跳出循环 } } // 打印1-10之间的奇数 for (int i 1; i 10; i) { if (i % 2 0) { continue; // 如果是偶数跳过本次循环不执行下面的cout } std::cout i ; } // 输出: 1 3 5 7 9掌握了运算符和流程控制你的程序就具备了基本的逻辑能力。接下来我们需要一种方式来组织更复杂的数据和操作这就是函数和数组。4. 函数与数组模块化与批量处理当代码越来越长把所有逻辑都堆在main函数里会变得难以阅读和维护。函数和数组是两种重要的代码组织工具。4.1 函数可复用的代码块函数是一段为了完成特定任务而封装起来的代码。你可以给它起个名字函数名可以给它一些输入参数它可以返回一个结果返回值。使用函数的好处是代码复用和逻辑清晰。一个函数主要包括以下几个部分返回类型函数执行完后返回的数据类型。如果不需要返回值用void。函数名遵循和变量名类似的命名规则最好用动词或动宾短语如calculateSum,printMessage。参数列表放在括号里是函数接收外部数据的入口。可以有零个或多个参数每个参数都需要指定类型。函数体花括号{}里的代码块是函数具体执行的逻辑。返回值使用return语句将结果返回给调用者。对于void函数return可以省略或者用return;提前结束函数。定义和调用函数#include iostream #include cmath // 包含数学函数如pow() // 1. 定义一个计算两个整数最大值的函数 int getMax(int a, int b) { // 返回类型int函数名getMax两个int型参数a和b if (a b) { return a; // 返回较大的值 } else { return b; } // 也可以写成: return (a b) ? a : b; } // 2. 定义一个打印欢迎信息的函数无返回值 void printWelcome(std::string userName) { // 返回类型void参数是string std::cout 欢迎你, userName ! std::endl; // void函数可以没有return语句或者只写 return; } // 3. 定义一个计算x的n次方的函数 double power(double x, int n) { double result 1.0; for (int i 0; i n; i) { result * x; // result result * x; } return result; } int main() { // 调用函数 int num1 10, num2 20; int maxVal getMax(num1, num2); // 调用getMax传入num1和num2返回值赋给maxVal std::cout 最大值是: maxVal std::endl; // 输出 20 printWelcome(初学者); // 调用printWelcome传入字符串初学者 double base 2.0; int exponent 3; double powResult power(base, exponent); // 计算2的3次方 std::cout base 的 exponent 次方是: powResult std::endl; // 输出 8 // 也可以使用标准库里的数学函数 double stdPow std::pow(base, exponent); std::cout 使用std::pow: stdPow std::endl; return 0; }函数声明原型如果函数定义在main函数之后编译器在main里看到函数调用时会不认识它。这时需要在文件开头或头文件中先进行函数声明告诉编译器这个函数长什么样返回类型、函数名、参数类型具体实现稍后再说。#include iostream // 函数声明原型 int add(int x, int y); void greet(); int main() { int sum add(5, 3); // 编译器看到声明知道add函数的存在允许调用 std::cout 和是: sum std::endl; greet(); return 0; } // 函数定义实现 int add(int x, int y) { return x y; } void greet() { std::cout Hello from function! std::endl; }4.2 数组同一类型数据的集合当你需要处理大量同类型数据时比如100个学生的成绩为每个学生都定义一个变量score1,score2, ...,score100是不现实的。这时就需要数组。数组是一种数据结构它可以在一个变量名下存储多个相同类型的值并通过索引下标来访问每个值。声明和初始化数组// 声明一个可以存放5个整数的数组 int scores[5]; // 数组名为scores大小为5索引从0到4 // 初始化数组声明时赋值 int numbers[5] {10, 20, 30, 40, 50}; // 完全初始化 int partial[5] {1, 2, 3}; // 部分初始化剩余元素自动为0 int autoSize[] {1, 2, 3, 4, 5}; // 编译器自动推断数组大小为5 // 访问数组元素数组名[索引] scores[0] 95; // 给第一个元素索引0赋值 scores[1] 87; int firstScore scores[0]; // 读取第一个元素的值 // 遍历数组通常用for循环 for (int i 0; i 5; i) { std::cout scores[ i ] scores[i] std::endl; }数组的注意事项索引从0开始这是编程界的惯例。一个大小为N的数组有效索引是0到N-1。越界访问是危险的访问scores[5]或scores[-1]属于数组越界程序可能会崩溃或者读取到垃圾数据这是非常常见的错误。数组大小必须是编译时常量在标准C中定义数组时大小必须是已知的常数不能是变量。例如int n10; int arr[n];在某些编译器如GCC扩展下可能允许但不是标准做法。更灵活的动态数组vector我们后面会讲。数组与函数的结合数组可以作为函数的参数传递。但这里有一个关键点当数组作为函数参数时它通常会“退化”为指向其首元素的指针。因此我们通常需要额外传递数组的大小。#include iostream // 函数打印整型数组的所有元素 void printArray(int arr[], int size) { // arr[] 实际上是一个指针 for (int i 0; i size; i) { std::cout arr[i] ; } std::cout std::endl; } // 函数计算数组元素的平均值 double calculateAverage(double arr[], int size) { double sum 0.0; for (int i 0; i size; i) { sum arr[i]; } return (size 0) ? (sum / size) : 0.0; // 防止除零错误 } int main() { int myArray[] {1, 2, 3, 4, 5}; int arrSize sizeof(myArray) / sizeof(myArray[0]); // 计算数组元素个数 printArray(myArray, arrSize); // 输出: 1 2 3 4 5 double temps[] {22.5, 23.1, 19.8, 25.0}; int tempSize sizeof(temps) / sizeof(temps[0]); double avgTemp calculateAverage(temps, tempSize); std::cout 平均温度: avgTemp std::endl; return 0; }注意sizeof(myArray)返回的是整个数组占用的字节数sizeof(myArray[0])返回的是第一个元素占用的字节数。两者相除就得到了数组的元素个数。这个方法只在数组定义的作用域内有效。如果数组被传递给函数在函数内部sizeof(arr)得到的是指针的大小而不是数组的大小所以必须在函数外计算好大小再传进去。函数和数组是构建复杂程序的基础模块。通过函数我们把大问题分解成小任务通过数组我们高效地管理批量数据。理解了它们你就已经迈过了C入门中最核心的门槛。接下来我们将进入更抽象但也更强大的领域面向对象编程。
返回列表