引入:字符串切割strtok()函數

問題引入

最近在解決AHNU在線測試http://172.16.94.19:8080/JudgeOnline/showproblem?problem_id=1496時,遇到了麻煩,問題描述如下:

Description

讀取一行文本,輸出相同的文本,但將所有整數中的數字替換成’x’(長度不限)。

Input

一行文本。

Output

替換後的一行文本。

Sample Input

My userID is john17 and my 4 digit pin is 12345 which is secret.

Sample Output

My userID is john17 and my x digit pin is xxxxx which is secret.

初步解決步驟如下:

①將輸入的文本text按照空格爲分隔符,將每個單詞存到字符串數組word中(單詞總數可由text字符串中空格數確定);

②對字符串數組word的每一個元素word[i]字符串進行判斷,若字符串word[i]中全由數字組成,則將該串的每一個字符替換爲'x';

③構造循環,依次輸出字符串數組的每一個元素,實現數字替換。

基於以上想法,構造以下函數,分別爲:字符串切割函數(實現步驟①)、字符串轉換函數(實現步驟②)

字符串切割函數

void Split(char *text,char **word)
{
	int i=0;
	int k=0;//當前已完成單詞數
	int j=0;
	while(i<strlen(text))
	{
		j=0;
		while(text[i]!=' '&&text[i]!='\0')
		{
			word[k][j]=text[i];
			j++; 
			i++;
		}
		word[k][j]='\0';
		//printf("%s ",word[k]);
		//printf("k:%d i:%d j:%d\n",k,i,j);
		k++;
		i++;
	}
}

字符串轉換函數

void Convert(char **word,int num)//若字符串s中全爲數字,則將所有數字轉化爲'x'
{
	int i,j=0;
	int count=0;
	int R[256]={0}; 
	/*********************初始化數組R**********************/
	for(i=48;i<=58;i++)
	R[i]=1;//數字位置置爲1
	 /*****************************************************/
	for(i=0;i<num;i++)
	{
		j=0;
		count=0;
		while(j<strlen(word[i]))
		{
			count+=R[word[i][j]];
			j++;
		}
		//printf("%d ",count);
		if(count==strlen(word[i]))//數字字符數等於字符串長度
		{
			j=0;
			while(j<strlen(word[i]))
			{
				word[i][j]='x';
				j++;
			}
		}
	}
}

主函數

int main()
{
	char text[300000];//要求輸入長度無限
	char **word;
	int num=0,i;
	gets(text);
	num=WordCount(text);
	word=(char**)malloc(num*sizeof(char*));
	for(i=0;i<num;i++)
	word[i]=(char*)malloc(50*sizeof(char));//爲每個單詞分配內存空間
	Split(text,word);
	Convert(word,num);
	for(i=0;i<num;i++)
	printf("%s ",word[i]);//輸出測試 
	for(i=0;i<num;i++)
	free(word[i]);//釋放每個單詞內存空間
	free(word);
	//printf("%d",num);
	return 0;
}

實際運行時,對於長度在可接受範圍內的字符串,運行效果良好。但對於測試數據5,輸入的數據爲一長度近300000的字符串,此時程序運行緩慢,近20s,提交時出現了Time Limit Exceed 的錯誤。通過分析,主要時間花費在字符串切割函數Split()中,因此若基於以上解題步驟,必須找到一種高效的字符串切割算法。

算法改進

實際上,C語言頭文件<string.h>中提供了字符串切割函數strok(),經過測試,該函數的時間複雜度較好,能夠滿足要求。將其與原字符串切割函數替換後,程序執行時間大大降低,可保持在10s內。Convert()字符串轉換函數思想不改,同時將字符串切割體現在主函數裏。修改後的Convert()和main()函數如下:

字符串轉換函數Convert()

void Convert(char *word)//若字符串s中全爲數字,則將所有數字轉化爲'x'
{
	int i,j=0;
	int count=0;
	int R[256]={0}; 
	/*********************初始化數組R**********************/
	for(i=48;i<=58;i++)
	R[i]=1;//數字位置置爲1
	 /*****************************************************/
		j=0;
		count=0;
		while(j<strlen(word))
		{
			count+=R[word[j]];
			j++;
		}
		if(count==strlen(word))//數字字符數等於字符串長度
		{
			j=0;
			while(j<strlen(word))
			{
				word[j]='x';
				j++;
			}
		}
}

主函數main()

int main(void)
{
    char text[3000000];
    gets(text);
    char *temp = strtok(text," ");
    printf("%s\n",temp);
    while(temp)
    {
    	Convert(temp);
        printf("%s ",temp);
        temp = strtok(NULL," ");
    }
    return 0;
}

結論

strotok()函數切割字符串效率較高,實際應用中應當掌握該函數的參數以及返回類型,必要時需要明白實現機制。關於strotok()函數我將在下一篇博客中詳細介紹。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章