捉虫大赛,顾名思义就是找bug,找啊找啊找bug。做题过程比较蛋疼,没带书什么的又不让上网。
A 今夕是何年
unsigned char year[]="\xB8\x12\x20\x00\x00\xC3";
int main(int argc, char* argv[])
{
printf("%x\n", (int(*)())&year());
return 0;
}
这个直接就是,字符串指针转换函数指针然后执行,错在少加一对括号。
unsigned char year[]="\xB8\x12\x20\x00\x00\xC3";
int main(int argc, char* argv[])
{
printf("%x\n", ((int(*)())&year)());
return 0;
}
B 数组的节操
#include <stdio.h>
#define TOTAL_ELEMENTS (sizeof(array)/sizeof(array[0]))
int main()
{
int d = -1;
int x;
int array[10];
array[0] = 1;
array[1] = 2;
if (d <= TOTAL_ELEMENTS - 2)
x = array[d+1];
printf("%i\n",x);
return 0;
}
这题弱弱的跪了,后来一问,大家都会做,原因是sizeof返回的是一个无符号整形,和-1比较的时候,会把-1转换成无符号型的一个很大的数,导致结果错误。
这个···谁知道嘛,出题者太阴险了。
C 数组数组快显灵
#include <iostream>
using namespace std;
void a()
{
volatile int array[10];
for (int i= 0; i<10; i++)
array[i] = i;
}
void b()
{
int array[10];
for (int i=0; i<10; i++)
cout<<array[i]<<endl;
}
int main()
{
a();
b();
}
这题比较牛逼,volatile这个修饰符是确保变量不会变编译优化,每次读取强制读取内存中的值,多线程的时候用得较多,不过这题还是会因为编译器不同而产生不同结果,
原因是c的内部变量,存储在堆栈中不会自动释放内存,函数b的数组堆栈空间,有可能与函数a的数组空间,有一部分吻合。
D 二进制转换器
#include <iostream>
using namespace std
int main()
{
short int number = 43690;//二进制形式为:1010101010101010
short int temp = 1 << 16;
for (int i = 0;i <= 16;i++)
{
if (number && temp)
cout << "1";
else
cout << "0";
temp >> 1;
}
return 0;
}
这题主要考一下位运算,问题也比较多,重要的一个问题是,做右移处理的时候左边最高一位以符号位补全,所以只有符号位的时候,做右移操作会在左边最高位得到两个一
类似这样 100000000000 >> 1 == 11000000000000
#include <iostream>
using namespace std;
int main()
{
unsigned short int number = 43690;//二进制形式为:1010101010101010
unsigned short int temp = 1 << 15;
for (int i = 0;i < 16;i++)
{
if (number & temp)
cout << "1";
else
cout << "0";
temp >>= 1;
}
return 0;
}
E 疯狂的支票本
#include <iostream>
#include <string>
#include <vector>
#include <iomanip>
using namespace std;
class check_info {
public:
string date; // Date the check was written
string what;// What the entry is about
float amount; // Amount of check or deposit
public:
check_info():
date(""),
what("")
{};
public:
void read();
};
// The STL vector to hold the check data
typedef std::vector<check_info> check_vector;
void check_info::read()
{
cin >> date;
cin >> what;
cin >> amount;
}
int main()
{
// Checkbook to test
check_vector checkbook;
while (1) {
check_info next_info; // Current check
next_info.read();
checkbook.push_back(next_info);
if (cin.eof())
break;
}
float total = 0.00; // Total in the bank
for (check_vector::iterator
cur_check = checkbook.begin();
cur_check != checkbook.end();
cur_check++)
{
total += cur_check->amount;
}
cout << "Total:" << setiosflags(ios::fixed) << setprecision(2) << total << endl;
return (0);
}
这个题也给跪了,问题出在数据结束时会有一个\n在吧\n读完后,cin.eof()的值才会为true,所以会多读入一次数据。
还有就是,浮点数的精度问题,这个比较坑爹,这个问题教育了我们,浮点数在任何情况下都是有误差的(两位有效数字也有),特别是在运算过程比较多的情况下,整形在任何情况下都是没误差的,用高精度或者是整形代替浮点数运算,可以消除这种误差。
#include <iostream>
#include <string>
#include <vector>
#include <iomanip>
using namespace std;
class check_info {
public:
string date; // Date the check was written
string what;// What the entry is about
unsigned long long amount; // Amount of check or deposit
public:
check_info():
date(""),
what(""),
amount(0)
{};
public:
void read();
};
// The STL vector to hold the check data
typedef std::vector<check_info> check_vector;
void check_info::read()
{
unsigned long long temp;
cin >> date >> what >> temp;
amount = temp * 100;
cin.get();
cin >> temp;
amount += temp;
F 数据hold不住
/************************************************
* test the data_holder class. *
************************************************/
#include <iostream>
/************************************************
* data_holder -- A class to hold a single *
* integer *
* Note: By default the value of the data is 5. *
* Warning: More member functions need to be *
* added to this to make it useful. *
************************************************/
class data_holder
{
private:
int data; // Data to store
public:
// Constructor -- Set value to default (5)
data_holder(void):data(5) {};
// Destructor defaults
//
// Copy constructor
data_holder(const data_holder &old)
{
*this = old;
}
// Assignment operator
data_holder operator = (
data_holder old_data_holder)
{
data = old_data_holder.data;
return (*this);
}
// Get the data item
int get(void)
{
return (data);
}
};
int main()
{
// A data holder
data_holder var1;
// Copy of a data holder
data_holder var2(var1);
return (0);
}
这题的错误在于函数不断递归调用,直到程序堆栈溢出。
原因是重载操作符时,调用了一个值参变量,这种调用方法会生成一个新的拷贝,并调用初始化函数,但是程序中重载的初始化函数又调用了重载的操作符,所以会产生
无限递归调用。只要把传参的方式改成传递地址就可以了。
data_holder &operator=(
const data_holder &old_data_holder)
G 谁动了我的内核
void * memcpy (void * dst, const void * src, size_t count)
{
void * ret = dst;
while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
return(ret);
}
#define BBSIZE 1024
char kbuf[BBSIZE];
int copy_from_kernel(void *user_dest, int maxlen)
{
int len = BBSIZE < maxlen ? BBSIZE : maxlen;
memcpy(user_dest, kbuf, len);
return len;
}
这题也是无符号型和有符号型的问题,吧有符号负数赋给无符号型,会产生一个很大的数。
H URL解码器
/**********************************************************
* urldecode.c
* decode url code
* change %** to ASCII and print other characters
***********************************************************/
#include <stdio.h>
int main()
{
// n - encoded hexadecimal char
// c - current reading char
int n;
char c;
while(1)
{
// read the character.
scanf("%c",&c);
if(c=='%')
{
// decode the hex value.
// use "%x" format to read the value directly.
if(scanf("%x",&n))
printf("%c",(char)n);
else
printf("\nInvalid code!\n");
}
else
// is other character. print it.
printf("%c",c);
}
return 0;
}
这个题也很蛋疼,我又跪了,需要判断文件末尾,题目描述也不算很清楚,不多说了。
/**********************************************************
* urldecode.c
* decode url code
* change %** to ASCII and print other characters
***********************************************************/
#include <stdio.h>
int check(int *n)
{
if((*n)>='0' && (*n)<='9')(*n)-='0';
else if((*n)>='a' && (*n)<='f')(*n)-=('a'-10);
else if((*n)>='A' && (*n)<='F')(*n)-=('A'-10);
else
{
printf("\nInvalid code!\n%c",*n);
return 1;
}
return 0;
}
int main()
{
// n - encoded hexadecimal char
// c - current reading char
char c; int n,x;
while(scanf("%c",&c)!=EOF)
{
if(c=='%')
{
// decode the hex value.
// read the first
if((n=getchar())==EOF)
{
printf("\nInvalid code!\n");
break;
}
if(check(&n))continue;
x=n<<4;
// read the second
if((n=getchar())==EOF)
{
x>>=4;
printf("%c",x);
break;
}
if(check(&n))continue;
x|=n;
printf("%c",x);
}
else
// is other character. print it.
printf("%c",c);
}
return 0;
}
I 艺术就是消失
#include <stdlib.h>
#include <iostream>
#include <cstring>
/************************************************
* info -- A class to hold information. *
* *
* Note: *
* Because someone is walking all over our *
* memory and destroying our data, we *
* have put two guards at the beginning *
* and end of our class. If someone *
* messes with us these numbers will *
* be destroyed. *
* *
* Member functions: *
* set_data -- Store a string in our data. *
* get_data -- Get the data string. *
* check_magic -- Check the magic numbers. *
************************************************/
// Magic numbers for the start and end of the
// data in the class info
const int START_MAGIC = 0x11223344;
const int END_MAGIC = 0x5567788;
class info
{
private:
// Magic protection constant
const int start_magic;
// String to be stored
char data[30];
// Magic protection constant
const int end_magic;
public:
info(void):
start_magic(START_MAGIC),
end_magic(END_MAGIC)
{}
// Copy constructor defaults
// Assignment operator defaults
// Destructor defaults
// Store some data in the class
void set_data(
// Data to be stored
const char what[]
)
{
strcpy(data, what);
}
// Get the data from the class
char *get_data(void)
{
return (data);
}
// Verify that the magic
// numbers are correct
void check_magic(void)
{
if ((start_magic != START_MAGIC) ||
(end_magic != END_MAGIC))
{
std::cout <<
"Info has lost its magic\n";
}
}
};
/************************************************
* new_info -- Create a new version of the *
* info class. *
************************************************/
struct info *new_info(void)
{
struct info *result; // Newly created result.
result = (struct info *)
malloc(sizeof(struct info));
// Make sure the structure is clear
memset(result, '\0', sizeof(result));
return (result);
}
int main()
{
// An info class to play with
class info *a_info = new_info();
a_info->set_data("Data");
a_info->check_magic();
return (0);
}
这道题不知道出题者要搞啥,提供了一种用malloc为类分配内存空间的方法.
接法是在return之前加上
new(result) info;
最后说一下,在c++中class和struct极其相像,转来转去应该没啥问题。
J 学长的困惑
蛋疼题,不说了