1

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]);
            }   
        }
}
4

3 に答える 3

3

警告をオンにします。char s[50][50]に変換できませんchar*

これを試して:

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

これは、50 文字の少なくとも 1 つのバッファーへのポインターを渡すことをコンパイラーに通知します。これは、多次元配列が関数に渡されたときに崩壊するものです。

char[]そして、" は "と同じであるというばかげた考えをさらになくすchar*ために、何らかの理由でまだどこでも教えられている、これを読んでください: http://c-faq.com/aryptr/aryptr2.html

于 2013-05-19T16:34:28.477 に答える
1

あなたは近くにいます。これがあなたのコードの作業バージョンです。scanf()は ... の番号から改行を残すことに注意してください。二度とfgets()使用しないからですgets()よね?...そのため、.の後の改行まで読む必要がありますscanf()。もちろん、「コンピューターに数えさせるよりも、人間が数えた方が良いと人々が考えるのはなぜですか?」という興味深い質問があります。カウントを気にしない方が賢明でしょう。改訂されたコードnは、50 を超えないことを確認するために検証されることに注意してください。

長さ 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] = '\0';
        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);
            }
        }
    }
}

このコードは、最大 9 個のデータ文字、改行、および終端の null を受け入れるのに十分な長さの文字列に行を読み取ります。改行を削除し、最大 9 つのデータ文字と終端の null を残します。

サンプルラン:

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

長さ 8 以下の行で動作するオリジナル コード

#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] = '\0';
    }
    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);
            }
        }
    }
}

「大きな」変更点は、関数配列パラメーターが宣言および定義される方法です。1 行あたり 10 文字の 50 行の配列を渡すので、関数でそれを指定するだけです。プログラムの動作を変更せずに、関数パラメーターの次元から 50 を削除できます。

サンプル入力:

8
fed
abc
cba
def
hij
cba
xyz
aaa

実行例:

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

これを修正する必要があったという事実は、制限をテストすること (および制限を慎重に定義すること) の重要性を示しています。

改訂されたコードはまだ汎用コードではありません。入力の最大 50 行の固定制限、入力の一部として必要な行数のカウント、および行あたり最大 10 文字の固定行長はすべて、おもちゃのコードになります。そのため、GIGO(ガベージ イン、ガベージ アウト)は理不尽な反応ではありません。データ ファイルに長すぎる行が含まれている場合は、得られるものを取得します。コードがクラッシュすることはありませんが、出力が意味をなさない場合があります。

于 2013-05-19T21:46:09.217 に答える
0

変化する

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

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

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

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

だから変わる

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

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

また

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
于 2013-05-19T21:50:08.490 に答える