C语言 使用冒泡排序算法对字符串进行排序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16636890/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 06:23:28  来源:igfitidea点击:

sorting strings with bubble sort algorithm

c

提问by Johnny Cash

This code stores the number of words in an integer variable and the words in a multidimensionnel string then sorts the words alphabetically using a function. The problem I have is in the function call.

此代码将单词数存储在整数变量中,并将单词存储在多维字符串中,然后使用函数按字母顺序对单词进行排序。我的问题是在函数调用中。

#include<stdio.h>
#include<string.h>
void sort(char*[50],int);
int main ()
{
    int i,n=0;
    char s[50][10];

    scanf("%d",&n);//scaning the number of words

    for(i=0;i<=n;i++)//scaning the words
    gets(s[i]);

    sort(s,n);

    for(i=0;i<=n;i++)//printing the words sorted
    printf("%s\n",s[i]);
}
void sort(char*s[50],int n)
{
    int i,j,cmp;
    char tmp[1][10];

    //bubble sorting of words
    for(i=0; i<n; i++)
        for(j=0; j<n-1; j++)
        {
            cmp=strcmp(s[j],s[j+1]);

            if(cmp>0)
            {
                strcpy(tmp[0],s[j+1]);
                strcpy(s[j+1],s[j]);
                strcpy(s[j],tmp[0]);
            }   
        }
}

回答by StoryTeller - Unslander Monica

Turn on your warnings. char s[50][50]is not convertible to char*.

打开你的警告。char s[50][50]不能转换为char*.

Try this:

尝试这个:

void sort(char(*)[50],int);

This tells the compiler you pass in a pointer to at least one buffer of 50 characters. This is what multidimensional arrays decay to when passed into functions.

这告诉编译器您传递一个指向至少一个 50 个字符的缓冲区的指针。这就是多维数组在传递到函数时衰减的结果。

And to further rid you of the silly notion that "char[]is the same as char*", which for some reason is still taught everywhere, read this: http://c-faq.com/aryptr/aryptr2.html

为了进一步摆脱“char[]char*”相同的愚蠢观念,出于某种原因,这种观念仍然无处不在,请阅读:http: //c-faq.com/aryptr/aryptr2.html

回答by Jonathan Leffler

You're close. Here's a working version of your code. Note that the scanf()leaves the newline from the number for the ... fgets(), because you won't ever use gets()again, will you? ... so you need to read up to and including the newline after the scanf(). Of course, there's the interesting question of 'why do people think it is better for humans to count than to make computers count instead?' It would be more sensible not to bother with the count. Note that the revised code validates nto ensure it is not larger than 50.

你很接近。这是您的代码的工作版本。请注意,scanf()从 ... 的数字中留下换行符fgets(),因为您再也不会使用gets()了,是吗?...所以你需要阅读并包括scanf().之后的换行符。当然,还有一个有趣的问题是“为什么人们认为让计算机计数比让人类计数更好?” 不理会计数会更明智。请注意,修改后的代码会进行验证n以确保它不大于 50。

Revised code that works on lines of length 9 or shorter

适用于长度为 9 或更短的行的修订代码

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

void sort(char s[50][10], int);

