Как передать список в функцию c
Перейти к содержимому

Как передать список в функцию c

  • автор:

Передача list в качестве параметра функции

Я хочу передать неинициализированный list в качестве аргумента в функцию add , чтобы там его изменить. Что я делаю не так?

#include #include #include using namespace std; typedef struct < char author[30]; >SONG; void add( * b) < char a[30]; cin >> a; SONG singer; b.push_front(singer); /*тут я хочу получить массив и изменить его, но показывает ошибку*/ strcpy_s(singer.author, a); list::iterator it; it = b.begin(); b.insert(++it, singer); > int main() < list myList; cout > input; switch (input) < case 1: add(list&myList); /*вот тут хочу передать массив по ссылке*/ break; default: cout return 0; > 

Отслеживать

222k 15 15 золотых знаков 120 120 серебряных знаков 234 234 бронзовых знака

Функции со списками аргументов переменных (C++)

Функции, в объявлениях которых в качестве последнего члена указано многоточие (. ), могут принимать переменное число аргументов. В таких случаях C++ обеспечивает проверку типа только для явно объявленных аргументов. Переменные списки аргументов можно использовать, если функция должна быть настолько универсальной, что могут изменяться даже количество и типы аргументов. Семейство функций — это пример функций, использующих списки аргументов переменной. printf argument-declaration-list

Функции с переменными аргументами

Чтобы получить доступ к аргументам после объявления, используйте макросы, содержащиеся в стандартном файле , как описано ниже.

Блок, относящийся только к системам Майкрософт

Microsoft C++ допускает указывать многоточие в качестве аргумента, если это последний аргумент и перед многоточием стоит запятая. Поэтому объявление int Func( int i, . ); допускается, а объявление int Func( int i . ); — нет.

Завершение блока, относящегося только к системам Майкрософт

В объявлении функции, которая принимает переменное число аргументов, требуется по крайней мере один аргумент-местозаполнитель, даже если он не используется. Если этот аргумент-местозаполнитель не указан, доступ к остальным аргументам невозможен.

Когда аргументы типа char передаются в качестве аргументов переменной, они преобразуются в тип int . Аналогичным образом, когда аргументы типа float передаются в качестве аргументов переменной, они преобразуются в тип double . Для аргументов остальных типов могут выполняться обычные восходящие приведения целочисленных типов и типов с плавающей запятой. Дополнительные сведения см. в разделе «Стандартные преобразования».

Функции, которым необходимы списки с переменным количеством аргументов, объявляются с многоточием (. ) в списках аргументов. Используйте типы и макросы, описанные в , чтобы получить доступ к аргументам, передаваемым списком переменных. Дополнительные сведения об этих макросах см. в va_arg , va_copy, va_end va_start. в документации по библиотеке времени выполнения C.

В следующем примере показано, как макросы работают вместе с типом (объявленным в ):

// variable_argument_lists.cpp #include #include // Declaration, but not definition, of ShowVar. void ShowVar( char *szTypes, . ); int main() < ShowVar( "fcsi", 32.4f, 'a', "Test string", 4 ); >// ShowVar takes a format string of the form // "ifcs", where each character specifies the // type of the argument in that position. // // i = int // f = float // c = char // s = string (char *) // // Following the format specification is a variable // list of arguments. Each argument corresponds to // a format character in the format string to which // the szTypes parameter points void ShowVar( char *szTypes, . ) < va_list vl; int i; // szTypes is the last argument specified; you must access // all others using the variable-argument macros. va_start( vl, szTypes ); // Step through the list. for( i = 0; szTypes[i] != '\0'; ++i ) < union Printable_t < int i; float f; char c; char *s; >Printable; switch( szTypes[i] ) < // Type to expect. case 'i': Printable.i = va_arg( vl, int ); printf_s( "%i\n", Printable.i ); break; case 'f': Printable.f = va_arg( vl, double ); printf_s( "%f\n", Printable.f ); break; case 'c': Printable.c = va_arg( vl, char ); printf_s( "%c\n", Printable.c ); break; case 's': Printable.s = va_arg( vl, char * ); printf_s( "%s\n", Printable.s ); break; default: break; >> va_end( vl ); > //Output: // 32.400002 // a // Test string 

Приведенный выше пример иллюстрирует следующие важные правила:

  1. Перед тем как обращаться к аргументам из списка переменной длины, необходимо установить его маркер в качестве переменной типа va_list . В приведенном выше примере этот маркер имеет имя vl .
  2. К отдельным аргументам можно обращаться при помощи макроса va_arg . Макросу va_arg необходимо указать тип получаемых аргументов, чтобы он мог перенести из стека нужное количество байтов. Если вы ошибетесь и укажете другой тип, а его размер не будет совпадать с типом, который вызывающая программа передает макросу va_arg , это может привести к непредсказуемым результатам.
  3. Результат, полученный при помощи макроса va_arg , необходимо явным образом преобразовывать в нужный вам тип.

Для завершения обработки списка с переменным количеством аргументов необходимо вызвать макрос. va_end

Как происходит передача списка в функцию через параметр?

Доброго времени суток, я давно бьюсь над задачей создания связного списка, и не получается добавлять элементы.
Суть в том, что функция добавления элемента работает правильно, но как только происходит выход из функции списка как-бы и нет.
И так:
Вот структура элемента:

struct Node < string word; Node* next; >;

Есть функция инициализации списка:

Node* init(string str) < Node* item = new Node; item->word = str; item->next = NULL; return item; >

Допустим список инициализирован(с ней проблем нет), и я хочу добавить новый элемент вызывая следующую функцию:

void AddNode(Node* pfirst, string str) < Node *tmp, *item = new Node; item->word = str; item->next = NULL; tmp = pfirst; while (tmp->next != NULL) tmp = tmp->next; tmp->next = item; delete tmp; >

Согласно отладчику:
Список передаётся в функцию и добавляется новый элемент, но после завершения этой функции список превращается в мусор.
Вот так выглядит Main:

int main() < Node* head = NULL; head = init("One"); AddNode(head, "Two"); PrintList(head); // Функция печати списка return 0; >

Собсна вопрос: при передачи списка в функцию — это тот же список или новый, который просто так не вернётся указателю head? Мне что, нужно возвращать список return’ом? Как это реализовать?
Весь код:

spoiler

struct Node < string word; Node* next; >; Node* init(string str) < Node* item = new Node; item->word = str; item->next = NULL; return item; > void AddNode(Node* pfirst, string str) < Node *tmp, *item = new Node; item->word = str; item->next = NULL; tmp = pfirst; while (tmp->next != NULL) tmp = tmp->next; tmp->next = item; delete tmp; > void PrintList(Node* pfirst) < Node* tmp = pfirst; while (true) < cout word next == NULL) break; tmp = tmp->next; > > int main()

Не предлагайте создание списка классом, мне нужно выполнить именно так. Спасибо!

  • Вопрос задан более трёх лет назад
  • 347 просмотров

Функции в языке C. Передача аргументов по значению и по ссылке

Язык C как и большинство других языков программирования позволяет создавать программы, состоящие из множества функций, а также из одного или нескольких файлов исходного кода. До сих пор мы видели только функцию main , которая является главной в программе на C , поскольку выполнение кода всегда начинается с нее. Однако ничего не мешает создавать другие функции, которые могут быть вызваны из main или любой другой функции. В этом уроке мы рассмотрим создание только однофайловых программ, содержащих более чем одну функцию.

При изучении работы функций важно понимать, что такое локальная и что такое глобальная переменные. В языке программирования C глобальные (внешние) переменные объявляются вне какой-либо функции. С их помощью удобно организовывать обмен данными между функциями, однако это считается дурным тоном, т.к. легко запутывает программу. Локальные переменные в Си называют автоматическими. Область действия автоматических переменных распространяется только на ту функцию, в которой они были объявлены. Параметры функции также являются локальными переменными.

Структурная организация файла, содержащего несколько функций, может выглядеть немного по-разному. Так как выполнение начинается с main() , то ей должны быть известны спецификации (имена, количество и тип параметров, тип возвращаемого значения) всех функций, которые из нее вызываются. Отсюда следует, что объявляться функции должны до того, как будут вызваны. А вот определение функции уже может следовать и до и после main() . Рассмотрим такую программу:

#include // объявление функции float median (int a, int b); int main () { int num1 = 18, num2 = 35; float result; printf("%10.1f\n", median(num1, num2)); result = median(121, 346); printf("%10.1f\n", result); printf("%10.1f\n", median(1032, 1896)); } // определение функции float median (int n1, int n2) { float m; m = (float) (n1 + n2) / 2; return m; }

В данном случае в начале программы объявляется функция median . Объявляются тип возвращаемого ею значения ‒ float , количество и типы параметров ( int a, int b ). Обратите внимание, когда объявляются переменные, то их можно группировать: int a, b; . Однако с параметрами функций так делать нельзя, для каждого параметра тип указывается отдельно: (int a, int b) .

Далее идет функция main , а после нее ‒ определение median . Имена переменных-параметров в объявлении функции никакой роли не играют. Их вообще можно опустить, например, float median (int, int); . Поэтому когда функция определяется, то имена параметров могут быть другими, однако тип и количество должны строго совпадать с объявлением.

Функция median() возвращает число типа float . Оператор return возвращает результат выполнения переданного ему выражения; после return функция завершает свое выполнение, даже если далее тело функции имеет продолжение. Функция median() вычисляет среднее значение от двух целых чисел. В выражении (float) (n1 + n2) / 2 сначала вычисляется сумма двух целых чисел, результат преобразуется в вещественное число и только после этого делится на 2. Иначе мы бы делили целое на целое и получили целое (в таком случае дробная часть просто усекается).

В теле main функция median() вызывается три раза. Результат выполнения функции не обязательно должен быть присвоен переменной.

Эту же программу можно написать и так:

#include float median (int n1, int n2) { float m; m = (float) (n1 + n2) / 2; return m; } int main () { int num1 = 18, num2 = 35; float result; printf("%10.1f\n", median(num1, num2)); result = median(121, 346); printf("%10.1f\n", result); printf("%10.1f\n", median(1032, 1896)); }

Хотя такой способ и экономит одну строчку кода, однако главная функция, в которой отражена основная логика программы, опускается вниз, что может быть неудобно. Поэтому первый вариант предпочтительней.

Напишите функцию, возвращающую куб числа, переданного ей в качестве аргумента. Вызовите эту функцию с разными аргументами.

Статические переменные

В языке программирования C существуют так называемые статические переменные. Они могут быть как глобальными, так и локальными. Перед именем статической переменной пишется ключевое слово static .

Внешние статические переменные, в отличие от обычных глобальных переменных, нельзя использовать из других файлов в случае программы, состоящей из нескольких файлов. Они глобальны только для функций того файла, в котором объявлены. Это своего рода сокрытие данных, когда наружу не выставляют ничего лишнего, чтобы извне нельзя было случайно испортить данные.

Статические переменные, объявленные внутри функций, имеют такую же область действия, как автоматические. Однако в отличие от автоматических, значения локальных статических переменных не теряются, а сохраняются между вызовами функции:

#include int hello(); int main() { printf(" - %d-й вызов\n", hello()); printf(" - %d-й вызов\n", hello()); printf(" - %d-й вызов\n", hello()); } int hello () { static count = 1; printf("Hello world!"); return count++; }
Hello world! - 1-й вызов Hello world! - 2-й вызов Hello world! - 3-й вызов

В этом примере в функции hello() производится подсчет ее вызовов.

Передача аргументов по ссылке

В первом примере этого урока мы передавали в функцию аргументы по значению. Это значит, что когда функция вызывается, ей передаются в качестве фактических параметров (аргументов) не указанные переменные, а копии значений этих переменных. Сами переменные к этим копиям уже никакого отношения не имеют. В вызываемой функции эти значения присваиваются переменным-параметрам, которые, как известно, локальны. Отсюда следует, что изменение переданных значений никакого влияния на переменные, переданные в функцию при вызове, не оказывают. В примере выше даже если бы в функции median() менялись значения переменных n1 и n2, то никакого влияния сей факт на переменные num1 и num2 не оказал.

Однако можно организовать изменение локальной переменной одной функции с помощью другой функции. Сделать это можно, передав в функцию адрес переменной или указатель на нее. На самом деле в этом случае также передается копия значения. Но какого значения?! Это адрес на область памяти. На один и тот же участок памяти может существовать множество ссылок, и с помощью каждой из них можно поменять находящееся там значение. Рассмотрим пример:

#include void epow(int *, int); int main() { int x = 34, y = 6; epow(&x, 3); epow(&y, 1); printf("%d %d\n", x, y); // 34000 60 } void epow(int *base, int pow) { while (pow > 0) { *base = *base * 10; pow--; } }

Функция epow ничего не возвращает, о чем говорит ключевое слово void . Принимает эта функция адрес, который присваивается локальной переменной-указателю, и целое число. В теле функции происходит изменение значения по адресу, содержащемуся в указателе. Поскольку это адрес то переменной x , то y из функции main , то epow() меняет их значение.

Когда epow() вызывается в main , то в качестве первого параметра мы должны передать адрес, а не значение. Поэтому, например, вызов epow(x, 3) привел бы к ошибке, а вызов epow(&x, 3) ‒ правильный, т. к. мы берем адрес переменной x и передаем его в функцию. При этом ничего не мешает объявить в main указатель и передавать именно его (в данном случае сама переменная p содержит адрес):

int x = 34, y = 6; int *p; p = &x; epow(p, 3); p = &y; epow(p, 1); printf("%d %d\n", x, y);

Кроме того, следует знать, что функция может возвращать адрес.

Важно понять механизм так называемой передачи аргументов по ссылке, т.к. это понимание пригодится при изучении массивов и строк. Использовать указатели при работе с простыми типами данных не стоит. Лучше возвращать из функции значение, чем менять локальные переменные одной функции с помощью кода другой. Функции должны быть достаточно автономными.

Напишите программу, в которой помимо функции main были бы еще две функции: в одной вычислялся факториал переданного числа, в другой ‒ находился n-ый элемент ряда Фибоначчи ( n ‒ параметр функции). Вызовите эти функции с разными аргументами.

Курс с решением задач:
pdf-версия

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *