逝水流年

This is a blog to record my life, my work, my feeling …

Strxfrm函数

原型

1
size_t strxfrm ( char * destination, const char * source, size_t num );

功能:

根据num长度拷贝前num个字符到目的字符串中,并返回源字符串长度。

同时,该函数还可以自作为返回字符串长度,这时num=0,destination允许传入NULL。

参数:

destination 指向目的字符数组的指针,当num为0时,可以传NULL。

source 要拷贝的源字符串,以‘\0’结尾。

num 最大要拷贝到目的数组的字符的长度。

返回值:

返回source字符串的长度,不包含‘\0’。

1
2
3
4
5
6
7
8
9
10
11
12
#include <cstring>;
#include <iostream>;
#include <windows.h>;
int main(int argc, char* argv[])
{
    char* source = "1234567890 abc";
    char des[100];
    size_t len = strxfrm(des, source, 50);
    std::cout << "len:" << len <<std::endl;
    std::cout << "des:" << des <<std::endl;
    return 0;
}

output: len:14 des:1234567890 abc

这里举这个例子要说明的是num长度大于源字符串长度的原因,涉及到strxfrm函数的具体实现了。

1
2
strncpy(_string1, _string2, _count);
return strlen(_string2);

vs平台下该函数的实现非常简单,除了必要的验证外,只是调用了同是cstring的库函数中的两个基本函数。这也说明了为什么num长度超过源串后为什么没有问题,因为strncpy函数自动截取字符串到’\0’。

Inserter、back_inserter、front_inserter

inserter、back_inserter、front_inserter

分别返回三种类型的iterator:insert_iterator,back_insert_iterator,front_insert_iterator。这三种iterator被设计成允许不同的算法重写elements(例如copy方法)去替代插入操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// inserter example
#include <iostream>;
#include <iterator>;
#include <list>;
using namespace std;
int main () {
  list<int>; firstlist, secondlist;
  for (int i=1; i<=5; i++)
  { firstlist.push_back(i); secondlist.push_back(i*10); }
  list<int>;::iterator it;
  it = firstlist.begin(); advance (it,3);
  copy (secondlist.begin(),secondlist.end(),inserter(firstlist,it));
  for ( it = firstlist.begin(); it!= firstlist.end(); ++it )
      cout << *it << " ";
  cout << endl;
  return 0;
}

Output: 1 2 3 10 20 30 40 50 4 5

必须要提到的一点是,这三种迭代器是对容器有要求的,分别要求容器提供insert,push_back,push_front方法才行。

VS调试-library版本引起的内存问题

VS建立的项目,其中肯定涉及到DLL或者是LIB库,这时候调试起来会有一定不便,这里建议大家将相关项目建立成一个solution,只要设置好路径,就可以调试了,而且调试起来非常方便。但是当lib库或DLL库中涉及到内存分配,但是释放却在其他库或上层软件时,切记要保证EXE或DLL或者LIB的版本要一致,这里说的一直就是要求必须都是debug版本或者release版本,否则在内存处理上会出现一些问题。

例如:

在DLL中new出的内存,在上层delete的时候,会由于版本不一致,导致vs在对内存进行检查的时候略有不同,导致程序崩溃。希望大家多注意下。

分享一个日志函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>;
#include <stdarg.h>;
void logTest(const char* content, ...)
{
    FILE* logfile = fopen("log.txt", "a");
    if(logfile)
    {
        fprintf(logfile, "########## NEW LOG ########\n");
        va_list arg;
        va_start(arg, content);
        vfprintf(logfile, content, arg);
        va_end(arg);
        int status = fflush(logfile);
        fclose(logfile);
    }
}

关于跨平台的一些感受

最近几天一直在做代码移植工作,将Unix下的C/C++代码移植到Windows平台上,有一些小体会,这里记录下来跟大家分享下:

1、一定要注意跨平台的C++尽量使用STL,各个编译器对STL都支持,除了一些特性外基本无需修改。

2、使用的C库函数一定要注意,是C99标准还是C89标准,VS编译器2010以下对C99都不支持,很多函数都无法使用。

3、一些变量声明尽量放到函数开始,for循环中尽量不要声明变量,VS编译器2005之下对其支持不是很好。

4、尤其是在文件路径方面要注意,路径处理尽量放到上层实现。

