簡體   English   中英

按字母順序排列單詞 C

[英]Sorting words in alphabetically order C

所以我的練習是對一維字符數組中的單詞進行排序。 我的代碼幾乎可以工作,但它總是跳過最后一個字的最后一個字符。 這是我的代碼。 我添加了一些注釋以使其具有某種可讀性。 我知道這不是很棒的代碼,但我才剛剛開始編程。

int main(void) {
    char input[] = "If you are working on something that you really care about you dont have to be pushed The vision pulls you Steve Jobs";
    sort_alphabetically(input);
    printf("%s", input);
}

int sort_alphabetically(char tab[]) {
    int j = 0, k = 0, i = 0, g = 0, f = 0, l = 0;
    char tmp[1001];
    char tmp2[501][1001];

    while (tab[i] == ' ')  // skipping leading whitespaces
        i++;

    for (j = i; tab[j] != '\0'; j++) {
        if (tab[j] != ' ' && tab[j + 1] != '\0')
            k++;             // counting word length
        else if (tab[j] == ' ' || tab[j + 1] == '\0' || tab[j + 1] == '\0') {
            // copying word t0 2d array
            for (g = k; g > 0; g--) {
                tmp[l] = tab[j - g];
                l++;
            }
            tmp[l] = 0;
            strcpy(tmp2[f], tmp);  // copying
            f++;  //words ++ in  tmp2
            k = 0;  
            l = 0;  
            tmp[0] = 0;  
        }
    }
    tab[0] = 0;
    tmp[0] = 0;

    for (j = 0; j < f; j++) {    
       for (i = 0; i < f - 1; i++) {
           if (strcmp(tmp2[i], tmp2[i + 1]) > 0) {  //sorting words in alphabeticall order
               strcpy(tmp, tmp2[i]);   
               strcpy(tmp2[i], tmp2[i + 1]);   
               strcpy(tmp2[i + 1], tmp);
           }
       }
    }   

    for (i = 0; i < f; i++) {
        strcat(tab, tmp2[i]);    // copying to tab 
        strcat(tab, " ");   //adding spaces after each word
    }
    // removing whitespaces
    for (i = 0; tab[i] == ' ' || tab[i] == '\t'; i++);

    for (j = 0; tab[i]; i++) {
        tab[j++] = tab[i];
    }
    tab[j] = '\0';
}
;

運行此代碼后,它會在最后一個單詞 (Jobs) 中刪除s 如果有人能幫我做這道意大利面,我會很高興。

問題在於您如何處理空字節與空間。 在空格的情況下,當您復制字符串時,您實際上是空格上。 但是在空字節的情況下,您是空字節之前一個 這會導致一對一錯誤。 您需要修改代碼以避免對空格和空字節進行不同的處理:

for (j = i; tab[j] != '\0'; j++) {
    //In the space case, you are on the space, but in the \0 case
    //you were one before it.
    //Changed this if statement so that you always copy the string
    //when you're at the last character.
    if (tab[j + 1] == ' ' || tab[j + 1] == '\0') {

        //k is a length, but we're using it as an index
        //so we will need to adjust by one
        for (g = k; g > 0; g--) {
            tmp[l] = tab[j - g + 1];
            l++;
        }
    }
    else
    {
       k++;
    }
}

我通過放置打印語句來解決這個問題,這些語句顯示了每個周期的tab[j]的值和k的值。 使用打印語句或調試器觀察程序執行通常是診斷此類問題的最佳方法。

您遇到的問題是當您到達輸入( tab )字符串的末尾時將字符復制到tmp緩沖區; 也就是說,當tab[j + 1] == '\\0'為真時。 在這種情況下,您不會復制此for循環中的最后一個數據:

    for (g = k; g > 0; g--) {
        tmp[l] = tab[j - g];
        l++;
    }

要解決此問題,只需更改循環的“條件”以包含g為零時的內容,並在遇到空格字符時跳過此“迭代”:

    for (g = k; g >= 0; g--) { // Make sure to include any 'last' character
        if (tab[j - g] != ' ') { // ... but skip if this is a space
            tmp[l] = tab[j - g];
            l++;
        }
    }

另請注意,您在此行中有一個冗余測試:

    else if (tab[j] == ' ' || tab[j + 1] == '\0' || tab[j + 1] == '\0') {

沒有第三個測試(與第二個測試相同)也可以編寫,因此:

    else if (tab[j] == ' ' || tab[j + 1] == '\0') {

警告:大多數其他響應者都指出了您代碼中的主要錯誤,但這有一些較小的錯誤和一些簡化。

在執行strcat返回tab之前,我們應該執行tab[0] = 0以便初始strcat正常工作。

在復制單詞的那個之后執行strcat(tab," ")超出tab的末尾,因此是未定義的行為。 它還需要一個不必要的清理循環來刪除一開始不應該存在的額外空間。

最初的“拆分成單詞”循環可以[大大]簡化。

冒泡排序有一些標准的加速

我意識到您才剛剛開始 [有些學校實際上提倡ij等],但最好使用一些 [更多] 描述性名稱

無論如何,這是一個稍微重構的版本:

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

int opt_dbg;

#define dbg(_fmt...) \
    if (opt_dbg) \
        printf(_fmt)

void
sort_alphabetically(char tab[])
{
    char tmp[1001];
    char words[501][1001];
    char *src;
    char *dst;
    char *beg;
    int chr;
    int wordidx;
    int wordcnt;

    wordidx = 0;
    dst = words[wordidx];
    beg = dst;

    // split up string into individual words
    src = tab;
    for (chr = *src++;  chr != 0;  chr = *src++) {
        switch (chr) {
        case ' ':
        case '\t':
            // wait until we've seen a non-white char before we start a new
            // word
            if (dst <= beg)
                break;

            // finish prior word
            *dst = 0;

            // point to start of next word
            dst = words[++wordidx];
            beg = dst;
            break;

        default:
            *dst++ = chr;
            break;
        }
    }

    // finish last word
    *dst = 0;

    // get number of words
    wordcnt = wordidx + 1;

    if (opt_dbg) {
        for (wordidx = 0; wordidx < wordcnt; ++wordidx)
            dbg("SPLIT: '%s'\n",words[wordidx]);
    }

    // in bubble sort, after a given pass, the _last_ element is guaranteed to
    // be the largest, so we don't need to examine it again
    for (int passlim = wordcnt - 1;  passlim >= 1;  --passlim) {
        int swapflg = 0;

        // sorting words in alphabetical order
        for (wordidx = 0;  wordidx < passlim;  ++wordidx) {
            char *lhs = words[wordidx];
            char *rhs = words[wordidx + 1];

            if (strcmp(lhs,rhs) > 0) {
                dbg("SWAP/%d: '%s' '%s'\n",passlim,lhs,rhs);
                strcpy(tmp,lhs);
                strcpy(lhs,rhs);
                strcpy(rhs,tmp);
                swapflg = 1;
            }
        }

        // if nothing got swapped, we can stop early (i.e. everything is in
        // sort)
        if (! swapflg)
            break;
    }

    // clear out destination so [first] strcat will work
    tab[0] = 0;

    // copy back words into original string
    // adding the space as a _prefix_ before a word eliminates the need for a
    // cleanup to remove the last space
    for (wordidx = 0;  wordidx < wordcnt;  ++wordidx) {
        dbg("SORTED: '%s'\n",words[wordidx]);

        // adding spaces before each word
        if (wordidx > 0)
            strcat(tab, " ");

        // copying to tab
        strcat(tab,words[wordidx]);
    }
}

int
main(int argc,char **argv)
{
    char input[] = "If you  are  working on something that you really care"
        " about you dont have to be  pushed The vision pulls you Steve Jobs";

    --argc;
    ++argv;

    for (;  argc > 0;  --argc, ++argv) {
        char *cp = *argv;
        if (*cp != '-')
            break;

        switch (cp[1]) {
        case 'd':
            opt_dbg = ! opt_dbg;
            break;
        }
    }

    sort_alphabetically(input);
    printf("%s\n", input);

    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM