Код выполняется без ошибок или предупреждений, но происходит сбой

#c

#c

Вопрос:

Код пытается найти максимально возможное число из массива заданных чисел, используя массив символов вместо массива int. В моем сообщении о сборке нет ни предупреждений, ни ошибок. Тем не менее, когда я запускал этот код, он вылетает. Что-то не так в моем коде?

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

int cmp(const void *a, const void *b){
    const char **X = (const char **)a;
    const char **Y = (const char **)b;

    int char_len = strlen(*X)   strlen(*Y)   1;

    char XY[char_len];
    strcpy(XY, *X);
    strcat(XY, *Y);

    char YX[char_len];
    strcpy(YX, *Y);
    strcat(YX, *X);

    return strcmp(YX, XY);
}

int main (void) {
    int i,n;

    printf("enter number of salaries: ");
    scanf("%d", amp;n);
   
    char *array[n];
    int j = sizeof(array)/sizeof(array[0]);

    printf("nenter the salaries: ");
    for(i=0; i<n; i  ){
        scanf("t%s", amp;array[i]);
    }

    printf("nOutput: n");
    qsort(array, j, sizeof(array[0]), cmp);
    for(i=0;i<n;i  ){
        printf("%s", array[i]);
        return 0;
    }
}
  

Редактировать 1: я переместил массив * char[n] после сканирования, если это сработало. Тем не менее, он по-прежнему выходит из строя при выполнении строки qsort.

Комментарии:

1. n; char *array[n]; — сколько элементов имеет array ? (т.е.. каково значение n when array определено?)

2. я вижу, я понимаю, я попытался переместить *array[n] после scanf . Теперь код выполняется и выводит данные из размера массива, элементов массива. Тем не менее, все еще происходит сбой в строке qsort.

3. warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char **’ [-Wformat=] — получите лучший компилятор

Ответ №1:

Основная проблема, с которой вы сталкиваетесь, заключается в следующем:

 scanf("t%s", amp;array[i]);
  

array это массив указателей, и это передаст адрес одного из этих указателей в scanf, где %s будет записана строка поверх указателя (давая вам указатель мусора и, если строка достаточно длинная, записывая дополнительные указатели в массиве.

Что вы хотите, так это выделить некоторую память для строки и прочитать ее в нее, а затем сохранить указатель на эту память в массиве. Если вы используете систему POSIX, есть простой способ сделать это:

 scanf("t%ms", amp;array[i]);
  

Это будет использовать malloc для выделения ровно достаточного объема памяти для чтения строки (включая нулевой терминатор) и сохранения этого указателя в указанном элементе массива.

Также обратите внимание, t что строка формата не имеет значения — она просто пропускает начальные пробелы, что спецификатор s преобразования делает в любом случае.

Ответ №2:

n не инициализируется. Следовательно, неопределенное поведение при объявлении array[n]

 int i,n;
char *array[n];
int j = sizeof(array)/sizeof(array[0]);
  

Представьте, был ли n присвоен ноль при запуске. Изменение значения n в следующей scanf строке не приведет к изменению размера массива.

Кроме того, даже если n была достаточно назначена длина массива, это все еще неопределенное поведение:

 for(i=0; i<n; i  ){
    scanf("t%s", amp;array[i]);
}
  

Для каждой записи массива не выделяется память. Представьте, что после char* array[n] успешного объявления каждое значение указателя в этом массиве не определено. ЕСЛИ вам повезет, каждый элемент имеет значение NULL (0), и он быстро завершится сбоем. Но, скорее всего, вы получаете случайную память. И вы scanf копируете строку в память, которой ваша программа не владеет.

Комментарии:

1. понятно, большое вам спасибо. Я попытался переместить оба int i,n; char *array[n]; после сканирования, это работает! но все равно происходит сбой при выполнении строки qsort.

2. Потому что вы не выделили достаточно памяти для каждого элемента в массиве. Как вы думаете, на какой адрес scanf("t%s", amp;array[i]); копируется введенный пользователем ввод? Вы знаете, что malloc делает?