Archived

This topic is now archived and is closed to further replies.

archon

C++ interview questions and pitfalls

Recommended Posts

Hello Folks, I have a technical interview this week for a position requiring a bit more C++ than I have. I''ve spent today and friday reading, and my brain is a little fried right now. Anyways, I''m trying to laser beam on what to spend my remaining time studying and... my question is this: I was wondering if you all would be so kind as to post tough questions, trick questions that you would think would stump someone like me (I''ve been programming java professionally for a while, and this would be my first foray into professional C++), questions about thorny bits of theory and exceptions to the rules and crazy function declarations and lots of stuff that I probably don''t even know, about C++ (along with the answers preferrably Anything along these lines would be a big help. TIA! Archon

Share this post


Link to post
Share on other sites
Write atoi without using any built in libraries.

Reverse a char * string in place.

swap two ints without using a temporary variable.

Give a linked list, determine if it has a cycle.

Why is it better to use a function object over a function pointer for the STL sort(or any other stl algorithm for that matter)?

When a class has a virtual destructor, what does that imply? what if its destructor is non-virtual?

Say you''re making a class heirarchy of shapes. Should rectangle be derived from square?
What about square from rectangle?
Why?

State one case in which the code would clearly benefit from the presence of a goto.

Compare the design methodologies for the STL with the Java collections library. What are the design goals? Why were each designed the way they were?

If you could add one feature to the C++ language, what would it be?

If you could remove one feature from the c++ language, what would it be?

How would you provide behavior like the ''finally'' statement from java, in c++?

given the following class, in what order are the constructors called?

class X
{
X::X(string name,int size);
vector v;
int size;
string name;
}

X::X(string nm,int sz):
size(sz),v(size),name(nm)
{
//nothing to do
}

bonus points: what''s the bug in the code?

That''s a bunch for now, if you need them i''ll post answers later

Share this post


Link to post
Share on other sites
I'm dying to see the answers to some of those....
Actually I'm gonna to answer them myself (offline)

oh yeah and the bug is in the declaration of the constructor

Edited by - ChaosEngine on February 19, 2002 11:13:18 AM

Share this post


Link to post
Share on other sites
In the following code, what will the output be:

  
int main(int argc, char *argv[])
{
char *lpString = "abcdefghijklmnopqrstuvwxyz";
int nNumber = 0;

for(int i=0; i < 8; i++){
cout << nNumber[lpString];
nNumber += i;
}
cout << endl;

return 0;
}

Share this post


Link to post
Share on other sites
Not strictly C++, but you answer it in C++. This question was asked at my job interview.

Say you have two variables "a" and "b". How would you exchange the contents of these two variables without using any other intermediate storage?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
quote:
Original post by sjelkjd
swap two ints without using a temporary variable.



I think that is what he meant.

Share this post


Link to post
Share on other sites
name all the uses of static.

name all the uses of const.

Very simple, about 80% of applicants I saw when interviewing couldn''t answer.

Then there''s my infamous "clear_bit" question. Search for the thread entitled "Horrible Interviews" if you want to go over some old discussion.

Share this post


Link to post
Share on other sites
quote:
Original post by JonStelly
In the following code, what will the output be:



That wouldn't compile - nNumber doesn't have an operator []. I think you meant lpString[nNumber] ?

I like this thread, keep em coming

edit: the thread stoffel was on about

Edited by - Spiral on February 19, 2002 2:19:39 PM

Share this post


Link to post
Share on other sites
WARNING : I am no guru and do not claim all my answers are right

Write atoi without using any built in libraries.
don't want to write the code

Reverse a char * string in place.
I haven't use a char* in years

swap two ints without using a temporary variable.
a = a ^ b;
b = a ^ b;
a = a ^ b;

OR

void swap( int a, int b )
{
a = a ^ b;
b = a ^ b;
a = a ^ b;
}

Give a linked list, determine if it has a cycle.

Keep an array of integer the same size of the list
Go through the list.

If you ever increment one of the integer of in the array twice, you have a cycle.

If you can finish going through the list you don't.

Why is it better to use a function object over a function pointer for the STL sort(or any other stl algorithm for that matter)?

Because functors can get inlined in the function

When a class has a virtual destructor, what does that imply? what if its destructor is non-virtual?
It implies that it is a potential base class.
Non-virtual : It is not a base class and should not be used as a base class because we might leak if derived classes allocates memory

Say you're making a class heirarchy of shapes. Should rectangle be derived from square?
What about square from rectangle?
Why?

Annoying question. When you derive a class, the child should have different properties and/or behavior than the base.

square and rectangle do not really have different properties. The only thing is that square is a rectange with equal with and height.

square have different behavior than a rectangle. If you scale it, the scale of the with must equal the scale of the height.

So my answer is I would neither, but
Depending on the problem I would do this :

1. If in the software you can resize a square to a rectangle. I would not make a square class at all and provide some helper functions to detect if a rectangle is a square (if needed)

2. If the square is immutable, which means resizing cannot change it, then I would derive square from shape and if the overhead is not to high for the software, I would implemented it using a rectangle.

State one case in which the code would clearly benefit from the presence of a goto.
Don't know.

Compare the design methodologies for the STL with the Java collections library. What are the design goals? Why were each designed the way they were?
Good questions. I never actually worried about their design goals aside from removing the programmer from rewriting the same boring crap.

But I think they will be pretty much the same when Java implements templates.

If you could add one feature to the C++ language, what would it be?

Better control for access to member functions. Somekind of partial friend where you an specify which functions you want a class to use.

If you could remove one feature from the c++ language, what would it be?

All the C backward compatibility stuff because I don't need it.

How would you provide behavior like the 'finally' statement from java, in c++?

Create a class for which the destructor provide the same functionnality as the finally block and instantiate the class at the beginning of the a try block.

given the following class, in what order are the constructors called?

class X
{
X::X(string name,int size);
vector v;
int size;
string name;
}

X::X(string nm,int sz):
size(sz),v(size),name(nm)
{
//nothing to do
}

v constructor
size constructor
name constructor

Order of construction is the order in which they appear in class declaration.

bonus points: what's the bug in the code?

Size is being used before it is initialized

I hope my next answers are clear enough

All use of static

static member function,
static member,
static variable, (inside a function)
static variable ( for compilation unit only )
static function ( for compilation unit only )

All use of const

const member function GetWahter() const
const member class A { const int i } //define in cpp file
const parameter or return value const void* func( const void& )

const parameter makes parameter passing more efficient


const data ( const int = 3; ) //same as member, just not inside a class declaration.

const void* p ; cannot change element pointed to p

void* const p ; cannot change p

const void* const p ; cannot change p no element pointed to p

Jon stelly question

Segmentation fault Kidding :

it's aabddgkpv.

Why you ask?
because nNumber[string] is actually (nNumber + string)

A question like the following would be more fun.

char* s = "abcdefghijklmnopqrstuvwxyz";
int* v = (int*) s;

for( int i = 0; i < 4; ++i )
{
std::cout << reinterpret_cast(v)[0];
v += i;
}



So Am I hired??



Edited by - Gorg on February 19, 2002 2:53:28 PM

Share this post


Link to post
Share on other sites
Spirel, that''s the point of the question. And no, it''s written correctly and will compile and run just fine.

The program goes to the heart of how much you know about pointers and pointer arithmetic.

Share this post


Link to post
Share on other sites
Given the following code fragment, what will be the output?

      
void* a = (void*)0x00001000;
int* b = (int*)a;
char* c = (char*)a;

++b;
++c;

if ((void*)b == (void*)c)
printf("here I am\n");
else
printf("there you are\n");


Implement itoa

Given two arbitrary nodes in a binary search tree, how do you find the greatest common parent?

Implement inorder, perorder, and postorder traversal of a binary search tree. Now do it without recursion.

Implement your own malloc that only returns addresses aligned to a paragraph(16-bit) boundary. Now implement a corresponding free.

Edited by - noparity on February 19, 2002 3:08:46 PM

Edited by - noparity on February 19, 2002 3:10:18 PM

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
One of my personal interview favorites.

Write a function that adds 1 to an integer without using any "+"''s or "-"''s anywhere in the code.



Share this post


Link to post
Share on other sites
Gorg has it mostly right.

1.

int atoi(char *p) //basically like this
{
int sum=0;
while(*p)
{
sum*=10;
sum+=*p-''0'';
p++;
}
return sum;
}

add code to check for whitespace, +-,invalid inputs as you wish

2.
basically like this

void reverse(char *b)
{
char *e=b;
while(*e) e++;
while(e{
char temp=*e;
*e=*b;
*b=temp;
e--;
b++;
}
}

3. swapping
if you''re going to do it in a function, make sure your ints are passed by reference =)
or you can do it in one line:
a^=b^=a^=b;

4. cycles in a linked list
The easiest way is to take two pointers, advance one at twice the speed of the other, and see if they ever meet.(If you ever hit null, there''s no cycle).

5. Function objects: dead on, they can be inlined.

6. Virtual destructor: also dead on.

7. square and rectange: good answer, and i agree with you about the annoying question part. Basically you want an indication that the candidate has thought about what inheritence means.

8. Design methodologies: Kinda open ended...If you know both java and c++ you should be able to compare these too. I''m mainly a c++ guy, so i''m more familiar with c++. java needs templates to get the type safety available in the stl.

9. Adding & removing a feature from the language:
I''d love to see for_each made a part of the language, as in c#
so you could write something like the following

vector v;
for_each(int i;v.begin();v.end())
{
//do something with i
}

to remove: probably C style casts.

10. ''Finally'' : again, dead on answer. Make a local object, and let it''s constructor act as finally.

11. Code sample: the important thing to recognize is that constructors are called in the order of their declaration in the class definition.


Now for the other questions:

int Increment(int a) //no plus or minus
{
int index=1;
while(a&index)
{
a^=index;
index<<=1;
}
a|=index;
return a;
}



char* itoa(int i,char* c)
{
char *move=c;
int ii=0;
while(i) //reverse it
{
ii*=10;
ii+=i%10;
i/=10;
}
while(ii)
{
*move++=ii%10;
ii/=10;
}
*move=0;
return c;
}


Binary tree:

void PrintTree(node * root)
{
int visited=0;
vector nodestack;
vector node_visits;
vector maxstack;
int depth=0;
int maxdepth=0;

if(root==NULL)
return;

while(1)
{
if(root==NULL)
{
visited=node_visits.back();
node_visits.pop_back();
root=nodestack.back();
nodestack.pop_back();
depth--;
continue;
}
else
{
switch(visited)
{
case 0:
depth++;
nodestack.push_back(root);
node_visits.push_back(1);
root=root->left;
visited=0;
break;
case 1:
depth++;
visit();
nodestack.push_back(root);
node_visits.push_back(2);
root=root->right;
visited=0;
break;
case 2:
if(nodestack.empty())
goto done;

depth--;
root=nodestack.back();
nodestack.pop_back();
visited=node_visits.back();
node_visits.pop_back();
break;
}
continue;
}
}
done:


}

just change the call to visit() around to get pre,post, and inorder traversal

Share this post


Link to post
Share on other sites
Can someone verify that this works as intended please? :-)

int IncrementNoAddSub(int x)
{
if(!x) return 1;
double d = (x>0) ? x*1.00000000001 : x*0.99999999999;
return ceil(d);
}

Cheers,

Stuart.

Share this post


Link to post
Share on other sites
quote:
Original post by sjelkjd
Gorg has it mostly right.


3. swapping
if you''re going to do it in a function, make sure your ints are passed by reference =)



Doh! Just fast typing.

quote:


9. Adding & removing a feature from the language:
I''d love to see for_each made a part of the language, as in c#
so you could write something like the following

vector v;
for_each(int i;v.begin();v.end())
{
//do something with i
}




but there is a for_each


struct doStuffFunctor
{
void operator()( myClass& c )
{
//do stuff with c

}
}

#include <algorithm>

std::for_each( container.begin(),container.end(), doStuffFunctor() );


Share this post


Link to post
Share on other sites
Yeah, but the current implementation of for_each is so awkward that you often spend longer writing the function object and adding binders and whatnot that you may as well have written the loop explicitly in the first place.

[ MSVC Fixes | STL | SDL | Game AI | Sockets | C++ Faq Lite | Boost ]

Share this post


Link to post
Share on other sites
quote:
Original post by Kylotan
Yeah, but the current implementation of for_each is so awkward that you often spend longer writing the function object and adding binders and whatnot that you may as well have written the loop explicitly in the first place.



My sentiments exactly...although for_each does work on every container =)

Share this post


Link to post
Share on other sites
quote:
Original post by sjelkjd
3. swapping
if you''re going to do it in a function, make sure your ints are passed by reference =)
or you can do it in one line:
a^=b^=a^=b;

I wonder what that does to 2''s-complement signed integers... *hint* It also doesn''t work if you pass in the same variable by reference (ie swap(a, a)).

Personally I prefer the add and subtract trick; it''s guaranteed to work for all integers:
void Swap(int &a, int &b)
{
a += b;
b = a - b;
a -= b;
}

Just for the record.

[ GDNet Start Here | GDNet Search Tool | GDNet FAQ | MS RTFM [MSDN] | SGI STL Docs | Google! ]
Thanks to Kylotan for the idea!

Share this post


Link to post
Share on other sites
It works fine for 2;s complement. We are doing bit operations so it does not matter.

You are right, it does not work if you pass the same variable. You could solve it like that :



void Swap( int& a, int &b )
{
if ( &a == &b )
return;
a = a ^ b;
b = a ^ b;
a = a ^ b;
}



quote:
Original post by Oluseyi
[quote]Original post by sjelkjd
3. swapping
if you''re going to do it in a function, make sure your ints are passed by reference =)
or you can do it in one line:
a^=b^=a^=b;

I wonder what that does to 2''s-complement signed integers... *hint* It also doesn''t work if you pass in the same variable by reference (ie swap(a, a)).

Personally I prefer the add and subtract trick; it''s guaranteed to work for all integers:
void Swap(int &a, int &b)
{
a += b;
b = a - b;
a -= b;
}

Just for the record.

[ GDNet Start Here | GDNet Search Tool | GDNet FAQ | MS RTFM [MSDN] | SGI STL Docs | Google! ]
Thanks to Kylotan for the idea!


Share this post


Link to post
Share on other sites
Oluseyi:
The underlying bitwise representation doesn't affect the code. You can take int pointers to floats and make this code work.
However, the double reference is still a problem =(
Even your techinque is susceptible to it.

p.s. the nice thing about using xor is that is will work for all binary data that needs to be shallow copied, unless the arguments alias the same variable.

Edited by - sjelkjd on February 20, 2002 1:51:49 AM

Share this post


Link to post
Share on other sites
quote:
Original post by JonStelly
Spirel, that''s the point of the question. And no, it''s written correctly and will compile and run just fine.

The program goes to the heart of how much you know about pointers and pointer arithmetic.


Hmm. I didn''t know you could do that. I suppose its that it doesnt matter what order you add the memory offset of the array and the array position?

Share this post


Link to post
Share on other sites