NSMutableArray使用中遇到的内存问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
NSMutableArray* array1 = [[NSMutableArray alloc] init];
NSMutableArray* array2 = [[NSMutableArray alloc] init];
- (void)pushs:(NSInteger)VALUE {
    BOOL find = NO;
    [array2 removeAllObjects];
    for (NSNumber* item in array1) {
        NSInteger value = [item intValue];
        if (value == VALUE) {
            [array1 removeAllObjects];
            [array1 addObjectsFromArray: array2];
            [array1 addObject: item];
            find = YES;
            break;
        }
        else {
            [array2 addObject: item];
        }
    }
    if (!find) {
        NSNumber* newItem = [NSNumber numberWithInt: VALUE];
        [viewTypeArray addObject:newItem];
    }
}

当进入if (value == VALUE)后,[array1 addObject: value];执行完毕后,查看array1中的元素类型发现已经不再是NSNumber而是变为NSobject,取出使用报错,bad access。

该问题出现的几率比较随机。单独使用没有任何问题,放到整个工程中就出现问题。通过查看内存,发现NSMutableArray中存储的为NSNumber指针,array1和array2中指针地址一致,有可能是当[array1 removeAllObjects];后,item有可能被自动销毁,导致加入到array1中的值出现错误。修改为:

1
2
NSNumber* topItem = [NSNumber numberWithInt: value];
[array1 addObject:topItem];

问题解决。这个问题的根本原因还是内存的问题,objective-c的内存管理比较特殊,有很多隐藏的内存分配和自动回收,个人怀疑numberWithInt方法返回的NSNumber*对象为autorelease。

Strcmp, Stricmp — Compare Strings.

Returns

A negative number if the first string is ordinally less than the second string according to the ASCII character set, a positive number if the first string is greater than the second, and zero if the two strings are exactly equal.

Description

These functions can be used as comparison functions for sort and insert.

stricmp performs the same function as strcmp, but alphabetic characters are compared without regard to case. That is, “A” and “a” are considered equal by stricmp, but different by strcmp.

简单来说,strcmp区分大小写而stricmp不区分大小写而已。

Std::swap

1
template <class T>; void swap ( T& a, T& b );

Exchange values of two objects(交换两个对象的值)

Assigns the content of a to b and the content of b to a. (将a的内容给b,将b的内容给a。)

The behavior of this function template is equivalent to: (该函数模板的实现如下:)

1
2
3
4
template <class T>; void swap ( T& a, T& b )
{
    T c(a); a=b; b=c;
}

Notice how this function involves a copy construction and two assignment operations, which may not be the most efficient way of swapping the contents of classes that store large quantities of data, since each of these operations generally operate in linear time on their size.

(注意,该函数是通过调用一个拷贝构造函数和两个赋值操作来交换两个对象的内容,这并不是最高效的交换方法对大数据来说,因为每个操作时间都是跟对象大小的成正比的线性时间关系。)

Because this function template is used as a primitive operation by many other algorithms, it is highly recommended that large data types overload their own specialization of this function. Notably, all STL containers define such specializations (at least for the standard allocator), in such a way that instead of swapping their entire data content, only the values of a few internal pointers are swapped, making this operation to operate in real constant time with them. Parameters a, b Two objects, whose contents are swapped. The type must be copy constructible and support assignment operations.

(类型T必须包含拷贝构造和支持赋值操作。)

Return value none

Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// swap algorithm example
#include <iostream>;
#include <algorithm>;
#include <vector>;
using namespace std;
int main ()
{
    int x=10, y=20;                         // x:10 y:20
    swap(x,y);                              // x:20 y:10
    vector<int>; first (4,x), second (6,y);  // first:4x20 second:6x10
    swap(first,second);                     // first:6x10 second:4x20
    cout << "first contains:";
    for (vector<int>;::iterator it=first.begin(); it!=first.end(); ++it)
        cout << " " << *it;
    cout << endl;
    return 0;
}
Output:
first contains: 10 10 10 10 10 10

Complexity Constant: Performs exactly one copy construction and two assignments (although notice that each of these operations works on its own complexity).

我的“营销”开始

原本快乐的生活在年后完全被打乱了,不再有时间更新博客微薄,不再有时间看书学习,不再有时间睡懒觉,不再有时间看电影、看电视,完全脱离的轨道。一周5天工作,纯脑力劳动,一坐8个多小时对着电脑面对代码,这些都不再是工作,反倒是休息是开心;晚上要加班洗衣服,基本没有12点之前睡觉的,还好没在原单位上班,不然严重睡眠不足;周末要做的事情就更多了,不过基本都是体力劳动,大包小包的衣服都我来拎,累的我的胳膊一疼就是一周,这周更牛掰,我开始了我的销售生涯,从小区挨家挨户发小广告做起!

今天一共发了将近10栋楼,300户左右,那叫一个累啊,退都上下楼上的不利索了。就当锻炼了,既要锻炼到上半身也要锻炼到下半身嘛,哈哈。苦中作乐!希望生意越来越好吧。