массив баллов - PullRequest
       1

массив баллов

1 голос
/ 29 января 2020

Учитывая массив оценок, где 60 является самым высоким, а 36 - проходным. Функция вернет массив всех проходных баллов

#include <stdio.h>
#include <stdlib.h>

int* passingScores (int scores[], int size);

int main () {
    int B[] = {55, 35, 60, 25, 10, 43}; //expect display 55,60,43
    int size = 6;
    int* C;
    int i;

    C = passingScores(B, size);

    for (i=0; i<size; i++) {
        printf ("%d\n", C[i]); 
    }

    return 0;
}

код функции:

int* passingScores (int scores[], int size) {
    int i;
    int passingScore = 36;
    int* pass;

    pass = (int*)malloc(sizeof(int)*size);
    if (pass != NULL) {
        for (i=0; i<size; i++) {
            if (scores[i] > passingScore){
                pass[i] = scores[i];
            }   
        }   
    }
return pass;
}

элементами в массиве main являются:

55 , 35, 60, 25, 10, 43

результат после вызова функции будет:

55, 0, 60, 0, 0, 43

но я хотел получить такой результат, как:

55, 60, 43

просьба помочь :) спасибо!

Ответы [ 3 ]

1 голос
/ 29 января 2020

Для стартеров в соответствии со стандартом C функция main без параметров должна быть объявлена ​​как

int main( void )

Вы не должны использовать магические числа c, как в этом объявлении

int size = 6;

Размер исходного массива можно рассчитать.

Функция passingScores не меняет исходный массив. Поэтому его первый параметр должен быть объявлен с квалификатором const, как

const int scores[]

. Пользователь функции должен знать, сколько элементов прошло тест. Поэтому лучше, когда функция возвращает число пройденных оценок и принимает указатель на потенциально выделенный массив от пользователя по ссылке.

Вместо маги c число 36, объявленных в функции

int passingScore = 36;

лучше передать такое число в качестве аргумента функции. В этом случае функция будет более гибкой.

Вы выделяете избыточную память в функции. Сначала вы должны посчитать количество пройденных баллов. Исходный массив баллов может быть очень большим, но его элементов, прошедших тестирование, может быть очень мало.

А для массива, на который указывает указатель pass, необходимо использовать отдельный индекс для последовательного хранения выбранных значений.

И не забудьте освободить выделенную память.

Вот демонстрационная программа, которая показывает, как эта функция может быть реализована.

#include <stdio.h>
#include <stdlib.h>

size_t passingScores( const int scores[], size_t size, int passingScore, int **passed );

int main( void ) 
{
    int scores[] = { 55, 35, 60, 25, 10, 43 };
    const size_t SIZE = sizeof( scores ) / sizeof( *scores );
    int passingScore = 36;

    int *passed_scores = NULL;

    size_t n = passingScores( scores, SIZE, passingScore, &passed_scores );

    for ( size_t i = 0; i < n; i++ ) 
    {
        printf( "%d ", passed_scores[i] ); 
    }
    putchar( '\n' );

    free( passed_scores );

    return 0;
}

size_t passingScores( const int scores[], size_t size, int passingScore, int **passed )
{
    size_t n = 0;

    for ( size_t i = 0; i < size; i++ )
    {
        n += passingScore < scores[i];
    }

    if ( n != 0 )
    {
        *passed = malloc( n * sizeof( int ) );  

        if ( *passed != NULL )
        {
            for ( size_t i = 0, j = 0; i < size; i++ )
            {
                if ( passingScore < scores[i] ) ( *passed )[j++] = scores[i];
            }
        }
    }       

    return n;
}   

Вывод программы:

55 60 43
0 голосов
/ 29 января 2020

Проблемы заключаются в следующем утверждении:

 pass[i] = scores[i];

Вы не хотите копировать партитуру в элемент с таким же индексом; Вы хотите скопировать его в первый «свободный» слот. Вам нужно будет отслеживать, как используются элементы pass.


Есть еще одна проблема: вы выводите size чисел, даже если количество проходных баллов меньше.

В этом случае вместо того, чтобы сообщать вызывающему объекту количество элементов в возвращаемом массиве, мы могли бы просто поместить 0 в конце, чтобы указать конец. Но мы должны быть внимательны к случаю, когда все оценки проходят оценки!


Незначительная третья проблема: вы считаете, что оценка 36 является ошибочной! Пусть это будет уроком тестирования: всякий раз, когда вы проводите тестирование, всегда проводите тестирование в пределах и за пределами (в этом случае вы будете тестировать с оценками 35, 36 и 37).


