关于捉虫大赛的蛋疼想法

来源:互联网 发布:网络电视盒子 编辑:程序博客网 时间:2024/05/01 18:21

捉虫大赛,顾名思义就是找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 stdint 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 depositpublic:    check_info():        date(""),        what("")    {};public:    void read();    };// The STL vector to hold the check datatypedef 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 depositpublic:    check_info():        date(""),        what(""),        amount(0)    {};public:    void read();};// The STL vector to hold the check datatypedef 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 storepublic:    // 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 1024char 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 firstif((n=getchar())==EOF)            {                printf("\nInvalid code!\n");                break;            }if(check(&n))continue;            x=n<<4;            // read the secondif((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 infoconst 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 学长的困惑

蛋疼题,不说了