Форум русскоязычного сообщества Ubuntu


Следите за новостями русскоязычного сообщества Ubuntu в Twitter-ленте @ubuntu_ru_loco

Автор Тема: Как в С из функции передать несколько переменных.  (Прочитано 1489 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Oopss

  • Автор темы
  • Любитель
  • *
  • Сообщений: 55
    • Просмотр профиля
Здравствуйте!!!
Новичок в С, нужна помощь.
В общем в Паскале есть процедуры и функции. Функции возвращают одно значение присвоив его к себе. А процедуры могут возвращать кучу переменных.
В С процедур нет есть только функции. А как мне передать из функции на С кучу переменных. В общем нужено что нибудь аналогичное Паскалевским процедурам.
Пробовал так:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct package{                          //объявляю структуру шаблон функции
    char            str[100];
    unsigned int    len;
};

struct package *int_to_str (long unsigned int nbr )  //сама функчия, которая принимает данные типа long unsigned int, конвертирует их в данные типа char.
{
    struct   package    pack, *retu;

    unsigned long int   div ;
    unsigned int        len ;
    char                i ;
    char                res[100] ;
    
    i = 0 ;
    div = 1 ;
    len = 1 ;
    memset(res,0,100);

    while ( nbr / div >= 10 ){
        div *= 10 ;
        len ++;
    }

    pack.len = len;

    while ( len > 0 ){
        switch (nbr / div){
            case 0: pack.str [ i] = '0';    break;
            case 1: pack.str [ i] = '1';    break;
            case 2: pack.str [ i] = '2';    break;
            case 3: pack.str [ i] = '3';    break;
            case 4: pack.str [ i] = '4';    break;
            case 5: pack.str [ i] = '5';    break;
            case 6: pack.str [ i] = '6';    break;
            case 7: pack.str [ i] = '7';    break;
            case 8: pack.str [ i] = '8';    break;
            case 9: pack.str [ i] = '9';    break;
          
        }
        len --;
        i++;
        nbr %= div ;
        div /= 10 ;

    }

    printf("pack.len = %d, pack.str = ",pack.len);
    for(i=0;i<pack.len;i++)printf(" %c ",pack.str[i]);   //проверяем правильно ли заполнилась структура pack
    printf("\n");

    retu=&pack;
    return ( ( retu ) );
}

int main(void) {

    struct package *data;

    unsigned long int nbr=123456789;  //число которое я хочу преобразовать в символьный массив.

    unsigned long int   div = 1;
    int   len = 1;
    int   i ;
    char  *res ;

    data=int_to_str(nbr);                      //здесь заполняю структуру data из функции. В структуре должны содержаться число в символьном виде и длиня этого числа.

    printf("data.len = %d, data.str = ",data->len);
    for(i=0; i < data->len;i++)printf(" %c ",data->str[i]);   // проверяем что содержится в структуре data (и видем по цитате с низу что символьный массив гдето потерялся (( )
    printf("\n");
    return (EXIT_SUCCESS);
}

Функция должна возвратить адрес на структуру, в которой хранится число в символьном виде и колличество цифр в этом числе.
Результат выполнения программки такой:
Цитировать
pack.len = 9, pack.str =  1  2  3  4  5  6  7  8  9
data.len = 9, data.str =  p  �      �        �
Как правильно передавать несколько переменных из функции в программу?
 :idiot2:
Спасибо.
« Последнее редактирование: 01 Октября 2010, 22:08:14 от Oopss »

Оффлайн Mam(O)n

  • Старожил
  • *
  • Сообщений: 5855
    • Просмотр профиля
Главная твоя ошибка в этом:
   retu=&pack;
    return ( ( retu ) );
Ты возвращаешь адрес переменной, которая лежала в стеке на время вызова функции.. Соответственно после выхода из функции эта область памяти снова свободна и результат работы с этой областью памяти не предсказуем. Вот например у меня вообще все нормально отработало в твоем примере ))

Я бы посоветовал возвращать не адрес указывающий на структуру, а структуру целиком.

Пользователь решил продолжить мысль 01 Октября 2010, 22:45:05:
ЗЫ. А чем sprintf не угодил в противовес реализации данной сомнительной функции?
« Последнее редактирование: 01 Октября 2010, 22:45:05 от Mam(O)n »

Оффлайн VestniK

  • Активист
  • *
  • Сообщений: 594
    • Просмотр профиля
Re: Как в С из функции передать несколько пере
« Ответ #2 : 02 Октября 2010, 02:16:26 »
Если ты хочешь возвращать несколько значений из функции, толучше передавать указатель на переменную в которую нужно сложить результат. Например функция преобразования строки в число может выглядеть так:
void str2int(char *str, int *res, bool *ok) {
// implementation here
}
Первый параметр строка, которую мы преобразовываем в число и складываем по адресу указаному во второй переменной, а по адресу указанному в третей переменной складываем true если в строка успешно была преобразованна в число или false если нет.

Это был общий ответ. А по твоему примеру:

Строки в C являются массивами символов использующими символ '\0' (символ с кодом 0) как признак конца строки. Длинна строки нигде не храниться.

Как уже сказал Mam(O)n нельзя возвращать куазатель на локальную переменную функции, кажется на этот счёт компилятор даже warning выдаёт. Варианта два:
1 возвращать саму структуру, но при этом будет производиться копирование области памяти подайтово, что не хорошо с точки зрения быстродействия.
2 передавать указатель на структуру которая должна быть заполнена внутри функции, а внутри функции её заполнять.

З.Ы. Опять же, присоединяюсь к Mam(O)n'у относительно замечания о наличии функции sprintf
« Последнее редактирование: 02 Октября 2010, 02:18:02 от VestniK »

Оффлайн Oopss

  • Автор темы
  • Любитель
  • *
  • Сообщений: 55
    • Просмотр профиля
Re: Как в С из функции передать несколько пере
« Ответ #3 : 02 Октября 2010, 12:15:32 »
Если ты хочешь возвращать несколько значений из функции, толучше передавать указатель на переменную в которую нужно сложить результат. Например функция преобразования строки в число может выглядеть так:
void str2int(char *str, int *res, bool *ok) {
// implementation here
}
Первый параметр строка, которую мы преобразовываем в число и складываем по адресу указаному во второй переменной, а по адресу указанному в третей переменной складываем true если в строка успешно была преобразованна в число или false если нет.

Это был общий ответ. А по твоему примеру:

Строки в C являются массивами символов использующими символ '\0' (символ с кодом 0) как признак конца строки. Длинна строки нигде не храниться.

Как уже сказал Mam(O)n нельзя возвращать куазатель на локальную переменную функции, кажется на этот счёт компилятор даже warning выдаёт. Варианта два:
1 возвращать саму структуру, но при этом будет производиться копирование области памяти подайтово, что не хорошо с точки зрения быстродействия.
2 передавать указатель на структуру которая должна быть заполнена внутри функции, а внутри функции её заполнять.

З.Ы. Опять же, присоединяюсь к Mam(O)n'у относительно замечания о наличии функции sprintf
Спасибо идея передачи нескольких переменных из функции ясна.
По поводу функции sprintf, узнал про нее от Вас, прочитал вот тут про нее http://ru.wikipedia.org/wiki/Sprintf пишут что небезопастная функция  :).
Новичок пока, сильно не ругайте )).

Оффлайн Mam(O)n

  • Старожил
  • *
  • Сообщений: 5855
    • Просмотр профиля
пишут что небезопастная функция  :).
А разве про безопасный вариант snprintf там ничего не пишут?

Оффлайн Oopss

  • Автор темы
  • Любитель
  • *
  • Сообщений: 55
    • Просмотр профиля
пишут что небезопастная функция  :).
А разве про безопасный вариант snprintf там ничего не пишут?
Пишут   ;)

 

Страница сгенерирована за 0.031 секунд. Запросов: 21.