#c #loops #for-loop #epsilon
Вопрос:
В основном я пытаюсь создать программу, которая просматривает данный массив и проверяет, является ли правый элемент в 2 раза больше левого, если true вставляет среднее значение этих двух элементов в середине. После этого он распечатывает массив со вставленными элементами, а затем снова просматривает массив, подсчитывая, сколько раз появляется определенное число. Я успешно закодировал все это, используя ручку и бумагу, и записал проблему на более мелкие фрагменты, а затем закодировал ее на C, но проблема в том, что я ввожу 100 нулей (сто нулей). программа выводит, что число 0 повторяется 200 раз вместо 199. Я не знаю, почему. И извините за плохой код, моя текущая задача-научиться хорошо решать проблемы с ручкой и бумагой, после того, как я научусь этому и разовью свою логику, я постараюсь упростить код.
Input sample:
Enter the number of elements: 100
Enter the array: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
After adding middle element: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002.33412e-310
The number is repeated 200 time/s
Мой код
#include <math.h>
#include <stdio.h>
#define EPSILON 0.0001
int main() {
int n, i, j, k, digit, length = 0, digit_array[10] = {0};
double array[200], temp;
do {
printf("Enter number of elements: ");
scanf("%d", amp;n);
} while (n <= 0 || n >= 101);
printf("Enter elements: ");
length = n;
for (i = 0; i < length; i )
scanf("%lf", amp;array[i]);
for (i = 0; i < length; i ) {
temp = array[i] array[i];
if (fabs(temp - array[i 1]) < EPSILON) {
for (j = length; j > i 1; j--)
array[j] = array[j - 1];
array[i 1] = (array[i] array[i 1]) / 2.;
i ;
length ;
}
}
printf("After adding middle element: n");
for (i = 0; i < length; i )
printf("%g ", array[i]);
for (i = 0; i < length; i ) {
temp = array[i];
digit = ((int)(temp * 10)) % 10;
digit_array[digit] ;
}
printf("n");
for (i = 0; i < 10; i ) {
if (digit_array[i] != 0)
printf("Number %d is repeated %d time/s.n", i, digit_array[i]);
}
return 0;
}
Комментарии:
1. Я надеюсь, что это переход к пониманию того, почему связанные списки намного лучше вставлять посередине, чем массивы.
2. @яно, я все еще изучаю C, хочу сначала ознакомиться с массивами.
3. Код проходит через конец массива. На последней итерации цикл
i
равенlength-1
. Это означает , что выражениеtemp - array[i 1]
считываетсяarray[length]
, ноarray[length]
находится за пределами массива.4. Еще не полностью изучил код, но
for (i = 0; i < length-1; i )
может сработать.5. @user3386109 это выглядит правильно для меня: godbolt.org/z/j1sPcGc6x
Ответ №1:
Вместо того, чтобы постоянно перемещать массив, гораздо проще и быстрее использовать два массива. Все, что тебе нужно, это:
// Inputs:
// n: The number of inputs.
// a: An array of at least n doubles containing the inputs.
// b: An array of at least n*2-1 doubles that will containing the outputs.
// Outputs:
// m: The number of outputs.
// b: An array of at least m doubles containing the outputs.
size_t i = 0;
size_t j = 0;
double prev = b[j ] = a[i ];
while (i < n) {
double next = a[i];
if (fabs(prev*2 - next) < EPSILON) { // If a[i-1] exactly equal a[i]*2.
b[j ] = next / 2.0 prev / 2.0; // Or: b[j ] = prev * 1.5;
}
prev = b[j ] = a[i ];
}
size_t m = j;
Относительно prev * 1.5
:
average(next, prev)
= ( next prev ) / 2
= ( prev * 2 prev ) / 2
= ( prev * 3 ) / 2
= prev * 1.5
Включено в надлежащую функцию:
int f(double *a, size_t n, double **b_ptr, size_t *m_ptr) {
double b = malloc( (n*2-1) * sizeof(double) ); // We need up to this much.
if (b == NULL) {
*b_ptr = NULL;
return 0;
}
size_t i = 0;
size_t j = 0;
double prev = b[j ] = a[i ];
while (i < n) {
double next = a[i];
if (fabs(prev*2 - next) < EPSILON) { // If a[i-1] exactly equal a[i]*2.
b[j ] = next / 2.0 prev / 2.0; // Or: b[j ] = prev * 1.5;
}
prev = b[j ] = a[i ];
}
b = realloc(b, j * sizeof(double)); // Free the excess. (Optional)
size_t m = j;
*b_ptr = b;
*m_ptr = m;
return 1;
}
Комментарии:
1. Как я уже писал, я все еще изучаю задачи только для начинающих, я не понимаю половины написанного вами кода, я не думаю, что я делаю что-то хорошее для себя, просто копируя и вставляя код :/
2. Здесь нет ничего, что бы вы не использовали, кроме использованного malloc вместо жесткого кодирования размера массивов. Просто игнорируйте все до
int i = 0;
и после цикла. См. обновление3. Хорошо, я понял предыдущее * 1.5. Большое вам спасибо за разъяснения, ребята. Поскольку я все еще новичок в stackoverflow, я не знаю, как представить вас 1, ребята, но я думаю, что вам это все равно не нужно от меня. Большое вам спасибо @ikegami
4. Вы нажимаете на стрелку вверх рядом со столбом. Для этого может быть минимальная репутация?
5. Да, сэр, 15 повторений