1、实现C语言atoi函数的功能,实际我的函数功能要比atoi强大
int my_atoi(const char* str)
{
if (str == nullptr)
return 0;
bool negative_flag = false;
bool first_num_flag = false;
int first_num_pos, last_num_pos;
int i = 0;
while (str[i] != 0)
{
if (first_num_flag)
{
if (str[i] >= '0' && str[i] <= '9')
last_num_pos = i;
else
break;
}
else
{
if (str[i] == '-')
negative_flag = true;
else if (str[i] >= '1' && str[i] <= '9')
{
first_num_flag = true;
first_num_pos = last_num_pos = i;
}
else if (negative_flag)
negative_flag = false;
}
i++;
}
if (first_num_flag)
{
int sum = 0;
int n = last_num_pos - first_num_pos;
for (int i = first_num_pos; i <= last_num_pos; i++)
sum += (str[i] - 48)*pow(10.0, n--);//如果预先知道数据有多大,则可以设置权值,不调用pow函数以提升性能
if (negative_flag)
sum = -1 * sum;
return sum;
}
else
return 0;
}
2、已知char str[16];数组中元素的值为0或1,为了节省内存,将str中的元素存放在unsigned char arr[2];中,比如str[0]存放在arr[0]中的第0位,str[1]存放在arr[0]中的第1位,str[8]存放在arr[1]中的第0位。
char str[16] = {0,1,1,1,0,1,1,1,1,1,0,1,0,0,1,0};
unsigned char arr[2];
int i = 0, j = 0;
memset(arr, 0, sizeof(arr));
unsigned char tmp;
while (i < sizeof(str))
{
tmp = str[i];
tmp <<= i % 8;
arr[j] |= tmp;
i++;
if (i % 8 == 0)
j++;
}
3、注意以下表达式的用法
int a = 88;
a /= 1 + 2 * 3 + 4;
printf("a=%d\n",a);//输出结果为:a=8
a = 1;
a <<= 1 + 1;
printf("a=%d\n", a);//输出结果为:a=4
4、结构体对齐与限定结构体成员所使用的位数
#include <stdio.h>
#pragma pack(1)
struct A
{
char c : 3;//c只用到了3位
int i : 31;//i只用到了31位
};
void main()
{
printf("%d\n",sizeof(A));//1字节+4字节=5字节
A a;
a.c = 11;//11用二进制表示为1011,由于c占3位,所以只存储011,所以c的值为3
printf("%d\n", a.c);
a.c = 15;//15用二进制表示为1111,由于c占3位,所以只存储111,所以c的值为-1;
printf("%d\n", a.c);
getchar();
}
5、判断当前机器是大端模式还是小端模式,Intel处理器都是小端模式。
#include <stdio.h>
void main()
{
union Test
{
unsigned char c;
unsigned short s;
}t = { 0x1234 };
if (t.c == 0x34)
printf("Little-Endian\n");
else
printf("Big-Endian\n");
}
6、C/C++ static的用法
/*
以下代码输出结果为:
1
1
原因在于,static int i=++n;这种语句只会执行一次;
如果将static int i=++n;语句改为:
static int i;
i=++n;
则输出结果为:
5
5
由此说明,如果在WM_PAINT消息处理中执行:
static HDC hdcMem=CreateCompatibleDC(hdc);
则CreateCompatibleDC函数只会被执行一次。
*/
#include <iostream>
using namespace std;
int func(int& n)
{
static int i = ++n;
return i;
}
void main()
{
int n = 0, count = 0, ret = 0;
while (count++ < 5)
ret = func(n);
cout << n << endl;
cout << ret << endl;
getchar();
}
7、C++动态分配连续存储空间的矩阵及其释放
无论是静态分配还是动态分配,矩阵的列数必须被指定。
int(*p1)[3];//声明了一个指向3维数组的指针变量
int a1[3] = {1,2,3};
p1 = &a1;
printf("%p\n%p\n",p1,(p1+1));
上面代码段在x86机器上的输出结果为:
0x0030FEE0
0x0030FEEC
可见两个地址相差12字节,说明p1指向的是一个3维数组而不是一个int型数据。
int(*p1)[3];//声明了一个指向3维数组的指针变量
p1=new int[2][3];//动态分配了一个2行3列的矩阵
delete[]p1;//释放内存
8、将一个字符串逆序输出
//将字符串逆序输出(递归实现)
void reverse_output(const char* str)
{
if (!str)
return;
if (!*str)
return;
reverse_output(str + 1);
putchar(*str);
}
9、将字符串反转后再返回字符串
//反转字符串
char* reverse(char* str)
{
if (!str)
return NULL;
int i = 0, j = 0;
while (str[i++]);//求出字符串长度
i -= 2;
while (j < i)
{
char tmp = str[i];
str[i] = str[j];
str[j] = tmp;
i--;
j++;
}
return str;
}
10、约瑟夫环问题
//约瑟夫环问题,n代表人数,k代表数到多少后出列,依次输出出列人员的编号
void number(int n, int k)
{
if (n > 0 && k > 0)
{
int* pArr = (int*)malloc(n*sizeof(int));//pArr数组用于保存每个人的编号
for (int i = 0; i < n; i++)
pArr[i] = i + 1;
int total = n;//total存放总人数
int count = 0;//存放报数
int i = 0;//数组下标
while (total > 1)
{
if ((count = (count + 1) % k) == 0)//如果数到k,就出列
{
printf("%d\n",pArr[i]);//出列
pArr[i] = 0;
total--;//总人数减1
}
i = (i + 1) % n;
while (pArr[i] == 0)
i = (i + 1) % n;
}
printf("%d\n", pArr[i]);//最后一个人出列
free(pArr);
}
}
11、判断单链表是否有环
//判断单链表是否有环
typedef struct tagNode
{
int data;
Node* next;
}Node;
//头指针表示一个单链表,返回1表示有环;返回0表示无环
int HasCircle(Node* head)
{
Node *slow, *fast;
slow = fast = head;
while (slow != NULL && fast->next != NULL)
{
slow = slow->next;
fast = fast->next->next;
if (slow == fast)
return 1;
}
return 0;
}
12、对于一个频繁使用的短小函数,在C语言中用宏实现,在C++中用inline实现。
13、可编程内存在基本上分为这样的几大部分:静态存储区、堆区和栈区。他们的功能不同,对他们使用方式也就不同。
静态存储区:内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。它主要存放静态数据、全局数据和常量。
栈区:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
堆区:亦称动态内存分配。程序在运行的时候用malloc或new申请任意大小的内存,程序员自己负责在适当的时候用free或delete释放内存。动态内存的生存期可以由我们决定,如果我们不释放内存,程序将在最后才释放掉动态内存。 但是,良好的编程习惯是:如果某动态内存不再使用,需要将其释放掉,否则,我们认为发生了内存泄漏现象。
C语言中,static 修饰的变量都位于静态存储区,static修饰的全局变量只能在本源程序文件中被访问,不能在其它源程序文件中被访问,所以,C语言是允许不同源文件定义同名的全局变量的,但是要求最多只能有一个变量没有用static修饰。
14、new:先分配内存,再构造对象(调用构造函数);
delete:先销毁对象(调用析构函数),再释放内存。
15、C++类中的const成员变量只能用参数列表来初始化,不能在构造函数体内对其赋值。
16、explicit关键字的用法:
#include <iostream>
using namespace std;
class A
{
public:
explicit A(int x) { i = x; }
int i;
};
int main()
{
A a = 123;//因为加了explicit关键字,所以这里编译出错
getchar();
return 0;
}
17、void* operator new、void operator delete这两个重载函数,前者运行在对象构造之前,后者运行在对象析构之后,所以这两个函数如果定义为类成员函数,则必须是静态的,只有静态函数才不能访问对象的属性(数据成员)。如果没有使用static修饰,默认就是static的。
18、C++中,对野指针的操作可能导致程序崩溃,也可能程序不崩溃,视这个野指针指向的内存是否为只读或系统的核心。