Наконец, Вы динамически выделяете массив, но никогда не освобождаете его. Это не критично, что вы освобождаете его, потому что вы делаете это непосредственно перед выходом из программы, но это плохая привычка. (Одним из возможных последствий является то, что выход таких инструментов, как valgrind, станет очень шумным, если вы решите использовать его для решения проблемы sh.)


#include <stdio.h>
#include <stdlib.h>

int* getPassingScores(const int* scores, int num_scores) {
    const int passingScore = 36;

    // calloc is like malloc, but the memory will
    // be efficiently initialized to 0. This means
    // we don't need to do  pass[j] = -1; later.

    // Need to make sure we have enough space
    // when all the grades are passing grades!
    int* pass = calloc(num_scores, sizeof(int));
    if (!pass)
        return NULL;

    for (int i=0, j=0; i<num_scores; ++i) {
        if (scores[i] >= passingScore) {
           pass[j++] = scores[i];
        }   
    }

    return pass;
}

int main(void) {
    int scores[] = {55, 35, 60, 25, 10, 43};
    int num_scores = sizeof(scores)/sizeof(*scores);

    int* passingScores = getPassingScores(scores, num_scores);

    for (int i=0; passingScores[i]>0; ++i) {
        printf("%d\n", passingScores[i]); 
    }

    free(passingScores);    
    return 0;
}

Конечно, будет достаточно:

#include <stdio.h>

int main(void) {
    int scores[] = {55, 35, 60, 25, 10, 43};
    int num_scores = sizeof(scores)/sizeof(*scores);
    const int passingScore = 36;

    for (int i=0; i<num_scores; ++i)
        if (scores[i] >= passingScore)
            printf("%d\n", scores[i]);
}
0 голосов
/ 29 января 2020

Следующий код включает несколько предложений, в том числе добавление дополнительного индекса для отслеживания только проходных баллов и использование calloc вместо malloc для инициализации массива. (см. другие комментарии и предлагаемые изменения ниже.)

  int* passingScores (int scores[], int size);

int main (void)  //   Or use: int main(int argc, char *argv[]){...}
{                //But never: int main(){...}  
    int B[] = {55, 35, 60, 25, 10, 43}; //expect display 55,60,43
    //int size = 6;//do not use magic numbers
    int size = sizeof(B)/sizeof(B[0]);//yields number of elements in array B
    int* C;
    int i;

    C = passingScores(B, size);
    if(C)//test before using
    { 
        for (i=0; i<size; i++) {
            if(C[i] != 0) printf ("%d\n", C[i]); //include only passing scores
                                                 //(excluding zeros)
        }
        free(C);//free memory when done.
    }


    return 0;
}

int* passingScores (int scores[], int size) {
    int i, j = 0;//additional index j to track passing scores.
    int passingScore = 36;
    int* pass;

    //pass = (int*)malloc(sizeof(int)*size);//allocates un-initialized memory
    pass = calloc(size, sizeof(int));//calloc initializes memory to zero
    if (pass != NULL) {
        for (i=0; i<size; i++) {
            if (scores[i] > passingScore){
                pass[j] = scores[i];
                j++;//indexed only when passing score
            }   
        }   
    }
    return pass;
} 

Некоторые примечания по использованию calloc / malloc ... Для ваших целей предоставляется содержимое памяти, выделенное с помощью malloc как есть , включая любое содержимое, которое занимало это пространство до того, как вашему процессу было предоставлено право собственности. На моей машине с использованием malloc пространство занято:

pass[0] == 0xBAADFOOD (-1163005939)
pass[1] == 0xBAADFOOD
pass[2] == 0xBAADFOOD
pass[3] == 0xBAADFOOD
pass[4] == 0xBAADFOOD
pass[5] == 0xBAADFOOD

Таким образом, способ, которым вы выборочно записываете некоторые элементы этой памяти, оставил бы этот оригинальный контент в некоторых других области этого блока памяти, вызывающие проблемы при выводе результатов.
При использовании malloc таким образом рекомендуется инициализировать память перед использованием:

pass = malloc(size * sizeof(int));
if(pass)
{
    memset(pass, 0, size*sizeof(int));
    ...

В результате:

pass[0] == 0x00000000
pass[1] == 0x00000000
pass[2] == 0x00000000
pass[3] == 0x00000000
pass[4] == 0x00000000
pass[5] == 0x00000000  

Использование calloc выделяет память так же, как malloc, но затем очищает ее перед возвратом, сохраняя необходимость очищать ее с помощью memset .

Примечание. также нет необходимости или не рекомендуется приводить возврат [m] [c] allo c.

...