продолжает говорить ошибка сегментации - PullRequest
1 голос
/ 26 марта 2020

В этом коде постоянно повторяется ошибка сегментации.

for(i=0; i<(numTopps-1); i++)
    {
            if(kcalTopp[i]<kcalTopp[i+1])
            {
                temp=*kcalTopp[i];
                *kcalTopp[i]=*kcalTopp[i+1];
                *kcalTopp[i+1]=temp;
            }
    }

Я думаю, что вышеприведенная часть является проблемой. но я не могу понять, в чем проблема

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

void sort(int *kcalTopp[], int numTopps);

int main(void)
{  
int numTopps, doughPrice, eachToppPrice, kcalDough, i, j, totalKcal, highest, kcalperDol;
scanf("%d %d %d %d", &numTopps, &doughPrice, &eachToppPrice, &kcalDough);

int *kcalTopp;
kcalTopp=(int*)malloc(sizeof(int)*numTopps);

    for(i=0; i<numTopps; i++)
    {
        scanf("%d", &kcalTopp[i]);
    }

    totalKcal=kcalDough;
    highest=totalKcal/doughPrice;

    sort(&kcalTopp, numTopps);

    for(i=0; i<numTopps; i++)
    {
        for(j=0; j<=i; j++)
        {
            totalKcal=totalKcal+kcalTopp[j];
            kcalperDol=totalKcal/(doughPrice+i*eachToppPrice);
            if(kcalperDol>highest)
            {
                highest=kcalperDol;
            }
        }
    }

    printf("%d", highest);

    return 0;
}

void sort(int *kcalTopp[], int numTopps)
{

int temp, i;

    for(i=0; i<(numTopps-1); i++)
    {
            if(kcalTopp[i]<kcalTopp[i+1])
            {
                temp=*kcalTopp[i];
                *kcalTopp[i]=*kcalTopp[i+1];
                *kcalTopp[i+1]=temp;
            }
    }
}

Ответы [ 2 ]

1 голос
/ 26 марта 2020

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

Следующее содержит изменения в вашем исходном коде с целью иллюстрации некоторых предложений в комментарии . (не исправлять каждую ошибку logi c.) Редактирование включает обработку kcalTopp в качестве указателя на int память, а не на массив int *. Смотрите пояснения в комментариях:

//void sort(int *kcalTopp[], int numTopps);//*kcalTopp[] is an array of pointers 
void sort(int *kcalTopp, int numTopps);//*kcalTopp is a pointer to 'int' memory

int main(int argc, char *argv[])
{  
    int numTopps, doughPrice, eachToppPrice, kcalDough, i, j, totalKcal, highest, kcalperDol;
    //scanf("%d %d %d %d", &numTopps, &doughPrice, &eachToppPrice, &kcalDough);

    if(argv != 5) //simple reading in of command line args
    {
        printf("4 input values required.  Exiting");
        return 0;
    }

    //note, each of these calls includes simple for test for success before going on 
    numTopps = strtol(argv[1], (char **) NULL, 10);
    if(errno == ERANGE) {printf("argv[1] Bad input, exiting"); return 0;}
    doughPrice = strtol(argv[2], (char **) NULL, 10);
    if(errno == ERANGE) {printf("argv[2] Bad input, exiting"); return 0;}
    eachToppPrice = strtol(argv[3], (char **) NULL, 10);
    if(errno == ERANGE) {printf("argv[3] Bad input, exiting"); return 0;}
    kcalDough = strtol(argv[4], (char **) NULL, 10);
    if(errno == ERANGE) {printf("argv[4] Bad input, exiting"); return 0;}

    int *kcalTopp;
    //This statement (without cast) is sufficient to create memory for kcalTopp
    kcalTopp = malloc(sizeof(int)*numTopps);
    if(!kcalTopp)//should always test before using memory
    {
         printf("memory allocation failed, exiting");
         return 0;
    }

    for(i=0; i<numTopps; i++)
    {
        scanf("%d", &kcalTopp[i]);
    }

    totalKcal=kcalDough;
    highest=totalKcal/doughPrice;

    //sort(&kcalTopp, numTopps);
    //     ^ not needed
    sort(kcalTopp, numTopps);

    for(i=0; i<numTopps; i++)
    {
        for(j=0; j<=i; j++)
        {
            totalKcal=totalKcal+kcalTopp[j];
            kcalperDol=totalKcal/(doughPrice+i*eachToppPrice);
            if(kcalperDol>highest)
            {
                highest=kcalperDol;
            }
        }
    }

    printf("%d", highest);

    return 0;
}

void sort(int *kcalTopp, int numTopps)//note removal of []
{

    int temp, i;

    for(i=0; i<(numTopps-1); i++)
    {
            if(kcalTopp[i]<kcalTopp[i+1])
            {
                temp=kcalTopp[i];//note removal of '*' from all kcalTopp
                kcalTopp[i]=kcalTopp[i+1];
                kcalTopp[i+1]=temp;
            }
    }
}
1 голос
/ 26 марта 2020

Действительно, ваша проблема - это функция сортировки, которую вы описали, как вы и подозревали. Вы знаете, что именно делает *kcalTopp[i]=*kcalTopp[i+1];? В качестве параметра вы получаете int *array[], что эквивалентно int **array (вы можете видеть его как массив массивов целых). Поэтому, когда вы скажете C для доступа к array[i], вы получите доступ к i-му массиву. Это указатель, и фактически *kcalTopp[i] будет первым элементом из i-го массива. То, что вы делаете здесь, - это замена первых элементов из массивов, но на практике у вас есть один массив целых чисел (или, более технически, массив длиной 1 из массивов). Самое простое решение - написать:

temp=(*kcalTopp)[i];
(*kcalTopp)[i]=(*kcalTopp)[i+1];
(*kcalTopp)[i+1]=temp;

, чтобы просто изменить приоритет операторов. Теперь мы достигли следующего: мы берем первый массив из списка массивов (это единственный, который у нас есть, не так ли?) С (*kcalTopp); это int *, а не int ** больше. Теперь вы можете безопасно получить доступ к i-му элементу из него.

Без скобок вы сначала получите доступ к i-му массиву, потому что в *kcalTopp[i] часть [i] будет выполняться до * part.

В любом случае, чтобы упростить задачу, вы не обязаны принимать в качестве параметра int *kcalTopp[], вы можете просто взять int kcalTop[] или int *kcalTopp и больше не использовать *:

temp = kcalTopp[i];
kcalTopp[i] = kcalTopp[i+1];
kcalTopp[i+1] = temp;
...