捉虫大赛,顾名思义就是找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; }
#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; }
#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;
/************************************************ * 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)
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; }
#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); }
接法是在return之前加上
new(result) info;最后说一下,在c++中class和struct极其相像,转来转去应该没啥问题。
J 学长的困惑
蛋疼题,不说了