YXD's Blog

Home Contact Syndicate this Site (RSS 2.0) Syndicate this Site (Atom) 登录
  随笔 18 :: 收藏 1 :: 评论 0 :: 寻迹: 1

随笔

随笔归档

收藏

图库

Friends' Blogs

from cndev

Technical Blogs

1、从字符串A中找到匹配字符串B的第一个子串的位置,以下的代码经测试比Plauger的stl(VC7)中的
::std::string::find要快30%左右
// 仿函数版本
template < class Character = char, class Size = int >
struct StringFinder
{
 typedef Size size_t;
 typedef Character char_t;
 size_t operator()( const char_t* lpszSource, const char_t* lpszSearch )
 {
  // maybe the processing of the following line can delay to the caller
  if ( ( NULL == lpszSource ) || ( NULL == lpszSearch ) ) return -1;
  const char_t& cSource = *lpszSource;
  const char_t& cSearch = *lpszSearch;
  for ( ; ; )
  {
   if ( 0 == *lpszSearch )
   {
    return ( lpszSource - ( lpszSearch - &cSearch ) - &cSource );
   }
   if ( 0 == *lpszSource ) return -1;
   if ( *lpszSource != *lpszSearch )
   {
    lpszSource -= lpszSearch - &cSearch - 1;
    lpszSearch = &cSearch;
    continue;
   }
   ++ lpszSource;
   ++ lpszSearch;
  }
  return -1;
 }
};
// 函数版本
template < class char_t, class size_t >
size_t StringFind( const char_t* lpszSource, const char_t* lpszSearch )
{
 // maybe the processing of the following line can delay to the caller
 if ( ( NULL == lpszSource ) || ( NULL == lpszSearch ) ) return -1;
 const char_t& cSource = *lpszSource;
 const char_t& cSearch = *lpszSearch;
 for ( ; ; )
 {
  if ( 0 == *lpszSearch )
  {
   return ( lpszSource - ( lpszSearch - &cSearch ) - &cSource );
  }
  if ( 0 == *lpszSource ) return -1;
  if ( *lpszSource != *lpszSearch )
  {
   lpszSource -= lpszSearch - &cSearch - 1;
   lpszSearch = &cSearch;
   continue;
  }
  ++ lpszSource;
  ++ lpszSearch;
 }
 return -1;
}

2、字符串比较,同strcmp的功能,以下为仿函数版本。
struct StringCmp
{
 int operator()( const char* lpszStr1, const char* lpszStr2 )
 {
  if ( NULL == lpszStr1 )
  {
   if ( NULL == lpszStr2 ) return 0;
   return -1;
  }
  if ( NULL == lpszStr2 ) return 1;

  for ( ; ( 0 != ( ( *lpszStr1 ) & ( *lpszStr2 ) ) ); ++ lpszStr1, ++ lpszStr2 )
  {
   if ( *lpszStr1 < *lpszStr2 ) return -1;
   if ( *lpszStr1 > *lpszStr2 ) return 1;
  }
  if ( 0 != *lpszStr2 ) return -1;
  if ( 0 != *lpszStr1 ) return 1;
  return 0;
 }
};

3、快速排序算法(做了优化处理的),当元素总数不超过给定的阈值(threshold)时,采用插入排序,如果这个
做笔试题的话,个人认为难度偏大,因为其中程序部分可能技巧性比较强,需要很细心。俺也是花了很长时间上机
调试,我认为可能冒泡、插入排序更适合笔试。做完此题后,我还参读了Plauger's stl(VC7)中::std::sort
的源码,不同的是,其阈值默认为32,并且在超过阈值时也作了优化,小于或等于则都用了插入排序,呵呵。。。

struct NullType;

template < class T, class Iterator = T*, class Pr = NullType, class Diff = __int64, Diff threshold = 9 >
struct Sorter;

template < class T, class Iterator, class Diff, Diff threshold >
struct Sorter< T, Iterator, NullType, Diff, threshold >// sort by operator <
{
 typedef T type;
 typedef T& reference;
 typedef const T& const_reference;
 typedef T* pointer;
 typedef Iterator iterator;

 void operator()( iterator begin, iterator end )// sort in field [begin, end)
 {
  QuickSort( begin, end );
 }

