LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 06-07-2012, 03:01 AM   #1
will.cox
LQ Newbie
 
Registered: Jun 2012
Posts: 7

Rep: Reputation: Disabled
function that return a string problem


Hi All, I'm a c++ beginner. I get this code working just fine :
int main ()
{
time_t now = time(0);
struct tm tstruct;
char buf[11];
tstruct = *localtime(&now);
strftime(buf,sizeof(buf),"%Y-%m-%d", &tstruct);
printf(buf);
return 0;
} //result 2012-06-07

I need to called it several times so I turned it to function like this :

char GetDate()
{
time_t now = time(0);
struct tm tstruct;
char buf[11];
tstruct = *localtime(&now);
strftime(buf,sizeof(buf),"%Y-%m-%d", &tstruct);
return buf;
}
int main()
{
printf(GetDate()); // This is the final goal
return 0;
}

can't manage it to work. Also tried with std::string and ostringstream with no luck. It's obviously my lack of knowledge about data types and handling in c++. What is the right codes to obtain string output from a function? Thanks in advance.
 
Old 06-07-2012, 03:08 AM   #2
pan64
LQ Guru
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 9,874

Rep: Reputation: 2908Reputation: 2908Reputation: 2908Reputation: 2908Reputation: 2908Reputation: 2908Reputation: 2908Reputation: 2908Reputation: 2908Reputation: 2908Reputation: 2908
char GetDate() will return a single char. Probably you want: char *GetDate(), but there are other problems as well:
buf is visible only inside the function GetDate, so return buf may cause a segmentation fault in main. You would better use global buffer instead of a local one.
 
Old 06-07-2012, 05:18 AM   #3
will.cox
LQ Newbie
 
Registered: Jun 2012
Posts: 7

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by pan64 View Post
char GetDate() will return a single char. Probably you want: char *GetDate(), but there are other problems as well:
buf is visible only inside the function GetDate, so return buf may cause a segmentation fault in main. You would better use global buffer instead of a local one.
Thanks for quick reply. So I did it as you told

char buf[11];

char *GetDate()
{
time_t now = time(0);
struct tm tstruct;
tstruct = *localtime(&now);
strftime(buf,sizeof(buf),"%Y-%m-%d", &tstruct);
}
int main()
{
printf(GetDate());
}

segmentation fault still occured even using a global var.
Could you please show me your codes to get the line printf(GetDate()); working, if you dont mind. Thanks
 
Old 06-07-2012, 05:46 AM   #4
chrism01
LQ Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Centos 6.9, Centos 7.3
Posts: 17,417

Rep: Reputation: 2397Reputation: 2397Reputation: 2397Reputation: 2397Reputation: 2397Reputation: 2397Reputation: 2397Reputation: 2397Reputation: 2397Reputation: 2397Reputation: 2397
You are printf'ing the return value from the fn ... think about what that is in this version ...
http://linux.die.net/man/3/printf
 
1 members found this post helpful.
Old 06-07-2012, 05:47 AM   #5
pan64
LQ Guru
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 9,874

Rep: Reputation: 2908Reputation: 2908Reputation: 2908Reputation: 2908Reputation: 2908Reputation: 2908Reputation: 2908Reputation: 2908Reputation: 2908Reputation: 2908Reputation: 2908
try bigger buffer and try to debug your code to find out where the segfault occurred.
also you can try to insert printf ("Entering GetDate\n"); printf ("Exiting GetDate\n"); printf("before localtime"), "before strtime".... instead of debugging to find out where is the error. You can write:
Code:
main () {
char *r = GetDate();
printf(r);
}
and also with global buffer you do not need to return anything from GetDate, you just need to print the content of this buffer.

Actually there is no return value set in your GetDate, so printf(GetDate()) will fail. Have you got a compile message? You should use -Wall and take care about warnings also (there should be a message about this missing return value).
 
1 members found this post helpful.
Old 06-07-2012, 06:42 AM   #6
will.cox
LQ Newbie
 
Registered: Jun 2012
Posts: 7

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by pan64 View Post
try bigger buffer and try to debug your code to find out where the segfault occurred.
also you can try to insert printf ("Entering GetDate\n"); printf ("Exiting GetDate\n"); printf("before localtime"), "before strtime".... instead of debugging to find out where is the error.
I always did that trick too. Actually I cant get it clean compiled.

[QUOTE=pan64;4697683]You can write:
Code:
main () {
char *r = GetDate();
printf(r);
}
This code compiled ok but still generated segmentation fault error;


Quote:
Originally Posted by pan64 View Post
and also with global buffer you do not need to return anything from GetDate, you just need to print the content of this buffer.

Actually there is no return value set in your GetDate, so printf(GetDate()) will fail. Have you got a compile message? You should use -Wall and take care about warnings also (there should be a message about this missing return value).
Thanks a lot, I just need to print the buffer and I always check the compiler's messages.
Code:
char    buf[11];

char *GetDate()
{
  time_t     now = time(0);
  struct tm  tstruct;
  tstruct = *localtime(&now);
  strftime(buf,sizeof(buf),"%Y-%m-%d", &tstruct);
}
int main()
{
  GetDate();
  printf(buf);
}
But Im still curious about return value. I'll try it again.
@chrism01 : Thanks for the link. just what I need

Thanks all
 
Old 06-07-2012, 07:09 AM   #7
pan64
LQ Guru
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 9,874

Rep: Reputation: 2908Reputation: 2908Reputation: 2908Reputation: 2908Reputation: 2908Reputation: 2908Reputation: 2908Reputation: 2908Reputation: 2908Reputation: 2908Reputation: 2908
You do not need return value at all, you can simply write: void GetDate() because the result is stored in buf. Otherwise what do you want to return?
If you want to return the result (instead of using a global) you need to malloc storage area and return the pointer to that. And also you need to free that memory after printf.












_____________________________________
If someone helps you, or you approve of what's posted, click the "Add to Reputation" button, on the left of the post.
Happy with solution ... mark as SOLVED
(located in the "thread tools")
 
Old 06-07-2012, 03:06 PM   #8
colucix
LQ Guru
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,509

Rep: Reputation: 1978Reputation: 1978Reputation: 1978Reputation: 1978Reputation: 1978Reputation: 1978Reputation: 1978Reputation: 1978Reputation: 1978Reputation: 1978Reputation: 1978
Moved: This thread is more suitable in Programming and has been moved accordingly to help your thread/question get the exposure it deserves.
 
Old 06-07-2012, 05:06 PM   #9
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 946Reputation: 946Reputation: 946Reputation: 946Reputation: 946Reputation: 946Reputation: 946Reputation: 946
A non-re-entrant version of GetDate() function can be written as
Code:
const char *localdate(time_t when)
{
    static char  datebuf[16];
    struct tm   *when_tm;

    when_tm = localtime(&when);
    if (!when_tm)
        return NULL;

    if (strftime(datebuf, sizeof datebuf, "%Y-%m-%d", when_tm) >= sizeof datebuf)
        return NULL;

    return (const char *)datebuf;
}
Because datebuf is marked static, it exists in the data segment instead of stack; it always exists, but is accessible only within the function itself. It is basically a global variable, but only known to the function body.

You can use the function for example thus:
Code:
int main(void)
{
    printf("Today is %s.\n", localdate(time(NULL)));
    return 0;
}
You will want to supply the timestamp (time(NULL)) to the function. If you ever happen to use some date/time function twice, you want to obtain the time once, and use the same value everywhere; otherwise you may see a date change between the two uses. It really does happen, you know.

Each call to localdate() will overwrite the previous value. This means it is not re-entrant; if you use threads, two threads calling it at the same time will get a garbled value.

There are two options to make functions like this re-entrant: Either by letting the caller specify the buffer:
Code:
char *localdate_r(time_t when, char *buffer, size_t size)
{
    struct tm  when_tm;

    if (&when_tm != localtime_r(&when, &when_tm))
        return NULL;

    if (strftime(buffer, size, "%Y-%m-%d", &when_tm) >= size)
        return NULL;

    return buffer;
}

int main(void)
{
    char buffer[16];

    printf("Today is %s.\n", localdate_r(time(NULL), (char *)buffer, sizeof buffer));
    return 0;
}
Or, by allocating the buffer dynamically:
Code:
char *localdate_r(time_t when, char **bufptr, size_t *sizeptr)
{
    struct tm    when_tm;
    size_t       size;
    char        *buffer;

    if (&when_tm != localtime_r(&when, &when_tm))
        return NULL;

    if (!bufptr || !*bufptr) {
        if (sizeptr && *sizeptr > 11)
            size = *sizeptr;
        else
            size = 12;

        buffer = malloc(size);
        if (!buffer)
            return NULL;

    } else
    if (sizeptr && *sizeptr > 11) {
        buffer = *bufptr;
        size = *sizeptr;
    } else {
        size = 12;
        buffer = realloc(*bufptr, size);
        if (!buffer)
            return NULL;
    }

    if (bufptr)
        *bufptr = buffer;
    if (sizeptr)
        *sizeptr = size;

    if (strftime(buffer, size, "%Y-%m-%d", &when_tm) >= size)
        return NULL;

    return buffer;
}

int main(void)
{
    char   *buffer = NULL;  /* Must be initialized to NULL */
    size_t  length = 0;     /* Must be initialized to a sane value or zero */

    printf("Today is %s.\n", localdate_r(time(NULL), &buffer, &size));

    /* Discard buffer if used */
    if (buffer)
        free(buffer);
    buffer = NULL;
    length = 0;
    return 0;
}
The first approach is suitable only for single-threaded processes. The second approach is usually the simplest to implement. The last approach is the most flexible, and has been found very useful: compare C99 getline() to the old fgets() for example.

Last edited by Nominal Animal; 06-08-2012 at 08:45 AM. Reason: URL end tags
 
1 members found this post helpful.
Old 06-07-2012, 10:29 PM   #10
will.cox
LQ Newbie
 
Registered: Jun 2012
Posts: 7

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by Nominal Animal View Post
A non-re-entrant version of GetDate() function can be written as
Code:
const char *localdate(time_t when)
{
    static char  datebuf[16];
    struct tm   *when_tm;

    when_tm = localtime(&when);
    if (!when_tm)
        return NULL;

    if (strftime(datebuf, sizeof datebuf, "%Y-%m-%d", when_tm) >= sizeof datebuf)
        return NULL;

    return (const char *)datebuf;
}
Because datebuf is marked static, it exists in the data segment instead of stack; it always exists, but is accessible only within the function itself. It is basically a global variable, but only known to the function body.

You can use the function for example thus:
Code:
int main(void)
{
    printf("Today is %s.\n", localdate(time(NULL)));
    return 0;
}
You will want to supply the timestamp (time(NULL)) to the function. If you ever happen to use some date/time function twice, you want to obtain the time once, and use the same value everywhere; otherwise you may see a date change between the two uses. It really does happen, you know.

Each call to localdate() will overwrite the previous value. This means it is not re-entrant; if you use threads, two threads calling it at the same time will get a garbled value.

There are two options to make functions like this re-entrant: Either by letting the caller specify the buffer:
Code:
char *localdate_r(time_t when, char *buffer, size_t size)
{
    struct tm  when_tm;

    if (&when_tm != localtime_r(&when, &when_tm))
        return NULL;

    if (strftime(buffer, size, "%Y-%m-%d", &when_tm) >= size)
        return NULL;

    return buffer;
}

int main(void)
{
    char buffer[16];

    printf("Today is %s.\n", localdate_r(time(NULL), (char *)buffer, sizeof buffer));
    return 0;
}
Or, by allocating the buffer dynamically:
Code:
char *localdate_r(time_t when, char **bufptr, size_t *sizeptr)
{
    struct tm    when_tm;
    size_t       size;
    char        *buffer;

    if (&when_tm != localtime_r(&when, &when_tm))
        return NULL;

    if (!bufptr || !*bufptr) {
        if (sizeptr && *sizeptr > 11)
            size = *sizeptr;
        else
            size = 12;

        buffer = malloc(size);
        if (!buffer)
            return NULL;

    } else
    if (sizeptr && *sizeptr > 11) {
        buffer = *bufptr;
        size = *sizeptr;
    } else {
        size = 12;
        buffer = realloc(*bufptr, size);
        if (!buffer)
            return NULL;
    }

    if (bufptr)
        *bufptr = buffer;
    if (sizeptr)
        *sizeptr = size;

    if (strftime(buffer, size, "%Y-%m-%d", &when_tm) >= size)
        return NULL;

    return buffer;
}

int main(void)
{
    char   *buffer = NULL;  /* Must be initialized to NULL */
    size_t  length = 0;     /* Must be initialized to a sane value or zero */

    printf("Today is %s.\n", localdate_r(time(NULL), &buffer, &size));

    /* Discard buffer if used */
    if (buffer)
        free(buffer);
    buffer = NULL;
    length = 0;
    return 0;
}
The first approach is suitable only for single-threaded processes. The second approach is usually the simplest to implement. The last approach is the most flexible, and has been found very useful: compare C99 [URL=http://www.kernel.org/doc/man-pages/online/pages/man3/getline.3.html]getline()[/FONT] to the old [URL=http://www.kernel.org/doc/man-pages/online/pages/man3/fgets.3.html]fgets()[/FONT] for example.
Thanks very much to you all. I'd learn alot from this thread and wiped off my curiosity about return value.
Code:
const char *GetDate()
{
    time_t now = time(0);
    static char  buf[11];
    struct tm   *tstruct;
    tstruct = localtime(&now);
    strftime(buf, sizeof buf, "%Y-%m-%d", tstruct);
    return (const char *)buf;
}
int main()
{
  printf(GetDate());
  return 0;
}
Thanks again
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] C++: template function instantiation does not work with string as return value. Why? TITiAN Programming 29 06-27-2010 03:03 AM
problem with return function value in perl shifter Programming 2 02-23-2010 11:04 PM
Problem in checking function return value viveksnv Programming 3 10-02-2008 02:17 AM
sh script: problem with return value in function jhwilliams Linux - Software 1 06-20-2007 12:47 PM
can a function return a string? hubabuba Programming 13 03-06-2005 03:51 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 04:48 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration