Почему указатель на арифметику указателя не работает в моем условном выражении?

sm — это 2D-массив указателей на символы, выделяемый динамически. Мне нужно понять, почему мой указатель на арифметику указателя терпит неудачу в условном условии, если в структуре цикла.

2-й столбец в sm — это строка, которую мне нужно проверить с помощью ключа оценки gk, который представляет собой массив символов/строки. s содержит размер строки, а q - размер столбца для 2D-массива, hm - мой счетчик памяти кучи для функции освобождения, которая не импортируется для моего вопроса.

double *cals(char **sm, char *gk, int s, int q, unsigned *hm) {
    int c = 0;
    double *savg = malloc(s * sizeof(double));
    assert(savg);
    *hm += 1;

    for (int i = 0; i < s; *(savg + i) = c / q * 100 , c = 0,  ++i) {
        for (int j = 0; j < q; ++j) {
            if (*(*(sm + i * STUDENTATT + 1) + j) == *(gk + j)) 
                ++c;
        }
    }
    return savg;
}

person teaNcode    schedule 09.11.2018    source источник
comment
Показать объявление переменной, переданной как sm. Фактически, предоставьте минимальный, полный и проверяемый пример (MCVE).   -  person David C. Rankin    schedule 09.11.2018
comment
Это: sm + i * STUDENTATT + 1 выглядит за пределами того, что было выделено для sm, если предположить, что это что-то вроде sm = malloc(s * sizeof(char *));   -  person dbush    schedule 09.11.2018
comment
да, char ** sm = malloc(s * STUDENTATT *sizeof(char * )); это выражение, выделенное кучей, которое я использовал. STUDENTATT — это макрос, который я определил как значение 2. Так что это просто двумерный массив s * 2.   -  person teaNcode    schedule 09.11.2018
comment
1) Вы выделили указатели, но выделили ли вы фактическое хранилище для char? 2) (sm + i * STUDENTATT + 1) + j пахнет неправильно, я совершенно уверен, что это должно быть *(sm + i * q + j), если q - это количество столбцов (уберите определение, удалите +1). 3) Сравнение строк выполняется с использованием strcmp, если только вы не уверены, что оба указателя указывают на одну и ту же строку. 4) Вы не делаете ничего странного с hm - если это ваш счетчик выделения/свободной отладки, возможно, имеет смысл создать свои собственные макросы MALLOC/FREE и поместить счетчик туда, вместо того, чтобы передавать его.   -  person Groo    schedule 09.11.2018
comment
Этот код довольно запутан. Вы должны использовать оператор [] вместо *(...), и вам нужно отказаться от назначения несвязанных вещей из 3-го предложения цикла for. Вместо этого у вас должно быть что-то вроде for(int i=0; i<s; i++) {... savg[i] = c / q * 100; }. Также примечательно, что деление в этой операции происходит на целочисленные типы, я не уверен, было ли это намерением?   -  person Lundin    schedule 09.11.2018
comment
@Гру. ВАУ, я никогда не думал о том, чтобы использовать макрос в качестве счетчика для отслеживания распределения кучи. это блестяще. Я попробую это в следующий раз. Хорошо, я попробую *(sm + i * q + j) и прокомментирую позже. Я также собираюсь опубликовать всю эту программу, потому что по какой-то странной причине мой printf() в моей функции печати для этой же программы работает со сбоями. и сообщает мне, что произошло нарушение прав на чтение. непонятна причина.   -  person teaNcode    schedule 10.11.2018


Ответы (1)


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

Предположение-1 (значащее). Вам нужно найти, сколько символов в двух строках совпадают (не все символы), а затем найти процентное соотношение одинаковых символов к общему количеству символов. Если это так, используйте приведенный ниже код.

double *cals(char **sm, char *gk, int s, int q, unsigned *hm) {
    float c = 0;        // To force float division the c is declared as a float variable
    double *savg = malloc(s * sizeof(double));
    assert(savg);
    *hm += 1;       
    char* sm_i_key = NULL;
    unsigned int strlen_gk = strlen(gk);    
    unsigned int key_length = string_gk;

    for (int i=0; i<s; ++i) { //The calculation is moved inside for loop
            sm_i_key = *(sm+i*q+1); // You can also use sm_i_key = &sm[i*q+1]
            /* Uncomment this section if length of 2 strings are not bound to be equal
            if(strlen(sm_i_key) < strlen_gk){
                    key_length = sm_i_key; 
            }
            else{
                    key_length = strlen_gk
            }
            */
            for (int j = 0; j < key_length; ++j) {
                    if (sm_i_key[j] == gk[j]) 
                        ++c;
            }
            savg [i] = c / strlen_gk * 100; /* Since gk is the grade key it is assumed
            to be equal to the total number.*/
            c = 0;
        }          
    return savg;
}

Предположение-2. Вы хотите проверить, равны ли строки, начальный адрес которых хранится во втором столбце каждой строки двумерного массива sm, строке, хранящейся в массиве, на который указывает gk, а затем вычислить значение (double). Функция cals возвращает только 0,0 или 100,0, так как формула avgs[i]=c / q * 100 будет давать 0, только если строки не равны (поскольку целочисленное деление c/q всегда дает 0, если c меньше q, что имеет место здесь) и 100, если строки равны (тогда зачем использовать double для хранения значения, если хранятся только 0 и 100).

Если это так, то то, что вы здесь делаете, в порядке, если только массив gk и массив sm[i][2] не имеют разную длину строки (не q). Было бы лучше использовать strncmp для проверки равенства строк, если длина строки двух массивов обязательно будет разной. Используйте приведенный ниже код, чтобы сделать это: -

double *cals(char **sm, char *gk, int s, int q, unsigned *hm) {
    int c;
    char* sm_i_key = NULL;
    double *savg = malloc(s * sizeof(double));
    assert(savg);
    *hm += 1;       
    for (int i=0; i < s;++i){//The calculation is moved to a static assignment given below
        if(strncmp(sm_i_key, gk, strlen(gk) == 0)
        {
            savg[i] = 100.0;    // Since c/q * 100 => 100.0 if q == c
        }
        else
        {
            savg[i] = 0.0;      /*Since c/q *100 => 0.0 if q < c since integer 
            division will result in 0.*/
        }
    }              
    return savg;
}

Я надеюсь, что это помогает.

person jibin_raj24    schedule 10.11.2018