c字符串常用操作

#ifndef STRING_H
#define STRING_H

#define STRING_DEFAULT_CHUNK_SIZE 256

typedef struct {
    char *value;
    int length;
    int capacity;
    int chunk_size;
} String;

String *string_construct(const char *value);
String *string_construct_from_int(int value);
void string_destroy(String *string);
void string_set_value(String *string, const char *value);
void string_append_value(String *string, const char *value);
void string_prepend_value(String *string, const char *value);
const char *string_get_value(String *string);
int string_get_length(String *string);
void string_set_capacity(String *string, int capacity);
int string_get_capacity(String *string);
void string_set_chunk_size(String *string, int chunk_size);
int string_get_chunk_size(String *string);
void string_to_uppercase(String *string);
void string_to_lowercase(String *string);
void string_replace_character(String *string, char old_char, char new_char);
void string_left_trim(String *string);
void string_right_trim(String *string);
void string_trim(String *string);
#endif

 

 

 

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

 

 

#include "string.h"
#include "logger.h"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>

#ifdef DMALLOC
#include "dmalloc.h"
#endif

/*
 * FIXME: The string object maintains a length field, therefore the 
 *        NUL-character is not technically needed, but most of the time
 *        the string capacity will be more than the string length anyway,
 *        so maybe the wasted byte isn't anything to worry about.
 *
 * FIXME: Possibly write a function (for the event loop) that goes in and 
 *        lowers the capacity to string length when the loop is idling.
 */
String *string_construct(const char *value) {

    String *string = NULL;

    /*
     * Allocate space for the object and set all fields to zero.
     */
    string = calloc(1, sizeof(String));
    
    if (string == NULL) {
        return NULL;
    }

    /*
     * When resizing string, allocate proportional to STRING_DEFAULT_CHUNK_SIZE
     * bytes. 
     */
    string_set_chunk_size(string, STRING_DEFAULT_CHUNK_SIZE);

    /*
     * Initially the string should be one chunk big
     */
    string_set_capacity(string, string_get_chunk_size(string));

    /*
     * Initialize the string
     */
    string_set_value(string, value);

    return string;
}

String *string_construct_from_int(int value) {

    String *string = NULL;
    char *c_string = NULL;

    c_string = malloc(15);

    sprintf(c_string, "%d", value);

    string = string_construct(c_string);

    free(c_string);

    return string;
}

void string_destroy(String *string) {

    if (string == NULL) {
        return;
    }
    
    if (string->value != NULL) {
        free(string->value);
    }

    free(string);
}

void string_set_value(String *string, const char *value) {

    int length = 0, capacity = 0, chunk_size = 0;

    if (string == NULL) {
        return;
    }

    if (value == NULL) {
        value = "";
    }

    length = strlen(value);

    /*
     * If the length of the string is bigger than the object's current
     * capacity, then increase the capacity of the object to be large
     * enough for the string.
     */
    if (length > string_get_length(string)) {
        chunk_size = string_get_chunk_size(string);
        capacity = string_get_capacity(string);
        capacity += (length/chunk_size + 1) * chunk_size;
        string_set_capacity(string, capacity);
    }

    /*
     * Copy the string to the object
     */
    strcpy(string->value, value);
    string->length = length;

}

void string_prepend_value(String *string, const char *value) {

    char *construct_value = NULL;
    int length = 0;

    if (string == NULL) {
        return;
    }

    if (value == NULL) {
        return;
    }

    length = strlen(value) + string_get_length(string);

    construct_value = malloc((length + 1) * sizeof(char));

    if (construct_value == NULL) {
        return;
    }

    strcpy(construct_value, value);
    strcat(construct_value, string_get_value(string));
    string_set_value(string, construct_value);

    free(construct_value);

}

void string_append_value(String *string, const char *value) {

    char *new_value = NULL;
    int length = 0;

    if (string == NULL) {
        return;
    }

    if (value == NULL) {
        return;
    }

    length = string_get_length(string) + strlen(value);

    /*
     * This is an optimization that is not necessary, but might have 
     * better performance when appending small strings
     */
    if (length < string_get_capacity(string)) {
        strcat(string->value, value);
        string->length = length;
        return;
    }

    new_value = malloc((length + 1) * sizeof(char));

    if (new_value == NULL) {
        return;
    }

    strcpy(new_value, string_get_value(string));
    strcat(new_value, value);
    string_set_value(string, new_value);

    free(new_value);

}

const char *string_get_value(String *string) {

    if (string == NULL) {
        return NULL;
    }

    return string->value;
}

int string_get_length(String *string) {

    if (string == NULL) {
        return 0;
    }

    return string->length;
}

void string_set_capacity(String *string, int capacity) {

    if (string == NULL) {
        return;
    }

    if (capacity <= 0 || capacity == string_get_capacity(string)) {
        return;
    }

    string->value = realloc(string->value, capacity);

    if (string->value == NULL) {
        string->length = 0;
        return;
    }

    string->capacity = capacity;

    if (string->capacity <= string->length) {

        string->length = string->capacity - 1;
        string->value[string->length] = 0;
    }
}

int string_get_capacity(String *string) {

    if (string == NULL) {
        return 0;
    }

    return string->capacity;
}

void string_set_chunk_size(String *string, int chunk_size) {

    if (string == NULL) {
        return;
    }

    if (chunk_size <= 0) {
        chunk_size = STRING_DEFAULT_CHUNK_SIZE;
    }

    string->chunk_size = chunk_size;
}

int string_get_chunk_size(String *string) {

    if (string == NULL) {
        return 0;
    }

    return string->chunk_size;
}

void string_to_uppercase(String *string) {

    char *p = NULL;

    if (string == NULL) {
        return;
    }

    for (p = (char *) string->value; p[0] != 0; p++) {
        p[0] = (char) toupper(p[0]);
    }
}

void string_to_lowercase(String *string) {

    char *p = NULL;

    if (string == NULL) {
        return;
    }

    for (p = (char *) string->value; p[0] != 0; p++) {
        p[0] = (char) tolower(p[0]);
    }
}

void string_replace_character(String *string, char old_char, char construct_char) {

    char *p = NULL;

    if (string == NULL) {
        return;
    }

    for (p = (char *) string->value; p[0] != 0; p++) {
        if (p[0] == old_char) {
            p[0] = construct_char;
        }
    }
}


void string_left_trim(String *string) {

    char *new_value = NULL, *head = NULL, *tail = NULL;

    if (string == NULL) {
        return;
    }

    if (string_get_length(string) == 0) {
        return;
    }

    new_value = strdup(string_get_value(string));
    head = new_value;
    tail = new_value + string_get_length(string);
    while (head != tail && isspace(head[0])) {
        head++;
    }
    string_set_value(string, head);
    free(new_value);

}

void string_right_trim(String *string) {

    char *new_value = NULL, *tail = NULL;

    if (string == NULL) {
        return;
    }

    if (string_get_length(string) == 0) {
        return;
    }

    new_value = strdup(string_get_value(string));
    tail = new_value + string_get_length(string) - 1;
    while (tail != new_value && isspace(tail[0])) {
        tail--;
    }
    tail[1] = 0;
    string_set_value(string, new_value);
    free(new_value);
}

void string_trim(String *string) {

    if (string == NULL) {
        return;
    }
    
    if (string_get_length(string) == 0) {
        return;
    }

    string_left_trim(string);
    string_right_trim(string);
}

 

posted @ 2011-09-27 12:52  火腿骑士  阅读(230)  评论(0编辑  收藏  举报