unsigned char a=0xA5;
unsiged char b=~a>>4+1;
求b
解:unsigned char只能表示低八位,1个字节八位,这里0x表示十六进制,所以从0000到1111为16位,4位表示1位,C++中&&和 ||表示bool之间的与和或,&和 | 表示位运算的与和或,符号优先级顺序,加号大于移位运算符大于取反运算符 因此4+1=5,A5=1010 0101 右移五位=0000 0101取反=1111 1010因为b是unsigned char因此全是正的,为250
关于位运算一共有与,或,异或,左移,右移
位运算效率比除2乘2快许多,如果9与1,那么为1001&1也即为1,8与1为1000&1为0,
例题:
求出一个数的二进制中1的个数:将一个整数最后一位和1相与,然后右移一位
因为一个大于0的整数至少有1个1,那么从右往左找到第一个1,该数-1,表示该位为0,后面的位全部从0变为1,也即从右往左找到第一个1,该数-1表示该位左边不变,右边取反,注意两个取反的数相与得0,把原来的数和该数-1相与,左边部分不变,右边部分为0,
例题
1010和1101比较,我们发现都是1和都是0就不移动设为0,01和10就是移动设为1,那么是异或预算
char s[]="0123456789"; sizeof(s)=11 sizeof(*s)=1 //因为最后还有个\0位置,
int s[100]="0123456789" sizeof(s)=400
数组new出的数组大小比如是char[] s=new char[2]; 那么只给s[0],s[1]开辟内存,s[2]没有开辟内存
执行GetMemory(str);
void GetMemory (char*p, int num){
p=(char * )malloc(size of(char)*num);
} //这里的意思是传入str字符串为其开辟内存,但是,由于函数中形参的副本机制,没有返回指针,因此不能达到效果,每次执行一次函数就会申请一次内存,但是内存却不能有效释放,结果是内存一直被占用,造成内存泄漏
如果str为字符串,那么*str为第一个首字母而不是整个字符串的内容
c#
数组中str.length获取到的是数组初始化分配的大小,不是元素不为空的大小,因此,可以改用list,再用list.length
构造函数没有返回值,别犯二,public 函数名(){},还有static在public的后面,public static
二维数组初始化
- //规则二维数组的定义和初始化
- int[,] Arr = new int[2, 5] { { 1, 2, 3, 5, 6 }, { 1, 2, 3, 4, 5 } };
如果二维数组初始化,指定了行和列的大小必须上面的方法,如果只是指明了行的大小,那么下面每一行都要初始化数据,根据数据大小判断多少列
- //不规则二维数组
- int [][] arr = new int [3][ ]; //表示含有三个一维数组的数组
- arr[0] = new int[5]{1,2,3,4,5};
最后一行是一维数组的初始化,把整个数组放到后面
int[] numbers = new int[5] {1, 2, 3, 4, 5}; 或 int[] numbers ={1, 2, 3, 4, 5};
得到二维数组的行数和列数:
p.getlength(0);
p.getlength(1);
0代表的行数,1代表的列数
p.getlength(1);
0代表的行数,1代表的列数
<span style="color:#5a676f">输入一个整数,输出该数二进制表示中1的个数</span>
public static int GetResult(int target)
{
int n = 2; //2为底数
int res = 0; //为多少个1
while (true) //注意递归和迭代中迭代方式必须用while(true)来作为退出条件,不能用Math.Pow(n, m)作为退出条件
{
int m = 0; //m为幂
if(target==0){
break;
}
while (target >= Math.Pow(n, m))
{
m += 1;
}
target -= (int)Math.Pow(n, m-1);
res += 1;
}
return res;
}
剑指offer:
如果错误在于
应该是如果传参传的是对象本身而不是引用会调用拷贝构造函数
1 .
2
3.
4.
最后说下return this和return *this的区别,
class A
{
public:
int x;
A* get()
{
return this;
}
};
如果返回this,返回当前对象的地址,所以要拿A*接收
class A
{
public:
int x;
A get()
{
return *this; //返回当前对象的拷贝
}
};
如果返回的是*this,那么返回的是对象的引用,所以要用A&或者A来接收
c# internal关键字:
只有在同一程序集的文件中,内部类型或成员才可访问
Console.WriteLine("{0}{1}")中的{0}{1}是什么意思?
Console.WriteLine("{0}{1}",1,2);
会输出 12
Console.WriteLine("{0}{1}","1234",2);
会输出 12342
{0}表示第1个输出对象,{1}表示第2个输出对象,当然如果{0},{1}那么输出的是1234,2
C#中ref和out的作用:
在C#中通过使用方法来获取返回值时,通常只能得到一个返回值。因此,当一个方法需要返回多个值的时候,就需要用到ref和out
ref代码演示:
static void Main(string[] args)
{
int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
float avg = 0; //注意在传入ref类型的形参时,必须对它们进行初始化
int max = 0;
int min = 0;
int sum = GetIntResult(arr, ref avg, ref max, ref min);
Console.WriteLine("和:{0}\t平均值:{1}\t最大值:{2}\t最小值:{3}", sum, avg, max, min);
Console.Read();
}
static int GetIntResult(int[] arry, ref float avg, ref int max, ref int min)
{
int sum = 0;
max = arry[0];
min = arry[0];
for (int i = 0; i < arry.Length; i++)
{
sum += arry[i];
if (max < arry[i])
{
max = arry[i];
}
if (min > arry[i])
{
min = arry[i];
}
}
avg = sum / arry.Length;
return sum;
}
可以看到,调用完ref参数的函数,虽然返回的不是ref的参数,但是主函数仍然能把在调用函数修改后的值输出出来
out代码:
int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
float avg;//在使用out关键字时,不需要在此处初始化,但要在函数中初始化
int max;
int min;
int sum = GetIntResult(arr, out avg, out max, out min);
结果和上面一样。
结论:
关键字“ref“和”out”之间的唯一区别就是关键字ref要在传参前初始化,out在函数中初始化
C#中的ref和out提供了值类型按引用进行传递的解决方案,ref和out关键字将告诉编译器,现在传递的是参数的地址而不是参数本身,现在用ref和out修饰后,传递的就是这个指针,所以可以实现修改后a,b的值真正的交换。这就是ref和out给我们带来的好处。
算法:实现一个函数,把字符串中的每一个空格替换成”%20”。
第一个种方法:遍历每一个字符(第一个for循环),当遇到空格的时候后面的数整体移动3个单位(第二个for循环),时间复杂度为n2
更好的办法是:只使用一层for循环,用另一个数组接收这个数组的每一个值,将移动数组的语句变成赋值语句,并用2个变量保存接收到2个数组当中的第i位,当接收到空格,新数组加上”%20”,i+=3;即可,时间复杂度为n
判断两个小数是否相等的时候,比如float和double类型,不能直接d1==d2,要用他俩只差的绝对值是否在一个很小的范围内
排序:
我们可以看到时间复杂度要求这么低,很直观得到需要将一部分的时间复杂度转成了空间复杂度,也即牺牲一部分内存来得到运算效率。
如果是O(n)那也就是遍历一次一个for循环,那么第一次遍历所有数,找到最大值和最小值,第二次用一个新数组,开辟大小为(最大值-最小值)。
那么第0个位置放最小值有几个,第1个位置放最小值+1有几个,遍历需要排序的数,依次记录每个数有多少个,依次放到新数组中,遍历新数组,依次输出元素>0的记为排序后的
总结:要想把时间复杂度降下来,用一个数组接收最小值到最大值之间所有可能,记录每个元素出现次数即可,