【问题标题】:Sorting words in alphabetically order C按字母顺序对单词进行排序 C
【发布时间】:2020-02-09 17:13:35
【问题描述】:

所以我的练习是在一维字符数组中对单词进行排序。我的代码几乎可以工作,但它总是跳过最后一个单词的最后一个字符。这是我的代码。我添加了一些 cmets 以使其具有某种可读性。我知道这不是出色的代码,但我才刚刚开始编程。

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。如果有人能帮我做这个意大利面,我会很高兴的。

【问题讨论】:

  • 您的排序函数说它将返回一个 int。它没有。
  • “但我才刚开始编程。”、“如果有人可以帮助我”和@Retired Ninja 暗示你犯了一个常见的学习错误:不是首先使用自动化作为编译器并出现警告也没有完全启用。节省时间,大量时间,并完全启用编译器警告。在这里更快地反馈帖子。

标签: c arrays sorting char


【解决方案1】:

问题在于您如何处理空字节与空间。在空格的情况下,当您复制字符串时,您实际上是 on 空格的。但是在空字节的情况下,您是 在空字节之前的一个。这会导致一个错误。您需要修改代码以避免对空格和空字节进行不同的处理:

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 在每个循环中的值。使用打印语句或调试器观察程序执行通常是诊断此类问题的最佳方法。

【讨论】:

    【解决方案2】:

    您遇到的问题是当您到达输入 (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') {
    

    【讨论】:

    • 现在它是最后一个字符,但它打印JobsSteve而不是Jobs Steve
    • 也许尝试最新的编辑。不过科罗西亚给出的答案其实更好!
    【解决方案3】:

    警告:大多数其他响应者都指出了您代码中的主要错误,但这里有一些较小的错误和一些简化。

    在执行strcat 回到tab 之前,我们应该执行tab[0] = 0 以便initial 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;
    }
    

    【讨论】:

      猜你喜欢
      • 2016-02-08
      • 1970-01-01
      • 1970-01-01
      • 2013-05-02
      • 2014-02-08
      • 2011-08-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多