By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
454,605 Members | 1,391 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 454,605 IT Pros & Developers. It's quick & easy.

A function returning string or pointer

P: n/a
Hello to all,

as a result from my previous post I'm busy with splitting code into
functions.
The one problem ( out of many ) I encounter is how to properly
use/code a function which returns either array of characters(string) or
a pointer to this array.

I read some articles, some other posts and come to this solution:
char *read_name(void){
static char item_name[11];
char *p_item_name;

printf("Enter the description: ");
if (fgets(item_name, sizeof(item_name), stdin) != NULL){
/* if the input contains a new line */
if (( p_item_name = strchr(item_name, '\n')) != NULL ){
*p_item_name = '\0'; /* get rid of new line */
}
else {
while(getchar() != '\n'){ /* get rid of the rest in the buffer */
;
}
}
}
return item_name; /* return string in the form of character array */
}

Are there other solutions? What are the pros and cons using
array/pointer?

svata

Nov 13 '06 #1
Share this Question
Share on Google+
18 Replies


P: n/a
Hello Svata,
as a result from my previous post I'm busy with splitting code into
functions.
The one problem ( out of many ) I encounter is how to properly
use/code a function which returns either array of characters(string) or
a pointer to this array.

I read some articles, some other posts and come to this solution:
<snip>
Are there other solutions? What are the pros and cons using
array/pointer?
Your code is fine, especially if the item_name read should be truncated
to 10 characters (this limit could be defined as constant, BTW, to make
code change easier).

Cheers,
Loic.

Nov 13 '06 #2

P: n/a
svata wrote:
Hello to all,

as a result from my previous post I'm busy with splitting code into
functions.
The one problem ( out of many ) I encounter is how to properly
use/code a function which returns either array of characters(string) or
a pointer to this array.
You /must not/ return a pointer to an array which is a local
non-static variable of the function.
I read some articles, some other posts and come to this solution:

char *read_name(void){
static char item_name[11];
(fx:snip)
return item_name; /* return string in the form of character array */
}
So you /must not/ do this. The variable `item_name` evaporates when
the function returns, so the pointer to it isn't pointing anywhere
and any use of it gets you undefined behaviour -- which is a Very
Bad Thing.

You must return a pointer to store which will outlive the function
call: for example:

* a static array, usually a bad idea because different uses of the
function will share that array.

* mallocated store (which the using code will have to free)

* store passed in as an argument (so it's the caller's problem)

* mix as desired (carefully)

--
Chris "hantwig efferko VOOM!" Dollin
Meaning precedes definition.

Nov 13 '06 #3

P: n/a
lo******@gmx.net wrote:
Hello Svata,
>as a result from my previous post I'm busy with splitting code into
functions.
The one problem ( out of many ) I encounter is how to properly
use/code a function which returns either array of characters(string) or
a pointer to this array.

I read some articles, some other posts and come to this solution:

<snip>
>Are there other solutions? What are the pros and cons using
array/pointer?

Your code is fine,
Not so, as my reply to svata explains.

--
Chris "hantwig efferko VOOM!" Dollin
"People are part of the design. It's dangerous to forget that." /Star Cops/

Nov 13 '06 #4

P: n/a
Chris Dollin, the complete idiot, wrote:
svata wrote:
>Hello to all,

as a result from my previous post I'm busy with splitting code into
functions.
The one problem ( out of many ) I encounter is how to properly
use/code a function which returns either array of characters(string) or
a pointer to this array.

You /must not/ return a pointer to an array which is a local
non-static variable of the function.
>I read some articles, some other posts and come to this solution:

char *read_name(void){
static char item_name[11];

(fx:snip)
> return item_name; /* return string in the form of character array */
}

So you /must not/ do this.
OK, OK, I'm blind. I read it three times and didn't see `static`.
As soon as I posted, I saw it.

Sorry sorry sorry. Egg egg egg. Time to go hone.
You must return a pointer to store which will outlive the function
call: for example:

* a static array, usually a bad idea because different uses of the
function will share that array.
So you were OK to do what you did, except there's a gotcha you
need to beware of.

--
Chris "hantwig efferko VOOM!" Dollin
"Life is full of mysteries. Consider this one of them." Sinclair, /Babylon 5/

Nov 13 '06 #5

P: n/a
"svata" <sv******@centrum.czwrote in message
news:11**********************@h54g2000cwb.googlegr oups.com...
as a result from my previous post I'm busy with splitting code into
functions.
The one problem ( out of many ) I encounter is how to properly
use/code a function which returns either array of characters(string)
or
a pointer to this array.

I read some articles, some other posts and come to this solution:
....
Are there other solutions? What are the pros and cons using
array/pointer?
Returning a pointer to a static buffer is a common technique. However,
that has the problem that your callers need to be aware of that, and
they'll likely need to strdup() the results if they want to call the
function frequently. It also means the function is not reentrant, which
can kill you if you try to call that function from multiple threads,
signal handlers, etc.

malloc()ing a new buffer for each call is also done at times. That
solves the above problems, but it means that the caller needs to know to
free() the strings you return when they're done with them, or they'll
end up with a memory leak.

The last common option is to require the caller to provide a buffer (and
its size!) for you; you just put the string into their buffer. By
requiring the caller to do the malloc(), it makes it easier for them to
see they need to do a free(). Or they might use a local array, if they
know how big to make it.

The question in all cases is what to do if the buffer isn't big enough
for the input. If you _know_ that a certain size will never be
exceeded, you can go with that, but such "knowledge" usually turns out
to be incorrect after several maintenance/release cycles. You'll need
to spend as much time figuring out this problem as you are deciding who
allocates the buffer where.

S

--
Stephen Sprunk "God does not play dice." --Albert Einstein
CCIE #3723 "God is an inveterate gambler, and He throws the
K5SSS dice at every possible opportunity." --Stephen Hawking

--
Posted via a free Usenet account from http://www.teranews.com

Nov 13 '06 #6

P: n/a
svata wrote:
Hello to all,

as a result from my previous post I'm busy with splitting code into
functions.
The one problem ( out of many ) I encounter is how to properly
use/code a function which returns either array of characters(string) or
a pointer to this array.

I read some articles, some other posts and come to this solution:
char *read_name(void){
static char item_name[11];
char *p_item_name;

printf("Enter the description: ");
if (fgets(item_name, sizeof(item_name), stdin) != NULL){
/* if the input contains a new line */
if (( p_item_name = strchr(item_name, '\n')) != NULL ){
*p_item_name = '\0'; /* get rid of new line */
}
else {
while(getchar() != '\n'){ /* get rid of the rest in the buffer */
;
}
}
}
return item_name; /* return string in the form of character array */
}

Are there other solutions? What are the pros and cons using
array/pointer?
Stephen below suggests the caller supplying the buffer
(and length). It is sometimes desirable for the caller
to repeatedly call the function each time receiving as
much of the data as can fit in the buffer.

e.g.

int foo (char *buf, int length)
{
/* copy data_to_be_returned into buf, not exceeding length */
return 0;
}
....
char buf[20];
int length = foo (buf, sizeof buf);
while (length) {
length = foo (buf, sizeof buf);
/* Use the data here */
}

You can also make the called function behave differently
depending on the argument supplied, supplying a NULL pointer
for the buffer would return the length needed (hard to do with
the above example). This has the disadvantage of seriously
confusing the reader, so comment clearly in header, etc.

e.g.

int foo (char *buf)
{
/* process and store data to be returned in a static buffer */
if (!buf) {
return length_of_data_to_be_returned;
} else {
memcpy (buf, data_to_be_returned, length_of_data_to_be_returned);
}
return 0;
}
....
int length = foo (NULL);
char *buf = malloc (length);
if (!buf) {
/* error!!! */
} else {
foo (buf);
}
....
free (buf);
Basically, every solution will have pros and cons, and
it's up to you to choose which is best for the situation.
There is no "one-good-way" that can be applied to all
situations; be thankful that you've got such a variety
of methods available :-)

goose,
hth

Nov 13 '06 #7

P: n/a


svata wrote On 11/13/06 09:44,:
[...]
The one problem ( out of many ) I encounter is how to properly
use/code a function which returns either array of characters(string) or
a pointer to this array.
[...]
Others have addressed your immediate question. I'd like
to draw your attention to two other issues:

printf("Enter the description: ");
if (fgets(item_name, sizeof(item_name), stdin) != NULL){
Question 12.4 in the comp.lang.c Frequently Asked Questions
list http://www.c-faq.com/ explains why you'd be well-advised to
insert fflush(stdout); between these two lines.
/* if the input contains a new line */
if (( p_item_name = strchr(item_name, '\n')) != NULL ){
*p_item_name = '\0'; /* get rid of new line */
}
else {
while(getchar() != '\n'){ /* get rid of the rest in the buffer */
;
}
A good effort, but it overlooks one possibility: What does
getchar() return at end-of-input (or I/O error)? What will
this code do if that happens?

--
Er*********@sun.com

Nov 13 '06 #8

P: n/a
svata wrote:
Hello to all,

as a result from my previous post I'm busy with splitting code into
functions. The one problem ( out of many ) I encounter is how to
properly use/code a function which returns either array of
characters(string) or a pointer to this array.
I prefer making the caller pass in a buffer and a buffer size, and
then the function fills in the buffer and returns the length filled in.
(Or returns a status code and passes the length back via a
pointer parameter, etc.)

This way, the function is not tied to any particular memory
management scheme, and can be called from various places in
your code without having to waste any memory or perform any
acrobatics.

It is also common to allow the function to accept NULL as the
buffer, in which case it will return the size of buffer required, and
then the caller can allocate space if necessary and call the
function again.

Nov 13 '06 #9

P: n/a
"svata" <sv******@centrum.czwrites:
[...]
The one problem ( out of many ) I encounter is how to properly
use/code a function which returns either array of characters(string) or
[...]
Are there other solutions? What are the pros and cons using
array/pointer?
See the comp.lang.c FAQ, <http://www.c-faq.com/>, particularly
questions 7.5a and 7.5b.

--
Keith Thompson (The_Other_Keith) 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 '06 #10

P: n/a
Eric Sosman wrote:
A good effort, but it overlooks one possibility: What does
getchar() return at end-of-input (or I/O error)? What will
this code do if that happens?
It is EOF, am I right?

svata

Nov 14 '06 #11

P: n/a


svata wrote On 11/14/06 05:44,:
Eric Sosman wrote:

> A good effort, but it overlooks one possibility: What does
getchar() return at end-of-input (or I/O error)? What will
this code do if that happens?


It is EOF, am I right?
Yes, that's what getchar() will return. Now, what
will your code do if that happens?

--
Er*********@sun.com

Nov 14 '06 #12

P: n/a
Eric Sosman wrote:
Yes, that's what getchar() will return. Now, what
will your code do if that happens?
So, it should look as follows:

while(getchar() != EOF && getchar() != '\n'){
;
}

One has to check for EOF as well, I suppose.

svata

Nov 14 '06 #13

P: n/a
svata wrote:
Eric Sosman wrote:
> Yes, that's what getchar() will return. Now, what
will your code do if that happens?

So, it should look as follows:

while(getchar() != EOF && getchar() != '\n'){
;
}

One has to check for EOF as well, I suppose.
You realise that code will test two different characters?
(Even if they have the same value ...)

--
Chris "hantwig efferko VOOM!" Dollin
Nit-picking is best done among friends.

Nov 14 '06 #14

P: n/a
svata wrote:
Eric Sosman wrote:
Yes, that's what getchar() will return. Now, what
will your code do if that happens?

So, it should look as follows:

while(getchar() != EOF && getchar() != '\n'){
;
}

One has to check for EOF as well, I suppose.
Don't call getchar() twice. Each call will return a different value.
Also you're discarding both return values. I think you may find the
following code snippet more suited to what you were probably trying to
do.

int c;
....

while((c = getchar()) != EOF) {
if(c != '\n') {
DO_SOMETHING;
}
}

Now a return value of EOF could be caused either by end of file or some
kind of I/O error. Presumably, you'd consider the former to be a normal
condition and the latter as an error of some severity. To find which of
them caused getchar() to return EOF, you might use ferror() and/or
feof(). The former returns non-zero if the stream has encountered an
I/O error, while the latter returns true when end of file has been
reached on the stream. Once you determine that then appropriate action
can be taken. Use clearerr() to reset the stream's end of file and
error indicators.

Nov 14 '06 #15

P: n/a
svata wrote:
Eric Sosman wrote:
> Yes, that's what getchar() will return. Now, what
will your code do if that happens?

So, it should look as follows:

while(getchar() != EOF && getchar() != '\n'){
}

One has to check for EOF as well, I suppose.
This is agonizing. To put it out of its misery:

int flushln(FILE *f) {
int ch;

while ((EOF != (ch = getc(f)) && (ch != '\n')) continue;
return ch;
}

Replace your code with "someint = flushln(stdin);" and decide what
needs doing when (and if) someint becomes EOF.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>

Nov 14 '06 #16

P: n/a
CBFalconer wrote:
This is agonizing. To put it out of its misery:

int flushln(FILE *f) {
int ch;

while ((EOF != (ch = getc(f)) && (ch != '\n')) continue;
return ch;
}
This is correct code, but tricky code. It's a sufficiently common idiom
in C programs that I would expect any programmer to be able to
understand it, along with the even commoner idiom:
while((ch = getc(fp)) != EOF) { ... }

That said, however, in my opinion it is best practise to avoid trying to
put the whole loop contents into the loop condition when it's not needed.

If one wants to write simple, easy to read C, I think one should adhere
to the rule that loop bodies are supposed to make changes to program
state, while (while, for, if) conditions are supposed to make a decision
based on the current program state but not make changes to that state.

Here's another way to write it, which is simpler to read in my opinion:

int flushln(FILE *fp)
{
int ch;

do
{
ch = getc(fp);
}
while(ch != EOF && ch != '\n');

return ch;
}

--
Simon.
Nov 14 '06 #17

P: n/a
Simon Biber wrote:
CBFalconer wrote:
This is agonizing. To put it out of its misery:

int flushln(FILE *f) {
int ch;

while ((EOF != (ch = getc(f)) && (ch != '\n')) continue;
return ch;
}

This is correct code, but tricky code. It's a sufficiently common idiom
in C programs that I would expect any programmer to be able to
understand it, along with the even commoner idiom:
while((ch = getc(fp)) != EOF) { ... }

That said, however, in my opinion it is best practise to avoid trying to
put the whole loop contents into the loop condition when it's not needed.

If one wants to write simple, easy to read C, I think one should adhere
to the rule that loop bodies are supposed to make changes to program
state, while (while, for, if) conditions are supposed to make a decision
based on the current program state but not make changes to that state.

Here's another way to write it, which is simpler to read in my opinion:

int flushln(FILE *fp)
{
int ch;

do
{
ch = getc(fp);
}
while(ch != EOF && ch != '\n');

return ch;
}
This may be okay for flushing input but if you want to process it, then
having the test for EOF and NL at the bottom is wasteful as the code
within the DO clause has to do the test anyway.

Nov 14 '06 #18

P: n/a
In article <11*********************@m7g2000cwm.googlegroups.c om>,
santosh <sa*********@gmail.comwrote:
> do
{
ch = getc(fp);
}
while(ch != EOF && ch != '\n');
>This may be okay for flushing input but if you want to process it, then
having the test for EOF and NL at the bottom is wasteful as the code
within the DO clause has to do the test anyway.
A reasonable compiler will optimise that if you could. Even if it
doesn't, clarity is usually much more important than that kind of
micro-optimisation.

-- RIchard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Nov 14 '06 #19

This discussion thread is closed

Replies have been disabled for this discussion.