Как отобразить все значения, хранящиеся в массиве, и как передать эти значения второй функции {C}

#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 ожидает a double , нет необходимости указывать префикс модификатора длины 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 цифрами после десятичной точки «.