URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 4504
[ Назад ]

Исходное сообщение
"возврат строки"

Отправлено lemegeton , 24-Июл-05 09:09 
Есть функция, которая формирует строку. Как мне ее вернуть???
...
str[512];
...
retturn str;

ругается типа что я возвращаю адрес локальной переменной.
функция объявлена так - char*function();


Содержание

Сообщения в этом обсуждении
"возврат строки"
Отправлено gyn61 , 24-Июл-05 10:43 
>Есть функция, которая формирует строку. Как мне ее вернуть???
>...
>str[512];
>...
>retturn str;
>
>ругается типа что я возвращаю адрес локальной переменной.
>функция объявлена так - char*function();

static char str[512];

Только функция не реентерабельна :(

Можно ещё:

char *str = malloc(sizeof(char) * 512);

но тогда вызывающая сторона должна делать free() или будут утечки памяти :(


"возврат строки"
Отправлено chip , 24-Июл-05 16:07 
>Есть функция, которая формирует строку. Как мне ее вернуть???
>...
>str[512];
>...
>retturn str;
>
>ругается типа что я возвращаю адрес локальной переменной.
>функция объявлена так - char*function();

Корректнее в функцию передавать адрес буфера + его[буфера] размер. Примеры,
strncpy или ее более "продвинутый" аналог strlcpy (OpenBSD, FreeBSD)
http://www.freebsd.org/cgi/man.cgi?query=strlcpy&apropos=0&s...



"возврат строки"
Отправлено lemegeton , 24-Июл-05 17:37 
спасибо за советы. Просто я думал сделать так - функция принимает команду выполняет, на выходе выдает строку. Как оказалось дальше что вернуть корректнее будет указатель на строку( как я понял указатель на первый элемент массива). Фича в том что в функции происходит построчное считывание из файла - fgets(), и получается что в строке, что заполняется fgets содержится последняя строка файла. Теперь я бьюсь над конкатенацйей строк, но пока тщетно, решение нашел пройтись по всем элементам массива(строки) и занести их в другой. НО почему то в конечном массиве содержиться только первай строчка файла...А привыводе на экран после печатанья этой строчки сообщение - segmentation fault. Есть соображения у кого - нибудь по этому поводу, подскажите. Я конечно много незнаю, просто 2 ой день на си программирую ;)

"возврат строки"
Отправлено lemegeton , 24-Июл-05 22:34 
допер сам - надо при вызове fgets() сдвигать указатель на строку на количество позиций раное количеству символов в строке,
типа:
while(fgets(&str[pointer],128,f))
{
pointer=strlen(str);
}
работает! Всем спасибо.

"возврат строки"
Отправлено chip , 24-Июл-05 23:43 
>допер сам - надо при вызове fgets() сдвигать указатель на строку на
>количество позиций раное количеству символов в строке,
>типа:
>while(fgets(&str[pointer],128,f))
>{
>pointer=strlen(str);
>}
>работает! Всем спасибо.

ИМХО, это что-то ужасное :(



"возврат строки"
Отправлено lemegeton , 25-Июл-05 10:16 
>>допер сам - надо при вызове fgets() сдвигать указатель на строку на
>>количество позиций раное количеству символов в строке,
>>типа:
>>while(fgets(&str[pointer],128,f))
>>{
>>pointer=strlen(str);
>>}
>>работает! Всем спасибо.
>
>ИМХО, это что-то ужасное :(
может быть. я не претендую на звание лучшего программиста, поэтому и спросил здесь, в форуме. Если есть варианты лучше подскажите, я буду только рад.


"возврат строки"
Отправлено chip , 25-Июл-05 12:14 
>может быть. я не претендую на звание лучшего программиста, поэтому и спросил
>здесь, в форуме. Если есть варианты лучше подскажите, я буду только
>рад.

Задача до конца не ясна :( Если чтение файла, то я бы сделал так:


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>

static const char *progname;

void
usage() {
  fprintf(stderr, "Usage: %s filename\n", progname);
  exit(1);
}

void
die() {
  perror(progname);
  exit(1);
}

int
main(int argc, char *argv[])
{
  FILE   *fp;
  struct stat st;
  char   *content;
  int    rval;

  progname = argv[0];
  if (argc < 2) usage();

  memset(&st, 0, sizeof(st));
  rval = stat(argv[1], &st);
  if (-1 == rval) die();

  fp = fopen(argv[1], "r");
  
  content = malloc(st.st_size + 1);
  if (!content) die();

  rval = fread(content, st.st_size, 1, fp);
  if (0 == rval) die();
  content[st.st_size] = '\0';
  fclose(fp);
  fprintf(stdout, "%s", content);
  free(content);

  return 0;
}


"возврат строки"
Отправлено dimus , 25-Июл-05 10:36 

>Теперь я бьюсь над конкатенацйей строк, но
>пока тщетно, решение нашел пройтись по всем элементам массива(строки) и занести
>их в другой. НО почему то в конечном массиве содержиться только
>первай строчка файла...А привыводе на экран после печатанья этой строчки сообщение
>- segmentation fault.

По поводу Segmentation fault - это наверняка трабла с указателями.

По поводу слияния строк - а вы уверены, что надо Вам именно это? Если реч идет о многострочных командах, вроде как в Си, то говорить лучше о слиянии команд. А вообще вот как можно слить две строки:

char* str1 = "bla-bla-bla\n";
char* str2 = "mla-mla-mla\n";

char* cat_string( char* s1, char* s2 )
{
   char* str = NULL;
   int len;

   // Вычислим необходимый размер памяти
   len = strlen(s1);
   len = len + strlen(s2) + 1;

   str = malloc(len);
   if( str )
   {
      // Это довольно опасный код. Если есть малейшая возможность,
      // что во время вызова функции длина строки может увеличиться,
      // следует использовать strncpy и strncat.
      strcpy( str, s1 );
      strcat( str, s2 );
   }

   return str;
}

А вообще, почему бы не считать файл одним куском, а не построчно? Тогда все, что надо - это выполнить разделение по разделителям команд. Можно потом загнать указатели на эти команды например в связанный список, или в массив, и потом работать с ним дальше.


"возврат строки"
Отправлено Vladislav , 25-Июл-05 12:33 
Сишники...)) Как у вас все сложно, как много велосипедов))

std::string doSomething(const std::string & in)
{
  return "...";
}


"возврат строки"
Отправлено Аноним , 25-Июл-05 15:16 
>Сишники...)) Как у вас все сложно, как много велосипедов))
>

А как в плюсах локальную переменную вернуть? Там тоже фокусов может быть немало.


"возврат строки"
Отправлено dimus , 25-Июл-05 15:46 
Локальная переменная имеет время жизни, равное времени жизни функции. После того, как функция прекратит свое существование, эта переменная бесследно исчезает. Пример:

char* my_func( void )
{
   // В стеке будет выделен кусок размером MY_ARRAY_SIZE
   char my_array[MY_ARRAY_SIZE];
   // Возвращаем указатель на этот кусок стека - НЕ ДЕЛАЙТЕ ТАК НИКОГДА
   return my_array;
}
// Вышли из функции - стек разрушен, значения, сохраненные в my_array
// будут затерты при первом же вызове какой-либо другой функции


"возврат строки"
Отправлено lemegeton , 29-Июл-05 10:43 
>Сишники...)) Как у вас все сложно, как много велосипедов))
>
>std::string doSomething(const std::string & in)
>{
>  return "...";
>}
Прошу прощение за ламерский вопрос, но где можно почитать про стандартные классы в с++? Желательно на русском. И еще, если так просто можно все решить на с++, зачем применяют С?


"возврат строки"
Отправлено chip , 29-Июл-05 23:16 
>>Сишники...)) Как у вас все сложно, как много велосипедов))
>>
>>std::string doSomething(const std::string & in)
>>{
>>  return "...";
>>}
>Прошу прощение за ламерский вопрос, но где можно почитать про стандартные классы
>в с++? Желательно на русском. И еще, если так просто можно
>все решить на с++, зачем применяют С?

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



"возврат строки"
Отправлено Ghecko , 28-Июл-05 11:51 
>По поводу Segmentation fault - это наверняка трабла с указателями.
>
>По поводу слияния строк - а вы уверены, что надо Вам именно
>это? Если реч идет о многострочных командах, вроде как в Си,
>то говорить лучше о слиянии команд. А вообще вот как можно
>слить две строки:
>
>char* str1 = "bla-bla-bla\n";
>char* str2 = "mla-mla-mla\n";
>
>char* cat_string( char* s1, char* s2 )
>{
>   char* str = NULL;
>   int len;
>
>   // Вычислим необходимый размер памяти
>   len = strlen(s1);
>   len = len + strlen(s2) + 1;
>
>   str = malloc(len);
>   if( str )
>   {
>      // Это довольно опасный код. Если
>есть малейшая возможность,
>      // что во время вызова функции
>длина строки может увеличиться,
>      // следует использовать strncpy и strncat.
>
>      strcpy( str, s1 );
>      strcat( str, s2 );
>   }
>
>   return str;
>}
>
>А вообще, почему бы не считать файл одним куском, а не построчно?
>Тогда все, что надо - это выполнить разделение по разделителям команд.
>Можно потом загнать указатели на эти команды например в связанный список,
>или в массив, и потом работать с ним дальше.
Я бы маленькие поправки внес:
char* str1 = "bla-bla-bla\n";
char* str2 = "mla-mla-mla\n";

