2015-03-02 49 views
0

我的代碼位於底部。我試圖採取兩個字符串,並根據我收到的編輯抄本來更改它們。我寫了我的代碼,但我不明白爲什麼我得到這樣一個奇怪的輸出。我的目標是首先存儲這兩個字符串的值,然後將它們變成一個二維數組,但是我沒有參與那個目標的第一部分。這裏的問題:字符對齊怪異輸出

創建,以滿足以下的函數:

輸入:編輯轉錄,和2個原始字符串(3串)

輸出:含有兩種比對後編輯一個2 d陣列

實施例:

s1 = 「vintner」 
s2 = 「writers」 
trans = 「RIMDMDMMI」 

R表示 「替換」 I代表 「插入」 M代表 「匹配」 d代表 「刪除」 答:

alignment={「v_intner_」, 
「wri_t_ers」}; //return a 2d array 

函數原型:

char** getAlignment(char* s1, char* s2, char* s3); 

這裏是我下面的代碼:

char TestS1[] = "vintner"; 
char TestS2[] = "writers"; 
char TestS3[] = "RIMDMDMMI"; 
char twoDarray[2][10]; 

char** getAlignment(char* s1, char* s2, char* s3){ 
    char transTemp[n]; 
    char s1Temp[n]; 
    char s2Temp[n]; 
    char sOne[n]; 
    char sTwo[n]; 
    strcpy(sOne, s1); 
    strcpy(sTwo, s2); 
    int jj; 
    strcpy(transTemp, s3); 
    int kk; 
    for(jj=0, kk=0; jj<n, kk<n; jj++, kk++){ 

     if(transTemp[jj]=='R') 
     { 
      s1Temp[kk] = sOne[jj]; 
      s2Temp[kk] = sTwo[jj]; 
     } 

     if(transTemp[jj]=='I'){ 
      s1Temp[kk] = '_'; 
      s1Temp[kk+1] = sOne[jj]; 
      s2Temp[kk] = sTwo[jj]; 
      kk++; 
     } 

     if(transTemp[jj] == 'M'){ 
      s1Temp[kk] = sOne[jj]; 
      s2Temp[kk] = sTwo[jj]; 
     } 

     if(transTemp[jj] == 'D'){ 
      s2Temp[kk] = '_'; 
      s2Temp[kk+1] = sTwo[jj]; 
      s1Temp[kk] = sOne[jj]; 
      kk++; 
     } 


    } 

    printf("\ns1Temp = %s\n", s1Temp); 
    printf("\ns2Temp = %s\n", s2Temp); 


    return 0; 
} 

main() 
{ 
printf("The new method returns: ", getAlignment(TestS1,TestS2,TestS3)); 
return 0; 
} 
+1

無格式說明在這裏:'的printf( 「新方法返回:」 getAlignment(TestS1,TestS2,TestS3));' – 2015-03-02 06:55:07

+0

是啊,感謝指出了這一點。但是,我並不在意printf語句發生了什麼。我只是想調用這個函數。我關注的值被打印在函數中。 – 2015-03-02 06:59:24

+0

你正試圖返回一個'int'函數來返回一個'char **' – 2015-03-02 07:00:19

回答

1

你的問題真有兩部分:如何返回兩個字符串?爲什麼我沒有獲得期望的輸出?

C中的字符串是字符數組。你很少返回字符串。將字符數組傳遞給函數以及其最大長度並填充該數組更爲常見。 <string.h>中的功能可以做到這一點。在我看來,一個好的設計模型是:snprintf:它填充緩衝區,注意不要溢出它,確保結果正確地以null結尾,並返回緩衝區足夠大時寫入的字符數。最後一個屬性允許你傳遞一個空值(並且作爲一個特殊情況,指針爲NULL),以找出需要多少個字符並根據需要分配內存。

所以原型的功能看起來是這樣的:

int getAlignment(char *res1, char *res2, size_t n, 
    const char* s1, const char* s2, const char* trans); 

除了生成的字符串可能是你的情況不同的長度。

您也可以返回一個字符串,但你要麼必須在堆上,這意味着客戶端代碼必須明確free它,或指針到現有存儲返回與malloc分配新的內存。當然,您可以只返回一個字符串。

您可以從函數返回多個值作爲結構體。將函數傳遞給函數或從函數返回時,結構不會衰減爲指針。我將在下面的示例中使用該方法。

至於第二個問題:你的主要問題是你有三個字符串 - 兩個源字符串和一個翻譯字符串 - 但只保留兩個索引。所有字符串都是獨立遍歷的;字符串的索引之間沒有同步。

您隨時追加到結果字符串。 「驅動」字符串是trenslation字符串,所以您只能通過主循環來遍歷。

要注意的另一件事是您不需要製作源字符串的副本。這不僅是必要的,而且也是危險的,因爲strcpy可能會溢出緩衝區。使用strncpy來處理溢出會截斷輸入字符串。

我已經更新您的實現:

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

#define N 10 

struct Result { 
    char res1[N]; 
    char res2[N]; 
}; 

struct Result getAlignment(const char* s1, const char* s2, const char* trans) 
{ 
    struct Result res; 

    int j1 = 0;    // index into s1 
    int j2 = 0;    // index into s2 
    int n = N - 1;   // leave 1 char for null terminator 

    while (*trans) { 

     if (*trans == 'R') { 
      if (j1 < n) res.res1[j1++] = *s1++; 
      if (j2 < n) res.res2[j2++] = *s2++; 
     } 

     if (*trans == 'I'){ 
      if (j1 < n) res.res1[j1++] = '_'; 
      if (j1 < n) res.res1[j1++] = *s1++; 
      if (j2 < n) res.res2[j2++] = *s2++; 
     } 

     if (*trans == 'M') { 
      if (j1 < n) res.res1[j1++] = *s1++; 
      if (j2 < n) res.res2[j2++] = *s2++; 
     } 

     if (*trans == 'D') { 
      if (j1 < n) res.res1[j1++] = *s1++; 
      if (j2 < n) res.res2[j2++] = '_'; 
      if (j2 < n) res.res2[j2++] = *s2++; 
     } 

     trans++; 
    } 

    // null-terminate strings 
    res.res1[j1] = '\0'; 
    res.res2[j2] = '\0'; 

    return res; 
} 

int main() 
{ 
    char *str1 = "vintner"; 
    char *str2 = "writers"; 
    char *trans = "RIMDMDMMI"; 

    struct Result res = getAlignment(str1, str2, trans); 

    printf("%s\n%s\n\n", res.res1, res.res2); 

    return 0; 
} 

注意事項:

  • 翻譯字符串指針通過,從而節省了指數運行。

  • 僅當有足夠的空間時,纔會將結果字符串附加到後面。您可以將N更改爲5,並查看結果字符串在4個字符後如何截斷,從而丟失信息,但會防止緩衝區溢出。

  • 結果字符串索引和源字符串指針隨着你的增加而增加。

  • 只能讀取源字符串。 (這就是爲什麼複製沒有意義。)所以它們應該在函數簽名中爲const char *