>第 25 章 C标准库>字符串操作函数>分割字符串>习题

tianyebj tianyebj@gmail.com
2009-10-16 00:08:19

习题1:
#include <stdio.h>
#include <string.h>

static char *pp;
static size_t len;

char *strtok2(char *str, const char *delim)
{
	char *pos;
	if (str != NULL) {
		len = strlen(delim);
		pp = str;
	}
	str = pp;
	if (str == NULL) return NULL;
	pos = strstr(str, delim);
	if (pos != NULL) {
		*pos = '\0';
		pp = pos + len;
	} else {
		pp = NULL;
	}
	return str;

}

char *strtok_r2(char *str, const char *delim, char **saveptr)
{
	char *pos;
	int len = strlen(delim);
	if (str == NULL) {
		str = *saveptr;
	}
	if (str == NULL) return NULL;
	pos = strstr(str, delim);
	if (pos != NULL) {
		*pos = '\0';
		*saveptr = pos + len;
	} else {
		*saveptr = NULL;
	}
	return str;
}




int main(void)
{
	char str[] = "root:x::0:root:/root:/bin/bash:";
	char *token;
	token = strtok2(str, ":");
	printf("%s\n", token);
	while ((token = strtok2(NULL, ":")) != NULL)
		printf("%s\n", token);
	printf("============\n");
	char str2[] = "root=x=:0:root=/root:=bin/bash:";
	char *save_ptr;
	token = strtok_r2(str2, "=", &save_ptr);
	printf("%s\n", token);
	while ((token = strtok_r2(NULL, "=", &save_ptr)) != NULL)
		printf("%s\n", token);
	
	return 0;
}


tianyebj tianyebj@gmail.com
2009-10-17 21:29:10

习题2:
har *)malloc(MAX_LEN);
	char *pos = strchr(url, '?');
	u.pnum = 0;
	if (pos != NULL) {
		strncat(u.url_path, url, pos - url);
		char *token;
		token = strtok(pos + 1, "&");
		set_param(&u.plist[u.pnum++], token);
		while ((token = strtok(NULL, "&")) != NULL) {
			set_param(&u.plist[u.pnum++], token);
		}
	} else {
		strcat(u.url_path, url);
	}
	return u;	
}

void free_url(url_t u) {
	free(u.url_path);
	u.url_path = NULL;
	int i;
	for (i = 0; i < u.pnum; i++) {
		free(u.plist[i].q);
		u.plist[i].q = NULL;
		free(u.plist[i].v);
		u.plist[i].v = NULL;

	}
}

void print_url(url_t u) {
	printf("path: %s\n", u.url_path);
	int i;
	for (i = 0; i < u.pnum; i++) {
		printf("==========\n");
		printf("q: %s\n", u.plist[i].q);
		printf("v: %s\n", u.plist[i].v);
	}
}

int main(void)
{
	//char *url;//this is the problem
	char url[MAX_LEN];
	scanf("%s", url);
	url_t u = parse_url(url);
	print_url(u);
	free_url(u);
}


tianyebj tianyebj@gmail.com
2009-10-17 21:30:52

重发第2题:

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

#define N 10 //max param numbers
#define MAX_LEN 100 // max len of path
#define MAX_P 20 // max len of param
struct param_t {
	char *q;
	char *v;
};

typedef struct {
	char *url_path;
	struct param_t plist[N];
	int pnum;
} url_t;

void set_param(struct param_t *p, char *token) {
	char *pos = strchr(token, '=');
	p->q = (char *)malloc(MAX_P);
	p->v = (char *)malloc(MAX_P);
	if (pos != NULL) {
		p->q = strncat(p->q, token, pos - token);
		p->v = strcat(p->v, pos + 1);
	} else {
		p->q = strcat(p->q, token);
		*(p->v) = '\0';
	}
}


url_t parse_url(char *url)
{
	char header[8] = "http://";
	char url_header[8];
	strncpy(url_header, url, 7);
	url_header[7] = '\0';
	header[7] = '\0';
	if (strcmp(url_header, header)) {
		printf("url error!\n");
		exit(2);
	}
	url_t u;
	u.url_path = (char *)malloc(MAX_LEN);
	char *pos = strchr(url, '?');
	u.pnum = 0;
	if (pos != NULL) {
		strncat(u.url_path, url, pos - url);
		char *token;
		token = strtok(pos + 1, "&");
		set_param(&u.plist[u.pnum++], token);
		while ((token = strtok(NULL, "&")) != NULL) {
			set_param(&u.plist[u.pnum++], token);
		}
	} else {
		strcat(u.url_path, url);
	}
	return u;	
}

void free_url(url_t u) {
	free(u.url_path);
	u.url_path = NULL;
	int i;
	for (i = 0; i < u.pnum; i++) {
		free(u.plist[i].q);
		u.plist[i].q = NULL;
		free(u.plist[i].v);
		u.plist[i].v = NULL;

	}
}

void print_url(url_t u) {
	printf("path: %s\n", u.url_path);
	int i;
	for (i = 0; i < u.pnum; i++) {
		printf("==========\n");
		printf("q: %s\n", u.plist[i].q);
		printf("v: %s\n", u.plist[i].v);
	}
}

int main(void)
{
	//char *url;//this is the problem
	char url[MAX_LEN];
	scanf("%s", url);
	url_t u = parse_url(url);
	print_url(u);
	free_url(u);
}


吴书杰 wsj3000@gmail.com
2010-03-29 16:55:07

第一题:
char *strtok(char *SOURCE, const char *DELIMITERS)
{
	static char * lloc = NULL;
	int i;
	SOURCE != NULL ? lloc=SOURCE : 0;

	if(lloc[0] == '\0')
			return NULL;
	for(i=0; lloc[i]!='\0'; i++){
		if(matchchr(lloc[i], DELIMITERS)){
			if(matchchr(lloc[i+1], DELIMITERS)){
				lloc[i] = '\0';
				continue;
			}else
				break;
		}
	}

	if(lloc[i] == '\0'){
		lloc = lloc+i;
		return lloc-i;
	}else{
		lloc[i] = '\0';
		lloc = lloc+i+1;
		return lloc-i-1;
	}
}

char *strtok_r(char *SOURCE, const char *DELIMITERS,
    char **LASTS)
{
	int i;
	SOURCE != NULL ? *LASTS=SOURCE : 0;

	if(*LASTS[0] == '\0')
		return NULL;
	for(i=0; (*LASTS)[i]!='\0'; i++){
		if(matchchr((*LASTS)[i], DELIMITERS)){
			if( matchchr( (*LASTS)[i+1], DELIMITERS) ){
				(*LASTS)[i] = '\0';
				continue;
			}else
				break;
		}
	}
	if((*LASTS)[i] == '\0'){
		*LASTS = *LASTS+i;
		return *LASTS-i;
	}else{
		(*LASTS)[i] = '\0';
		*LASTS = *LASTS+i+1;
		return *LASTS-i-1;
	}
}

int matchchr(char chr, const char * chs)
{
	for(; *chs != '\0'; chs++){
		if(*chs == chr){
			return 1;
		}
	}
	return 0;
}


吴书杰 wsj3000@gmail.com
2010-03-29 17:10:13

压缩了一点代码:
char *strtok(char *SOURCE, const char *DELIMITERS)
{
	static char * lloc = NULL;
	int i;
	SOURCE != NULL ? lloc=SOURCE : 0;

	if(lloc[0] == '\0')
			return NULL;
	for(i=0; lloc[i]!='\0'; i++){
		if(matchchr(lloc[i], DELIMITERS)){
			if(matchchr(lloc[i+1], DELIMITERS)){
				lloc[i] = '\0';
				continue;
			}else
				break;
		}
	}

	if(lloc[i] != '\0')
		lloc[i++] = '\0';
	lloc = lloc+i;
	return lloc-i;

}

char *strtok_r(char *SOURCE, const char *DELIMITERS,
    char **LASTS)
{
	int i;
	SOURCE != NULL ? *LASTS=SOURCE : 0;

	if(*LASTS[0] == '\0')
		return NULL;
	for(i=0; (*LASTS)[i]!='\0'; i++){
		if(matchchr((*LASTS)[i], DELIMITERS)){
			if( matchchr( (*LASTS)[i+1], DELIMITERS) ){
				(*LASTS)[i] = '\0';
				continue;
			}else
				break;
		}
	}
	if((*LASTS)[i] != '\0')
		(*LASTS)[i++] = '\0';
	*LASTS = *LASTS+i;
	return *LASTS-i;
}

int matchchr(char chr, const char * chs)
{
	for(; *chs != '\0'; chs++){
		if(*chs == chr)
			return 1;
	}
	return 0;
}


Ben benzhemin@gmail.com
2010-07-28 15:29:09

第一题
char *strtok(char *str, const char *delim) {
    static char *startp = NULL;
    if (str == NULL) {
        while ((*startp) != '\0' && (*startp) == *delim) {
            startp++;
        }
        str = startp;
    } else {
        startp = str;
    }
    while ((*startp) != '\0' && (*startp) != *delim) {
        startp++;
    }
    if ((*startp) == *delim) {
        *startp = '\0';
        startp++;
    }
    while((*startp)==*delim){
        startp++;
    }
    if(*str=='\0'){
        return NULL;
    }
    return str;
}


char *strtok_r_custom(char* str, const char* delim, char** saveptr){
    int delimlen = strlen(delim);

    char *strstart;
    if(str == NULL){
        strstart = *saveptr;
        while(cmpequal(*saveptr, delim, delimlen)==0){
            (*saveptr)++;
        }
        if(cmpequal(*saveptr, delim, delimlen)==1){
            **saveptr = '\0';
            (*saveptr)++;
        }
        while(cmpequal(*saveptr, delim, delimlen)==1){
            (*saveptr)++;
        }
    }else{
        strstart = str;
        while(cmpequal(str, delim, delimlen)==0){
            str++;
        }
        if(cmpequal(str, delim, delimlen)==1){
            *str = '\0';
            str++;
        }
        while(cmpequal(str, delim, delimlen)==1){
            str++;
        }
        *saveptr = str;
    }
    if((*strstart) == '\0'){
        return NULL;
    }
    return strstart;
}

int cmpequal(char* str, char* delim, int delimlen){
    if(*str=='\0'){
        return 2;
    }
    for(int i=0; i<delimlen; i++){
        if(*str==delim[i]){
            return 1;
        }
    }
    return 0;
}


赖先科 lvtomato19@163.com
2010-12-17 11:56:09

1.5比较字符串中的函数并不仅是遇到'\0'才结束,当比较出现不同的字符时,比较也会结束。


宋劲杉 songjinshan@gmail.com
2011-01-01 18:57:00

确实表达不严谨,在正式出版的书里会改过来,谢谢指出!


tangfei tangfei518@sina.com
2011-05-12 17:57:14

#define PATH_LEN_MAX 100
#define QUERY_PARAM_LEN_MAX 20
#define QUERY_PARAM_NUMBER_MAX 10

#define NO_QUERY 1
#define SUCCESS 0
#define PATH_FORM_ILLEGAL -1
#define KEY_VALUE_PAIR_ERROR -2
#define QUERY_FORM_ERROR -3


typedef struct{
	char key[QUERY_PARAM_LEN_MAX];
	char value[QUERY_PARAM_LEN_MAX];
}query_param;

typedef struct{
	char url_path[PATH_LEN_MAX];
	query_param query_param_list[QUERY_PARAM_NUMBER_MAX];
	int query_param_number;
}url;


int parse_url(char *url_str, url *instance)
{
	url url_n;
	char *token, *subtoken;
	char *ptr1,*ptr2,*ptr3;
	int i;
	
	token = strtok_r(url_str, "?", &ptr1);
	if (NULL == strstr(token, "http://"))
		return PATH_FORM_ILLEGAL;
	else
		strcpy(instance->url_path, token);
	
	if (NULL == ptr1)
		return NO_QUERY;
	
	for (i=0; token=strtok_r(ptr1, "&", &ptr2); i++,ptr1=NULL) {

		if (subtoken=strtok_r(token, "=", &ptr3)) {
			if ('\0'==*ptr3)
				return KEY_VALUE_PAIR_ERROR;
			strcpy(instance->query_param_list[i].key, subtoken);
			strcpy(instance->query_param_list[i].value, ptr3);
		}
		strtok_r(NULL, "=", &ptr3);
		if (NULL!=ptr3)
			return KEY_VALUE_PAIR_ERROR;
	}
	
	if (0 == i)
		return 	QUERY_FORM_ERROR;
	
	instance->query_param_number = i;
	
	return SUCCESS;
}

void print_error(int n)
{
	switch(n){
	case 1: printf("The url has not query!\n");
		break;
	case 0: printf("Get url success!\n");
		break;
	case -1: printf("Path form is wrong!\n");
		break;
	case -2: printf("key form is wrong!\n");
		break;
	case -3: printf("Query form is wrong\n");
		break;
	default: printf("Unkonwn error!\n");
		break;									
	}
}
void print_url(url *purl)
{
	int i = 0;
	
	if ('\0'==*(purl->url_path)){
		printf("Path is empty!\n");
		return;	
	}
	printf("PATH:%s\n",purl->url_path);
	
	if (0==purl->query_param_number){
		printf("Query key is empty!\n");
		return;	
	}
	for (; i<purl->query_param_number; i++) {
		printf("---------QUERY KEY %d--------\n",i+1);	
		printf("KEY:%s\n",purl->query_param_list[i].key);
		printf("VALUE:%s\n",purl->query_param_list[i].value);
	}
}

int main(int argc, char *argv[])
{
	char *url_s = "http://www.google.cn/search?complete=1&hl=zh-CN&ie=GB2312&q=linux&meta= ";
	url url_n;
	int ret;
	
	memset((void *)&url_n, 0x00, sizeof(url));
	print_url(&url_n);
	
	ret = parse_url(url_s, &url_n);
	
	print_error(ret);
	
	print_url(&url_n);

	return 0;
}


chen liang epstein_2002@yahoo.com.cn
2011-11-02 16:57:28

第一题答案:
#include <stdio.h>
#include <stdlib.h>

int isdelim(const char *mark,const char *delim)
{
	while(*delim!='\0')
	{
		if(*mark==*delim)
			return 1;
		delim++;
	}
	return 0; 	
}

char *strtok(char *str, const char *delim)
{
	static char *local_pointer=NULL;
	char   *delim_char,*return_pointer;
	
	if(!delim)
		return NULL;
	
	if(str)
	{
		local_pointer=str;
	}
	
	if(!local_pointer)
		return NULL;
	return_pointer=local_pointer;
	while(*local_pointer!='\0')
	{
		if(isdelim(local_pointer,delim))
		{	
			*local_pointer='\0';
			local_pointer++;
			return return_pointer;
		}		
		local_pointer++;			
	}
	return NULL;
}

char *strtok_r(char *str, const char *delim, char **saveptr)
{
	char	*local_pointer;
	char	*delim_char,*return_pointer;
	   
	if(!delim)
	   return NULL;
		 
    if(str)
	{
		*saveptr=str;
	}
    local_pointer=*saveptr;
		
	if(!local_pointer)
		return NULL;
	
	return_pointer=local_pointer;
			    
	while(*local_pointer!='\0')
	{
		if(isdelim(local_pointer,delim))
		{
			*local_pointer='\0';
			local_pointer++;
			*saveptr=local_pointer;
			return return_pointer;
		}
		local_pointer++;
	}
	return NULL;
}
int main(int argc,char *argv[])
{
	char str[] = "root:x::0:root:/root:/bin/bash:";
	char *token,*token_return,*token_save;
    
    for(token=str;;token=NULL)
	{
		token_return=strtok_r(token,":",&token_save);
		if(!token_return)
			break;
		 printf("%s\n", token_return);
	}
	return 0;
}
希望大家多指点!谢谢!


peerben benzhemin@gmail.com
2011-11-10 21:44:16

int isdelem(char c, const char *split){
	while(split!=NULL && *split != '\0'){
		if(c == *split){
			return 1;
		}
		split++;
	}
	return 0;	
}

char* str_tok_r(char *str, const char *split, char **saveptr){
	char* pstart;
	char* pcur;

	if(*saveptr != NULL){
		if(**saveptr == '\0'){
			str = NULL;
		}else{
			str = *saveptr;
		}
	}

	while(str!=NULL && *str!='\0' && isdelem(*str, split)){
		str++;
	}

	pstart = pcur = str;

	while(pcur!=NULL && *pcur!='\0'){
		if(!isdelem(*pcur, split)){
			pcur++;
		}else{
			*pcur = '\0';
			pcur++;
			*saveptr = pcur;
			break;
		}
	}

	if(pcur!=NULL && *pcur == '\0'){
		*saveptr = NULL;
	}
	return pstart;
}

貌似我写的很麻烦


peerben benzhemin@gmail.com
2011-11-10 22:22:34

char* str_tok_r(char *str, const char *split, char **saveptr){
	char* pstart;
	char* pcur;

	if(str == NULL){
		str = *saveptr;
	}

	while(str!=NULL && *str!='\0' && isdelem(*str, split)){
		str++;
	}

	pstart = pcur = str;

	while(pcur!=NULL && *pcur!='\0'){
		if(!isdelem(*pcur, split)){
			pcur++;
		}else{
			*pcur = '\0';
			pcur++;
			*saveptr = pcur;
			break;
		}
	}

	if(pcur!=NULL && *pcur == '\0'){
		*saveptr = NULL;
	}
	return pstart;
}
修正


peerben benzhemin@gmail.com
2011-12-12 14:22:41

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

typedef struct _query_param{
    char *key;
    char *value;
    struct _query_param *next;
} query_param;

typedef struct _url_node{
    char *path; 
    query_param *param;
} url_node;

url_node *parse_url(char *url_path);
void print_url(url_node *node);
void free_url(url_node *node);

int main(void){
    char *url_path = "http://www.google.cn/search?complete=1&hl=zh-CN&ie=GB2312&q=linux&meta=";
    char *url_path2 = "http://www.baidu.com/s?wd=linux&cl=3";
    
    url_node *node = parse_url(url_path);
    print_url(node);
    free_url(node);
	
    return 0;
}

url_node *parse_url(char *url_path){
    size_t len = strlen(url_path);
    char *url_to_parse = (char *)malloc(sizeof(char)*len+1);
    strcpy(url_to_parse, url_path);
	
    char *url = strtok(url_to_parse, "?");
    char *param = strtok(NULL, "?");
	
    url_node *node = (url_node *)malloc(sizeof(url_node));
    node->path = (char *)malloc(strlen(url)+1);
    strcpy(node->path, url);
	
    char *param_str;
    char *saveptr1, *saveptr2;
    while((param_str=strtok_r(param, "&", &saveptr1))!=NULL){
		param = NULL;
		
        query_param *new_param = (query_param *)malloc(sizeof(query_param));
        char *param_key = strtok_r(param_str, "=", &saveptr2);
        char *param_value = strtok_r(NULL, "=", &saveptr2);
        if(param_key!=NULL){
            new_param->key = malloc(strlen(param_key)+1);
            strcpy(new_param->key, param_key);
        }
        if(param_value!=NULL){
            new_param->value = malloc(strlen(param_value)+1);
            strcpy(new_param->value, param_value);
        }
		
        query_param **p_param = &node->param;
        query_param *last_param = node->param;
        while(last_param!=NULL){
            p_param = &last_param->next;
            last_param = last_param->next;
        }
        *p_param = new_param;         
    }
	
    free(url_to_parse);
	
    return node;
}

void print_url(url_node *node){
    printf("url path:%s\n", node->path);
    query_param *param = node->param;
    while(param!=NULL){
        printf("key:%s\n", param->key);
        printf("value:%s\n", param->value);
		
        param = param->next;
    }
}

void free_url(url_node *node){
    free(node->path);
    node->path = NULL;
	
    query_param *last_param = node->param;
    while(last_param!=NULL){
        query_param *temp = last_param;
        last_param = last_param->next;
        free(temp);
    }
	
    free(node);
}


如果您有建设性意见,哪怕只是纠正一个错别字,也请不吝赐教,您留下的姓名和email将会出现在本书前言的致谢中。再次感谢您的宝贵意见!