Chinaunix首页 | 论坛 | 博客
  • 博客访问: 519556
  • 博文数量: 184
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1172
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-21 13:40
个人简介

技术改变命运

文章分类

全部博文(184)

文章存档

2020年(16)

2017年(12)

2016年(156)

我的朋友

分类: C/C++

2016-08-03 07:59:03

2016.9.4
分针和时针每隔(12/11)小时重合一次,一个钟面上分针和时针一昼夜重合(22)次

360 除以 (6-1/2) = 12/11小时
24除以12/11 = 22
本题考查钟表分针所转过的角度计算.钟表里的分钟与时针的转动问题本质上与行程问题中的两人追及问题非常相似.行程问题中的距离相当于这里的角度;行程问题中的速度相当于这里时(分)针的转动速度.
2016.8.16
和其他操作系统类似,Linux也支持两种进程:普通进程和实时进程。实时进程具有一定程度上的紧迫性,要求对外部事件做出非常快的响应;而普通进程则没有这种限制。所以,调度程序要区分对待这两种进程,通常,实时进程要比普通进程优先运行。这两种进程的区分也反映在task_struct数据结构中了。2016.8.25
在华为、中兴等企业招聘笔试面试中曾经出现过这样一道题目:什么函数不能声明为虚函数?

该题答案为:普通函数(非成员函数)、静态成员函数、内联成员函数、构造函数、友元函数
字符串转化成整数:

点击(此处)折叠或打开

  1. #include<stdio.h>
  2. int strToInt(const char *str)
  3. {
  4.     if (str == NULL)
  5.         return 0;
  6.     static const int MAX_INT =(int)((unsigned int)~0>>1);
  7.     static const int MIN_INT =-(int)((unsigned int)~0>>1)-1;
  8.     while (isspace(*str))
  9.         str++;
  10.     int sign = 1;
  11.     if (*str == '+' || *str == '-')
  12.     {
  13.         if (*str == '-')
  14.             sign = -1;
  15.         str++;
  16.     }     
  17.     unsigned int n = 0;//这一这里的unsigned
  18.     while (isdigit(*str))
  19.     {    
  20.         int c = *str - '0';
  21.         if (sign > 0 && (n > MAX_INT/10) || (n == MAX_INT/10 && c > MAX_INT % 10))
  22.         {
  23.             n = MAX_INT;
  24.             break;
  25.         }
  26.         if (sign < 0 && (n > (unsigned int)MIN_INT/10) || (n == MIN_INT/10 && c > (unsigned int)MIN_INT % 10))
  27.         {
  28.             n = MIN_INT;
  29.             break;
  30.         }
  31.         n = n*10 +c;
  32.         str++;
  33.     }
  34.         return sign > 0 ? n:-n;
  35. }
  36. int main()
  37. {
  38.     char *str = "123";
  39.     printf("%d\n",strToInt(str));
  40.     return 0;
  41. }

空结构体/类的大小为1。
微软笔试题:
what is the result of the follong program?


点击(此处)折叠或打开

  1. #include<iostream>
  2. #include<malloc.h>
  3. #include<string.h>
  4. using namespace std;
  5. char* f(char *str,char ch)
  6. {
  7.     char *it1 = str;
  8.     char *it2 = str;
  9.     while (*it2 != '\0')
  10.     {
  11.         while (*it2 == ch)
  12.         {
  13.             it2++;
  14.         }
  15.         *it1++ = *it2++;
  16.     }
  17.     return str;
  18. }
  19. int main(int argc,char *argv[])
  20. {
  21.     char *a = new char[10];
  22.     strcpy(a,"abcdcccd");
  23.     cout << f(a,'c');
  24.     delete[] a;
  25.     return 0;
  26. }
答案是abddcccd

\0

d

c

c

c

d

c

b

a


修改之后,上部分不变!

\0

d

c

c

c

d

d

b

a

下面的程序输出是什么?(2010 网易)

点击(此处)折叠或打开

  1. int main()
  2. {
  3.     int n;
  4.     char y[10] = "ntse";
  5.     char *x = y;
  6.     n = strlen(x);
  7.     *x = x[n];
  8.     x++;
  9.     printf("x = %s\n",x);
  10.     printf("y = %s\n",y);
  11.     return 0;
  12. }
输出结果:
x  =  tse
y = 
因为n=4,语句"n*x = x[n]"的功能是将x指向的第一个字符'\n'修改为'\0'。

 assert宏的原型定义在中,其作用是如果它的条件返回错误,则终止程序执行,原型定义:

#include <assert.h> void assert( int expression );

  assert的作用是现计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort 来终止程序运行。

(2012 完美世界)
32位小端字节序的机器上,如下代码:

点击(此处)折叠或打开

  1. char array[12] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08};
  2. short *pshort = (short *)array;
  3. int *pint = (int *)array;
  4. long long *pint64 = (long long *)array;
  5. printf("0x%x,0x%x,0x%x,0x%x",*pshort,*(pshort+2),*pint64,*(pint+2))
输出结果为:0x201,0x605,0x4030201,0x8070605。
注解:printf是最右侧的元素先入栈,若入栈元素是char,short等小于4个字节的类型,入栈时也占4个字节。无符号时高位补1,有符号时,高位补符号位。大于4个字节时,如long long,则按实际字节数入栈。

点击(此处)折叠或打开

  1. std::string name1 = "youku";
  2. const char *name2 = "youku";
  3. char name3[] = {'y','o','u','k','u'};
  4. size_t l1 = name1.size();//5
  5. size_t l2 = strlen(name2);//5
  6. size_t l3 = sizeof(name2);/4
  7. size_t l4 = sizeof(name3);//5;
  8. size_t l5 = strlen(name3);//?不确定
name3数组并未设置空字符,故strlen将数组name3后面的字符解释为数组中的字符,直到遇到空字符为止!!


c++空类默认产生哪些类成员函数:
class Empty


{

  public:

      Empty(); // 缺省构造函数

      Empty( const Empty& ); // 拷贝构造函数

      ~Empty(); // 析构函数

       Empty& operator=( const Empty& ); // 赋值运算符

       Empty* operator&(); // 取址运算符

       const Empty* operator&() const; // 取址运算符 const

};

默认构造函数 
析构函数 
拷贝构造函数 
赋值运算符(operator=) 
取址运算符(operator&)(一对,一个非const的,一个const的) 

     当然,所有这些只有当被需要才会产生。比如你定义了一个类,但从来定义过该类的对象,也没使用过该类型的函数参数,那么

基本啥也不会产生。在比如你从来没有进行过该类型对象之间的赋值,那么operator=不会被产生。

class Empty
{
public:
          Empty();                  //   缺省构造函数

          Empty(const   Empty&);    //   拷贝构造函数

          ~Empty();                 //   析构函数

          Empty& perator=(const Empty&); //   赋值运算符

           Empty* operator&();              //   取值运算符
          const Empty* operator&() const;   //   取值运算符

};


例如有以下class:

class StringBad
{
 private :
         char   * str;
          int len;

 public :
           StringBad( const   char   * s);
           StringBad();
           ~ StringBad();

} ;


在构造函数和析构函数定义当中有如下定义:

StringBad::StringBad( const   char   * s)
{
         len = std::strlen(s);
         str =   new   char [len +   1 ];

}

StringBad::StringBad()
{
        len =   4 ;
        str =   new   char [ 4 ];

}

StringBad:: ~ StringBad()
{

        delete [] str;
}

    那么在程序当中如果有以下代码:

    StringBad sports( " Spinach Leaves Bow1 for bollars " );

    StringBad sailor = sports;

    以上的第二条初始化语句将会调用什么构造函数?记住,这种形式的初始化等效于下面的语句:

    StringBad sailor = StringBad(sports);

    因为sports的类型为StringBad,因此相应的构造函数原型应该如下:

    StringBad( const StringBad & );

      当我们使用一个对象来初始化另一个对象时,编译器将自动生成上述构造函数(称为复制构造函数,因为它创建对象的一

个副本)

      现在我们来看看我们没有定义复制构造函数的情况下调用隐式复制构造函数将会出现什么情况。

      从构造函数定义的代码片断可以看到,当中使用new操作符初始化了一个指针str,而隐式的复制构造函数是按值进行复制

的,那么对于指针str,将会进行如下复制:

      sailor.str = sports.str;

       这里复制的不是字符串,而是一个指向字符串的指针!也就是说,我们将得到两个指向同一个字符串的指针!由此会产生的

问题将不言而喻。当其中一个对象调用了 析构函数之后,其str指向的内存将被释放,这个时候我们如果调用另一个对象,其

str指向的地址数据会是什么?很明显将会出现不可预料的结果。

       所以由此可见,如果类中包含了使用new初始化的指针成员,应当定义一个复制构造函数,以复制指向的数据,而不是指针,

被称为深度复制。因为默认的浅复制(或成为成员复制)仅浅浅的赋值指针信息。

      我们再看以下代码片断,我们稍做修改:

      StringBad headline1( " Celery Stalks at Midnight " );

      StringBad knot;

      knot = headline1;

       这里的最后一行将与以上例子有所区别,现在是将已有对象赋给另一个已有对象,这将会采取其他操作,即使用重载的赋值

操作符。(我们需要知道的是:初始化总是会调用复制构造函数,而使用=操作符时也可能调用赋值操作符)因为允许对

象赋值,这是通过自动为类重载赋值操作符实现的。其原型如下:

      Class_name & Class_name:: operator   = ( const Class_name & );

      它接受并返回一个指向类对象的引用。

      与隐式的复制构造函数一样,隐式的对象赋值操作符也会产生同样的问题,即包含了使用new初始化的指针成员时,只会采

用浅复制。所以我们需要使用同样的解决办法,即定义一个重载的赋值操作符来实现深度复制。

      所以综上所述,如果类中包含了使用new初始化的指针成员,我们应该显式定义一个复制构造函数和一个重载的赋值

操作符来实现其深度复制,避免由此带来的成员复制问题

    1. 以下函数哪个是拷贝构造函数,为什么?

    X::X(const X&);

    X::X(X);

    X::X(X&, int a=1);

    X::X(X&, int a=1, b=2);

    2. 一个类中可以存在多于一个的拷贝构造函数吗?

    3. 写出以下程序段的输出结果, 并说明为什么? 如果你都能回答无误的话,那么你已经对拷贝构造函数有了相当的了解。

#include
#include

struct X {
template
      X( T& ) { std::cout << "This is ctor." << std::endl; }

template
      X& perator=( T& ) { std::cout << "This is ctor." << std::endl; }
};

void main() {
      X a(5);
      X b(10.5);
      X c = a;
      c = b;
}


    解答如下:

    1. 对于一个类X,如果一个构造函数的第一个参数是下列之一:

    a) X&

    b) const X&

    c) volatile X&

    d) const volatile X&

    且没有其他参数或其他参数都有默认值,那么这个函数是拷贝构造函数。

    X::X(const X&); //是拷贝构造函数

    X::X(X&, int=1); //是拷贝构造函数

   2.类中可以存在超过一个拷贝构造函数,

class X {
public:
      X(const X&);
      X(X&);            // OK
};
注意,如果一个类中只存在一个参数为X&的拷贝构造函数,那么就不能使用const X或volatile X的对象实行拷贝初始化。

class X {
public:
     X();
     X(X&);
};

const X cx;
X x = cx;    // error

    如果一个类中没有定义拷贝构造函数,那么编译器会自动产生一个默认的拷贝构造函数。

    这个默认的参数可能为X::X(const X&)或X::X(X&),由编译器根据上下文决定选择哪一个。

    默认拷贝构造函数的行为如下:

    默认的拷贝构造函数执行的顺序与其他用户定义的构造函数相同,执行先父类后子类的构造。

    拷贝构造函数对类中每一个数据成员执行成员拷贝(memberwise Copy)的动作。

    a)如果数据成员为某一个类的实例,那么调用此类的拷贝构造函数。

    b)如果数据成员是一个数组,对数组的每一个执行按位拷贝。

    c)如果数据成员是一个数量,如int,double,那么调用系统内建的赋值运算符对其进行赋值。

    3. 拷贝构造函数不能由成员函数模版生成。

struct X {
template
      X( const T& );    // NOT copy ctor, T can't be X

 template
      perator=( const T& ); // NOT copy ass't, T can't be X
};

        原因很简单, 成员函数模版并不改变语言的规则,而语言的规则说,如果程序需要一个拷贝构造函数而你没
有声明它,那么编译器会为你自动生成一个。 所以成员函数模版并不会阻止编译器生成拷贝构造函数, 赋值运算
符重载也遵循同样的规则。(参见Effective  3edition, Item45)
逆邻接矩阵:

Adapter适配器模式
作用:将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

分为类适配器模式和对象适配器模式。

系统的数据和行为都正确,但接口不符时,我们应该考虑使用适配器,目的是使控制范围之外的一个原有对象与某个接口匹配。适配器模式主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况。

想使用一个已经存在的类,但如果它的接口,也就是它的方法和你的要求不相同时,就应该考虑用适配器模式。

比如购买的第三方开发组件,该组件接口与我们自己系统的接口不相同,或者由于某种原因无法直接调用该组件,可以考虑适配器。
在Adapter模式的两种模式中,有一个很重要的概念就是接口继承和实现继承的区别和联系。接口继承和实现继承是面向对象领域的两个重要的概念,接口继承指的是通过继承,子类获得了父类的接口,而实现继承指的是通过继承子类获得了父类的实现(并不统共接口)。在C++中的public继承既是接口继承又是实现继承,因为子类在继承了父类后既可以对外提供父类中的接口操作,又可以获得父类的接口实现。当然我们可以通过一定的方式和技术模拟单独的接口继承和实现继承,例如我们可以通过private继承获得实现继承的效果(private继承后,父类中的接口都变为private,当然只能是实现继承了。),通过纯抽象基类模拟接口继承的效果,但是在C++中pure virtual function也可以提供默认实现,因此这是不纯正的接口继承,但是在Java中我们可以interface来获得真正的接口继承了。
Input: 
每一行输入一个大整数,最多200位长度, 输入的最后一行是一个0, 表示输入的结束。

  1. 123456789012345678901234567890
  2. 123456789012345678901234567890
  3. 123456789012345678901234567890
  4. 0

Output:
输出输入的所有的数的和。
  1. 370370367037037036703703703670

下面是用字符数组实现的:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>

  /**

   计算两个大整数的和,输入:a和b分别使用字符串表示的两个大整数,输出:c是a和b的和

  */

  1. void sum(char *a, char *b, char *c) {
  2.    int i, j, k;
  3.    int len1 = strlen(a);
  4.    int len2 = strlen(b);
  5.    k = (len1 > len2) ? len1: len2;
  6.    memset(c, '0', k);
  7.    c[k+1] = '\0';
  8.    int carry = 0, temp;
  9.    for(i=len1-1, j=len2-1; i>=|| j>=0; i--, j--, k--)
  10.    {
  11.       temp = carry;
  12.       if(i>=0) temp += a[i] - '0';
  13.       if(j>=0) temp += b[j] - '0';
  14.       
  15.       if (temp >= 10) {
  16.          c[k] = temp - 10 + '0';
  17.          carry = 1;
  18.       } else {
  19.          c[k] = temp + '0';
  20.          carry = 0;
  21.       }
  22.    }
  23.    c[k] = carry + '0';
  24. }

  25. int main()
  26. {
  27.    char a[200], b[200], c[200], *p;
  28.    scanf("%s",a);
  29.    while(true) {
  30.       scanf("%s", b);
  31.       if(strcmp(b, "0") == 0) break;
  32.       sum(a, b, c);
  33.       p = c;
  34.       if(*== '0') p++;
  35.       strcpy(a, p);
  36.    }
  37.    
  38.    printf("The result is: %s \n", a);
  39.    system("pause");
  40.    return 0;
  41. }


阅读(1826) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~