#c #arrays #pointers #parameter-passing
#c #массивы #указатели #передача параметров
Вопрос:
Основной целью программы является отображение всех значений в массиве, называемых «каналами», чтобы пользователь мог видеть все возможные варианты. После того, как я предложу пользователю выбрать один из четырех каналов, мне нужно передать эти значения во вторую функцию, чтобы что-то вычислить. Это то, что у меня есть до сих пор.
Я также не могу использовать какие-либо циклы.
Пожалуйста, помогите.
#include <stdio.h>
// Я использую структуру для хранения всех значений в массиве
typedef struct
{
char* name;
double n; //roughness
double slope;
double width;
double depth;
} CHANNEL;
main ()
{
CHANNEL channels [4] = {
{"Channel1", 0.035, 0.0001, 10.0, 2.0},
{"Channel2", 0.020, 0.0002, 8.0, 1.0},
{"Channel3", 0.015, 0.0010, 20.0, 1.5},
{"Channel4", 0.030, 0.0007, 24.0, 3.0}
};
// Я хочу отобразить все каналы и их значения прямо здесь … я знаю, что мне нужно использовать printf, но нужно ли мне использовать указатель?
printf("Please note:n 0 = Channel 1 n 1 = Channel 2 n 2 = Channel 3 n 3 = Channel 4);
printf("Pick a channel from 0-3n");
int c = 0;
scanf("%i", amp;c);
CHANNEL chosen = channels [c];
}
// Вот что у меня есть для второй функции на данный момент, у меня есть формула о том, как рассчитать скорость, но я не знаю, как передать выбранные значения, а также нужно ли мне все еще помещать прототип функции вверху?
CHANNEL calculateVelocity(CHANNEL channels[])
{
double velocity;
//THIS IS THE EQUATION I NEED TO USE
//velocity = (slope/n)*(pow((width/depth)/width 2 * depth),(2/3));
}
Комментарии:
1. Итак, в основном вы хотите передать selected
CHANNEL
функции и использовать ее переменные-члены?2. @BenceKaulics да, это именно то, что я хочу сделать
3. Примечание. Вы пропускаете
"
своиprintf
вызовы.4. @JohnBode мы еще не изучали их в классе
5. @AjAlmero: К сожалению, отображение элементов в массиве — идеальный вариант использования цикла. Мне интересно, что ваш преподаватель решил преподавать определения массивов и функций перед базовыми структурами управления.
Ответ №1:
Помимо отсутствия "
в printf
вызовах (от них обоих) и того, что вы забыли возвращаемое значение main
, которое таким образом является значением по умолчанию int
, вы начали довольно хорошо.
CHANNEL chosen
теперь это выбранный канал, чтобы использовать его данные, которые вы должны передать своей функции. Поскольку вы собираетесь использовать его значения и не хотите их изменять, вы можете передать его по значению в свою функцию.
Ваша функция должна возвращать double
скорость double
. Для доступа к переменным-членам необходимо использовать следующий sytnax:
double calculateVelocity(const CHANNEL selected)
{
double velocity;
double n = selected.n;
double slope = selected.slope;
double width = selected.width;
double depth = selected.depth;
//THIS IS THE EQUATION I NEED TO USE
velocity = (slope/n)*pow(((width/depth)/width 2 * depth),(2.0/3.0));
return velocity;
}
На вашем месте я бы также проверил ввод с консоли, чтобы вы не передали неверный индекс в свой channels
массив.
int main ()
{
CHANNEL channels [4] = {
{"Channel1", 2.0, 2.0, 10.0, 2.0},
{"Channel2", 0.020, 0.0002, 8.0, 1.0},
{"Channel3", 0.015, 0.0010, 20.0, 1.5},
{"Channel4", 0.030, 0.0007, 24.0, 3.0}
};
printf("Please note:n 0 = Channel 1 n 1 = Channel 2 n 2 = Channel 3 n 3 = Channel 4n");
printf("Pick a channel from 0-3n");
int c = 0;
scanf("%i", amp;c);
if(c < 0 || c > 3)
{
printf("Input is invalid: %dn", c);
return 1;
}
CHANNEL chosen = channels [c];
printf("Calculated velocity: %fn" ,calculateVelocity(chosen));
return 0;
}
и включить math.h
для pow
.
Комментарии:
1. Возможно, вы захотите объяснить, почему следует использовать промежуточные переменные внутри
calculateVelocity()
, а не просто использовать члены структуры, переданные функции.2. @alk Я не хотел портить читаемость кода или исходное уравнение. А также я нахожу более понятным синтаксис.
3. Придирка: спецификатор преобразования
f
ожидает adouble
, нет необходимости указывать префикс модификатора длиныl
(ell).
Ответ №2:
Давайте рассмотрим каждый из ваших вопросов по одному. Прямо сейчас я сомневаюсь, что ваше printf
утверждение делает то, что вы намереваетесь. Для печати каждого канала и содержащихся в нем элементов я бы предложил создать вспомогательную функцию, возможно, выглядящую примерно так:
void CHANNEL_print(CHANNEL* channel) {
printf("%sn", channel->name);
printf("%lfn", n); // Note that %lf is for doubles
// print the rest of the values just like this...
}
Я не собираюсь выполнять функцию целиком, потому что, похоже, этот вопрос является какой-то домашней проблемой (почему бы вам еще не использовать цикл ??) и я не хочу полностью отказываться от ответа. Однако вы должны быть в состоянии довольно легко разобраться с остальным.
Что касается второй функции, вы правы в том, что перед ее вызовом потребуется прототип функции или само определение. Похоже, что вы хотите использовать только одно CHANNEL
значение в функции, поэтому ваш прототип должен выглядеть примерно так
double calculateVelocity(CHANNEL* channel)
поскольку (я полагаю) вы хотите вернуть вычисленную вами скорость. Указатель должен быть указателем на канал, который вы хотите передать функции (т.е. amp;channel[c]
) Тогда само вычисление внутри функции будет выглядеть следующим образом:
velocity = (channel->slope / channel->n) * pow((channel->width / channel->depth) / channel->width 2 * channel->depth, 2.0/3.0)
Обратите внимание, что 2/3 = 0
, поскольку это целочисленное деление, и )
в вашем уравнении было лишнее.
Комментарии:
1. должен ли я указывать эту вспомогательную функцию перед основной или после
2. Вы можете либо объявить прототип функции до
main
и определить функцию после, либо объявить и определить функцию перед main . Какой бы вы ни выбрали, зависит от личных предпочтений.
Ответ №3:
просто примечание, вам нужен прототип функции, если определение функции находится во внешнем модуле или определение функции приходит после ее вызова.
Ответ №4:
Я знаю, вы сказали, что вам не разрешено использовать циклы, но итерация по массиву — это практически идеальный вариант использования цикла. Вот как я бы использовал цикл для отображения содержимого вашего массива:
printf( " s%8s%8s%8s%8sn", "Name", "N", "Slope", "Width", "Depth" );
printf( " s%8s%8s%8s%8sn", "----", "-", "-----", "-----", "-----" );
for ( size_t i = 0; i < N; i ) // where N is the number of rows in the array
{
printf( %20s%8.3f%8.4f%8.1f%8.1fn",
channels[i].name,
channels[i].n,
channels[i].slope,
channels[i].width,
channels[i].depth
);
При этом выводится 2-строчный заголовок, за которым следует содержимое массива, которое будет выглядеть примерно так (у меня нет удобного компилятора, поэтому я не могу закодировать его и опубликовать вывод):
Name N Slope Width Depth
---- - ----- ----- -----
Channel1 0.035 0.0001 10.0 2.0
Channel2 0.020 0.0002 8.0 1.0
Channel3 0.015 0.0010 20.0 1.5
...
В вашем случае N будет равно 4.
Структура for
цикла
for ( expr1opt ; expr2opt ; expr3opt ) statement
В for
цикле expr1
сначала вычисляется; это выражение обычно инициализирует счетчик цикла или какое-либо другое условие. Затем expr2
вычисляется; если он вычисляет ненулевое значение ( true
), тогда выполняется тело цикла. После выполнения тела цикла expr3
вычисляется; это обычно обновляет счетчик цикла или обновляет какое-либо другое условие. Затем expr2
вычисляется снова. Тело цикла выполняется до тех пор, пока expr2
значение не будет равно нулю.
Любой или все из expr1
, expr2
, и expr3
могут быть опущены.
Несколько слов о строках printf
формата…
Спецификатор формата принимает вид
% [flags] [field-width] [. precision] [length-modifier] conversion-specifier
Итак, s
означает «напечатать строку в поле шириной не менее 20 символов, дополненную пробелами слева». %8.3f
означает напечатать значение с плавающей запятой в поле шириной не менее 8 символов, включая десятичную точку, с не более чем 3 цифрами после десятичной точки «.