int main(void)
{
    int i;
    int n = 0;
    char s[50][10];
    char line[11];

    if (scanf("%d", &n) != 1)
    {
        fprintf(stderr, "Failed to read a number\n");
        return 1;
    }
    if (n <= 0 || n > 50)
    {
        fprintf(stderr, "%d is out of the range 1..50\n", n);
        return 1;
    }
    // Gobble rest of first line
    while ((i = getchar()) != EOF && i != '\n')
        ;

    for (i = 0; i < n; i++)
    {
        if (fgets(line, sizeof(line), stdin) == 0)
            break;
        // Remove newline from input
        size_t len = strlen(line);
        assert(len > 0 && len <= sizeof(s[i]));
        line[len-1] = '
Before:
Number 34
Number 39
Number 32
Number 30
Number 22
Number 34
Number 57
Number 28
Number 30
Number 47
Number 43
Number 23
Number 22
After:
Number 22
Number 22
Number 23
Number 28
Number 30
Number 30
Number 32
Number 34
Number 34
Number 39
Number 43
Number 47
Number 57
'; strcpy(s[i], line); } n = i; // In case the file was shorter than stated! printf("Before:\n"); for (i = 0; i < n; i++) printf("%s\n", s[i]); sort(s, n); printf("After:\n"); for (i = 0; i < n; i++) printf("%s\n", s[i]); return 0; } void sort(char s[50][10], int n) { int i, j, cmp; char tmp[10]; if (n <= 1) return; // Already sorted for (i = 0; i < n; i++) { for (j = 0; j < n-1; j++) { cmp = strcmp(s[j], s[j+1]); if (cmp > 0) { strcpy(tmp, s[j+1]); strcpy(s[j+1], s[j]); strcpy(s[j], tmp); } } } }

This code reads lines into a string long enough to take up to 9 data characters, a newline, and the terminal null. It removes the newline, leaving up to 9 data characters and a terminal null.

此代码将行读入一个足够长的字符串中,最多可包含 9 个数据字符、一个换行符和终端 null。它删除换行符,留下最多 9 个数据字符和一个终端空值。

Sample run:

示例运行:

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

void sort(char s[50][10], int);

int main(void)
{
    int i;
    int n = 0;
    char s[50][10];

    if (scanf("%d", &n) != 1)
    {
        fprintf(stderr, "Failed to read a number\n");
        return 1;
    }
    if (n <= 0 || n > 50)
    {
        fprintf(stderr, "%d is out of the range 1..50\n", n);
        return 1;
    }
    // Gobble rest of first line
    while ((i = getchar()) != EOF && i != '\n')
        ;

    for (i = 0; i < n; i++)
    {
        if (fgets(s[i], sizeof(s[i]), stdin) == 0)
            break;
        // Remove newline from input
        size_t len = strlen(s[i]);
        assert(len > 0);
        s[i][len-1] = '
8
fed
abc
cba
def
hij
cba
xyz
aaa
'; } n = i; // In case the file was shorter than stated! printf("Before:\n"); for (i = 0; i < n; i++) printf("%s\n", s[i]); sort(s, n); printf("After:\n"); for (i = 0; i < n; i++) printf("%s\n", s[i]); return 0; } void sort(char s[50][10], int n) { int i, j, cmp; char tmp[10]; if (n <= 1) return; // Already sorted for (i = 0; i < n; i++) { for (j = 0; j < n-1; j++) { cmp = strcmp(s[j], s[j+1]); if (cmp > 0) { strcpy(tmp, s[j+1]); strcpy(s[j+1], s[j]); strcpy(s[j], tmp); } } } }

Original code that works on lines of length 8 or shorter

适用于长度为 8 或更短的行的原始代码

$ ./srt < data
Before:
fed
abc
cba
def
hij
cba
xyz
aaa
After:
aaa
abc
cba
cba
def
fed
hij
xyz
$

The 'big' change is the way the function array parameter is declared and defined. You're passing an array of 50 rows with 10 characters per row, so simply specify that in the function. You could drop the 50 from the dimensions of the function parameter with no change to the program's behaviour.

“大”变化是函数数组参数的声明和定义方式。您要传递 50 行的数组,每行 10 个字符,因此只需在函数中指定即可。您可以从函数参数的维度中删除 50,而不会改变程序的行为。

Sample input:

样本输入:

void sort(char*[50],int);
...
void sort(char*s[50],int n)

Example run:

示例运行:

void sort(char(*)[10],int);//not char(*)[50]
...
void sort(char(*s)[10],int n)

The fact that this needed revising shows the importance of testing the limits (and carefully defining the limits).

这需要修改的事实表明测试限制(并仔细定义限制)的重要性。

The code as revised is still not general purpose code. The fixed limit of at most 50 lines of input, the count of the number of lines required as part of the input, and the fixed line length of at most 10 characters per line all make it toy code. As such, GIGO (garbage in, garbage out) is not an unreasonable reaction. If the data file contains overlong lines, you get what you get. The code won't crash, but the output may not make much sense.

修订后的代码仍然不是通用代码。最多 50 行输入的固定限制,作为输入的一部分所需的行数的计数,以及每行最多 10 个字符的固定行长都使其成为玩具代码。因此,GIGO(垃圾进,垃圾出)并不是一种不合理的反应。如果数据文件包含过长的行,你会得到你所得到的。代码不会崩溃,但输出可能没有多大意义。

回答by BLUEPIXY

change

改变

//remain newline
scanf("%d",&n);

to

scanf("%d%*c",&n);//read and drop newline

and

for(i=0;i<=n;i++)

to

for(i=0;i<n;i++)

so change

所以改变

char *p[50];
for(i=0;i<n;++i)
    p[i]=&s[i][0];
sort(p,n);//OK only exchange of pointer in this case

to

##代码##

or

或者

##代码##