 void InsertionSort( iterator begin, iterator end )// sort in field [begin, end)
 {
  type swap_temp;
  for ( iterator i = begin + 1; i < end; ++ i )
  {
   for ( iterator j = i; ( j > begin ) && ( *j < *( j - 1 )  ); -- j )
   {
    swap_temp = *j;
    j[0] = j[-1];
    j[-1] = swap_temp;
   }
  }
 }

 void QuickSort( iterator begin, iterator end )// sort in field [begin, end)
 {
  Diff diff = end - begin;
  // optimize speed with InsertionSort if the number of elements is not more than threshold
  if ( threshold >= diff )
  {
   InsertionSort( begin, end );
   return;
  }

  // find pivot
  iterator pivot = begin + ( diff >> 1 );

  // swap pivot with the element before end
  type swap_temp;
  swap_temp = end[-1];
  end[-1] = *pivot;
  pivot[0] = swap_temp;

  // partition
  iterator right_first = Partition( begin, end - 2, end[-1] );

  // restore pivot to primary position
  if ( right_first < ( end - 1 ) )
  {
   swap_temp = right_first[0];
   right_first[0] = end[-1];
   end[-1] = swap_temp;
  }

  if ( ( right_first - begin ) > 2 )
   QuickSort( begin, right_first );// sort in field [begin, right_first)
  if ( ( end - right_first ) > 3 )
   QuickSort( right_first + 1, end );// sort in field [right_first + 1, end )
 }
private:
 iterator Partition( iterator first, iterator last, const_reference pivot )
 {
  iterator last_temp = last;
  type swap_temp;
  for ( ; first < last; )
  {
   if ( *last < pivot )
   {
    if ( *first < pivot )
    {
     ++ first;
     continue;
    }
    swap_temp = *first;
    first[0] = *last;
    last[0] = swap_temp;
    ++ first;
    -- last;
   }
   else
   {
    if ( *first < pivot )
    {
     ++ first;
     -- last;
     continue;
    }
    -- last;
    continue;
   }
  }
  // calculate the first position of right part
  for ( ; ( !( pivot < *last ) )&& ( last <= last_temp ); ++ last ) {}
  return last;
 }
};

template < class T, class Iterator, class Pr, class Diff, Diff threshold >
struct Sorter< T, Iterator, Pr, Diff, threshold >// sort by Pr
{
 // Just change it1 < it 2 to Pr( it1, it2 )
};

4、判断字符串是否为回环串,类似于"abcdcba"(?),这个可能挺简单,但是好像很多大公司出的
笔试题似乎都很简单,不知其考察点在于什么。。。

template < class Character = char >
struct IsCircleString
{
 typedef Character char_t;
 bool operator()( const char_t* pStr )
 {
  const char_t* pLast = pStr;
  for ( ; 0 != *pLast; ++ pLast ) {}
  if ( ( ( pLast - pStr ) & 0x1 ) == 0 ) return false;//偶数即返回false
  -- pLast;
  for ( ; pStr < pLast; ++ pStr, -- pLast )
  {
   if ( *pStr != *pLast ) return false;
  }
  return true;
 }
};

发表于 @ 2004-12-14 12:16

Feedback

# 回复: 网上收罗的几道程序笔试题,并附上我的C++解答,有兴趣的可以看看,如果有好的题望不吝赐教。。。俺急需这样的题啊 2004-12-14 16:40:00 mumu6791
不懂不懂

# 回复: 网上收罗的几道程序笔试题,并附上我的C++解答,有兴趣的可以看看,如果有好的题望不吝赐教。。。俺急需这样的题啊 2005-01-04 16:14:00 zhangyv
你的做法并不是最好的。

1 使用KMP串匹配算法进行字符串匹配是最优的,我给出PASCAL的代码。
program KMP;
var
s,t: string;
i,m,n,k: integer;
pi: array[1..20] of integer;
procedure Comput(var t: string);
var
m,i,k: integer;
begin
m := length (t);
pi[1] := 0;
k := pi[1];
for i := 2 to m do
begin
while (k > 0) and (t[i] <> t[k+1]) do
k := pi[k];
if (t[i] = t[k+1]) then k := k+1;
pi[i] := k;
end;
end;

function KMPmatcher(var s,t: string): integer;
begin
n := length (s);
m := length (t);
Comput(t);
k := 0;
for i := 1 to n do
begin
while (k > 0) and (t[k+1] <> s[i]) do
k := pi[k];
if t[k+1] = s[i] then k := k+1;
if k = m then
begin
KMPmatcher := i-m+1;
exit;
end;
end;
end;

begin
Write ('Please Input main string ');
Readln (s);
Write ('Please Input Matcher string ');
Readln (t);
Write ('Matcher from ', KMPmatcher(s,t));
end.


2
/* return :
* 0: src == dest
* 1: src > dest
* -1: src < dest
*/
int strcmp(char *src, char *dest)
{
// (*src == *dest && *src!=NULL && *dest != NULL)
while ( *src== *dest && *src ) {
++src;
++dest;
}
return *src - *dest;
}


3
你可以参考STL的实现代码,更好的解决方式参见:
http://search.csdn.net/Expert/topic/2364/2364150.xml?temp=.3768274

4
偶数个元素的字符串也有可能是回文串,如: abccba


# 回复: 网上收罗的几道程序笔试题,并附上我的C++解答,有兴趣的可以看看,如果有好的题望不吝赐教。。。俺急需这样的题啊 2005-01-04 16:15:00 zhangyv
比较不错的笔试题,附上我的解答:


1、完成字符串拷贝可以使用 sprintf、strcpy 及 memcpy 函数,请问这些函数
有什么区别,你喜欢使用哪个,为什么?

答:
说明:
sprintf是用在文本显示,但是该函数的实现过于复杂,容易出现内存错误非常危险;
strcpy即标准字符串拷贝函数,遇到'\0'就结束拷贝,如果src比dst大,将出现缓冲区溢出问题;
memcpy用来做内存拷贝,可以用来从一个源地址,拷贝任何数据类型的对象到目标地址;
这三个函数都是比较危险的,所以需要慎重使用。

分析:
(1)对于strcpy,有时候可以使用strncpy函数替代。使用strncpy函数,如果src比dst大,则该函数不
会抛出一个错误;当达到最大尺寸时,它只是停止复制字符。可以避免潜在的缓冲区溢出的问题。
(2)对于sprintf可以使用snprintf来替代,可以避免缓冲区溢出。
(3)memcpy必须保证缓冲区大小保持一致,否则将出现缓冲区溢出。

结论:
通常对于完成字符串拷贝,我通常使用strcpy,因为这是标准C的字符串类型的拷贝函数。对于常量的字

符串拷贝使用strcpy是安全的,有时候可以使用strncpy减少代码的潜在安全问题。
---------------------------------------------

2、变量的声明和定义有什么区别?

答:
变量声明只是给编译器一个提示,和运行环境无关;而变量定义是分配了具体的内存空间。
比如:
extern int a; //变量声明
int b; //变量定义
---------------------------------------------

3、请写出下面代码在 32 位平台上的运行结果,并说明 sizeof 的性质:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
char a[30];
char *b = (char *)malloc(20 * sizeof(char));
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(b));
printf("%d\n", sizeof(a[3]));
printf("%d\n", sizeof(b+3));
printf("%d\n", sizeof(*(b+4)));
return 0 ;
}
答:
在32位系统下(如WIN32),指针长度为32位,并且,
a是一个有30个元素的字符型数组;b是一个字符串指针;a[3]是字符型;b+3是指针;*(b+4)是字符型。
因此输出:
30、4、1、4、1

---------------------------------------------
4、请完成以下题目。注意,请勿直接调用 ANSI C 函数库中的函数实现。

a)请编写一个 C 函数,该函数给出一个字节中被置 1 的位的个数,并请
给出该题的至少一个不同解法。
b)请编写一个 C 函数,该函数将给定的一个字符串转换成整数。
c)请编写一个 C 函数,该函数将给定的一个整数转换成字符串。
d)请编写一个 C 函数,该函数将一个字符串逆序。
e)请编写一个 C 函数,该函数在给定的内存区域搜索给定的字符,并返回
该字符所在位置索引值。
f)请编写一个 C 函数,该函数在一个字符串中找到可能的最长的子字符串,
该字符串是由同一字符组成的。

