
10.2
一
关于EOF:
在C语言编程中,while 是一种常用的循环结构,可以让我们重复执行特定的代码块,直到满足某个条件为止。其中一种常见的应用场景是使用 EOF(End of File)作为循环结束的条件,这种方法特别适用于处理文件输入或用户输入的情况,让程序能够持续读取数据,直到遇到文件结束或用户输入结束为止。
EOF 是一个特殊的值,通常定义在 头文件中,表示“文件结束”或“输入结束”的状态。在大多数系统中,EOF 的值为 -1。当我们使用输入函数(如 scanf()、getchar() 等)读取数据时,如果遇到文件结束或输入结束的情况,这些函数会返回 EOF 值。
如下例:
#include<stdio.h>
int main(void)
{
int n;
while(scanf("%d",&n)!=EOF)
{
printf("%d",n);
}
return 0;
}
该例子使用了EOF实现了读取并输出任意次用户输入,直至读取到EOF。
值得注意的是,使用 EOF 作为循环结束条件时,我们需要注意一些潜在的陷阱:
- 在某些系统上,EOF 可能不是 -1,因此,最好使用 EOF 常量而不是直接使用 -1。
- 当从文件读取数据时,到达文件末尾会触发 EOF,但从标准输入读取时,用户需要手动触发 EOF,在Linux中是 Ctrl+D ,在Windows中 Ctrl+Z(在VS Code中要连续三次输入Ctrl+Z+Enter)。
- 在处理二进制数据时,要小心使用 EOF 作为结束条件,因为 -1 可能是有效的数据值。
- 在网络编程中,EOF 可能表示连接关闭,而不仅仅是数据结束。
总的来说,使用 EOF 作为 while 循环的结束条件,允许我们创建能够处理不定长输入的程序,无论是从文件还是用户输入。
10.3
一
关于结构体:
结构体是C语言提供的一种复合数据类型。
结构体可以将多个不同类型的数据组织在一起,形成一个新的数据类型。这些数据可以是基本数据类型(如 int、float、char 等),也可以是其他的结构体类型。每个数据在结构体中被称为成员或者字段。通过结构体,我们可以将所有相关的数据打包成一个整体,更好地表达数据之间的逻辑关系。
要使用结构体,需要先定义结构体类型,它的基本语法格式如下:
struct 结构体名称
{成员类型1 成员名称1;成员类型2 成员名称2;...成员类型n 成员名称n;};//注意最后要加分号
struct 是定义结构体的关键字,结构体名称用于标识这个新的数据类型,花括号内部包含了若干成员变量的声明。每个成员变量都有自己的类型和名称,它们之间用分号分隔。
注意,为了和变量名、函数名进行区分,结构体名的首字母一般要大写。
结构体是一种类型,而不是变量,不能赋值;定义了结构体类型后,还需要声明结构体变量才能使用。
声明结构体变量有两种方式:先定义类型再声明变量,或者在定义类型的同时声明变量。
// 方式 1:先定义类型,再声明结构体变量
struct Student s1; //使用了已经定义的结构体类型 Student
// 方式 2:定义类型的同时声明结构体变量
struct Student{char name[50];int id;int age;float score;} s1, s2;
结构体变量的成员可以在声明时初始化,也可以在声明后单独赋值。初始化时要注意成员的顺序必须与定义时的顺序一致。
// 声明时初始化
struct Student s1 = {"张三", 10001, 18, 85.5};
// 声明后单独赋值,例子中使用了.访问结构体中的变量
struct Student s2;
strcpy(s2.name, "李四"); // 字符数组不能直接赋值,需要使用 strcpy
s2.id = 10002;
s2.age = 19;
s2.score = 92.5;
如果是结构体变量,可以使用点运算符.访问结构体成员;如果是结构体指针,则使用箭头运算符->访问结构体成员。
结构体变量之间可以直接赋值,这将复制所有成员的值,也即把一个结构体的内存直接拷贝给另一个结构体。
但是需要注意,这是一种浅拷贝,如果结构体中包含指针成员,赋值操作只会复制指针的值,而不会复制指针指向的数据,这种情况下需要手动进行深拷贝。
二
关于格式字符:
10.15
一
关于getline()函数:
使用cin和>>来获取输入,只会从第一个非空白字符开读入,到第一个空白字符结束。
想要获取包含空格的输入,可以使用getline()函数。该函数包括在头文件string中,会读取在换行符之前的字符。其使用格式如下所示:
getline(std::cin,example)//example是接收字符串的string变量名称。
二
关于foreach循环:
10.16
一
关于reverse()函数:
reverse()函数定义在头文件algorithm中,可以用于反转一个序列中的元素(如将 1 3 3 1 5 变为 5 1 3 3 1 )。
如下例所示:
#include<iostream>
#include<algorithm>
#include<vector>
int main()
{
std::vector<int> a(100);
for(int i=0; i<100; i++)
{
a[i]=i;
}
std::reverse( a.begin(), a.end() );
for(int i=0; i<100; i++)
{
std::cout<<a[i]<<" ";
}
return 0;
}
10.20
一
- 传入两个整数,max()函数与min()函数分别会返回其中的最大与最小值。它们定义在头文件algorithm中。
二
一个用于获取整数位数的自定义函数模板:
int f(int num)
{
return std::to_string(abs(num)).length();
}
该函数返回的值为to_string(abs(num)).length()
其中【 abs() 】用于取绝对值,【 to_string() 】用于转换为字符串,【 .lengrh() 】用于获取字符串的长度。
该函数需要头文件string。
10.22
一
C++标准库中一些实现二分查找的函数:
std::binary_search(vec.begin(),vec.end(),key)其需要的参数分别为:指向查找开始的元素的迭代器,指向查找结束的元素的下一个元素的迭代器(注意,是指向结束元素的下一个元素的迭代器!),以及需要查找的值。其返回布尔值——存在(true)与不存在(false)。std::lower_bound(vec.begin(),vec.end(),key)其需要的参数与【 binary_search() 】相同,区别在于该函数返回的是指向指定序列中第一个不小于给定值的元素的迭代器,若未找到返回指向结束元素的下一个元素的迭代器。std::upper_bound(vec.begin(),vec.end(),key)其需要的参数与【 binary_search() 】相同,区别在于该函数返回的是指向指定序列中第一个大于给定值的元素的迭代器,未找到时返回值与lower_bound()函数相同。
注意:
- 这三种函数都需要头文件algorithm。
- 由于【 lower_bound() 】与【 upper_bound() 】函数返回的是迭代器,在输出时需要注意。 如下所示:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> arr = {2, 4, 6, 8, 10};
// 查找第一个大于等于6的元素
auto it = std::lower_bound(arr.begin(), arr.end(), 6);
// 计算索引
int index = it - arr.begin();
std::cout << "元素6的索引是: " << index << std::endl; // 输出: 2
std::cout << "元素的值是: " << *it << std::endl; // 输出: 6
return 0;
}
10.31
一
补一下C++中用来实现前缀和和差分的函数:
#include<iostream>
#include<vector>
#include<numeric>
int main()
{
std::vector<int> a(100);
for(int i=0;i<100;i++)
{
a[i]=i;
}
std::vector<int> sum(100);
std::vector<int> difference(100);
partial_sum(a.begin(),a.end(),sum.begin());
adjacent_difference(a.begin(),a.end(),difference.begin());
for(int i=0;i<100;i++)
{
std::cout<<a[i]<<" ";
}
std::cout<<std::endl;
for(int i=0;i<100;i++)
{
std::cout<<sum[i]<<" ";
}
std::cout<<std::endl;
for(int i=0;i<100;i++)
{
std::cout<<difference[i]<<" ";
}
std::cout<<std::endl;
return 0;
}
上面的程序使用了partial_sum函数与adjacent_difference函数,输出了a数组,a数组的前缀和与a数组的差分。
注意,partial_sum函数与adjacent_difference函数需要引入头文件numeric。
二
一个用于计算快速幂的自定义函数模板:
//该函数计算(a^b) mod c
long long f(long long a,long long b,long long c)
{
long long ans=1;
while(b>0)
{
if(b&1)
{
ans=(ans*a)%c;
}
a=(a*a)%c;
b>>=1;
}
return ans;
}
后记:
感觉这个月好像什么都没学啊······
身边同学的学习进度不知道什么时候已经超过我一大截了,看来进算法集训室是希望不大了QAQ
到最后算法也没学多少,高数还落下了,英语更是一言难尽。
我简直就是BAKA啊
(;´д`)ゞ

