Mac OS编译node-webkit概要

1)下载depot_tools,zip下载不了,直接git clone下

2)depot_tools加环境变量

3)gclient sync

a)python下载安装不了,可以手动安装python2.7.6,复制python.exe到depot_tools

b)git下载安装不了,可以手动安装git,设置环境变量到bin路径

c)sync先会下载chromium.src,有1.5G,如果用gclient sync会老是出错,因为太大了,国内环境大家都懂的。所以推荐使用github客户端来clone,clone下来后重命名到node-webkit/src

d)以后会clone88个工程,这个过程很懊恼,会话很久时间,googlesource.com网络有不是很稳定,所以先自己加个域名解析,会快点,如果是github的项目,建议跟c)一样,用客户端下载后放入目录。这里clone的都是chromium.src下的DEPS.git文件里的配置项目

e)88个项目都clone完成后,gclient会安装llvm/clang,然后编译。我使用的是OS X 11,编译时候老是提示clang: error: invalid deployment target for -stdlib=libc++ (requires OS X 10.7 or later) ,解决方案为修改node_webkit/src/tools/clang/scripts/update.sh MACOSX_DEPLOYMENT_TARGET=10.5 ==> MACOSX_DEPLOYMENT_TARGET=10.7

f)On OSX you’ll see error messages reporting cycle in .gyp file dependency graph detected. It can be ignored because gclient wants to run gyp_chromium without a switch we need. Please move on to the Build section
Error: Command /usr/bin/python src/build/gyp_chromium returned non-zero exit status 1 in /Users/gexin/Documents/nw_workspace/node_webkit
Hook ‘/usr/bin/python src/build/gyp_chromium’ took 42.73 secs

g)cd node-webkit/src
export GYP_GENERATORS=‘ninja’
./build/gyp_chromium content/content.gyp
ninja -C out/Release nw -j4

Myeclipse中JSP图片显示问题

src="${pageContext.request.contextPath}/pic/title_1.jpg"

${pageContext.request.contextPath}表示取得项目的WebRoot目录

如果页面不支持el表达式,则可以使用<%=request.getContextPath()%>代替

C++打印文件内容(类似cat命令)

1,类似cat的命令,查看文件的内容。
2,运行格式:./read_file file.in
3,注意,程序设定了单行长度最长为1000,可以修改。在考虑类似getline什么时候可以不需要确定读取的字符长度。

read_file.cpp

#include<iostream>
using namespace std;
#include<fstream>

int main(int argc,char *argv[])
{
if(argc<2)
{
   cout<<"Please input source file.."<<endl;
   return -1;
}
fstream infile(argv[1]);
if(infile==NULL)
{
   cout<<"The source file is empty"<<endl;
   return -1;
}
char buff[1000];
while(!infile.eof())
{
   infile.getline(buff,1000);
   cout<<buff<<endl;
   if(infile.peek()==-1)break;
}
return 0;
}

C++排序(从文件读入数据,重定向到out文件)

1,从file.in文件中读入数据保存在sort数组中。
2,对sort数组排序,重定向到file.out文件中。

sorting.cpp

#include <iostream>
using namespace std;
#include <fstream>

int main()
{
fstream infile("file.in");
if(infile==NULL)
{
   cout<<"file.in is empty.."<<endl;
   return 0;
}
int sort[21];
int i=0;
while(!infile.eof())
{
   //if(infile.peek()==-1)break;
   int c=infile.get();
   if(c==’\n’)break;
   if(c==’ ‘)continue;
   sort[i]=c-48;
   i++;
}
infile.close();
cout<<"sort:";
for(int k=0;k<i;k++)
{
   cout<<sort[k];
}
cout<<endl;

int tmp;
for(int n=0;n<i;n++)
{
   for(int m=n;m<i;m++)
   {
    if(sort[m]>sort[n])
    {
     tmp=sort[m];
     sort[m]=sort[n];
     sort[n]=tmp;
    }
   }
}

cout<<"sorting:";
for(int j=0;j<i;j++)
{
   cout<<sort[j];
}
cout<<endl;

fstream outfile("file.out",ios::out|ios::app);
for(int j=0;j<i;j++)
{
   outfile<<sort[j]<<‘ ‘;
}
//outfile<<‘\0′;
outfile.close();
return 0;
}

pro*c++实现类似分页机制

1,本程序类似于分页机制,程序运行要求输入pagecout和page,pagecount表示每页显示的记录条数,page表示第几页;

pagecount_page.pc

#include<iostream>
using namespace std;
#include"sqlca.h"

EXEC SQL BEGIN DECLARE SECTION;
char *uid="
soft/soft@192.168.0.2:1521/orasoft";
int pagecount;
int page;
int u_id;
int c_cursor;
char u_name[20];
EXEC SQL END DECLARE SECTION;

void sqlerr()
{
EXEC SQL WHENEVER SQLERROR CONTINUE;
cout<<sqlca.sqlerrm.sqlerrmc<<endl;
EXEC SQL ROLLBACK WORK RELEASE;
exit(1);
}

