[英]SOLVED-what am I doing wrong that strtok does right in splitting a string
上一個問題是:strtok 在拆分字符串時做對了,我做錯了什么。 突然將 strtok 分離到 function 也不會產生正確的結果?
這是我第一次在 stackoverflow 中提問,所以請原諒我是否冗長和不連貫。 問題的最后一部分在該問題正文的底部進行了詳細說明。
所以,我正在做我的大學分配的課程評估,其中一個問題是:
刪除重復的單詞並僅打印唯一的單詞
輸入:單個句子,其中每個單詞由空格分隔
Output:由空格分隔的唯一單詞[單詞順序應與輸入中的順序相同]
例子:
輸入:adc aftrr adc art
Output:adc aftrr 藝術
現在,我有了解決方案,即在空格上拆分字符串並將單詞添加到數組(集合)中(如果它尚不存在),但正是實現部分讓我費盡心機
#include <stdio.h>
#include <string.h>
#define MAX 20
int exists(char words[][MAX], int n, char *word){ // The existence check function
for(int i=0;i < n;i++)
if(strcmp(words[i],word) == 0)
return 1;
return 0;
}
void removeDuplicateOld(char*);
void removeDuplicateNew(char*);
int main(){
char sentence[MAX*50] = {0}; //arbitary length
fgets(sentence,MAX*50,stdin);
sentence[strcspn(sentence,"\n")]=0;
printf("The Old One : \n");
removeDuplicateOld(sentence);
printf("\nThe New One : \n");
removeDuplicateNew(sentence);
}
使用strtok分割字符串的函數:
void removeDuplicateNew(char *sentence){
char words[10][MAX] = {0};
int wi=0;
char *token = strtok(sentence," ");
while(token != NULL){
if(exists(words,wi,token)==0) {
strcpy(words[wi++],token);
}
token = strtok(NULL," ");
}
for(int i=0;i<wi;i++) printf("%s ",words[i]);
}
使用我的舊方法的舊 function(在我遇到空格之前構造一個詞):
void removeDuplicateOld(char *sentence){
char objects[10][MAX] = {0}; //10 words with MAX letters
char tword[MAX];
int oi=0, si=0, ti=0;
while(sentence[si]!='\0'){
if(sentence[si] != ' ' && sentence[si+1] != '\0')
tword[ti++] = sentence[si];
else{
if(sentence[si+1] == '\0')
tword[ti++]=sentence[si];
tword[ti]='\0';
if(exists(objects,oi,tword) == 0){
strcpy(objects[oi++],tword);
}
ti=0; // The buffer[tword] is made to be overwritten
}
si++;
}
for(int i=0;i<oi;i++)
printf("%s ",objects[i]);
}
已解決:將 if(sentence[si+1] == '\0') 更改為 if(sentence[si+1] == '\0' && sentence[si]!=' ')
這是 output:
輸入:abc def ghi abc jkl ghi
舊一:
abc def ghi jkl
新的那一個:
abc def ghi jkl
請注意,輸入中的尾隨空格和 output 未被檢查,因為它們自己的驅動程序代碼未正確處理它們,而 strtok 方法可以並通過所有測試。
現在這兩種方法似乎產生了相同的結果,但它們確實根據測試用例產生了不同的輸出,並且在將 strtok 方法作為一個單獨的函數 [removeDuplicateNew] 的頂部,它在一個測試用例中失敗,而在 main 方法中編寫它本身通過了所有測試,看到這些結果:
Strtok 方法作為單獨的 Function 測試用例結果
以下已移至單獨的問題線程
在 main 方法本身中編碼時:
int main(){
char sentence[MAX*50] = {0}; //arbitary length
fgets(sentence,MAX*50,stdin);
sentence[strcspn(sentence,"\n")] = 0;
char words[10][MAX] = {0};
int wi=0;
char *token = strtok(sentence," ");
while(token != NULL){
if(exists(words,wi,token)==0) {
strcpy(words[wi++],token);
}
token = strtok(NULL," ");
}
for(int i=0;i<wi;i++) printf("%s ",words[i]);
}
作為記錄,它是放在 main 方法中的相同代碼,所以這里到底發生了什么,當我將它分離為 function 並將字符串作為參數傳遞時,它突然無法正常工作。
還有關於我的問題構建的任何建議,措辭表示贊賞。
你的代碼...
void removeDuplicateOld(char *sentence){
char objects[10][MAX] = {0}; //10 words with MAX letters
char tword[MAX];
int oi=0, si=0, ti=0;
while(sentence[si]!='\0'){
if(sentence[si] != ' ' && sentence[si+1] != '\0')
tword[ti++] = sentence[si];
else{
// right here have hit SP.
// if SP followed by '\0'
// then append SP to my word... wrong! <=====
if(sentence[si+1] == '\0')
tword[ti++]=sentence[si];
tword[ti]='\0';
這就是庫 function strtok()
比hand rolled
代碼更好用的原因。
它已經過測試並證明可以像它所說的那樣工作。
有更好的方法來使用strtok()
for( char *p = sentence; (p = strtok( p, " \n") ) != NULL; p = NULL )
if( exists( words, wi, p ) == 0 )
strcpy( words[wi++], p );
這就是你所需要的。 strtok() 甚至會為您修剪緩沖區中的 LF,無需額外付費。
最后的建議:您可以考慮可以輕松增長的鏈表 (LL),而不是固定大小的單詞指針數組。 function 將 append 一個新詞到列表的末尾,如果在遍歷到 append 到 LL 的末尾時發現它是重復的,則可以悄悄地吃掉這個詞。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.