方法

判断闰年

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
bool isLeapYear(int year) {  
// 闰年的条件:
// 1. 能被4整除但不能被100整除
// 2. 能被400整除
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
return true;
} else {
return false;
}
}

int main() {
int year;
cout << "请输入一个年份: ";
cin >> year;
if (isLeapYear(year)) {
cout << year << " 是闰年。" << endl;
} else {
cout << year << " 不是闰年。" << endl;
}
return 0;
}

【易错:ASCII码】s[i]-‘0’;和(int)s[i];为什么结果不一样

在C++中,s[i] - '0'(int)s[i] 表达式虽然都涉及到将字符转换为整数,但它们的目的和结果通常是不同的。

  1. s[i] - '0'

    这个表达式通常用于将字符(假设它是一个数字字符,即 '0''9' 之间的某个字符)转换为对应的整数值。在ASCII编码中,数字字符 '0''9' 是连续排列的,且 '0' 的ASCII码值是48。因此,当你从一个数字字符中减去 '0' 时,你实际上是在计算该字符与 '0' 在ASCII表中的距离,这个距离恰好等于该字符所代表的数字值。

    例如,如果 s[i]'5',那么 s[i] - '0' 的结果将是 5 - 48 + 48(这里的 48'0' 的ASCII码值,但加48再减48是为了说明原理,实际上直接计算 53 - 48)等于 5

  2. (int)s[i]

    这个表达式将字符 s[i] 强制转换为整数类型。但是,这里转换得到的是字符的ASCII码值,而不是字符所代表的数字值(如果它是一个数字字符的话)。

    例如,如果 s[i]'5',那么 (int)s[i] 的结果将是 53,因为 '5' 在ASCII表中的值是53。

因此,这两个表达式在用途和结果上是不同的。s[i] - '0' 用于将数字字符转换为对应的整数值,而 (int)s[i] 则用于获取字符的ASCII码值。在实际编程中,你应该根据具体需求选择使用哪个表达式。


输入字符串

在C++中,字符串的输入方法有多种,以下是几种常见的方法:

  1. 使用cin直接输入

    • cin >> str;:这种方法从标准输入读取单个单词,存储在变量str中。它会在遇到空格或换行符时停止读取,因此只能读取到第一个空格之前的部分。
  2. 使用cin.get()输入

    • cin.get(str, size);:从标准输入读取指定大小的字符串(包括空字符),存储在字符数组str中。这种方法可以读取包含空格的字符串,但需要注意数组的大小,以避免溢出。
  3. 使用getline()函数输入

    • getline(cin, str);:从标准输入读取整行,包括空格和换行符(换行符会被丢弃),存储在字符串str中。这种方法常用于需要读取包含空格的整行输入的情况。
  4. 使用gets()函数输入(注意:gets()函数是不安全的,已被C++标准弃用,推荐使用gets_s()或其他安全的字符串输入方法):

    • gets(str);:从标准输入读取一行字符串,包括空格,直到遇到换行符为止。换行符会被存储在字符串中,但通常会被后续的输入操作覆盖或丢弃。由于gets()函数存在缓冲区溢出的风险,因此不推荐使用。
  5. 使用scanf()输入

    • scanf("%s", str);:这种方法只能读取不包含空格的字符串。当输入字符串中包含空格时,scanf()会在遇到第一个空格时停止读取。此外,使用scanf()时需要注意缓冲区的大小,以避免溢出。同时,scanf()会在输入缓冲区中留下换行符,这可能会影响后续的输入操作。
  6. 使用getchar()逐个字符输入

    • char ch; while((ch = getchar()) != '\n') { /* 处理字符 */ }:这种方法通常用于逐个字符地读取输入,直到遇到换行符为止。它可以用于读取包含空格的字符串,但需要手动处理字符和构建字符串。
  7. 使用文件输入流

    • 如果需要从文件中读取字符串,可以使用文件输入流ifstream。例如,ifstream infile("filename.txt"); string line; while(getline(infile, line)) { /* 处理每行 */ }

需要注意的是,以上方法中有些是不安全的或已被弃用的(如gets()),在实际编程中应尽量避免使用。同时,对于不同的应用场景和需求,可以选择最适合的字符串输入方法。例如,对于需要读取包含空格的整行输入的情况,通常推荐使用getline()函数。


for循环遍历字符串

在C++中,你可以使用for循环来遍历一个string字符串。string提供了多种访问其字符的方法,包括使用下标运算符[]和迭代器。以下是一些使用for循环遍历字符串的示例:

使用下标运算符

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
#include <string>

int main() {
string str = "Hello, World!";
for (size_t i = 0; i < str.size(); ++i) {
cout << str[i] << ' ';
}
cout << endl;
return 0;
}

在这个例子中,str.size()返回字符串的长度,str[i]访问字符串中位置为i的字符。注意,size_t是一个无符号整数类型,通常用于表示大小和索引。

使用范围for循环(C++11及以上)

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
#include <string>

int main() {
string str = "Hello, World!";
for (char c : str) {
cout << c << ' ';
}
cout << endl;
return 0;
}

范围for循环(也称为基于范围的for循环)简化了遍历容器的语法。在这个例子中,c将依次被赋值为字符串str中的每个字符。

使用迭代器

虽然在这个特定的情况下使用下标运算符或范围for循环可能更常见,但了解如何使用迭代器来遍历字符串也是很有用的,因为迭代器是STL中更通用的概念。

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
#include <string>

int main() {
string str = "Hello, World!";
for (string::iterator it = str.begin(); it != str.end(); ++it) {
cout << *it << ' ';
}
cout << endl;
return 0;
}

在这个例子中,str.begin()返回一个指向字符串第一个字符的迭代器,str.end()返回一个指向字符串末尾之后位置的迭代器(不是最后一个字符,而是最后一个字符之后的位置,用作循环的结束条件)。*it解引用迭代器以获取它所指向的字符。

注意,从C++11开始,你还可以使用auto关键字来自动推导迭代器的类型,从而简化代码:

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
#include <string>

int main() {
string str = "Hello, World!";
for (auto it = str.begin(); it != str.end(); ++it) {
cout << *it << ' ';
}
cout << endl;
return 0;
}

在这个修改后的例子中,auto使得代码更加简洁,并且减少了因类型错误而导致的问题。


取数字里的每一位数

1
2
3
4
5
6
7
// b用来保存当前的数字,c用来保存当前的位置
int b,c;
while(b!=0)
{
c=b%10;//求余取当前位数
b=b/10;//除10取下一位
}

函数

【函数】isalpha、isspace、isdigit判断字母空格和数字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
int main() {  
char input[1000]; // 假设输入字符不会超过1000个
cout << "请输入一行字符: ";
cin.getline(input, 1000); // 使用getline以获取包含空格的整行输入

int letters = 0;
int spaces = 0;
int digits = 0;
int others = 0;

for (int i = 0; input[i] != '\0'; ++i) {
if (isalpha(input[i])) {
++letters;
} else if (isspace(input[i])) {
++spaces;
} else if (isdigit(input[i])) {
++digits;
} else {
++others;
}
}

cout << "英文字母个数: " << letters << endl;
cout << "空格个数: " << spaces << endl;
cout << "数字个数: " << digits << endl;
cout << "其他字符个数: " << others << endl;

return 0;
}

【函数】toupper和tolower大小写转换

toupper 函数

toupper 函数用于将小写字符转换为对应的大写字符。如果传入的字符不是小写字母,则函数返回该字符本身。

tolower 函数

tolower 函数用于将大写字符转换为对应的小写字符。如果传入的字符不是大写字母,则函数返回该字符本身。

1
2
3
4
5
6
7
8
//1.a.begin()和a.end()定义了要进行转换的范围,即容器a的开始和结束迭代器。
//2.第三个参数a.begin()指定了转换后元素存储的起始位置,这里直接在原容器a上进行修改。
//3.::tolower是一个函数指针,指向C标准库中的tolower函数,该函数用于将大写字符转换为小写字符。注意,这里使用的是全局命名空间的tolower,所以前面有::。

//转换为大写
transform(a.begin(),a.end(),a.begin(),::toupper);
//zuan'hua
transform(a.begin(),a.end(),a.begin(),::tolower);

【函数】sscanf和ssprintf的用法

sscanf是C语言中的一个函数,用于从字符串中读进与指定格式相符的数据。它是scanf函数的字符串版本,允许从一个字符串而不是标准输入中读取数据。

sscanf

一、sscanf函数原型

1
int sscanf(const char *str, const char *format, ...);
  • str:待解析的字符串。
  • format:字符串格式描述,用于指定如何从字符串中读取数据。
  • ...:一序列数目不定的指针参数,用于存储解析后的数据。

二、基本用法

sscanf函数支持多种数据类型的读取,包括字符串(%s)、整型(%d, %ld等)、浮点型(%f, %lf等)。使用时,需要在format字符串中指定数据类型,并提供相应的指针参数来存储读取的数据。

例如:

1
2
3
4
5
char str[] = "123 456.78";  
int a;
float b;
sscanf(str, "%d %f", &a, &b);
printf("a = %d, b = %.2f\n", a, b);

输出结果为:

1
a = 123, b = 456.78

三、高级用法

  1. 取指定长度的字符串

    使用%[width]格式说明符可以读取指定长度的字符串。例如:

    1
    2
    3
    4
    char str[] = "123456789";  
    char buf[10];
    sscanf(str, "%4s", buf);
    printf("%s\n", buf);

    输出结果为:1234

  2. 取到指定字符为止的字符串

    使用%[^chars]格式说明符可以读取直到遇到指定字符集为止的字符串。例如:

    1
    2
    3
    4
    char str[] = "123456abcdedf";  
    char buf[50];
    sscanf(str, "%[^A-Z]", buf);
    printf("%s\n", buf);

    输出结果为:123456abcdedf

  3. 忽略指定字符

    使用%*格式说明符可以忽略指定数量的字符或满足特定格式的字符串。例如:

    1
    2
    3
    4
    char str[] = "iios/12DDWDFF@122";  
    char buf[50];
    sscanf(str, "%*[^/]/%[^@]", buf);
    printf("%s\n", buf);

    输出结果为:12DDWDFF

  4. 读取多个数据类型

    sscanf函数可以一次读取多个数据类型,只需在format字符串中依次指定数据类型,并提供相应的指针参数即可。例如:

    1
    2
    3
    4
    5
    char str[] = "AT+COM=123456,789.012";  
    int a;
    float b;
    sscanf(str, "AT+COM=%d,%f", &a, &b);
    printf("a = %d, b = %.2f\n", a, b);

    输出结果为:a = 123456, b = 789.01

四、注意事项

  • 使用sscanf函数时,要确保提供的缓冲区足够大,以避免缓冲区溢出问题。

  • sscanf函数的返回值表示成功读取的数据项数量,可以通过检查返回值来判断读取是否成功。

  • 在处理复杂格式的字符串时,要仔细设计format字符串,以确保正确读取数据。

sprintf是C语言中的一个标准库函数,全称是“string print”,意为“字符串打印”。这个函数的主要功能是将格式化的数据写入某个字符串中,即发送格式化输出到一个字符串所指向的内存区域。

sprintf

一、sprintf函数原型

sprintf函数的声明通常如下:

1
2
3
c复制代码

int sprintf(char *str, const char *format, ...);
  • str:这是一个指向字符数组的指针,该数组用于存储格式化后的字符串。
  • format:这是一个格式控制字符串,用于指定输出的格式。它可以包含嵌入的格式标签,这些标签会被随后附加参数中指定的值替换,并按需求进行格式化。
  • ...:这是一个可变参数列表,用于指定要格式化的数据。这些数据的类型和数量应与格式控制字符串中的格式标签相匹配。

二、格式标签

