Как изменить код, в котором мы должны найти пиковый элемент?

#c #arrays #data-structures

#c #массивы #структуры данных

Вопрос:

у меня есть задача, в которой я должен написать программу, чтобы найти пиковый элемент в массиве. Я его закодировал, но когда я показал его своей учительнице, она сказала мне, что это неточно, хотя он отлично работал на Dev C .Она сказала мне изменить его. Может кто-нибудь сказать мне, что не так с кодом и как мне его изменить.

 int main(){
    int arr[50];
    cout<<"Enter size:";
    int n;
    cin>>n;
    cout<<"Elements:";
    for(int i=0;i<n;i  ){
        cin>>arr[i];
    }
    for(int i=0;i<n;i  ){
        if(arr[i]>arr[i 1] amp;amp; arr[i]>arr[i-1]){
            cout<<"PEAK: "<<arr[i]<<endl;
        }
    }
    return 0;
}
  

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

1. Первое, что нужно исправить: Если i есть 0 , что arr[i-1] вам дает?

2. Он не показал никаких error..so я думал, что это может принять мусорное значение..

Ответ №1:

Проблема заключается во втором for теле цикла. Как указал NathanOliver в комментариях, arr[i] > arr[i-1] должен попытаться получить доступ к памяти с недопустимым смещением, когда i равно 0. То же самое касается другого условия — arr[i] > arr[i 1] приведет к доступу за пределы — ну, ваш arr может содержать максимум 50 элементов, поэтому, если n меньше 50, вы должны обращаться только к неинициализированной памяти. Условие нахождения пика может быть переписано как:

 for (unsigned i = 0u; i < n; i  ){
    bool isPeak = true;
    if (i > 0 amp;amp; arr[i] < arr[i - 1]){
        isPeak = false;
    }
    if (i < n - 1 amp;amp; arr[i] < arr[i   1]){
        isPeak = false;
    }
    if (isPeak){
        std::cout << "PEAK: " << arr[i] << 'n';
    }
}
  

Это использует короткое замыкание логических операторов — выражения вычисляются слева направо, поэтому — если мы вернемся к i > 0 amp;amp; arr[i] < arr[i - 1] условию — потенциально опасная проверка (которая может привести к недопустимому доступу) не будет выполнена, если первое условие ( i > 0 ) равно false.

Что касается самого кода, теперь он проверяет каждую сторону текущего элемента отдельно.

Еще лучше (хотя, вероятно, это не связано с тем, что имеет в виду ваш учитель) было бы использовать std::vector . Тогда код мог бы обрабатывать более 50 элементов.

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

1. Большое спасибо… что означает i= 0u в коде ur?

2. Это второстепенная вещь, вы могли бы с таким же успехом написать int i = 0 или int i = 0u . u в конце числового литерала означает, что этот литерал (в данном случае 0) имеет тип unsigned . Если бы вы использовали 0 , он был бы типа int по умолчанию. Для получения дополнительной информации смотрите: en.cppreference.com/w/cpp/language/integer_literal Для ваших первых упражнений по кодированию это действительно не имеет значения. Это может иметь значение, если вы полагаетесь на автоматический вывод типа. auto foo = 0; определяет foo как int , тогда как auto foo = 0u; дал бы вам unsigned foo .

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

4. Это выходит за рамки данного вопроса, но я обнаружил, что сайты с проблемами программирования, такие как HackerRank или Codewars (которые я широко использовал, хотя иногда они довольно медленные), являются неплохим способом улучшения. Возможно, вы также захотите попробовать другие языки программирования, если чувствуете, что у вас проблемы с C (особенно с учетом того, что его могут с трудом преподавать в университете). Это действительно зависит от того, что вам нравится делать — в целом просто продолжайте практиковаться. Запуск вашего собственного проекта — это также хороший способ столкнуться с новыми проблемами и повеселиться. Удачи!

5. отлично, сделаем это,