Wskaźniki i tablica dwuwymiarowa, błąd testu maszynowego

0

Cześć!
Zadanie polega na wprowadzeniu 25 wartości to tablicy dwuwymiarowej 5x5, a następnie program oblicza i wyświetla min. max. oraz średnią dla każdego wiersza i kolumny. Program działa, wszystko liczy poprawnie, ale test maszynowy wyrzuca błąd i nie wiem jak go poprawić:

main.c:30:22: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
     int const *ptr = ptrA;

Poniżej kompletny kod programu:

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

int row_statistics(const int *ptr, int width, int height, int row_id, int* max, int* min, float *avg);
int column_statistics(const int *ptr, int width, int height, int column_id, int* max, int* min, float *avg);

int main()
{
    int i,j;
    int times=25;
    int max;
    int *p_max = &max;
    int min;
    int *p_min = &min;
    float avg;
    float *p_avg = &avg;
    int column_id, row_id;
    int tab[5][5];
    /*int tab[5][5] = {
    {55, 73, 30, 82, 15},
    {91, 90, 92, 11, 31},
    {63, 56, 45, 97, 25},
    {6 , 55, 50, 22, 99},
    {28, 39, 60,  2, 58}
  };*/

    int (*ptrA)[5];
    ptrA = tab;
    int const *ptr = ptrA;

    printf("Podaj liczby:\n");
     for (i=0;i<5;i++)
        for(j=0;j<5;j++)
    {
        scanf("%d", *(ptrA+i)+j);
    }

 /*for(i=0;i<5;i++)
    {
        for(j=0;j<5;j++)
        {
            printf("%d ", *(*(ptr+i)+j));
        }
        printf("\n");
    }*/

   for(column_id=0;column_id<5;column_id++)
    {
        column_statistics(ptr, 5, 5, column_id, p_max, p_min, p_avg);
        printf("%d %d %.2f", min, max, avg);
        printf("\n");

    }
    for(row_id=0; row_id<times; row_id=row_id+5)
    {
        row_statistics(ptr, 5, 5, row_id, p_max, p_min, p_avg);
        printf("%d %d %.2f", min, max, avg);
        printf("\n");

    }
  return 0;
}


int row_statistics(const int *ptr, int width, int height, int row_id, int* max, int* min, float *avg)
{
    if (ptr != NULL || max != NULL || min!= NULL || avg!=NULL)
    {
        int i=0;
        height = height+0;

        *(min) = *(ptr+row_id);
        *(max)= *(ptr+row_id);

        int suma = *(ptr+row_id);
        for(i=1; i<width; i++)
        {
             if (*(min)> *(ptr+row_id+i))
            {
                *(min)= *(ptr+row_id+i);
            }

            if(*(max) < *(ptr+row_id+i))
            {
                *(max)=*(ptr+row_id+i);
            }
            suma = suma + *(ptr+row_id+i);
        }
        *(avg) = ((float) suma) / 5.0;
        return 1;

    }
    else
    {
        return 0;
    }

}

int column_statistics(const int *ptr, int width, int height, int column_id, int* max, int* min, float *avg)
{
    if (ptr != NULL || max != NULL || min!= NULL || avg!=NULL)
    {
        int i=0;
        width = width + 0;

        *(min) = *(ptr+column_id);
        *(max)= *(ptr+column_id);

        int suma = *(ptr+column_id);
        for(i=5;i<(height*5); i=i+5)
        {
             if (*(min)> *(ptr+column_id+i))
            {
                *(min)= *(ptr+column_id+i);
            }

            if(*(max) < *(ptr+column_id+i))
            {
                *(max)= *(ptr+column_id+i);
            }
            suma = suma + *(ptr+column_id+i);
        }
        *(avg)= ((float) suma) / 5.0;
        return 1;
    }
    else
    {
        return 0;
    }
}

3

Wskaźnik na tablicę i wskaźnik na element to różne rzeczy, więc system typów nie pozwala na ich wzajemne przypisywanie. Ciężko mi określić co chciałeś osiągnąć we wskazanej linii.

1

Pewnie miało być tak:

int const *ptr = *ptrA;

ale zgadzam się też nie mam pojęcia co to ma robić i nie zamierzam wnikać.

FYI z tego co mi wiadomo C ma taką dziwną funkcjonalność, która nie działa w C++ (do zweryfikowania):

int row_statistics(const int ptr[][width], int width, int height, int row_id, int* max, int* min, float *avg)
// wymiar tablicy zależny od wartości argumentu funkcji
{
    ...

Swoją drogą nie musiałbyś tak kombinować, jak byś nie miał liczby magicznej 5, ale zdefiniował stałą.

1

Używanie wskaźników zamiast [] masz jakoś wymuszone? Bo to zwyczajne zaciemnianie kodu.

0

@kq
Potrzebowałem dodatkowego wskaźnika, aby jeden z testów maszynowych został zaakceptowany (pewnie chodzi o jakąś samą dodatkową inicjalizację).
@MarekR22
Dzięki za wskazówkę, po tym int const *ptr = *ptrA; test maszynowy przechodzi, ale innego testu mi teraz nie przechodzi, a dokładniej dla mniejszej tablicy np. 3x3 wyrzuca błędne wyniki tj. moje funkcje nie są uniwersalne.
@tajny_agent
Tak, w zadaniu nie mogę korzystać z nawiasów kwadratowych []. Bez wskaźników ten program jest bardzo prosty i chyba chodziło właśnie o jego utrudnienie.

Dziękuje Wam bardzo za wskazówki. Obecnie nadal siedzę nad tym programem, bo została mi do poprawienia już jego logika. Jak coś będę pisał. ;)

1
BogatyPejs napisał(a):

Tak, w zadaniu nie mogę korzystać z nawiasów kwadratowych []. Bez wskaźników ten program jest bardzo prosty i chyba chodziło właśnie o jego utrudnienie.

To takie tworzenie sztucznych problemów, których nigdy nie będziesz musiał w przyszłości rozwiązywać ;)

A swoją drogą do obliczania statystyk wystarczy Ci jedna funkcja. Jeśli dodatkowo upakowałbyś statystyki do struktury to mogłaby wyglądać mniej więcej tak:

void CalculateStats( const int** data, Stats* stats, int index, int column_mode )
{
  if ( data && stats && ( index >= 0 && index < TABLE_DIMENSION ) ) {
    int* pval = NULL;
    int sum = 0;
    if ( column_mode ) { pval = data + index; }
    else { pval = data + ( index * TAB_DIMENSION ); }
    stats->min = stats->max = *pval;
    for ( int i = 0; i < TAB_DIMENSION; ++i ) {
      pval = ( column_mode ? data + i * TAB_DIMENSION + index ) : data + index * TAB_DIMENSION + i;
      if ( *pval > stats->max ) { stats->max = *pval; }
      if ( *pval < stats->min ) { stats->min = *pval; }
      sum += *pval;
    }
    stats->average = sum / TAB_DIMENSION;
  }
}
0

@kq
@MarekR22
@tajny_agent
Hejka! Udało mi się skończyć program. Otóż okazało się, że należało również poprawić moje funkcje, kiedy dla funkcji wchodzić będą argumenty dla tablicy, która nie była kwadratowa... Dziwne. Jaki jest sens zabezpieczania programu w wewnątrz samej funkcji, jeżeli użytkownika ogranicza mój main(), gdzie nie dość, że pobieram od użytkownika określoną przeze mnie ilość wartości do tablicy, to jeszcze sam określam jej wymiar. W każdym razie, jak jesteście ciekawi rozwiązania, to znajduje się ono poniżej (PS przechodzi pozytywnie wszystkie testy, lekko ponad 100 różnych):

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

int row_statistics(const int *ptr, int width, int height, int row_id, int* max, int* min, float *avg);
int column_statistics(const int *ptr, int width, int height, int column_id, int* max, int* min, float *avg);

int main()
{
    int i,j;
    int max;
    int *p_max = &max;
    int min;
    int *p_min = &min;
    float avg;
    float *p_avg = &avg;
    int tab[5][5];
    /*int tab[5][5] = {
    {55, 73, 30, 82, 15},
    {91, 90, 92, 11, 31},
    {63, 56, 45, 97, 25},
    {6 , 55, 50, 22, 99},
    {28, 39, 60,  2, 58}
  };*/

    int (*ptrA)[5];
    ptrA = tab;
    int const *ptr = *ptrA;

    printf("Podaj liczby:\n");
     for (i=0;i<5;i++)
        for(j=0;j<5;j++)
    {
        scanf("%d", *(ptrA+i)+j);
    }

 /*for(i=0;i<5;i++)
    {
        for(j=0;j<5;j++)
        {
           printf("%2d ", *(*(ptrA+i)+j));
        }
        printf("\n");
    }*/
     //printf("\n");

        column_statistics(ptr, 5, 5, 0, p_max, p_min, p_avg);
        column_statistics(ptr, 5, 5, 1, p_max, p_min, p_avg);
        column_statistics(ptr, 5, 5, 2, p_max, p_min, p_avg);
        column_statistics(ptr, 5, 5, 3, p_max, p_min, p_avg);
        column_statistics(ptr, 5, 5, 4, p_max, p_min, p_avg);

        row_statistics(ptr, 5, 5, 0, p_max, p_min, p_avg);
        row_statistics(ptr, 5, 5, 1, p_max, p_min, p_avg);
        row_statistics(ptr, 5, 5, 2, p_max, p_min, p_avg);
        row_statistics(ptr, 5, 5, 3, p_max, p_min, p_avg);
        row_statistics(ptr, 5, 5, 4, p_max, p_min, p_avg);

    return 0;
}


int row_statistics(const int *ptr, int width, int height, int row_id, int* max, int* min, float *avg)
{
    if (ptr == NULL || max == NULL || min == NULL || avg == NULL || row_id >= height || row_id<0 || width<0)
    {
        return 0;
    }

    else
    {
        int i=0;
        int stop;
        stop = width;
        row_id = row_id*width;

        *(min) = *(ptr+row_id);
        *(max)= *(ptr+row_id);

        int suma = *(ptr+row_id);
        for(i=1; i<width; i++)
        {
             if (*(min)> *(ptr+row_id+i))
            {
                *(min)= *(ptr+row_id+i);
            }

            if(*(max) < *(ptr+row_id+i))
            {
                *(max)=*(ptr+row_id+i);
            }
            suma = suma + *(ptr+row_id+i);

        }
        *(avg) = ((float) suma) / stop;
        printf("%d %d %.2f", *min, *max, *avg);
        printf("\n");
        return 1;
    }

}

int column_statistics(const int *ptr, int width, int height, int column_id, int* max, int* min, float *avg)
{
    if (ptr == NULL || max == NULL || min == NULL || avg == NULL || column_id >= width || column_id<0 || height<0)
    {
        return 0;
    }

    else
    {
        int i=0;
        int stop;
        stop = height;
        int skok = width;

        *(min) = *(ptr+column_id);
        *(max)= *(ptr+column_id);

        int suma = *(ptr+column_id);
        for(i=skok;i<(height*skok); i=i+skok)
        //for(i=1; i<height; i++)
        {
             if (*(min)> *(ptr+column_id+i))
            {
                *(min)= *(ptr+column_id+i);
            }

            if(*(max) < *(ptr+column_id+i))
            {
                *(max)= *(ptr+column_id+i);
            }
            suma = suma + *(ptr+column_id+i);
        }
        *(avg)= ((float) suma) / stop;
        printf("%d %d %.2f", *min, *max, *avg);
        printf("\n");
        return 1;
    }
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1