char* cat_string( char* s1, char* s2 )
{
   char* str = NULL;
   int len;

   // Вычислим необходимый размер памяти
   len = strlen(s1) + strlen(s2) + 1; /* Смысла писать в 2 строки не вижу */

   if(str = malloc(len) != NULL) /* так мне кажется более красиво просто */
   {
      // Это довольно опасный код. Если есть малейшая возможность,
      // что во время вызова функции длина строки может увеличиться,
      // следует использовать strncpy и strncat.
      strcpy( str, s1 );
      strcat( str, s2 );
   }

   return str;
}


"возврат строки"
Отправлено sas , 28-Июл-05 12:12 
>
>   if(str = malloc(len) != NULL) /* так мне кажется

Error:  should be if ( (str=malloc(len)) != NULL )

or

just

if ( (str=malloc(len)) ) {...

>более красиво просто */
>   {
>      // Это довольно опасный код. Если
>есть малейшая возможность,
>      // что во время вызова функции
>длина строки может увеличиться,
>      // следует использовать strncpy и strncat.
>

I know this is not your comment, but I cannot be silent :)

Absolutely wrong comment. In the single threaded environment data cannot be changed and strcpy will work fine. In multithreaded environment one should use mutex for example to avoid dirty reads and overwrites.


strncpy & company should be used if you have some buffer of the fixed lenghth and do not want to overwrite it:

char buf[ BUFSZ ];

strncpy( buf, str, BUFSZ-1 );
buf[ BUFSZ -1 ] = '\0';


>      strcpy( str, s1 );
>      strcat( str, s2 );
>   }
>
>   return str;
>}
>



"возврат строки"
Отправлено dimus , 04-Авг-05 11:11 

>Absolutely wrong comment.
Да нет, не wrong

>In the single threaded environment data cannot be changed
>and strcpy will work fine.
Согласен

>In multithreaded environment one should use
>mutex for example to avoid dirty reads and overwrites.
Не совсем согласен с вашим утверждением. Приведите пример исходного кода, плиз.

>strncpy & company should be used if you have some buffer of
>the fixed lenghth and do not want to overwrite it:
МОЕ МНЕНИЕ - лучше всегда использовать подобные функции, и вообще забыть о существовании strcpy.



"возврат строки"
Отправлено dimus , 04-Авг-05 11:31 
Хочу добавить пояснение к своему несогласию.
Утверждение sas насчет мьютексов верно для многопоточных приложений - желающие могут почитать man pthread_mutex_init - однако данные в некоторых случаях могут меняться не только другими потоками. Если рассмотреть случай, когда данные находятся в разделяемой памяти, или, что еще хуже, в буфере какого-то устройства, становится понятно, что тут просто так не отделаешься.
МОЕ МНЕНИЕ: лучше подстраховаться, тем более, что накладные затраты на вызов функции с проверкой длины лишь немногим больше, чем на функцию без такой проверки. Как говорится, береженого Бог бережет.

"возврат строки"
Отправлено sas , 04-Авг-05 17:15 
>Хочу добавить пояснение к своему несогласию.
>Утверждение sas насчет мьютексов верно для многопоточных приложений - желающие могут почитать
>man pthread_mutex_init - однако данные в некоторых случаях могут меняться не
>только другими потоками. Если рассмотреть случай, когда данные находятся в разделяемой
>памяти, или, что еще хуже, в буфере какого-то устройства, становится понятно,
>что тут просто так не отделаешься.
>МОЕ МНЕНИЕ: лучше подстраховаться, тем более, что накладные затраты на вызов функции
>с проверкой длины лишь немногим больше, чем на функцию без такой
>проверки. Как говорится, береженого Бог бережет.

Sorry for english, but this laptop does not have russian characters on the keyboard and i do not      remember layout.

1. If there is a resource which can be changed from different threads or processes or ... you need to use some kind of synchronization (mutexes, semaphores etc).

2. Since you allocated exact memory for particular operation it is possible and better/faster to use strcpy/memcpy etc. Moreover your comment stated that if data could be changed on the fly then strncpy ("n" family for the future) will save you. This is wrong from conceptual point of view.

3. I already mentioned when it is neccessary to use "n" family functions in my previous post.

<qoute>
char buf[ BUFSZ ];

strncpy( buf, str, BUFSZ-1 );
buf[ BUFSZ -1 ] = '\0';
</quote>

Only when you have buffer which should be protected from overwriting and overreading (in case of strncpy remember of the '\0')

Thanks and good luck
--- sas


"возврат строки"
Отправлено knsi , 01-Авг-05 14:58 
Функция не может вернуть строку ибо такого типа данных нет в с, но можно сделать так,

struct sString
{
char str[512];
}

//Пример функции
sString func1()
{
...
sString temp;
...
return temp;
}

//пример использования
void func2()
{
printf(((char *)&func1());
}
еще можно с переопределениями операторов, как это сделано в CString, но будет только в c++ работать