473,779 Members | 2,016 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

return a string

Hello,

How to I do to return a string as a result of a function.
I wrote the following function:

char prt_tralha(int num)
{
int i;
char tralha[num];

tralha = "#";
for( i = 0; i < num-1; i++ )
strcpy(tralha, strcat(tralha," #"));

return tralha;
}

And I really like to use it, thus:

int main()
{
printf("%s \n", prt_tralha(5));

return 0;
}

But when I compile it, gcc shows this message:

tmp.c: In function `prt_tralha':
tmp.c:16: error: incompatible types in assignment
tmp.c:20: warning: return makes integer from pointer without a cast
tmp.c:20: warning: function returns address of local variable

Thanks,

Nascimento
Nov 14 '05
23 3614
Nascimento wrote on 29/04/05 :
How to I do to return a string as a result of a function.
I wrote the following function:

char prt_tralha(int num)
{
int i;
char tralha[num];

tralha = "#";
This is not going to happen. You can't change the value of an array
that way. You want strcpy().
for( i = 0; i < num-1; i++ )
strcpy(tralha, strcat(tralha," #"));
Note that this is dangerous. The order of execution of the parameters
is defined by the implementation. BTW, chances are that strcat() is
called before strcpy(). Additionally, strcpy() only works with non
overlapping strings. Your construction doesn't guarantee that.

(To the gurus : [C99] shouldn't the 'restrict' keyword used here by the
compiler to generate some warning ?)

As a rule of thumb, don't use functions as a parameter to another
function. In mosts cases, it hurts...

Finally, it seems to be a very complicated way of filling a string...

return tralha;
Returning the address of a local variable is, in most cases, a
nonsense.
}

And I really like to use it, thus:

int main()
{
printf("%s \n", prt_tralha(5));

return 0;
}

But when I compile it, gcc shows this message:

tmp.c: In function `prt_tralha':
tmp.c:16: error: incompatible types in assignment
Ok, see above.
tmp.c:20: warning: return makes integer from pointer without a cast
Ok, I missed this one. Your function returns a char. You probably want
a char *.
tmp.c:20: warning: function returns address of local variable


A common newbie error. The fact is that the last warning *is* the
point. The address returned by a function must be valid after the
function has terminated. Keep in mind that the duration of the local
variables is limited to the bloc where it was defined. Meaning that
outside of the bloc, it doesn't longer exist. Hence, its address is no
longer valid. Returning its address is technically possible (say for
debug purpose), but dereferencing it out of the function invokes an
undefined behaviour.

There are 3 ways to correct your code.

- The worst : qualifying the array of char with 'static'. This
deceiving solution looks simple and easy, but it can generate other
more subtle bugs preventing from using the function in some cases
(nested calls, mutual calls, recursion, preemptive threads etc.)

- Passing the address of an array. The caller is the game master. He
defines the array, and ask the function to act on it through (address,
size) parameters. (see fgets() for example)

- The function is allocating the array. The caller gives enough
information so that the function is able to compute the requested size
for the array. That done, it allocates the array (malloc()), process
it, and returns its address. The duration of the allocated bloc is
under the control of the program. It ends with an appropriate free().

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"Clearly your code does not meet the original spec."
"You are sentenced to 30 lashes with a wet noodle."
-- Jerry Coffin in a.l.c.c++

Nov 14 '05 #11
iru_muzgo wrote on 29/04/05 :
void
ptr_tralha(char *s)
{
while (*s != '\0') /* while the contents of s are different
* from NULL */
NULL is off-topic here. You meant 0. The probel, is what makes you
think that there is a 0 in the area pointed by s ? And even if ther is
one, what makes you think that it is at the right position ?

This is a serious design problem...
*s++ = '#'; /* s = '#' . increment s */
}

int
main(void)
{
char s[5];
As you can see, the contain of is undetermined.
ptr_tralha(s);
hence, the behaviour is undefined. Anything could happen...
puts(s);
return 0;
}


--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"Mal nommer les choses c'est ajouter du malheur au
monde." -- Albert Camus.

Nov 14 '05 #12
(supersedes <mn************ ***********@YOU RBRAnoos.fr>)

iru_muzgo wrote on 29/04/05 :
void
ptr_tralha(char *s)
{
while (*s != '\0') /* while the contents of s are different
* from NULL */
NULL is off-topic here. You meant 0. The probem is, what makes you
think that there is a 0 in the area pointed by s ? And even if there is
one, what makes you think that it is at the correct position ?

This is a serious design problem...
*s++ = '#'; /* s = '#' . increment s */
}

int
main(void)
{
char s[5];
As you can see, the contain of is undetermined.
ptr_tralha(s);
hence, the behaviour is undefined. Anything could happen...
puts(s);
return 0;
}


--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"Clearly your code does not meet the original spec."
"You are sentenced to 30 lashes with a wet noodle."
-- Jerry Coffin in a.l.c.c++

Nov 14 '05 #13
"Emmanuel Delahaye" <em***@YOURBRAn oos.fr> writes:
(supersedes <mn************ ***********@YOU RBRAnoos.fr>)

iru_muzgo wrote on 29/04/05 :
void
ptr_tralha(char *s)
{
while (*s != '\0') /* while the contents of s are
different * from NULL */
NULL is off-topic here.


NULL isn't off-topic, it's merely wrong.
You meant 0.


Yes, or '\0'.

[snip]

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #14
"Emmanuel Delahaye" <em***@YOURBRAn oos.fr> writes:
Nascimento wrote on 29/04/05 : [...]
for( i = 0; i < num-1; i++ )
strcpy(tralha, strcat(tralha," #"));


Note that this is dangerous. The order of execution of the parameters
is defined by the implementation. BTW, chances are that strcat() is
called before strcpy().


Actually, I think it's guaranteed that strcat() will be called before
strcpy(). The order of evaluation of the arguments is unspecified,
but the function can't be called until all its arguments have been
evaluated; there's a sequence point between the evaluation of the
arguments and the actual call. It's bad code, but not for that
reason.
Additionally, strcpy() only works with non
overlapping strings. Your construction doesn't guarantee that.
In fact, it guarantees that the strings do overlap.

[...]
As a rule of thumb, don't use functions as a parameter to another
function. In mosts cases, it hurts...


I don't agree. It can be dangerous if you're dealing with pointers to
the same chunk of memory, but there's nothing wrong with using
function results as arguments in general.

printf("Length of string is %d\n", (int)strlen(s)) ;

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #15
On 29 Apr 2005 14:04:10 -0700,
Nascimento <un************ @gmail.com> wrote
in Msg. <cb************ **************@ posting.google. com>
Hello,

How to I do to return a string as a result of a function.


All the answers you ever needed were already given. Here's a summary
(which I only post to reflect ,y own knowledge on the subject matter --
this is an invitation to the gurus to tear it apart).

1. Declare a static array of char in your function and return it (as the
asctime() function does). Simple but very limited.
Problem: printf("%s %s\n", foo(a), foo(b)); prints the same thing twice.

2. malloc() memory for the string inside your function and return pointer
to it. Simple but ugly because you have to remember to free the memory
later. Problem: printf("%s\n", foo(a)); is a memory leak. Also if the
function is tucked away in some library you have to make an effort to
provide a way to use an alternative allocation function.

3. Pass an already allocated buffer and its size to your function. Most
flexible but awkward, especially if all you want is to print some quantity
in a special format. Problem: Function must check buffer overflow and
signal error when buffer is too small.

All three methods have their respective drawbacks, so you must select the
one best suited to your purpose.

--Daniel
Nov 14 '05 #16
On Fri, 29 Apr 2005 23:56:05 GMT, Keith Thompson <ks***@mib.or g>
wrote:
Alan Balmer <al******@att.n et> writes:
On 29 Apr 2005 14:04:10 -0700, un************@ gmail.com (Nascimento)
wrote:[...]
{
int i;
char tralha[num];


You can't declare a variable size array.


Yes you can, if you have a C99 compiler or a pre-C99 compiler that
supports the feature. (The form of the diagnostics implies that he's
probably using gcc, which does support VLAs.)

Quite right. I've been in C89 mode too long (since somewhat before
1989 :-)
I covered the portability issues in my previous followup.


--
Al Balmer
Balmer Consulting
re************* ***********@att .net
Nov 14 '05 #17
Daniel Haude <ha***@kir.phys net.uni-hamburg.de> writes:
On 29 Apr 2005 14:04:10 -0700,
Nascimento <un************ @gmail.com> wrote
in Msg. <cb************ **************@ posting.google. com>
Hello,

How to I do to return a string as a result of a function.
All the answers you ever needed were already given. Here's a summary
(which I only post to reflect ,y own knowledge on the subject matter --
this is an invitation to the gurus to tear it apart).


Good answers, but I have a couple of quibbles.
1. Declare a static array of char in your function and return it (as the
asctime() function does). Simple but very limited.
Problem: printf("%s %s\n", foo(a), foo(b)); prints the same thing twice.
I've used a variant of this. I had a function returning char* that
declared two local static variables, an array of arrays of char (for
the results), and an index. On each call, it would cycle the index
through the array and use a fresh sub-array for the result. This
allowed, say, half a dozen distinct calls to be active simultaneously.
It's not pretty, and it still forces you to decide in advance both how
big the result can be and how many distinct results you need, but it's
a bit more flexible than using a single static array.
2. malloc() memory for the string inside your function and return pointer
to it. Simple but ugly because you have to remember to free the memory
later. Problem: printf("%s\n", foo(a)); is a memory leak. Also if the
function is tucked away in some library you have to make an effort to
provide a way to use an alternative allocation function.
Why does tucking it away in some library imply that you need to
support an alternative allocation function? There may be (or may not)
an issue for functions that are part of the standard library <OT>and
kernel code may not be able to use malloc()</OT>, but in most cases
there's no reason a library function can't use malloc().
3. Pass an already allocated buffer and its size to your function. Most
flexible but awkward, especially if all you want is to print some quantity
in a special format. Problem: Function must check buffer overflow and
signal error when buffer is too small.
Actually, it seems to me that #2 is the most flexible technique. It
allows the function itself to determine exactly how much memory it
needs, and imposes minimal complexity on the call (apart from the need
to free the allocated memory).
All three methods have their respective drawbacks, so you must select the
one best suited to your purpose.


Yes.

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #18
Keith Thompson wrote:

Daniel Haude <ha***@kir.phys net.uni-hamburg.de> writes:
On 29 Apr 2005 14:04:10 -0700,
Nascimento <un************ @gmail.com> wrote
in Msg. <cb************ **************@ posting.google. com>
Hello,

How to I do to return a string as a result of a function.


All the answers you ever needed were already given. Here's a summary
(which I only post to reflect ,y own knowledge on the subject matter --
this is an invitation to the gurus to tear it apart).


Good answers, but I have a couple of quibbles.
1. Declare a static array of char in your
function and return it (as the
asctime() function does). Simple but very limited.
Problem: printf("%s %s\n", foo(a), foo(b));
prints the same thing twice.


I've used a variant of this. I had a function returning char* that
declared two local static variables, an array of arrays of char (for
the results), and an index. On each call, it would cycle the index
through the array and use a fresh sub-array for the result. This
allowed, say, half a dozen distinct calls to be active simultaneously.
It's not pretty, and it still forces you to decide in advance both how
big the result can be and how many distinct results you need, but it's
a bit more flexible than using a single static array.
2. malloc() memory for the string inside your function
and return pointer
to it. Simple but ugly because you have to remember
to free the memory
later. Problem: printf("%s\n", foo(a));
is a memory leak. Also if the
function is tucked away in some library you have
to make an effort to
provide a way to use an alternative allocation function.


Why does tucking it away in some library imply that you need to
support an alternative allocation function? There may be (or may not)
an issue for functions that are part of the standard library <OT>and
kernel code may not be able to use malloc()</OT>, but in most cases
there's no reason a library function can't use malloc().
3. Pass an already allocated buffer and its size to your function.
Most
flexible but awkward,
especially if all you want is to print some quantity
in a special format.
Problem: Function must check buffer overflow and
signal error when buffer is too small.


Actually, it seems to me that #2 is the most flexible technique. It
allows the function itself to determine exactly how much memory it
needs, and imposes minimal complexity on the call (apart from the need
to free the allocated memory).


I'm partial to number 3.
Actually the called function doesn't have to do any checking or
signaling as long the programmer considers the onus to
be on the calling function to supply a buffer large enough.
With number 3 you can use any kind of object,
automatic, static or allocated.
If an allocated object is used, then it is allocated and freed
in the same function, which is good.

#include <limits.h>
#include <stddef.h>
#include <stdio.h>

#define E_TYPE unsigned char
#define P_TYPE unsigned
#define STRING " %s = 0x%x\n"
#define INITIAL 0
#define FINAL 0xf
#define OFFSET (sizeof(e_type) * CHAR_BIT - 4)
#define INC(E) (++(E))

typedef E_TYPE e_type;
typedef P_TYPE p_type;

void bitstr(char *str, const void *obj, size_t n);

int main(void)
{
e_type e;
char ebits[CHAR_BIT * sizeof e + 1];

puts("\n/* BEGIN output from bitstr.c */\n");
for (e = INITIAL; FINAL >= e; INC(e)) {
bitstr(ebits, &e, sizeof e);
printf(STRING, OFFSET + ebits, (p_type)e);
}
puts("\n/* END output from bitstr.c */");
return 0;
}

void bitstr(char *str, const void *obj, size_t n)
{
unsigned mask;
const unsigned char *byte = obj;

while (n-- != 0) {
mask = ((unsigned char)-1 >> 1) + 1;
do {
*str++ = (char)(mask & byte[n] ? '1' : '0');
mask >>= 1;
} while (mask != 0);
}
*str = '\0';
}

--
pete
Nov 14 '05 #19
Keith Thompson wrote:
.... snip ...
I've used a variant of this. I had a function returning char* that
declared two local static variables, an array of arrays of char (for
the results), and an index. On each call, it would cycle the index
through the array and use a fresh sub-array for the result. This
allowed, say, half a dozen distinct calls to be active simultaneously.
It's not pretty, and it still forces you to decide in advance both how
big the result can be and how many distinct results you need, but it's
a bit more flexible than using a single static array.


I have used a system that looked roughly like this:

#define BUFSIZE 20
#define NBUFS 9 /* or whatever */

struct abuf {struct abuf *next; char buf[BUFSIZE]};

static struct abuf *initbuffs(void )
{
struct abuf *nxt, *first;
int i;

first = nxt = malloc(sizeof *nxt); /* No error testing */
first->buf = "";
for (i = NBUFS; i; i--) {
nxt->next = malloc(sizeof *(nxt->next));
nxt->buf = "";
}
return (nxt->next = first); /* forming ring buffer */
} /* initbuffs */

/* ------------------- */

char *getbuf(void)
{
static struct abuf *curbuff;

if (!curbuff) curbuff = initbuffs();
curbuff = curbuff->next;
return curbuff->buf;
} /* getbuf */

which does all its allocating on the very first call. Nothing
outside this code need know how it is built.

--
"If you want to post a followup via groups.google.c om, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
Nov 14 '05 #20

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
4529
by: Phil Powell | last post by:
My first time working with a PHP class, and after 6 hours of working out the kinks I am unable to return a value from the class, so now I appeal to the general audience what on earth did I do wrong this time? This is the code the retrieves the values: if (($hasRegistered || $hasPreRegistered) && !empty($uplinenumber)) { // CHECK TO SEE IF UPLINE NUMBER IS A VALID NUMBER $regNumberGenerator = new RegNumberGenerator($uplinenumber,...
12
4132
by: Jose Fernandez | last post by:
Hello. I'm building a web service and I get this error. NEWS.News.CoverNews(string)': not all code paths return a value This is the WebMethod public SqlDataReader CoverNews(string Sport) {
12
3799
by: Michael Maes | last post by:
Hello, I have a BaseClass and many Classes which all inherit (directly) from the BaseClass. One of the functions in the BaseClass is to (de)serialize the (inherited) Class to/from disk. 1. The Deserialization goes like: #Region " Load "
7
1808
by: nafri | last post by:
hello all, I want to create a function that returns the first element of the Array that is input to it. However, the Input Array can be an Array of points, double, or anyother type, which means the return type of the function depends on the type of the objects the Input array holds. I can have the return type as Object, but it has problems like late binding and more importantly the client has to always Cast it. For example. class...
16
4929
by: Dany | last post by:
Our web service was working fine until we installed .net Framework 1.1 service pack 1. Uninstalling SP1 is not an option because our largest customer says service packs marked as "critical" by Microsoft must be installed on their servers. Now german Umlaute (ä, ü, ö) and quotes are returned incorrectly in SOAP fault responses. This can be easily verified: Implement the following in a web service method (just raises a SOAPException with a...
9
3220
by: MSDNAndi | last post by:
Hi, I have a set of simple webservices calls that worked fine using .NET Framework 1.0. I am calling a Java/Apache based webservices, the calling side is not able to supply a proper WSDL. What it does is to call a webservice with two parameters, one being a integer, the other one being a "String" which contains XML (not the best practice, however that is the target interface and we cannot change that).
18
4064
by: Pedro Pinto | last post by:
Hi there once more........ Instead of showing all the code my problem is simple. I've tried to create this function: char temp(char *string){ alterString(string); return string;
2
2478
by: utab | last post by:
Dear all, I tried sth easy(actually this was an exercise) but I tried to use the standard lib. heavily for this problem(as far as I can). There was one point I could not figure out. The problem is : ../a.out 1.3+3.2+.1+40/3*8/7-4*5-32 The program will parse the argument and find the result of the above expression. I have two versions(the 2nd is working , not perfect ;-}),
6
2410
KoreyAusTex
by: KoreyAusTex | last post by:
If anyone can help me figure out the what the missing return statements are, I think it might be the fact that I need to add a return false in the getValue()? import java.util.*; public class Card { // instance variables //suits private int suit; private int spades;
14
2037
by: =?Utf-8?B?QmVu?= | last post by:
Hi all, I'm trying to understand the concept of returning functions from the enclosing functions. This idea is new to me and I don't understand when and why I would need to use it. Can someone please shed some light on this subject? Thanks a lot, Ben
0
9474
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10306
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9930
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7485
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6724
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5373
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
4037
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3632
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2869
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.