0.字符串定义
char str1[] = "123456"; // 存放在栈区,可读可写
// char *str2 = "12345"; // 存放在只读数据区,不可以进行修改,需要加const进行修饰
const char *str2 = "12345";
#include <iostream>
#include <string.h>
using namespace std;
char str1[] = "123456"; // 存放在栈区,可读可写
// char *str2 = "12345"; // 存放在只读数据区,不可以进行修改,需要加const进行修饰
const char *str2 = "12345";
int main()
{
// 字符串定义:方法3
char *str3 = (char *)malloc(128);
strcpy(str3, "1234");
cout << str3 << endl;
free(str3); // 字符串使用完之后,立即进行释放
return 0;
}
1.字符串翻转
#include <iostream>
#include <string.h>
using namespace std;
// 字符串逆序
void Reverse(char *str)
{
int length = strlen(str);
for (size_t i = 0; i < length / 2; i++)
{
char temp = str[i];
str[i] = str[length - 1 - i];
str[length - 1 - i] = temp;
}
}
int main()
{
char str1[] = "12345";
Reverse(str1);
cout << str1 << endl; // 54321
return 0;
}
2.字符串排序
描述:随便输入几个字母,按照a~z顺序排列,采用冒泡排序算法进行设计。
#include <iostream>
#include <string.h>
using namespace std;
// 冒泡排序
void BubbleSort(char arr[], int n)
{
for (int i = 0; i < n - 1; i++)
{
int flag = 0;
for (int j = 0; j < n - 1 - i; j++)
{
if (arr[j] > arr[j + 1])
{
char temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
flag = 1;
}
}
if (flag == 0)
{
break;
}
}
}
int main()
{
char str[] = "AaBbcC";
int n = strlen(str);
BubbleSort(str, n);
cout << str << endl; // ABCabc
return 0;
}
3.统计汉字和字母的个数
注意:使用GBK编码,使用UTF-8编码,程序计算结果有误。
- 在UTF-8编码中,一个汉字占3个字节
- 在GBK编码中,一个汉字占2个字节
#include <iostream>
using namespace std;
// 统计汉字和字母的个数
void Count(char arr[])
{
int i = 0;
int zh = 0;
int en = 0;
while (arr[i]) // 执行到结束符\0
{
if (arr[i] < 0) // 一个汉字由两个小于0的字符组成
{
zh++;
i += 2;
}
else
{
en++;
i++;
}
}
cout << "zh = " << zh << endl;
cout << "en = " << en << endl;
cout << "sum = " << zh + en << endl;
}
int main()
{
char str[] = "C++汉字";
Count(str);
return 0;
}
4.打印9*9乘法表
#include <iostream>
using namespace std;
int main()
{
for (short i = 1; i <= 9; i++)
{
for (short j = 1; j <= i; j++)
{
cout << i << "x" << j << "=" << i * j << "\t";
}
cout << endl; // 完成一行后,进行换行
}
return 0;
}
5.将字符串中的大写字母转化为小写字母
ASCII:A(65)、a(97),a - A = 32
#include <iostream>
#include <string.h>
using namespace std;
// 字符串中大小写切换
void Shift(char arr[], int n)
{
for (int i = 0; i < n; i++)
{
// 大写转小写
if (arr[i] >= 'A' && arr[i] <= 'Z')
{
arr[i] += 32;
}
// 小写转大写
else if (arr[i] >= 'a' && arr[i] <= 'z')
{
arr[i] -= 32;
}
}
}
int main()
{
char str[] = "ABab";
int n = strlen(str);
Shift(str, n);
cout << str << endl;
return 0;
}
6.计算2的1024次方
- 在C语言中,int型占4个字节,4*8 = 32位,最大表示2的32次方-1。
- 方法:定一个大的数组(初始化为1),把数字当作字符串进行处理,模拟2进位的方法,最终得到的字符串进行逆序。
#include <iostream>
#include <string.h>
using namespace std;
// 字符串逆序
void Reverse(char *str)
{
int length = strlen(str);
for (size_t i = 0; i < length / 2; i++) // 由于要进行逆序,所以只需要交换前一半的字符即可
{
char temp = str[i];
str[i] = str[length - 1 - i];
str[length - 1 - i] = temp;
}
}
// 计算2的N次方
void Index(int n, char *str)
{
int i, j;
for (i = 0; i < n; i++)
{
int temp = 0; // 用于保存进位的临时变量
for (j = 0; j < strlen(str); j++)
{
int num = str[j] - '0'; // 将字符转换为对应的整数值
num = (num << 1) + temp; // 将当前位的数乘以2,并加上进位
temp = num / 10; // 计算进位
str[j] = num % 10 + '0'; // 将计算结果转换回字符型,并存储
}
if (temp > 0)
{
str[j] = temp + '0'; // 如果还有进位,存储在新的一位上
}
}
Reverse(str); // 计算完成后,需要将字符串逆序,得到正确的结果
}
int main()
{
int n = 16;
char str1[n] = {'1'};
Index(n, str1);
cout << str1 << endl; // 65536
return 0;
}
7.数组元素逆序
#include <iostream>
using namespace std;
// 数组元素逆序
void Reverse(int arr[], int n)
{
for (int i = 0; i < n / 2; i++)
{
int temp = arr[i];
arr[i] = arr[n - 1 - i];
arr[n - 1 - i] = temp;
}
}
int main()
{
int arr[] = {1, 2, 3, 4, 5};
int n = sizeof(arr) / sizeof(int);
Reverse(arr, n);
for (int i = 0; i < n; i++)
{
cout << arr[i] << ",";
}
cout << endl;
return 0;
}
8.宏定义
宏定义,防止头文件被重复编译
// 标识符可以自由命名,一般使用头文件名全部大写的方式,前面加_,把.改成_
#ifndef _LED_H
#define _LED_H
// 代码段
#endif
宏定义函数,带参
#include <iostream>
using namespace std;
#define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
int main()
{
int a = MAX(1, 2);
cout << a;
return 0;
}
通过宏定义的方式,计算数组的长度
#include <iostream>
using namespace std;
#define Len(arr) (sizeof(arr) / sizeof(arr[0]))
int main()
{
int a[] = {1, 2, 3};
int b = Len(a);
cout << b;
return 0;
}
9.不使用sizeof判断操作系统是64位还是32位
#include <stdio.h>
int main() {
if ((1L << 32) == 0) {
printf("64位系统\n");
} else {
printf("32位系统\n");
}
return 0;
}
10.如何判断链表是否有环
正常的单向链表,最后一个节点的指针域应该是NULL,表示后面没有节点。
如果把最后一个节点的指针域,改为前面的某个节点的地址,这样的链表叫做有环的链表。
如何判断链表是否有环:
1.定义两个指针:慢指针(每次走一步)、快指针(每次走两步)
2.如果链表没有环,快的指针肯定最先到达终点
3.如果链表有环,那么两个指针迟早相遇
int fcn(Node *head)
{
if (head == NULL)
{
return 0;
}
Node *fast = head;
Node *slow = head;
while (fast && slow) // 两个指针都不为空
{
// 如果某个指针为空,说明链表没有环
if (fast->next && fast->next->next)
{
fast = fast->next->next; // 快指针每次走两步
}
else
break;
if (slow->next)
{
slow = slow->next; // 慢指针每次走一步
}
else
break;
if (fast == slow) // 如果快慢指针在某个时刻相等,说明链表有环
return 1; // 链表有环
}
return 0; // 链表没有环
}
11.如何判断两个链表是否相交
如果两个链表相交,那么一定有重合的节点。
方法1:可以逐个判断第一个链表里面的节点,是否在第二个链表中。效率较低
方法2:相交的两个链表,他们的最后一个节点一定是重合的,所以只要让第一个链表的指针,指向最后一个节点。第二个链表的指针,也指向最后一个节点,判断这两个节点是否相同。
int is_cross(Node *head1, Node *head2)
{
if (head1 == NULL || head2 == NULL)
{
return 0;
}
Node *p1 = head1, *p2 = head2;
// 假设链表有头节点,两个指针分别移动到最后一个节点
// 如果指针相同,那链表就是相交的
while (p1->next)
{
p1 = p1->next;
}
while (p2->next)
{
p2 = p2->next;
}
if (p1 == p2)
{
return 1; // 链表相交
}
else
return 0; // 链表不相交
}
进阶:如何找出相交的那个节点
如果两个链表的长度一样,只要同时移动指针,最先相等的那个节点,一定就是相交的节点,所以可以先计算两个链表的长度差,然后先移动一个指针,保证长度一样后再同时向后走。
12. 手写链表的基本操作
链表的初始化、插入、遍历
链表相对于数组的优点:容量没有限制,插入删除的效率比较高。数组在内存中是一块连续的存储空间,链表在内存中不连续,由节点组成,每个节点包含两部分(数据域:存储数据,指针域:存储下一个节点的地址)
链表的初始化:空链表,只有一个头节点,没有数据域
#include <iostream>
using namespace std;
typedef struct Node
{
int data;
struct Node *next;
} Node;
// 链表的初始化
int InitList(Node **h)
{
if (h == NULL)
{
return 0;
}
(*h) = (Node *)malloc(sizeof(Node));
if ((*h) == NULL)
return 0;
(*h)->next = NULL;
return 1;
}
int main()
{
Node *head = NULL; // 链表的初始化:形成一个空的链表
int ret = InitList(&head);
if (ret == 0)
cout << "链表初始化失败" << endl;
else
cout << "链表初始化成功" << endl;
return 0;
}
13.找出字符串中不含有重复字符的最长子串的长度
例如,abcabcbb的无重复字符的最长子串是“abc”
#include <iostream>
using namespace std;
int lengthofLongestSubstring(char *s)
{
int exist[256] = {0};
char *left = s;
char *right = s;
int max = 0;
while (*right != 0)
{
if (exist[*right] == 1)
{
exist[*left++] = 0;
}
else
{
exist[*right++] = 1;
int t = right - left;
if (t > max)
max = t;
}
}
return max;
}
int main()
{
char str[] = "abcabcdd";
int a = lengthofLongestSubstring(str);
cout << a << endl; // 输出4
return 0;
}
14.将字符串转化为整数
#include <iostream>
#include <string.h>
using namespace std;
// 将字符串转换为整数
void Conver_Int(char str[], int &num)
{
int len = strlen(str);
cout << "str len = " << len << endl;
for (int i = 0; i < len; i++)
{
if (str[i] > '0' && str[i] < '9')
{
// 将字符转换为整数
int temp = str[i] - 48; // 0的ASCII为48
num = num * 10 + temp;
}
}
}
int main()
{
char str[] = "123456";
int num = 0;
Conver_Int(str, num);
cout << num + 1 << endl; // 输出123457
return 0;
}
15.将整数转化为字符串
#include <iostream>
using namespace std;
void Int_String(int num, char str[])
{
int i = 0;
int isNegative = 0;
// 处理负数
if (num < 0)
{
isNegative = 1;
num = -num; // 如果是负数,将其转为正数
}
// 处理特殊情况:整数为0
if (num == 0)
{
str[i++] = '0'; // 如果整数为0,将字符'0'存入字符串
}
// 将整数转换为字符串(从右到左)
while (num > 0)
{
int digit = num % 10; // 取出整数的最后一位数字
str[i++] = '0' + digit; // 将数字字符存入字符串
num /= 10; // 移除最后一位数字
}
// 如果是负数,添加负号
if (isNegative)
{
str[i++] = '-'; // 如果是负数,添加负号到字符串
}
str[i] = '\0'; // 在字符串末尾添加 null 终止字符
// 反转字符串,因为上面的循环是从右到左构建的
int len = i; // 计算字符串的长度
for (int j = 0; j < len / 2; j++)
{
char temp = str[j]; // 交换字符的位置
str[j] = str[len - j - 1];
str[len - j - 1] = temp;
}
}
int main()
{
int num = -12345;
char str[20];
Int_String(num, str);
cout << str << endl; // 输出字符串-12345
return 0;
}