格式控制字符串中的格式标签以“%”开头,后跟一个或多个字符来指定数据类型、宽度、精度等。常见的格式标签包括:

  • %d:表示一个整数。
  • %f:表示一个浮点数。
  • %c:表示一个字符。
  • %s:表示一个字符串。
  • %%:表示一个百分号字符。

此外,还可以指定输出的宽度和精度。例如,%5d表示输出的整数宽度至少为5个字符,不足部分用空格填充;%.2f表示输出的浮点数保留两位小数。

三、使用示例

以下是一个使用sprintf函数的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>  

int main() {
char buffer[50];
int num = 123;
float pi = 3.14159;

// 使用sprintf函数将格式化的数据写入buffer字符串中
sprintf(buffer, "The number is %d and the value of pi is %.2f", num, pi);

// 使用printf函数输出buffer字符串的内容
printf("%s\n", buffer);

return 0;
}

输出结果为:

1
2
3
复制代码

The number is 123 and the value of pi is 3.14

四、注意事项

  1. 缓冲区大小:使用sprintf函数时,需要确保提供的缓冲区足够大,以存储格式化后的字符串。如果缓冲区太小,可能会导致缓冲区溢出,进而引发程序崩溃或安全问题。
  2. 参数匹配:可变参数列表中的参数应与格式控制字符串中的格式标签一一对应,且类型相匹配。否则,可能会导致未定义的行为或程序崩溃。
  3. 返回值:sprintf函数返回成功写入字符串中的字符数(不包括终止符’\0’)。如果发生错误,则返回负值。可以通过检查返回值来判断写入是否成功。

【函数】n的阶乘和累加

阶乘

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//递归方法
//递归方法利用阶乘的递归特性,即n! = n * (n-1)!,通过反复调用自身来计算阶乘。这种方法代码简洁,但对于较大的数可能会导致栈溢出。
int factorial(int n) {
if (n == 0) {
return 1;
} else {
return n * factorial(n - 1);
}
}

//循环方法
//循环方法通过循环逐步计算阶乘,避免了递归方法的栈溢出问题。对于较大的数,这种方法通常更可靠。
int factorial(int n) {
int result = 1;
for (int i = 1; i <= n; i++) {
result *= i;
}
return result;
}
//标准库函数
//C++标准库中提供了一个名为tgamma的函数,它可以计算阶乘(但需要注意的是,tgamma(n)实际上返回的是(n-1)!的伽马函数值,所以要计算n!需要调用tgamma(n+1))。不过,这种方法通常不是最直接或最高效的,因为它涉及浮点数运算和伽马函数的计算。
#include <cmath>
double factorial(int n) {
return tgamma(n + 1);
}

累加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*在C++中,计算一个数从1加到它本身(即计算`1 + 2 + ... + n`),最直接的方法是使用循环或数学公式。对于这种方法,效率主要取决于算法的时间复杂度。*/

//使用循环
//使用循环的方法是最直观的,时间复杂度为O(n):
int sum(int n) {
int result = 0;
for (int i = 1; i <= n; ++i) {
result += i;
}
return result;
}

//使用数学公式
//然而,有一个数学公式可以直接计算出这个结果,即等差数列求和公式:
//使用这个公式,可以将时间复杂度降低到O(1):
int sum(int n) {
return n * (n + 1) / 2;
}

【函数】sort排序

1
2
3
4
5
6
7
8
9
10
11
12
//sort默认升序(从小到大)

//降序排序方法:
//a.使用greater<int>()
int arr[] = { 2, 4, 5, 3, 1 };
ort(arr, arr + 5, greater<int>());
//b.自定义一个比较大小的函数,将大的排前面
bool cmp(int x,int y)
{
return x > y;
}
sort(arr,arr + 10,cmp);

【函数】reverse翻转数组

1
2
3
// 翻转函数
int a[5] = {1, 2, 3, 4, 5};
reverse(a, a+5);

【函数】向上/下取整(ceil/floor)

1
2
3
4
//向上取整
double rounded_num1 = ceil(num1);
//向下取整
double rounded_num1 = floor(num1);