2015-06-28 45 views
0

當我運行我爲'strlen'編寫的程序時,我不斷收到錯誤。 (當一個字符串出現在另一個字符串的末尾時,strlen返回1)。我想這是第一次給出錯誤的while循環,因爲當我把printf("%c\n", *s);而不是空的;,它只是正常工作。語法有什麼問題?雖然執行'strend'時出現循環錯誤

#include <stdio.h> 

int strend(char *s, char *t) 
{ 
    int len; 
    int dummy; 
    while (*s++) 
     ; // why error??? 
    while (*t++) 
     len++; 

    for (; len>0 ; len--) 
    { 
     if (*(s-len) != *(t-len)) 
      return 0; 
    } 
    return 1; 
} 

int main() { 
    char one[] = "I 0dont like youa"; 
    char two[] = "ke youa"; 
    printf("%d\n", strend(one, two)); 
} 
+3

初始化'和'0' len'。 –

+0

改爲'while(* s)++ s;對於(len = 0; * t; ++ t)++ len;' – BLUEPIXY

+1

對於64位很長的字符串,代碼將會失敗。更好地使用'size_t'而不是'int'。 – alk

回答

4

首先你忘了初始化LEN,你應該爲0

int len=0; 

初始化其次使用:

while (*s) 
    s++; // s should be incremented only if *s is not 0. 
while (*t) 
{ 
    t++; //Same issue here. 
    len++; 
} 
2

所有局部變量LEN的第一個未初始化

int len; 

所以該函數已經具有未定義的行爲。環

while (*s++); 
while (*t++) len++; 

兩個指針指向超出每個字符串的結束零後

二。因此,該比較(以及for循環本身)

if (*(s-len) != *(t-len)) 

無效。 的確讓我們假設我們有

char s[] = { 'a', '\0' }; 
char t[] = { 'a', '\0' }; 

len個將等於1(前提是你最初初始化LEN 0)以上的循環後。同時,t和s將指向終止零之後的內存。因此*(s - len)*(t - len)將表示元素'\0',您將只比較這些終止零,而不會比較具有'a'的元素,因爲for循環的條件爲len>0。這意味着當len等於1時,循環只有一次迭代。

一個正確的函數可以寫成更簡單,更清晰

int strend(const char *s, const char *t) 
{ 
    const char *p = s; 
    const char *q = t; 

    while (*s++); 
    while (*t++); 

    while (s != p && t != q && *(s - 1) == *(t - 1)) --s, --t; 

    return t == q; 
} 

如果是不重要的其中一個字符串出現在另一個字符串的末尾,則可以替換該return語句

return t == q; 

爲以下一個

return s == p || t == q; 

在這種情況下本程序

//... 

int main(void) { 
    char one[] = "I 0dont like youa"; 
    char two[] = "ke youa"; 
    printf("%d\n", strend(one, two)); 
    printf("%d\n", strend(two, one)); 
} 

將輸出

1 
1 

而如果使用使用第一return語句return t == q;然後程序

//... 

int main(void) { 
    char one[] = "I 0dont like youa"; 
    char two[] = "ke youa"; 
    printf("%d\n", strend(one, two)); 
    printf("%d\n", strend(two, one)); 
} 

將輸出

1 
0 
+0

thx很多!但後來我不明白在我的代碼中'printf'有什麼不同。它似乎找出未初始化的len本身並正確運行代碼。你知道原因嗎? – deNsuh

+0

@deNsuh對不起。我沒有明白你的意思。 –

+0

@deNsuh考慮到因爲len沒有初始化,程序有未定義的行爲。這意味着它可以給出預期的結果或意想不到的結果。 –

0

錯誤應該來,因爲的錯誤唱歌初始化int len = 0;。我建議使用while總是擁抱這樣的while { /*your code*/ };

無論如何,你的第一個while循環應該沒問題。我用兩個分離的循環做了一些修改。

#include <stdio.h> 

int strend(char *s, char *t) 
{ 
    int len = 0;   // init 0 
    int i = 0, 
     j = 0; 

    while (*s++) { i++; } // get both string lengths 
    while (*t++) { j++; } 

    if (i > j)    // compare and use shorter one 
     len = j; 
    else 
     len = i; 

    len++;     // offset: start from 1st character 
          // [fix-issue: 2015-06-28 12:41] 
    for (; len>0 ; len--) 
    { 
     //printf("%d: \"%c\" \"%c\"\n", len, *(s-len), *(t-len)); // test-out 

     if (*(s-len) != *(t-len)) 
      return 0; 
    } 

    return 1; 
} 

int main() 
{ 
    char one[] = "ABCDE"; 
    char two[] = "CDE"; 
    printf("test case 1: [%s][%s] %d\n", one, two, strend(one, two)); 

    two[1] = '_'; 
    printf("test case 2: [%s][%s] %d\n", one, two, strend(one, two)); 

    two[0] = '?'; 
    two[1] = 'D'; 
    printf("test case 3: [%s][%s] %d\n", one, two, strend(one, two)); 

    two[0] = 'C'; 
    two[2] = '#'; 
    printf("test case 4: [%s][%s] %d\n", one, two, strend(one, two)); 
} 

輸出是這樣的:

test case 1: [ABCDE][CDE] 1                                  
test case 2: [ABCDE][C_E] 0                                  
test case 3: [ABCDE][?DE] 0                                  
test case 4: [ABCDE][CD#] 0