讲解两个小点scanf和scanf_s的区别字符串输入scanf是C语言的标准输入输出,scanf_s是微软为C语言提供的安全增强版本两种用法#include stdio.h int main() { // 1. 读取数值类型int/float/double int num; printf(输入一个整数); scanf(%d, num); // 数值类型需传变量地址 printf(你输入的整数是%d\n, num); // 2. 读取字符串风险点无长度限制输入过长会溢出 char str[10]; printf(输入一个字符串scanf); scanf(%s, str); // 字符串无需数组名本身是地址 printf(scanf读取的字符串%s\n, str); return 0; }#include stdio.h #include stdlib.h // 可选用于处理错误码 int main() { // 1. 读取数值类型和scanf完全一致 int num; printf(输入一个整数); scanf_s(%d, num); printf(你输入的整数是%d\n, num); // 2. 读取字符串必须传「数组长度」作为额外参数 char str[10]; printf(输入一个字符串scanf_s); // 格式scanf_s(%s, 字符串变量, 字符串长度); int ret scanf_s(%s, str, (unsigned)_countof(str)); // _countof获取数组长度 if (ret ! 1) { // 检查是否读取成功 printf(输入错误/字符串过长\n); exit(1); } printf(scanf_s读取的字符串%s\n, str); // 3. 读取单个字符也需传长度固定为1 char ch; printf(输入一个字符); scanf_s(%c, ch, 1); // 字符必须传长度1 printf(你输入的字符是%c\n, ch); return 0; }字符串输入c语言中原本没有字符串类型字字符串是以\0结尾的字符数组本质上都是用户输入的字符输入到字符数组中并自动补充\0的或者是手动补充基础的字符串输入方式scanf#include stdio.h int main() { // 定义字符数组长度要留1位给 \0 char str[50]; printf(请输入一个单词无空格); // 注意str 前面不需要加 因为数组名本身就是地址 scanf(%s, str); printf(你输入的内容是%s\n, str); return 0; }当输入的是hello输出的是hello而当输入hello world的时候输出的还是hello。读取含空格的字符串fgets();#include stdio.h int main() { char str[50]; printf(请输入一句话可含空格); // fgets(字符数组, 最大读取长度, 输入源) // stdin 表示从控制台输入 fgets(str, sizeof(str), stdin); printf(你输入的内容是%s, str); return 0; }这时输入hello world的时候就输出的是hello worldfgets函数会将用户输入的\n也读取进来比如hello world回车数组中就是hello world\n\0#include stdio.h int main() { int age; // 存储年龄数字 char hobby[50]; // 存储爱好字符串可含空格 // 1. 先用scanf读取数字 printf(请输入你的年龄); scanf(%d, age); // 输入数字后按回车回车符会留在输入缓冲区 // 2. 再用fgets读取字符串 printf(请输入你的爱好可含空格); fgets(hobby, sizeof(hobby), stdin); // 直接读取到缓冲区里的回车符不会等你输入 // 输出结果 printf(你的年龄%d\n, age); printf(你的爱好%s, hobby); // 这里会直接输出空行因为hobby里只有回车符 return 0; }输入年龄20 后再次输入爱好games打印的结果是20 和空为什么会有这样的结果呢?当我们输入20的时候会将回车也输入进去fgets会将缓冲区中的\n读取不会等待输入爱好所以hobby输出的是空行解决这个问题的方法就是在scanf后面加上getchar将换行符读取了。getchar();这个函数会读取缓冲区中的一个字符。int a10; const int b20; int arr[a]{0}; int arr[b]{0};在上面的代码中当我们在c下编译的时候都编译不通过原因是在c中将const变量也视为变量不能作为数组的长度。而在c中可以int arr[b]{0}是可以编译通过的将他视为常量处理编译的时候直接将b替换成20来处理。int n1 5; const int n2 10; int arr[n2]{ 0 }; //c修改const变量时必须进行转换 int* n2p const_castint*(n2); *n2p 100; cout n2; cout *n2p;const和指针int main() { int a10,b20; int *p1a; const int *p2b; int *const p3a; const int * const p4a; }int main() { // 1. 定义普通整型变量a10b20都有可读写权限 int a10,b20; // 2. 普通指针 p1指向变量a的地址 int *p1a; /* 特性 - 无const修饰p1本身可修改能指向其他地址指向的内容也可修改 - 合法操作p1b; *p130; - 核心权限最大可改指针指向、可改指向的内容 */ // 3. const修饰「指向的内容」的指针 p2指向变量b的地址 const int *p2b; /* 特性 - const在*前 → 修饰「指针指向的内容」即*p2内容只读、指针可改 - 合法操作p2a; 指针换指向 - 非法操作*p230; 不能通过p2修改b的值编译器报“只读内容”错 - 核心仅限制“修改内容”不限制“换指向” */ // 4. const修饰「指针本身」的指针 p3指向变量a的地址 int *const p3a; /* 特性 - const在*后 → 修饰「指针p3本身」指针只读、内容可改 - 必须初始化这里a否则编译器报错只读变量无法后续赋值 - 合法操作*p340; 修改a的值 - 非法操作p3b; 不能换指向编译器报“只读指针”错 - 核心仅限制“换指向”不限制“修改内容” */ // 5. const同时修饰「内容指针」的指针 p4指向变量a的地址 const int * const p4a; /* 特性 - const在*前 *后 → 双重只读内容只读、指针也只读 - 必须初始化这里a否则编译器报错 - 合法操作仅能读取 → printf(%d, *p4); - 非法操作*p450; 改内容、p4b; 换指向两者都报错 - 核心权限最小只能读不能改任何东西 */ }总结const 在 * 前 → 内容不可改const 在 * 后 → 指针不可改。
const关键字
讲解两个小点scanf和scanf_s的区别字符串输入scanf是C语言的标准输入输出,scanf_s是微软为C语言提供的安全增强版本两种用法#include stdio.h int main() { // 1. 读取数值类型int/float/double int num; printf(输入一个整数); scanf(%d, num); // 数值类型需传变量地址 printf(你输入的整数是%d\n, num); // 2. 读取字符串风险点无长度限制输入过长会溢出 char str[10]; printf(输入一个字符串scanf); scanf(%s, str); // 字符串无需数组名本身是地址 printf(scanf读取的字符串%s\n, str); return 0; }#include stdio.h #include stdlib.h // 可选用于处理错误码 int main() { // 1. 读取数值类型和scanf完全一致 int num; printf(输入一个整数); scanf_s(%d, num); printf(你输入的整数是%d\n, num); // 2. 读取字符串必须传「数组长度」作为额外参数 char str[10]; printf(输入一个字符串scanf_s); // 格式scanf_s(%s, 字符串变量, 字符串长度); int ret scanf_s(%s, str, (unsigned)_countof(str)); // _countof获取数组长度 if (ret ! 1) { // 检查是否读取成功 printf(输入错误/字符串过长\n); exit(1); } printf(scanf_s读取的字符串%s\n, str); // 3. 读取单个字符也需传长度固定为1 char ch; printf(输入一个字符); scanf_s(%c, ch, 1); // 字符必须传长度1 printf(你输入的字符是%c\n, ch); return 0; }字符串输入c语言中原本没有字符串类型字字符串是以\0结尾的字符数组本质上都是用户输入的字符输入到字符数组中并自动补充\0的或者是手动补充基础的字符串输入方式scanf#include stdio.h int main() { // 定义字符数组长度要留1位给 \0 char str[50]; printf(请输入一个单词无空格); // 注意str 前面不需要加 因为数组名本身就是地址 scanf(%s, str); printf(你输入的内容是%s\n, str); return 0; }当输入的是hello输出的是hello而当输入hello world的时候输出的还是hello。读取含空格的字符串fgets();#include stdio.h int main() { char str[50]; printf(请输入一句话可含空格); // fgets(字符数组, 最大读取长度, 输入源) // stdin 表示从控制台输入 fgets(str, sizeof(str), stdin); printf(你输入的内容是%s, str); return 0; }这时输入hello world的时候就输出的是hello worldfgets函数会将用户输入的\n也读取进来比如hello world回车数组中就是hello world\n\0#include stdio.h int main() { int age; // 存储年龄数字 char hobby[50]; // 存储爱好字符串可含空格 // 1. 先用scanf读取数字 printf(请输入你的年龄); scanf(%d, age); // 输入数字后按回车回车符会留在输入缓冲区 // 2. 再用fgets读取字符串 printf(请输入你的爱好可含空格); fgets(hobby, sizeof(hobby), stdin); // 直接读取到缓冲区里的回车符不会等你输入 // 输出结果 printf(你的年龄%d\n, age); printf(你的爱好%s, hobby); // 这里会直接输出空行因为hobby里只有回车符 return 0; }输入年龄20 后再次输入爱好games打印的结果是20 和空为什么会有这样的结果呢?当我们输入20的时候会将回车也输入进去fgets会将缓冲区中的\n读取不会等待输入爱好所以hobby输出的是空行解决这个问题的方法就是在scanf后面加上getchar将换行符读取了。getchar();这个函数会读取缓冲区中的一个字符。int a10; const int b20; int arr[a]{0}; int arr[b]{0};在上面的代码中当我们在c下编译的时候都编译不通过原因是在c中将const变量也视为变量不能作为数组的长度。而在c中可以int arr[b]{0}是可以编译通过的将他视为常量处理编译的时候直接将b替换成20来处理。int n1 5; const int n2 10; int arr[n2]{ 0 }; //c修改const变量时必须进行转换 int* n2p const_castint*(n2); *n2p 100; cout n2; cout *n2p;const和指针int main() { int a10,b20; int *p1a; const int *p2b; int *const p3a; const int * const p4a; }int main() { // 1. 定义普通整型变量a10b20都有可读写权限 int a10,b20; // 2. 普通指针 p1指向变量a的地址 int *p1a; /* 特性 - 无const修饰p1本身可修改能指向其他地址指向的内容也可修改 - 合法操作p1b; *p130; - 核心权限最大可改指针指向、可改指向的内容 */ // 3. const修饰「指向的内容」的指针 p2指向变量b的地址 const int *p2b; /* 特性 - const在*前 → 修饰「指针指向的内容」即*p2内容只读、指针可改 - 合法操作p2a; 指针换指向 - 非法操作*p230; 不能通过p2修改b的值编译器报“只读内容”错 - 核心仅限制“修改内容”不限制“换指向” */ // 4. const修饰「指针本身」的指针 p3指向变量a的地址 int *const p3a; /* 特性 - const在*后 → 修饰「指针p3本身」指针只读、内容可改 - 必须初始化这里a否则编译器报错只读变量无法后续赋值 - 合法操作*p340; 修改a的值 - 非法操作p3b; 不能换指向编译器报“只读指针”错 - 核心仅限制“换指向”不限制“修改内容” */ // 5. const同时修饰「内容指针」的指针 p4指向变量a的地址 const int * const p4a; /* 特性 - const在*前 *后 → 双重只读内容只读、指针也只读 - 必须初始化这里a否则编译器报错 - 合法操作仅能读取 → printf(%d, *p4); - 非法操作*p450; 改内容、p4b; 换指向两者都报错 - 核心权限最小只能读不能改任何东西 */ }总结const 在 * 前 → 内容不可改const 在 * 后 → 指针不可改。