473,385 Members | 1,829 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

A function returning string or pointer

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
18 2318
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
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
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
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
"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
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


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
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
"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
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


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
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
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
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
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
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
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
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: john | last post by:
Relatively new to C coding, so any help would greatly be appreciated. I'm having problems try to return my string array from my parsing function. When I do a printf I am getting the correct value...
14
by: Stegano | last post by:
I am learning C Programming after working with Java for 5 years. I want to know where can I find the source files for C language itself. For example strcat is a function, which concatenates two...
2
by: None | last post by:
Hello, 1. The prototype of function signal in signal.h: void (*signal(int sig, void (*func)(int)))(int); is some complex to me. Would you please explain it to me in detail with the C...
14
by: Mike Labosh | last post by:
How do you define whether the return value of a function is ByRef or ByVal? I have a utility class that cleans imported records by doing *really heavy* string manipulation in lots of different...
8
by: ais523 | last post by:
I use this function that I wrote for inputting strings. It's meant to return a pointer to mallocated memory holding one input string, or 0 on error. (Personally, I prefer to use 0 to NULL when...
9
by: cmk128 | last post by:
Hi Why put * in front of the function name in the declaration? int (*write)(struct inode *, struct file *, const char *, int); thanks from Peter (cmk128@hotmail.com)
11
by: Antoninus Twink | last post by:
What's the correct syntax to define a function that returns a pointer to a function? Specifically, I'd like a function that takes an int, and returns a pointer to a function that takes an int and...
5
by: Travis | last post by:
I am using a function that returns a const char * that is usually a word, etc. How can I check to see if what it returns is empty? I tried if (function() == "") and (function() == NULL) and...
26
by: aruna.mysore | last post by:
Hi all, I have a specific problem passing a function pointer array as a parameter to a function. I am trying to use a function which takes a function pointer array as an argument. I am too sure...
13
by: Sri Harsha Dandibhotla | last post by:
Hello all. I recently came across a function declaration as : char(*(*x()))(); This was not in some code but it was in a C questions thread on some group. I tried to decipher what it returns but...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
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...
0
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,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

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.