int main()
{
EXEC SQL WHENEVER SQLERROR DO sqlerr();
EXEC SQL CONNECT :uid;

cout<<"Please input pagecount:";
cin>>pagecount;
cout<<"Please input page:";
cin>>page;
c_cursor=(page-1)*pagecount+1;
cout<<"FECTH FROM :"<<c_cursor<<endl;
EXEC SQL WHENEVER NOT FOUND STOP;
EXEC SQL DECLARE emp_cursor SCROLL CURSOR FOR SELECT * FROM T_USER;
EXEC SQL OPEN emp_cursor;
cout<<"The pagecount:"<<pagecount<<",The page:"<<page<<endl;
cout<<"     u_id u_name     "<<endl;
cout<<"——— ———–"<<endl;
//EXEC SQL FETCH ABSOLUTE :c_cursor emp_cursor INTO :u_id,:u_name;
for(int i=0;i<pagecount;i++)
{
   EXEC SQL WHENEVER NOT FOUND DO break;
   EXEC SQL FETCH NEXT emp_cursor INTO :u_id,:u_name;
   cout<<"        "<<u_id<<" "<<u_name<<endl;
}
EXEC SQL CLOSE emp_cursor;
EXEC SQL COMMIT WORK RELEASE;
return 0;
}

C++笔试(网上收集)

这是一位同学整理的常见的笔试/面试题目,答案仅供参考,不代表本人观点。

这个东西有些参考价值,和同学讨论一下发现还是有些错误,

1.已知strcpy 函数的原型是:

char *strcpy(char *strDest, const char *strSrc);

其中strDest 是目的字符串,strSrc 是源字符串。不调用C++/C 的字符串库函数,请编写函数 strcpy

答案:

char *strcpy(char *strDest, const char *strSrc)

{

if ( strDest == NULL || strSrc == NULL)

return NULL ;

if ( strDest == strSrc)

return strDest ;

char *tempptr = strDest ;

while( (*strDest++ = *strSrc++) != ‘’)

;

return tempptr ;

}

2.已知类String 的原型为:

class String

{

public:

String(const char *str = NULL); // 普通构造函数

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

~ String(void); // 析构函数

String & operate =(const String &other); // 赋值函数

private:

char *m_data; // 用于保存字符串

};

请编写String 的上述4 个函数。

答案:

String::String(const char *str)

{

if ( str == NULL ) //strlen在参数为NULL时会抛异常才会有这步判断

{

m_data = new char[1] ;

m_data[0] = ” ;

}

else

{

m_data = new char[strlen(str) + 1];

strcpy(m_data,str);

}

}

String::String(const String &other)

{

m_data = new char[strlen(other.m_data) + 1];

strcpy(m_data,other.m_data);

}

String & String::operator =(const String &other)

{

if ( this == &other)

return *this ;

delete []m_data;

m_data = new char[strlen(other.m_data) + 1];

strcpy(m_data,other.m_data);

return *this ;

}

String::~ String(void)

{

delete []m_data ;

}

3.简答

3.1 头文件中的ifndef/define/endif 干什么用?

答:防止该头文件被重复引用。

3.2#i nclude <filename.h> 和#i nclude “filename.h” 有什么区别?

答:对于#i nclude <filename.h> ,编译器从标准库路径开始搜索filename.h

对于#i nclude “filename.h”,编译器从用户的工作路径开始搜索filename.h

3.3 在C++ 程序中调用被C 编译器编译后的函数,为什么要加extern “C”?

答:C++语言支持函数重载,C 语言不支持函数重载。函数被C++编译后在库中的名字与C 语言的不同。假设某个函数的原型为: void foo(int x, int y);

该函数被C 编译器编译后在库中的名字为_foo , 而C++ 编译器则会产生像_foo_int_int 之类的名字。

C++提供了C 连接交换指定符号extern“C”来解决名字匹配问题。

3.4 一个类有基类、内部有一个其他类的成员对象,构造函数的执行顺序是怎样的。(Autodesk)

答:先执行基类的(如果基类当中有虚基类,要先执行虚基类的,其他基类则按照声明派生类时的顺序依次执行),再执行成员对象的,最后执行自己的。

3.5 请描述一个你熟悉的设计模式(Autodesk)

3.6 在UML 中,聚合(aggregation)和组合(composition)有什么区别 Autodesk)

答案:聚合关系更强,类似于pages 和book 的关系;组合关系要弱,类似于books和bookshelf 的关系。

3.7C#和C++除了语法上的差别以外,有什么不同的地方?(Autodesk,Microsoft)

答案:(C#我只是了解,不是很精通)

(1) c#有垃圾自动回收机制,程序员不用担心对象的回收。(2)c#严禁使用指针,只能处理对象。如果希望使用指针,则仅可在unsafe 程序块中能使用指针。(3)c#只能单继承。(4)必须通过类名访问静态成员。不能像C++中那样,通过对象访问静态成员。(5)在子类中覆盖父类的虚函数时必须用关键字override,覆盖父类的方法要用关键字new

3.8ADO.net 和ADO 的区别?

答案:实际上除了“能够让应用程序处理存储于DBMS 中的数据“这一基本相似点外,两者没有太多共同之处。但是ADO 使用OLE DB 接口并基于微软的COM 技术,而ADO.NET 拥有自己的ADO.NET 接口并且基于微软的.NET 体系架构。众所周知.NET 体系不同于COM 体系,ADO.NET 接口也就完全不同于ADO和OLE DB 接口,这也就是说ADO.NET 和ADO是两种数据访问方式。ADO.net 提供对XML 的支持。

3.9 New delete 与malloc free 的区别 ( Autodesk)

答案:用malloc 函数不能初始化对象,new 会调用对象的构造函数。Delete 会调用对象的destructor,而free 不会调用对象的destructor.

3.10 #define DOUBLE(x) x+x (Autodesk)

i = 5*DOUBLE(10); i 是多少?正确的声明是什么?

答案:i 为60。正确的声明是#define DOUBLE(x) (x+x)

3.11 有哪几种情况只能用intialization list 而不能用assignment? (Autodesk)

答案:当类中含有const、reference 成员变量;基类的构造函数都需要参数;类中含有其他类的成员对象,而该类的构造函数都需要参数。

3.11 C++是不是类型安全的? (Autodesk)

答案:不是。两个不同类型的指针之间可以强制转换。C#是类型安全的。

3.12 main 函数执行以前,还会执行什么代码? (Autodesk)

答案:全局对象的构造函数会在main 函数之前执行。

3.13 描述内存分配方式以及它们的区别。 (Autodesk , Microsoft)

答案:1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static 变量。

(2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集。

(3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc 或new 申请任意多少的内存,程序员自己负责在何时用free 或delete 释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。

3.14 什么是虚拟存储器?virtual memory 怎样映射到physical memory?页面替换算法有哪些? (Microsoft)

见操作系统 p238 页。掌握的页面替换算法NRU,FIFO,第二次机会页面替换算法,LRU

3.15 有四个同样的容器,里面装满了粒数相同的药丸,正常药丸的质量为m,变质药丸的质量为m+1,现在已知这四个容器中,有一个装的全是变质药丸,用电子秤只称一次,找出哪个容器装的是变质药丸 (Microsoft)

答案:把四个容器依次编号为1、2、3、4,然后从中分别取出1、2、3、4 粒药丸,称这10 粒药丸的质量,如果质量为10m+1,则说明第一个容器装的是变质药丸,如果为10m+2 则说明第二个装的变质药丸,依次类推。

3.16 比较一下C++中static_cast 和 dynamic_cast 的区别。 (Autodesk)

dynamic_casts在帮助你浏览继承层次上是有限制的。它不能被用于缺乏虚函数的类型上,它被用于安全地沿着类的继承关系向下进行类型转换。如你想在没有继承关系的类型中进行转换,你可能想到static_cast

3.17 Struct 和class 的区别 (Autodesk)

答案:struct 中成员变量和成员函数默认访问权限是public,class 是private

3.18 当一个类A 中没有生命任何成员变量与成员函数,这时sizeof(A)的值是多少,如果不是零,请解释一下编译器为什么没有让它为零。(Autodesk)

答案:肯定不是零。我举个反例,如果是零的话,声明一个class A[10]对象数组,而每一个对象占用的空间是零,这时就没办法区分A[0],A[1]…了

3.19 在8086 汇编下,逻辑地址和物理地址是怎样转换的?(Intel)

答案:通用寄存器给出的地址,是段内偏移地址,相应段寄存器地址*10H+通用寄存器内地址,就得到了真正要访问的地址。

3.20 描述一下C++的多态 (microsoft)

答案:C++的多态表现在两个部分,一个是静态连编下的函数重载,运算符重载;动态连编下的虚函数、纯虚函数(抽象类)

4.写出BOOL,int,float,指针类型的变量a 与零的比较语句。

答案:

BOOL : if ( !a )

int : if ( a == 0)

float : const EXPRESSION EXP = 0.000001

if ( a < EXP && a >-EXP)

pointer : if ( a != NULL)

5.请说出const 与#define 相比优点

答案:

(1) const 常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误。

(2) 有些集成化的调试工具可以对const 常量进行调试,但是不能对宏常量进行调试。

6.简述数组与指针的区别

数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。指针可以随时指向任意类型的内存块。

(1)修改内容上的差别

char a[] = “hello”;

a[0] = ‘X’;

char *p = “world”; // 注意p 指向常量字符串

p[0] = ‘X’; // 编译器不能发现该错误,运行时错误

(2) 用运算符sizeof 可以计算出数组的容量(字节数)。sizeof(p),p 为指针得到的是一个指针变量的字节数,而不是p 所指的内存容量。C++/C 语言没有办法知道指针所指的内存容量,除非在申请内存时记住它。注意当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针。

char a[] = "hello world";

char *p = a;

cout<< sizeof(a) << endl; // 12 字节

cout<< sizeof(p) << endl; // 4 字节

计算数组和指针的内存容量

void Func(char a[100])

{

cout<< sizeof(a) << endl; // 4 字节而不是100 字节

}

7.类成员函数的重载、覆盖和隐藏区别

答案:

成员函数被重载的特征:

(1)相同的范围(在同一个类中);

(2)函数名字相同;

(3)参数不同;

(4)virtual 关键字可有可无。

覆盖是指派生类函数覆盖基类函数,特征是:

(1)不同的范围(分别位于派生类与基类);

(2)函数名字相同;

(3)参数相同;

(4)基类函数必须有virtual 关键字。

“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:

(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。

(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual 关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)

8.There are two int variables: a and b, don’t use “if”, “? :”, “switch”

or other judgement statements, find out the biggest one of the two

numbers.

答案:( ( a + b ) + abs( a – b ) ) / 2

9.如何打印出当前源文件的文件名以及源文件的当前行号?

答案:

cout << __FILE__ ;

cout<<__LINE__ ;

__FILE__和__LINE__是系统预定义宏,这种宏并不是在某个文件中定义的,而是由编译器定义的。

10.main 主函数执行完毕后,是否可能会再执行一段代码,给出说明?

答案:可以,可以用_onexit 注册一个函数,它会在main 之后执行int fn1(void), fn2(void), fn3(void), fn4 (void);

void main( void )

{

String str("zhanglin");

_onexit( fn1 );

_onexit( fn2 );

_onexit( fn3 );

_onexit( fn4 );

printf( "This is executed first.\n" );

}

int fn1()

{

printf( "next.\n" );

return 0;

}

int fn2()

{

printf( "executed " );

return 0;

}

int fn3()

{

printf( "is " );

return 0;

}

int fn4()

{

printf( "This " );

return 0;

}

The _onexit function is passed the address of a function (func) to be called when the program terminates normally. Successive calls to _onexit create a register of functions that are executed in LIFO (last-in-first-out) order. The functions passed to _onexit cannot take parameters.

11.如何判断一段程序是由C 编译程序还是由C++编译程序编译的?

答案:

#ifdef __cplusplus

cout<<"c++";

#else

cout<<"c";

#endif

12.文件中有一组整数,要求排序后输出到另一个文件中

答案:

void Order(vector<int> &data) //起泡排序

{

int count = data.size() ;

int tag = false ;

for ( int i = 0 ; i < count ; i++)

{

for ( int j = 0 ; j < count – i – 1 ; j++)

{

if ( data[j] > data[j+1])

{

tag = true ;

int temp = data[j] ;

data[j] = data[j+1] ;

data[j+1] = temp ;

}

}

if ( !tag )

break ;

}

}

void main( void )

{

vector<int>data;

ifstream in("c:\\data.txt");

if ( !in)

{

cout<<"file error!";

exit(1);

}

int temp;

while (!in.eof())

{

in>>temp;

data.push_back(temp);

}

in.close();

Order(data);

ofstream out("c:\\result.txt");

if ( !out)

{

cout<<"file error!";

exit(1);

}

for ( i = 0 ; i < data.size() ; i++)

out<<data[i]<<" ";

out.close();

}

13.排序方法比较 (intel)

排序方法 平均时间 最坏时间 辅助存储

直接插入排序

起泡排序

快速排序

简单选择排序

堆排序

归并排序

基数排序

14.一个链表的结点结构

struct Node

{

int data ;

Node *next ;

};

typedef struct Node Node ;

(1)已知链表的头结点head,写一个函数把这个链表逆序 ( Intel)

Node * ReverseList(Node *head) //链表逆序

{

if ( head == NULL || head->next == NULL )

return head;

Node *p1 = head ;

Node *p2 = p1->next ;

Node *p3 = p2->next ;

p1->next = NULL ;

while ( p3 != NULL )

{

p2->next = p1 ;

p1 = p2 ;

p2 = p3 ;

p3 = p3->next ;

}

p2->next = p1 ;

head = p2 ;

return head ;

}

(2)已知两个链表head1 和head2 各自有序,请把它们合并成一个链表依然有序。

Node * Merge(Node *head1 , Node *head2)

{

if ( head1 == NULL)

return head2 ;

if ( head2 == NULL)

return head1 ;

Node *head = NULL ;

Node *p1 = NULL;

Node *p2 = NULL;

if ( head1->data < head2->data )

{

head = head1 ;

p1 = head1->next;

p2 = head2 ;

}

else

{

head = head2 ;

p2 = head2->next ;

p1 = head1 ;

}

Node *pcurrent = head ;

while ( p1 != NULL && p2 != NULL)

{

if ( p1->data <= p2->data )

{

pcurrent->next = p1 ;

pcurrent = p1 ;

p1 = p1->next ;

}

else

{

pcurrent->next = p2 ;

pcurrent = p2 ;

p2 = p2->next ;

}

}

if ( p1 != NULL )

pcurrent->next = p1 ;

if ( p2 != NULL )

pcurrent->next = p2 ;

return head ;

}

(2)已知两个链表head1 和head2 各自有序,请把它们合并成一个链表依然有序,这次要求用递归方法进行。 ( Autodesk)

答案:

Node * MergeRecursive(Node *head1 , Node *head2)

{

if ( head1 == NULL )

return head2 ;

if ( head2 == NULL)

return head1 ;

Node *head = NULL ;

if ( head1->data < head2->data )

{

head = head1 ;

head->next = MergeRecursive(head1->next,head2);

}

else

{

head = head2 ;

head->next = MergeRecursive(head1,head2->next);

}

return head ;

}

15.分析一下这段程序的输出 (Autodesk)

class B

{

public:

B()

{

cout<<"default constructor"<<endl;

}

~B()

{

cout<<"destructed"<<endl;

}

B(int i):data(i)

{

cout<<"constructed by parameter" << data <<endl;

}

private:

int data;

};

B Play( B b)

{

return b ;

}

int main(int argc, char* argv[])

{

B temp = Play(5);

return 0;

}

请自己执行一下看看。

16.写一个函数找出一个整数数组中,第二大的数 (microsoft)

答案:

const int MINNUMBER = -32767 ;

int find_sec_max( int data[] , int count) //类似于1 4 4 4这样的序列将认为1是第二大数

{

int maxnumber = data[0] ;

int sec_max = MINNUMBER ;

for ( int i = 1 ; i < count ; i++)

{

if ( data[i] > maxnumber )

{

sec_max = maxnumber ;

maxnumber = data[i] ;

}

else

{

if ( data[i] > sec_max )

sec_max = data[i] ;

}

}

return sec_max ;

}

17 写一个在一个字符串中寻找一个子串第一个位置的函数

这个题目的一般算法比较简单我就不给出了,如果要求高效率的话请参见数据结构中的KMP 算法,不过在笔试时间有限情况下,写出那个算法还是挺难的。

英文题目

1. Introduce yourself in English

2. What is your great advantage you think of yourself?

3. What is your drawback you think of yourself?

Maybe I will feel very tense if I make a speech in front of a lot of people.

4. How do you feel shanghai?

16. 关联、聚合(Aggregation)以及组合(Composition)的区别?

涉及到UML中的一些概念:关联是表示两个类的一般性联系,比如“学生”和“老师”就是一种关联关系;聚合表示has-a的关系,是一种相对松散的关系,聚合类不需要对被聚合类负责,如下图所示,用空的菱形表示聚合关系:

                           500){this.resized=true;this.style.width=500;}" border=0>

从实现的角度讲,聚合可以表示为:

class A {…} class B { A* a; …..}

而组合表示contains-a的关系,关联性强于聚合:组合类与被组合类有相同的生命周期,组合类要对被组合类负责,采用实心的菱形表示组合关系:

                            500){this.resized=true;this.style.width=500;}" border=0>

实现的形式是:

class A{…} class B{ A a; …}

参考文章:http://www.cnitblog.com/Lily/archive/2006/02/23/6860.html

          http://www.vckbase.com/document/viewdoc/?id=422

17.面向对象的三个基本特征,并简单叙述之?

1. 封装:将客观事物抽象成类,每个类对自身的数据和方法实行protection(private, protected,public)

2. 继承:广义的继承有三种实现形式:实现继承(指使用基类的属性和方法而无需额外编码的能力)、可视继承(子窗体使用父窗体的外观和实现代码)、接口继承(仅使用属性和方法,实现滞后到子类实现)。前两种(类继承)和后一种(对象组合=>接口继承以及纯虚函数)构成了功能复用的两种方式。

3. 多态:是将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。

18. 重载(overload)和重写(overried,有的书也叫做“覆盖”)的区别?

常考的题目。从定义上来说:

重载:是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。

重写:是指子类重新定义复类虚函数的方法。

从实现原理上来说:

重载:编译器根据函数不同的参数表,对同名函数的名称做修饰,然后这些同名函数就成了不同的函数(至少对于编译器来说是这样的)。如,有两个同名函数:function func(p:integer):integer;和function func(p:string):integer;。那么编译器做过修饰后的函数名称可能是这样的:int_func、str_func。对于这两个函数的调用,在编译器间就已经确定了,是静态的。也就是说,它们的地址在编译期就绑定了(早绑定),因此,重载和多态无关!

重写:和多态真正相关。当子类重新定义了父类的虚函数后,父类指针根据赋给它的不同的子类指针,动态的调用属于子类的该函数,这样的函数调用在编译期间是无法确定的(调用的子类的虚函数的地址无法给出)。因此,这样的函数地址是在运行期绑定的(晚绑定)。

19. 多态的作用?

主要是两个:1. 隐藏实现细节,使得代码能够模块化;扩展代码模块,实现代码重用;2. 接口重用:为了类在继承和派生的时候,保证使用家族中任一类的实例的某一属性时的正确调用。

20. Ado与Ado.net的相同与不同?

除了“能够让应用程序处理存储于DBMS 中的数据“这一基本相似点外,两者没有太多共同之处。但是Ado使用OLE DB 接口并基于微软的COM 技术,而ADO.NET 拥有自己的ADO.NET 接口并且基于微软的.NET 体系架构。众所周知.NET 体系不同于COM 体系,ADO.NET 接口也就完全不同于ADO和OLE DB 接口,这也就是说ADO.NET 和ADO是两种数据访问方式。ADO.net 提供对XML 的支持。

21. New delete 与malloc free 的联系与区别?

答案:都是在堆(heap)上进行动态的内存操作。用malloc函数需要指定内存分配的字节数并且不能初始化对象,new 会自动调用对象的构造函数。delete 会调用对象的destructor,而free 不会调用对象的destructor.

22. #define DOUBLE(x) x+x ,i = 5*DOUBLE(5); i 是多少?

答案:i 为30。

23. 有哪几种情况只能用intialization list 而不能用assignment?

答案:当类中含有const、reference 成员变量;基类的构造函数都需要初始化表。

24. C++是不是类型安全的?

答案:不是。两个不同类型的指针之间可以强制转换(用reinterpret cast)。C#是类型安全的。

25. main 函数执行以前,还会执行什么代码?

答案:全局对象的构造函数会在main 函数之前执行。

26. 描述内存分配方式以及它们的区别?

1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static 变量。

2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集。

3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc 或new 申请任意多少的内存,程序员自己负责在何时用free 或delete 释放内存。动态内存的生存期由程序员决定,使用非常灵活,但问题也最多。

27.struct 和 class 的区别

答案:struct 的成员默认是公有的,而类的成员默认是私有的。struct 和 class 在其他方面是功能相当的。

从感情上讲,大多数的开发者感到类和结构有很大的差别。感觉上结构仅仅象一堆缺乏封装和功能的开放的内存位,而类就象活的并且可靠的社会成员,它有智能服务,有牢固的封装屏障和一个良好定义的接口。既然大多数人都这么认为,那么只有在你的类有很少的方法并且有公有数据(这种事情在良好设计的系统中是存在的!)时,你也许应该使用 struct 关键字,否则,你应该使用 class 关键字。

28.当一个类A 中没有生命任何成员变量与成员函数,这时sizeof(A)的值是多少,如果不是零,请解释一下编译器为什么没有让它为零。(Autodesk)

答案:肯定不是零。举个反例,如果是零的话,声明一个class A[10]对象数组,而每一个对象占用的空间是零,这时就没办法区分A[0],A[1]…了。

29. 在8086 汇编下,逻辑地址和物理地址是怎样转换的?(Intel)

答案:通用寄存器给出的地址,是段内偏移地址,相应段寄存器地址*10H+通用寄存器内地址,就得到了真正要访问的地址。

30. 比较C++中的4种类型转换方式?

请参考:http://blog.bioon.com/user1/8688/archives/2006/45399.shtml,重点是static_cast, dynamic_cast和reinterpret_cast的区别和应用。

第一个pro*c++程序

程序说明:

1,从dynamic_file.in中读入动态的sql语句,创建跟T_USER一样的表T_USER2,并且插入一条数据;
2,从dynamic_file1.in中读入动态的sql语句,删除T_USER2表;
3,把所有的sql语句内容,错误信息,时间存储在dynamic_file.log的日志文件中。

dynamic_file.pc

#include <iostream>
using namespace std;
#include "sqlca.h"
#include "fstream"
#include "time.h"

EXEC SQL BEGIN DECLARE SECTION;
char *uid="
soft/soft@192.168.0.2:1521/orasoft";
char sqlstmt[100];
//char buf[100]
EXEC SQL END DECLARE SECTION;

//fstream outfile("dynamic_file.log");

void sqlerr()
{
EXEC SQL WHENEVER SQLERROR CONTINUE;
fstream errlog("dynamic_file.log",ios::out|ios::app);
cout<<sqlca.sqlerrm.sqlerrmc<<endl;
time_t ltime;
time(&ltime);
//cout<<time<<endl;
errlog.write(ctime(&ltime),strlen(ctime(&ltime)));
errlog.write(sqlca.sqlerrm.sqlerrmc,strlen(sqlca.sqlerrm.sqlerrmc));
errlog<<‘\n';
EXEC SQL ROLLBACK WORK RELEASE;
errlog.close();
exit(1);
}

int main(int argc,char* argv[])
{
if(argc<2)
{
   cout<<"please input source file like:<filename> <source file>"<<endl;
   return 0;
}
EXEC SQL WHENEVER SQLERROR DO sqlerr();
EXEC SQL CONNECT :uid;

fstream infile(argv[1]);
cout<<"source file:"<<argv[1]<<endl;
if(infile==NULL)
{
   cout<<"the source file is empty.."<<endl;
   return 0;
}

fstream outfile("dynamic_file.log",ios::out | ios::app);
while(!infile.eof())
{
   //cout<<infile.get()<<endl;
   infile.getline(sqlstmt,100);
   cout<<"sqlstmt:"<<sqlstmt<<endl;
   EXEC SQL EXECUTE IMMEDIATE :sqlstmt;
   time_t ltime;
   time(&ltime);
   outfile<<ctime(&ltime);
   outfile.write(sqlstmt,strlen(sqlstmt));
   outfile<<‘\n';
   if(infile.peek()==-1)break;
}
EXEC SQL COMMIT WORK RELEASE;
infile.close();
outfile.close();
cout<<"————–OK————–"<<endl;
return 0;
}

dynamic_file.in

CREATE TABLE T_USER2 AS SELECT * FROM T_USER
INSERT INTO T_USER2 VALUES(100,’ABC’)

dynamic_file1.in

DROP TABLE T_USER2

有些地方还需要改进,比如把写log功能封装到一个类

C++中get()和getline()的使用区别1

问题一:

#include <iostream>

#include <string>

using namespace std;

void main(void)

{

string st ;

cout<<"Input st:";

getline(cin,st);

cout<<st<<endl;

}



上面这段代码,如果输入abc,那么需要按两次回车键才能显示abc(在VC6中),因为getline有三个参数,第三个参数是字符串的结束符,也就是当getline遇到这个结束符时,就不在接受输入了,比如写成 getline(cin,st,’s’); 即使输入的是abcsabc 那么也只会显示 abc ,因此对于上面出现的情况,有人说getline默认情况下以回车(‘\n’)作为结束符,第一次按回车表示字符串结束,第二次按回车才开始输出。也有人说这是VC6的bug,我觉得前一种解释比较合理,因为:



如果你输入abc(回车)abc,那么程序会显示abc,可见回车的确是函数默认的结束符。

同理1getline(cin,candybar
.pinpai); 就是当输入一串字符串后赋值给candybar.pinpai,然后再按二次回车才显示在屏幕上!

问题二:

1.cin.getline是读入一行字符,比如:

#include <iostream.h>

void main()

{

char str[20];

cout<<"Input :";

cin.getline(str,20);

cout<<str<<endl;

}

当输入:abd cdrasdf g的时候就会输出:abd cdrasdf g。

2.cin.get()第一个用法,是读入一个字符。

#include <iostream.h>

void main()

{

char str;

cout<<"Input :";

str=cin.get();

cout<<str<<endl;

}

当你输入“ABAF”的时候,只会显示“A”,因为只读入了一个字符(空格也可以读入)。

3.cin.get()第二个用法,也是输入一行(同cin.getline()),但是区别就是,不输出分隔符~



===============================================

C++中get()和getline()的使用区别2

另一篇文章

用getline()读取输入行

当程序使用cin输入时,cin用空白符和行结束符将各个值分开。根据所需输入的值,如需读取一整行文本并且分开不同的域,则要使用getline成员函数


getline(char*line,int size,char =‘"n’)

第二个参数是本次读取的最大字符个数,第三个参数是分隔字符,作为读取一行结束的标志。

下面的函数从键盘读取一行文本

#include <iostream>

using namespace std;



int main()

{

char str[128];



cin.getline(str,sizeof(str));

cout <<"you typed :" <<str<<endl;





}
#include <iostream>

using namespace std;



int main()

{

char str[128];

cout<<"please input text and enter"<<endl;

cin.getline(str,sizeof(str),‘X’);

cout <<"you typed first line:" <<str<<endl;



cin.getline(str,sizeof(str));

cout <<"sencond line :"<<str<<endl;



}

在键入X之前,可以按一次到多次回车键,而并不结束第一个cin.getline()的输入 。 第一个cin.getline()的输入操作将以键入X后的第一个回车结束。

cin.getline() 与 cin>>str 的一个不同是,前者输入一行,行中可以包含空格,后者却以空格或回车作为字串结束,不包含空格。

用get()读取一个字符

每次获取一个字符:char istream:[img]editor/images/smilies/default/24.gif[/img]

//get.cpp

#include <iostream>

using namespace std;



int main()

{

char letter;



while(!cin.eof())

{

letter=cin.get();

letter=toupper(letter);

if (letter==‘Y’)

{

cout <<" "nY have been met "n";

break;



}

cout <<letter;

}



}





使用流成员函数的输入操作不只限于键盘,上例程序可从重定向输入中读取。

$ ./get < get.cpp

letter =cin.get();与cin>>letter 都是从输入流中取一个字符,但却有区别,默认情况下,cin>>letter将跳过任何在文件中发现的任何空白字符(空白字符指空格, tab,backspace,回车) .而cin.get不跳过空白字符。

用get()输入一系列字符



istream&istream::get(char*,int n,char delim=‘"n’);



istream fin("abc.txt");


char buffer[80];

fin>>buffer; //不能保证输入字符个数在80以内。

可以改写为

istream fin("abc.txt");

char buffer[80];

fin.get(buffer,80); //保证输入字符个数在80以内

getline()与get()第二种形式相同,唯一的例外是getline()从输入流中输入一系列字符时包括分隔符,而get()不包括分隔符。

put成员函数,依次输出字符。

#include <iostream>

using namespace std;



int main()

{

char letter;

for (letter=‘A’; letter<=‘Z’;letter++)

cout.put(letter);



}

cout<<letter; 与cout.put(letter)的区别是:前者显示以数据类型表示的形式,后者以字符方式显示。若letter是char型,两者一样。若 letter是int型,则cout<<letter显示数字而不是字符了。

#include <iostream>

#include <fstream>

using namespace std;



int main()

{

ifstream in("put.cpp");



if (in.fail())

{

cerr<<"Error opening the file"n";

}



while (!in.eof( ) )

{

cout.put(in.get() );

}



}

//注意get()这种形势它读取了空白符(含回车符),不跳过任何的字符。与


get(char * ,int n ,delim=’"n’)这种行式不同,他不包括分隔符delim.



cin<<的结束符有enter space tab

cin.get()的结束符只有enter,但会把enter放入队列等待

cin.getline()的结束符也只有enter,但不会把enter放入队列





如果用cin>>…做过输入,在使用cin.getline之前,需要处理一下。处理的方法很多,你可以在cin>>…的输入语句后加一个语句cin.get();。

Oracle Pro*C 动态SQL技术

Pro*C的常用动态SQL技术一共有3种:

  1. 用于处理不包含宿主变量的动态SQL, 不能用于SELECT语句.
  2. 用于处理输入宿主变量个数和类型已经确定的动态SQL, 不能用于SELECT语句.
  3. 用于处理选择列表项和输入宿主变量个数已经确定的动态SQL, 此种方法可以处理所有前两种方法能处理的情况, 此外, 还能处理SELECT语句.

由于第3种方法已经包含前两种方法的处理范围, 这篇文章我们主要介绍第3种方法.

1 介绍:

1.1 适用语句:

  • DML(Data Manipulation Language 数据操纵语言)
  • DDL(Data Definition Language 数据定义语言)
  • DCL(Data Control Language 数据控制语言)
  • 以及事务控制语句
  • 而且还可以处理SELECT语句

    用SQL语句举例就是:

  • DELETE FROM tbl_name WHERE name=xxx
  • CREATE TABLE tbl_name(cola INT)
  • GRANT SELECT ON xx TO xxx
  • COMMIT
  • INSERT INTO tbl_name VALUES(:a)
  • DELETE FROM tbl_name WHERE name=:a
  • SELECT name FROM tbl_name WHERE no=xxx

1.2 不能处理的语句:

总体来讲就是对象名和列名不能使用宿主变量, 例如:

  • INSERT INTO :a VALUES(:b)
  • SELECT :a, :b FROM tbl_name WHERE name=:c

2 处理步骤:

2.1 PREPARE语句:

PREPARE命令用于明明和解析SQL语句, 语法如下:

EXEC SQL PREPARE statement_name
    
FROM {:host_string | string_literal};

说明:

  • statement_name: 预编译器标识符.
  • host_string: 包含SQL语句的宿主变量.
  • string_literal: SQL语句文本字符串.

2.2 DECLARE游标:

使用PREPARE准备了SQL语句之后, 应该执行内嵌DECLARE命令定义游标, 语法如下:

EXEC SQL DECLARE cursor_name CURSOR
    
FOR statement_name;

说明:

  • cursor_name: 游标名.
  • statement_name: statement标识符, 在PREPARE过程中使用的.

2.3 OPEN打开游标:

当开始游标时, 会执行游标所对应的SQL语句, 语法如下:

EXEC SQL OPEN cursor_name [USING host_variable_list];

说明:

  • cursor_name: 游标名, 前面DECLARE的.
  • host_variable_list: 输入的宿主变量列表.

当执行OPEN命令时, 如果SQL语句不是SELECT语句, 会直接执行该语句, 此后可以关闭游标; 如果SQL语句是SELECT语句, 那么会将查询结果放到游标结果集中, 还必须使用内嵌的FETCH语句提取并处理游标结果集, 之后再关闭游标.

2.4 FETCH提取游标数据:

当SQL语句是SELECT语句时, OPEN之后会把结果存放到游标结果集中, 为了处理查询结果, 需要使用FETCH来提取数据, 语法如下:

EXEC SQL FETCH cursor_name INTO host_variable_list;

说明:

cursor_name: 游标名, 前面OPEN的.

host_variable_list: 输入的宿主变量列表.

2.5 CLOSE关闭游标:

提取并处理完游标数据后, 关闭游标, 语法如下:

EXEC SQL CLOSE cursor_name;

3 代码举例:

/* 大组成员表结构 */
struct GrpMember
{
    
char str_bgID[22];  /* 大组ID */

    
char str_matID[22]; /* 素材ID */
     …
     …
};

/**
* 素材检索
* 填冲好一个输入结构, 作为函数的参数进行调用.
*
* 这个输入结构中的各各成员项可以为空,
* 通过判断来确定数据库检索条件, 即: SELECT语句后面的条件.
*
*/

void MatSearch(struct GrpMember *in)
{
    
/* 定义临时变量 */

    
char buf[256]; /* buffer */

    /* 定义宿主变量 */
     EXEC SQL BEGIN DECLARE SECTION;
        
char sql_buf[1024]; /* 存放SQL语句 */
        
struct GrpMember ret; /* 查询结果 */
     EXEC SQL END DECLARE SECTION;

    /**
      * 根据参数, 构造SQL语句
      *
      * 1 把SQL语句的前半部分拷贝到buffer中.
      * 2 判断输入参数的结构中各成员项是否为空, 如不为空, 则add到buffer中.
     
*/

     strcpy(sql_buf,
"SELECT * FROM TBL_GRPMEMBER WHERE 1=1 ");
    
if (!
isEmpty(str_bgID))
     {
         sprintf(buf,
"AND tbl_str_bgID = %s "
, str_bgID);
         strcat(sql_buf, buf);
     }
     …
     …

    /* 准备动态SQL */
     EXEC SQL PREPARE sql_stmt FROM :sql_buf;

    /* 定义游标 */
     EXEC SQL DECLARE c1 CURSOR FOR sql_stmt;

    /* 打开游标: 执行查询 */
     EXEC SQL OPEN c1;

    /* 提取查询结果 */
    
while(1)
     {
         EXEC SQL FETCH c1 INTO ret;
/* 此处伪代码, 应该逐项INTO, 逗号分割, 具体见游标的使用 */

     }

     EXEC SQL CLOSE c1;
}