5、给出演示上述函数功能的一个简单程序,并请编写对应的 Makefile 文件
答:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int A(unsigned char a_char)
{
int cnt = 0;
for (char b = 0x80; a_char; a_char <<= 1) {
if ( a_char >= b )
++cnt;
}
return cnt;
}

int A_other(unsigned char a_char)
{
int cnt = 0;
//a char has 8 bits
for (int i = 0; i < 8; ++i){
cnt += (a_char & 0x01);
a_char >>= 1;
}
return cnt;
}

long B(char* str)
{
long aInt = 0;
long step = 1;
for (int i = strlen(str)-1; i >= 0; --i){
if (str[i] < '0' || str[i] > '9')
return -1;
aInt += (str[i] - '0') * step;
step *= 10;
}
return aInt;
}

int C(long aInt, char* str)
{
int i;
for (i = 0; aInt; aInt /= 10, ++i){
str[i] = (aInt % 10) + '0';
}
str[i] = '\0';
return 0;
}

int D(char *str)
{
int i;
int j = strlen(str) - 1;
char tmp;
for (i = 0; i < j; ++i, --j){
tmp = str[i];
str[i] = str[j];
str[j] = tmp;
}
return 0;
}
int E(char *start, char *end, char **p, const char target)
{
for (*p = start; *p < end; ++(*p)){
if (**p == target){
return 0;
}
}
*p = NULL;
return 1;
}

int F(char *src, char a)
{
int cnt, index;
char *p;
cnt = index = 0;
for (p = src; *p; ++p){
if (*p == a)
++cnt;
else {
if (index < cnt){
index = cnt;
}
cnt = 0;
}
}
return index;
}

int main(void)
{
char t = 0x8f;
printf("%d\n", A(t));
printf("%d\n", A_other(t));

printf("%ld\n", B("54387"));

char* str;
str = (char *) malloc (4 * sizeof(char));
C(1222345, str);
printf("%s\n", str);

D(str);
printf("%s\n", str);

char *p;
E(str, str+10, &p, '4');
if (p)
printf("%c\n", *p);

printf("%d\n", F(str, '2'));

if (str){
free(str);
str = NULL;
}

return 0;
}

---------------------------------------------
Makefie:
直接使用automake/autoconf就可以得出完善的结果,完全没有必要自己纯手工编写。
基本格式如下,不包括环境和编译器检察等等:
OBJS = test.o
CC = gcc
CFLAGS = -Wall -O -g

myprog : $(OBJS)
$(CC) $(OBJS) -o myprog

test.o : test.c string.h stdio.h stdlib.h
$(CC) $(CFLAGS) -c test.c -o test.o

.PHONY : clean
clean :
rm *.o
rm myprog

---------------------------------------------

# 回复: 网上收罗的几道程序笔试题,并附上我的C++解答,有兴趣的可以看看,如果有好的题望不吝赐教。。。俺急需这样的题啊 2005-01-05 00:00:00 yxd
to zhangyv: hehe, 不错,3ks a lot!

# 回复: 网上收罗的几道程序笔试题,并附上我的C++解答,有兴趣的可以看看,如果有好的题望不吝赐教。。。俺急需这样的题啊 2006-04-08 12:42:00 let me give u a question !!!
Write a program that converts a C++ string representing a number in Roman numeral form to
decimal form. The symbols used in the Roman numeral system and their equivalents are given below:
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
For example, the following are Roman numbers: XII (12), CII (102), XL (40).
The rules for converting a Roman number to a decimal number are as follows:
a. Set the value of the decimal number to zero.
b. Scan the string containing the Roman character from left to right. If the character is not one
of the symbols in the numeral symbol set, the program must print an error message and
terminate. Otherwise, continue with the following steps. (Note that there is no equivalent
to zero in Roman numerals.)

If the next character is the last character, add the value of the current character to the decimal value.
If the value of the current character is greater than or equal to the value of the next character, add the value of the current character to the decimal value.
If the value of the current character is less than the next character, subtract the value of the current character from the decimal value.


# celebrity feet scans - Sportster.org Forums 2008-06-24 17:01:00 Pingback/TrackBack
celebrity feet scans - Sportster.org Forums

发表评论

标题:  
署名:  
链接:
内容:
验证码: