469,330 Members | 1,306 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,330 developers. It's quick & easy.

Any way to take a word as input from stdin ?

I searched the c.l.c archives provided by Google as Google Groups with
"word input" as the key words and did not come up with anything good.
C++ has std::string for taking a word as input from stdin. C takes input
in 2 ways:

1) as a character, etchar()
2) as a whole line, fgets()
as C programmer, are we supposed to create a get_word function everytime
when we need a words as input from stdin ( e.g. terminal)
--
www.lispmachine.wordpress.com
my email is @ the above blog.
Google Groups is Blocked. Reason: Excessive Spamming

Sep 10 '08
209 7571
On 17 Sep, 07:17, Ron Ford <r...@example.invalidwrote:
On Tue, 16 Sep 2008 06:28:30 +0000, Richard Heathfield posted:
<snip>
>I think it's about here that I like to pretend I'm from Missouri.
Show me.

As it polls redder with the Palin nomination, Huck sighed, 'Ashcroft
sucks."
if you have a political point to make then do it in english.
Or, better, don't make the point on a technical news group.

--
Nick Keighley

Sep 17 '08 #101
Ron Ford said:

<snip>
As it polls redder with the Palin nomination, Huck sighed, 'Ashcroft
sucks."
I don't understand what this has to do with the subject of discussion. In
fact, you frequently baffle me with incomprehensible replies that seem to
bear no relation to what is being discussed or indeed to anything
whatsoever. Is this deliberate? If so, please stop. Think about it - the
more you jar people off, the less help you'll get with your C questions.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Sep 17 '08 #102
On 17 Sep, 07:59, arnuld <sunr...@invalid.addresswrote:
On Wed, 17 Sep 2008 06:29:37 +0000, Richard Heathfield wrote:
Yes, you could do that, except that (a) it might not be the user's stupid
fault (it may simply be that your machine is low on memory), and (b) there
may be a way to recover. If this is a mere learning exercise and the
learning task is not error recovery, then yes, by all means bomb out.
That's the "student solution" and, like cryptosporidium, is very common.

http://en.wikipedia.org/wiki/Cryptosporidium

..aye.... , so lets learn the practical aspects like error-recovery too. I
don't like academic solutions BTW
when, exactly, did "academic" become a pejorative term?
"Yes it works in practice - but does it work in theory?"

"There is nothing as practical as a good theory."

--
Nick Keighley
Sep 17 '08 #103
Nick Keighley said:
On 17 Sep, 07:59, arnuld <sunr...@invalid.addresswrote:
<snip>
>..aye.... , so lets learn the practical aspects like error-recovery too.
I don't like academic solutions BTW

when, exactly, did "academic" become a pejorative term?
What makes you think he's using it pejoratively? He's just saying he
doesn't like academic solutions. I don't like salmon, but that doesn't
mean I consider "salmon" to be a pejorative term.
"Yes it works in practice - but does it work in theory?"

"There is nothing as practical as a good theory."
This isn't about theory vs practice, but about good practice vs indifferent
practice.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Sep 17 '08 #104
On Wed, 17 Sep 2008 06:57:38 +0000, Richard Heathfield wrote:
>arnuld said:
*pc = calloc(AVERAGE_SIZE - 1, sizeof **pc);
why sizeof **pc and not sizeof *pc ?
> pc_begin = *pc;

if( (! *pc) )
{
perror("can not allocate memory, sorry babe!");
return 1;
}
Okay - although it's better not to embed messages like this in library
functions if you can avoid it.

its *not* a library function. its my function. and which message you are
talking about, perror or return call ?
Don't forget to check that return value in the caller.
yes, will do that when get_words will be ready.
I thought you wanted to stop at whitespace?

Also, it's better to move pc_begin than *pc, if you must move either of
them. Given that you have idx keeping track of things, I see no reason to
modify *pc (and plenty of reasons not to), and no reason for pc_begin to
exist at all. You can simply do (*pc)[idx] = ch;
Because [] make it look like an array when you can never pass an array in
C, you always pass a pointer and that *pc++ reminds of that i am working
in a region of memory starting at *pc and ending at *pc == '\0'. 3rd, when
I start using [] i start forgetting how to use pointers.

pc_begin is there because i have rad enough that any callto malloc/calloc
*must* be accompanied by call to free(), other wise we will have a memory
leak. Since I am moving the original pointer (pc), I use pc_begin to save
the beginning position of original pointer, so that I can pass that to
free().

> *++pc = '\0';
pc is char **, so ++pc is char ** (and utterly invalid),
invalid ? I am moving the pointer to next value, so that I can assign to
the **pc .

and *++pc is char*, so you're setting a wild pointer to 0. Not good. Could
be worse, but not good.
That should be **++pc , my typo in the original code.

*pc = calloc(cursize, sizeof **pc);
why sizeof **pc, why not sizeof(char*) ?
new = realloc(*pc, 2 * cursize * sizeof *new);
Same question. Why sizeof *new rather than sizeof char* ?
if(GSW_OK == rc)
{
pc_begin[idx++] = ch;
}
is it the same as **pc++ = ch; ? I think it is. Last, you did not free
the memory. Here is my code without realloc. First I will make calloc work
then I think about realloc. It Segfaults BTW :


#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
enum { AVERAGE_SIZE = 28 };

enum { GSW_OK, GSW_ENOMEM, GSW_ENORESIZE } ;
int get_single_word( char** );
int main( void )
{
char* pw; /* pw means pointer to word */

get_single_word( &pw );

printf("word you entered is: %s\n", pw);

return 0;
}

int get_single_word( char** pc )
{
int ret_value;
unsigned idx;
int ch;

size_t curr_size;
char* pc_begin;
*pc = calloc(curr_size, sizeof (char*));

if( *pc )
{
ret_value = GSW_OK;
pc_begin = *pc;
}
else
{
ret_value = GSW_ENOMEM;
return ret_value;
}

while( ( (ch = getchar()) != EOF) && isspace( (unsigned char)ch ))
{
continue; /* Leading whitespace, protection from some stupid user */
}

for( idx = 0; (ch = getchar()) && (! isspace((unsigned char) ch)); ++idx )
{
if( curr_size == idx )
{
/* realloc, we will think about it later.
use input of size less than ARRSIZE characters for now */
}

if( GSW_OK == ret_value )
{
**pc++ = ch;
}
}
**++pc = '\0';

return ret_value;
}


--
www.lispmachine.wordpress.com
my email is @ the above blog.
Google Groups is Blocked. Reason: Excessive Spamming

Sep 17 '08 #105
arnuld said:
>On Wed, 17 Sep 2008 06:57:38 +0000, Richard Heathfield wrote:
>>arnuld said:

>*pc = calloc(AVERAGE_SIZE - 1, sizeof **pc);

why sizeof **pc and not sizeof *pc ?
Think about it. First satisfy yourself that this is correct:

V = calloc(n, sizeof *V);

You need space sufficient to store the object for which the space is being
allocated, right? So sizeof V, which would only give you the size of the
pointer, would be wrong, yes?

*W = calloc(n, sizeof **W);

Here, we are taking the pointer value returned by calloc and storing it in
an object to which W points. That object, i.e. *W, must itself be a
pointer, and the kind of pointer it must be is the kind of pointer that
points to the kind of thing for which we're allocating space, so sizeof
**W will give us the right size.

Similarly:

**X = calloc(n, sizeof ***X);
***Y = calloc(n, sizeof ****Y);
****Z = calloc(n, sizeof *****Z);

>> pc_begin = *pc;

if( (! *pc) )
{
perror("can not allocate memory, sorry babe!");
return 1;
}
>Okay - although it's better not to embed messages like this in library
functions if you can avoid it.


its *not* a library function. its my function.
You mean you're going to use it once and throw it away? What will you do
the next time you want a function to read a word? Write it from scratch?
and which message you are
talking about, perror or return call ?
The perror call. The place to display this kind of error message is in the
application code, which in your case is basically main().

<snip>
pc_begin is there because i have rad enough that any callto malloc/calloc
*must* be accompanied by call to free(), other wise we will have a
memory leak.
You might want to try using the memory before you free it. After you've
freed it, it's too late.
Since I am moving the original pointer (pc), I use pc_begin
to save the beginning position of original pointer, so that I can pass
that to free().
That's rather pointless. If you're not going to use it, don't allocate it.
> *pc = calloc(cursize, sizeof **pc);

why sizeof **pc, why not sizeof(char*) ?
Why nail a type name into the call? If the type changes, you're stuck with
a maintenance task that my version renders unnecessary.
> new = realloc(*pc, 2 * cursize * sizeof *new);

Same question. Why sizeof *new rather than sizeof char* ?
Same answer.
>

> if(GSW_OK == rc)
{
pc_begin[idx++] = ch;
}

is it the same as **pc++ = ch; ? I think it is. Last, you did not free
the memory.
Of course I didn't free the memory. Yes, you're right that freeing the
memory is important. It's important to return books to the library too,
but if you're not going to read the book first, why take it out in the
first place?

Anyway, I finally got around to testing my code, and noticed some bugs.
Fixing those gives working code:

(Headers and #defines as before)

int get_single_word( char** pc )
{
int rc = GSW_ENOMEM; /* if we succeed, we'll update the status */
size_t idx = 0;
int ch;
char *pc_begin = NULL;
size_t cursize = AVERAGE_SIZE;
char *new = NULL;

*pc = calloc(cursize, sizeof **pc);
if(*pc != NULL)
{
rc = GSW_OK; /* so far so good */
pc_begin = *pc;

while((ch = getchar()) != EOF && isspace((unsigned char)ch))
{
continue; /* skipping leading whitespace */
}
if(ch != EOF)
{
pc_begin[idx++] = ch;

while(GSW_OK == rc &&
(ch = getchar()) != EOF &&
!isspace((unsigned char)ch))
{
if(cursize == idx + 1)
{
new = realloc(*pc, 2 * cursize * sizeof *new);
if(new == NULL)
{
rc = GSW_ENORESIZE; /* error - couldn't enlarge */
pc_begin[idx] = '\0';
}
else
{
*pc = new;
cursize *= 2;
}
}
if(GSW_OK == rc)
{
pc_begin[idx++] = ch;
}
}
}
}

if(*pc != NULL)
{
pc_begin[idx] = '\0';
}

return rc;
}
I used this main to drive the code:

int main(void)
{
char *word = NULL;
while(get_single_word(&word) == 0 && word[0] != '\0')
{
printf("[%s]\n", word);
free(word);
}
return 0;
}

and for this input:

Now is the time to come to
the aid of the party.

I got this output:

[Now]
[is]
[the]
[time]
[to]
[come]
[to]
[the]
[aid]
[of]
[the]
[party.]

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Sep 17 '08 #106
On Wed, 17 Sep 2008 07:38:29 +0000, Richard Heathfield posted:
Ron Ford said:

<snip>
>As it polls redder with the Palin nomination, Huck sighed, 'Ashcroft
sucks."

I don't understand what this has to do with the subject of discussion. In
fact, you frequently baffle me with incomprehensible replies that seem to
bear no relation to what is being discussed or indeed to anything
whatsoever. Is this deliberate? If so, please stop. Think about it - the
more you jar people off, the less help you'll get with your C questions.
Ashcroft must have meant less to you than the Americans he had to shut down
to prepare the way for extraconstitutionality. Among the first deviations
to established law were with DARPA, data mining, and spying on domestic
terrorists, aka democrats.

You can say it has nothing to do with C, the house language of the CIA, but
I'll beg to differ. Their methodology is as flawed as mismatched quotes.

You undercounted by one hundred percent on UB with return (*(int
*)p2)-(*(int *)p1); ask Huck. This is a newsgroup. The fundie
interpretation of the topic--there is no C but C--denies the funner part of
the medium, to say nothing of things that can't be said elsewhere, because
Mitt Romney types own every other medium.

Don't worry, I'll move along. I think 7-5 needs 2 solns, one that just
changes getop, and the better one that Ben could complete. Ciao,
C_Dreamer.

Here's 'show me" in two different languages, one that admits of whitespace,
and the other not, the context for which, of course, you snipped:

'Pokozhautye!'
"Zeig mal!"
--
A church is a place in which gentlemen who have never been to heaven brag
about it to persons who will never get there.
H. L. Mencken
Sep 17 '08 #107
On Wed, 17 Sep 2008 09:37:47 +0000, Richard Heathfield wrote:
Think about it. First satisfy yourself that this is correct:

V = calloc(n, sizeof *V);
This is from MAN page itself:

The calloc() function shall allocate unused space for an array
of nelem elements each of whose size in bytes is elsize. The space
shall be initialized to all bits 0.

Array elements in your example are of type V, not *V. This is what
confusing me.


The perror call. The place to display this kind of error message is in
the application code, which in your case is basically main().
so we *always* use perror() in main() ?

Anyway, I finally got around to testing my code, and noticed some bugs.
Fixing those gives working code:

cool :)
.... SNIP.....
int main(void)
{
char *word = NULL;
while(get_single_word(&word) == 0 && word[0] != '\0') {
printf("[%s]\n", word);
free(word);
}
we calloc the memory in some other function while freeing it in some
other. Thats really strange. I am not saying its wrong. I am saying its
feels strange for the programmers who has used languages like Lisp,
Python, Ruby and C++ (only using Std. Lib. like string and vector)
I will code the program and will work on understanding it :)

--
www.lispmachine.wordpress.com
my email is @ the above blog.
Google Groups is Blocked. Reason: Excessive Spamming

Sep 17 '08 #108
arnuld said:
>On Wed, 17 Sep 2008 09:37:47 +0000, Richard Heathfield wrote:
>Think about it. First satisfy yourself that this is correct:

V = calloc(n, sizeof *V);

This is from MAN page itself:

The calloc() function shall allocate unused space for an
array
of nelem elements each of whose size in bytes is elsize. The
space shall be initialized to all bits 0.

Array elements in your example are of type V, not *V. This is what
confusing me.
V isn't a type. It's a pointer. Let them be of type T, instead. Okay?

Yes, V points to n elements, each of which is sizeof *V bytes in size. What
is *V? It's the thing pointed to by V. What's sizeof *V, then? Right - the
size of one of these things. It's hard to make this any easier.
>The perror call. The place to display this kind of error message is in
the application code, which in your case is basically main().

so we *always* use perror() in main() ?
We do? I hardly ever use it at all. But if I do use it, I don't bury it in
a library function.
>.... SNIP.....
>int main(void)
{
char *word = NULL;
while(get_single_word(&word) == 0 && word[0] != '\0') {
printf("[%s]\n", word);
free(word);
}

we calloc the memory in some other function while freeing it in some
other. Thats really strange.
Why is that strange? You want to build these things into a list, don't you,
in due course? The way you seem to be wanting to do this, your list will
only ever have one entry in it at any given time.

allocate space for "Now"
add "Now" to list
remove "Now" from list
free "Now"
allocate space for "is"
add "is" to list
remove "is" from list
free "is"

etc, which is just stupid.

I am not saying its wrong. I am saying its
feels strange for the programmers who has used languages like Lisp,
Python, Ruby and C++ (only using Std. Lib. like string and vector)
Are you claiming Lisp can only do lists one element long?

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Sep 17 '08 #109
On 17 Sep, 08:45, Richard Heathfield <r...@see.sig.invalidwrote:
Nick Keighley said:
On 17 Sep, 07:59, arnuld <sunr...@invalid.addresswrote:
..aye.... , so lets learn the practical aspects like error-recovery too.
I don't like academic solutions BTW
when, exactly, did "academic" become a pejorative term?

What makes you think he's using it pejoratively? He's just saying he
doesn't like academic solutions. I don't like salmon, but that doesn't
mean I consider "salmon" to be a pejorative term.
but it is often used that way.

Are the algorithms in Knuth academic? Does arnuld dislike them?

"Yes it works in practice - but does it work in theory?"
"There is nothing as practical as a good theory."

This isn't about theory vs practice, but about good practice vs indifferent
practice.
and good practice often has a sound theoretical base.
--
Nick Keighley

Sep 17 '08 #110
On Wed, 17 Sep 2008 13:10:14 +0000, Richard Heathfield wrote:
V isn't a type. It's a pointer. Let them be of type T, instead. Okay?

Yes, V points to n elements, each of which is sizeof *V bytes in size. What
is *V? It's the thing pointed to by V. What's sizeof *V, then? Right - the
size of one of these things. It's hard to make this any easier.
I should have been more clear. Take a look st this:

char* T;
T = calloc( 10, sizeof(char));

while your expression is:

char* T;
T = calloc( 10, sizeof(*T));
Thats what I am talking about, I am looking for a place to store N
characters, not 10 pointers to pointers (in our original program). So why
create space for char** when we want to store char(s) in them. This is my
original question about calloc/malloc/realloc

Are you claiming Lisp can only do lists one element long?

No, I am claiming that we never ever think of managing memory in Lisp :)

--
www.lispmachine.wordpress.com
my email is @ the above blog.
Google Groups is Blocked. Reason: Excessive Spamming

Sep 17 '08 #111
arnuld <su*****@invalid.addresswrites:
No, I am claiming that we never ever think of managing memory in Lisp :)
I do. Less than in C, but I do.

Yours,

--
Jean-Marc
Sep 17 '08 #112
Nick Keighley wrote:
On 17 Sep, 08:45, Richard Heathfield <r...@see.sig.invalidwrote:
>Nick Keighley said:
>>On 17 Sep, 07:59, arnuld <sunr...@invalid.addresswrote:
>>>..aye.... , so lets learn the practical aspects like error-recovery too.
I don't like academic solutions BTW
when, exactly, did "academic" become a pejorative term?
What makes you think he's using it pejoratively? He's just saying he
doesn't like academic solutions. I don't like salmon, but that doesn't
mean I consider "salmon" to be a pejorative term.

but it is often used that way.
In context, arnuld was using the term "academic" in reference to
Richard's statement 'If this is a mere learning exercise and the
learning task is not error recovery, then yes, by all means bomb out.
That's the "student solution"...'. I think that the contextual meaning
was clearly pejorative ("mere learning exercise"), whether or not he
meant it to be more generally pejorative.
Sep 17 '08 #113
arnuld <su*****@invalid.addresswrites:
>On Wed, 17 Sep 2008 13:10:14 +0000, Richard Heathfield wrote:
>V isn't a type. It's a pointer. Let them be of type T, instead. Okay?

Yes, V points to n elements, each of which is sizeof *V bytes in size. What
is *V? It's the thing pointed to by V. What's sizeof *V, then? Right - the
size of one of these things. It's hard to make this any easier.

I should have been more clear. Take a look st this:

char* T;
T = calloc( 10, sizeof(char));

while your expression is:

char* T;
T = calloc( 10, sizeof(*T));
Thats what I am talking about, I am looking for a place to store N
characters, not 10 pointers to pointers (in our original program).
And there is the problem (in your understanding). sizeof (*T) is 1.
*T is the first char pointer to by T. It is not in any way a
pointer. It is a way to denote a single char.

It would have been slightly clearer, I think, if you had not used the
name T since Richard was using T as the type of the things pointed to
by V. Is this any clearer:

char *ptr;
ptr = calloc(10, sizeof *ptr);

?

--
Ben.
Sep 17 '08 #114
arnuld wrote:
....
I should have been more clear. Take a look st this:

char* T;
T = calloc( 10, sizeof(char));

while your expression is:

char* T;
T = calloc( 10, sizeof(*T));
Thats what I am talking about, I am looking for a place to store N
characters, not 10 pointers to pointers (in our original program). So why
create space for char** when we want to store char(s) in them. This is my
original question about calloc/malloc/realloc
It really appears to be a problem with your understanding of how sizeof
operates.

The above statement reserves space for 10 characters; "*T" is an
expression with type 'char', and therefore "sizeof *T" has exactly the
same value as sizeof(char);

In your original code, you had

int get_single_word( char** pc )

and

*pc = calloc(AVERAGE_SIZE-1, sizeof(char));

which Richard recommended that you change to:

*pc = calloc(AVERAGE_SIZE - 1, sizeof **pc);

"**pc" is an expression of type 'char', and therefore "sizeof **pc"
means exactly the same as sizeof(char).

The advantage of using "sizeof **pc" is that deciding whether or not
sizeof(char) is correct requires looking back at the declaration of
'pc'. You can determine whether or not "sizeof **pc" is the right value,
just by looking at this one line; it remains the the correct value, no
matter what the declaration of pc is (unless pc has a type for which the
calloc() call is inappropriate, in which case it's a constraint violation).
Sep 17 '08 #115
arnuld said:
>On Wed, 17 Sep 2008 13:10:14 +0000, Richard Heathfield wrote:
>V isn't a type. It's a pointer. Let them be of type T, instead. Okay?

Yes, V points to n elements, each of which is sizeof *V bytes in size.
What is *V? It's the thing pointed to by V. What's sizeof *V, then?
Right - the size of one of these things. It's hard to make this any
easier.

I should have been more clear. Take a look st this:

char* T;
T = calloc( 10, sizeof(char));

while your expression is:

char* T;
T = calloc( 10, sizeof(*T));
Not quite. It's:

T = calloc(10, sizeof *T);

(Spot the difference.)

Why you started using T as an object pointer name instead of as a type, I
don't know, but hey, that's legal. But it means we need a new name for the
type. Let's call it mytype.

mytype *T;
T = calloc(n, sizeof *T);
Thats what I am talking about, I am looking for a place to store N
characters, not 10 pointers to pointers (in our original program).
Oh, okay, N, not 10. T = calloc(N, sizeof *T);

Happy now?
So why
create space for char** when we want to store char(s) in them.
If T is a char *, then *T is a char, not a char **, so sizeof *T is 1.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Sep 17 '08 #116
Richard Heathfield <rj*@see.sig.invalidwrites:
arnuld said:
>>On Wed, 17 Sep 2008 13:10:14 +0000, Richard Heathfield wrote:
>>V isn't a type. It's a pointer. Let them be of type T, instead. Okay?

Yes, V points to n elements, each of which is sizeof *V bytes in size.
What is *V? It's the thing pointed to by V. What's sizeof *V, then?
Right - the size of one of these things. It's hard to make this any
easier.

I should have been more clear. Take a look st this:

char* T;
T = calloc( 10, sizeof(char));

while your expression is:

char* T;
T = calloc( 10, sizeof(*T));

Not quite. It's:

T = calloc(10, sizeof *T);

(Spot the difference.)
The first is more widely used in the real world in my experience. What
are the problems with

T = calloc( 10, sizeof(*T));

?
Sep 17 '08 #117
Ron Ford <ro*@example.invalidwrites:
On Wed, 17 Sep 2008 07:38:29 +0000, Richard Heathfield posted:
>Ron Ford said:

<snip>
>>As it polls redder with the Palin nomination, Huck sighed, 'Ashcroft
sucks."

I don't understand what this has to do with the subject of discussion. In
fact, you frequently baffle me with incomprehensible replies that seem to
bear no relation to what is being discussed or indeed to anything
whatsoever. Is this deliberate? If so, please stop. Think about it - the
more you jar people off, the less help you'll get with your C questions.

Ashcroft [...] Americans [...] extraconstitutionality. [...]
deviations [...] data mining [...] domestic terrorists [...].
Ron, I implore you, *please* knock off the political discussion. This
is not the place for it. Many people, myself most emphatically
included, have strong opinions on these things, and we could easily
spend tremendous amounts of bandwidth discussing them -- and we'd lose
the valuable *technical* resource that is this newsgroup.

More likely, people will just assume you're a troll who's *trying* to
disrupt this newsgroup, and will simply ignore you -- which is what I
intend to do if you continue trying to bring US politics into this
group.
You can say it has nothing to do with C, the house language of the CIA, but
I'll beg to differ.
Beg all you want, but do it somewhere else. It has nothing to do with
C.

If you feel the need to discuss politics, there are plenty of forums
(newsgroups, blogs, other web sites, your living room) where it's
perfectly appropriate.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 17 '08 #118
On 17 Sep, 14:10, Richard Heathfield <r...@see.sig.invalidwrote:
arnuld said:
On Wed, 17 Sep 2008 09:37:47 +0000, Richard Heathfield wrote:
Think about it. First satisfy yourself that this is correct:
* * V = calloc(n, * * sizeof *V);
<SNIP>
Array elements in your example are of type V, not *V. This is what
confusing me.

V isn't a type. It's a pointer. Let them be of type T, instead. Okay?

Yes, V points to n elements, each of which is sizeof *V bytes in size.

V points to a single element, not n of them. The element that it
points to is the first element of an array of n elements.


Sep 18 '08 #119
On Wed, 17 Sep 2008 14:06:52 +0000, James Kuyper wrote:
In context, arnuld was using the term "academic" in reference to
Richard's statement 'If this is a mere learning exercise and the
learning task is not error recovery, then yes, by all means bomb out.
That's the "student solution"...'. I think that the contextual meaning
was clearly pejorative ("mere learning exercise"), whether or not he
meant it to be more generally pejorative.

I think you guys need to stop arguing and listen to me instead ;) .
Forget about pejorative or bombing out.
My meaning of academic means, "being not practical" . In Indian computer
education system, clrscr() is the function that belongs to a language
named TURBO C, which is better than C. There is *only* one good C and that
is TURBO C. Same for VC++ which, of course , is much better than C++.
Microsoft has created a better language than C.

Thats *exactly* what I have been taught in my 3 years of graduation and
thats *exactly* what academic means. I did not even told that TURBO C was
actually a proprietary compiler. I was told it was the C.
okay, enough of real rant.

--
www.lispmachine.wordpress.com
my email is @ the above blog.
Google Groups is Blocked. Reason: Excessive Spamming

Sep 18 '08 #120
On 2008-09-17, arnuld <su*****@invalid.addresswrote:
>
My meaning of academic means, "being not practical" . In Indian computer
education system, clrscr() is the function that belongs to a language
named TURBO C, which is better than C. There is *only* one good C and that
is TURBO C. Same for VC++ which, of course , is much better than C++.
Microsoft has created a better language than C.
Well, TURBO C is not C, and VC++ is not C++. Microsoft should not have
named their products so similarly to those real languages.

(On the other hand, Microsoft does have some real languages now, like C#
and friends, which are perfectly fine languages in their own right, and
don't go around masquerading as other ones.)
Thats *exactly* what I have been taught in my 3 years of graduation and
thats *exactly* what academic means. I did not even told that TURBO C was
actually a proprietary compiler. I was told it was the C.
Well, that's silly.
>
okay, enough of real rant.
Yes - this entire article is off-topic.

--
Andrew Poelstra ap*******@wpsoftware.net
That was a joke. Jokes in mathematics, are sometimes not funny.
-Veselin Jungic
Sep 18 '08 #121
On Wed, 17 Sep 2008 14:27:39 +0000, James Kuyper wrote:
It really appears to be a problem with your understanding of how sizeof
operates.

The above statement reserves space for 10 characters; "*T" is an
expression with type 'char', and therefore "sizeof *T" has exactly the
same value as sizeof(char);
....SNIP....

Oh.. no... I think I overwhelmed by the pointers and arrays. Now I got it,
Ben's code also helped me a lot to clear up the confusion:
char *ptr;
ptr = calloc(10, sizeof *ptr);
*ptr is the char actually. same for **ppc in my program. I don't
understand why I was so much messed up in understating this little thing.


--
www.lispmachine.wordpress.com
my email is @ the above blog.
Google Groups is Blocked. Reason: Excessive Spamming

Sep 18 '08 #122
On Wed, 17 Sep 2008 09:37:47 +0000, Richard Heathfield wrote:

Anyway, I finally got around to testing my code, and noticed some bugs.
Fixing those gives working code:
...SNIP...

I wrote the program without looking at your code and it works fine :) .
..SNIP...
if(ch != EOF)
{
pc_begin[idx++] = ch;
So it is C programming style to do that ? I mean, whenever we get a ** or
a *** pointer in some function argument we should create a new * and
reference it to the original value. e.g. we had a dual indirection pointer
here char **pc, so we did:

pc_begin = *ppc;

or

char*** ppc;
pc_begin = **pppc;

which gives single pointer and has 2 benefits:

1) We can manipulate that single pointer easily without any ambiguous
and confusing pointer arithmetic.
2) It leaves the original pointer unchanged.
Is this the lesson here ?


--
www.lispmachine.wordpress.com
my email is @ the above blog.
Google Groups is Blocked. Reason: Excessive Spamming

Sep 18 '08 #123
On Wed, 17 Sep 2008 09:37:47 +0000, Richard Heathfield wrote:
...SNIP...
Anyway, I finally got around to testing my code, and noticed some bugs.
Fixing those gives working code:

(Headers and #defines as before)

int get_single_word( char** pc )
{
int rc = GSW_ENOMEM; /* if we succeed, we'll update the status */
size_t idx = 0;
int ch;
char *pc_begin = NULL;
size_t cursize = AVERAGE_SIZE;
char *new = NULL;

*pc = calloc(cursize, sizeof **pc);
if(*pc != NULL)
{
rc = GSW_OK; /* so far so good */
pc_begin = *pc;
.....SNIP...
This whole program is based on that condition of *pc != NULL. Why don't
we put a line like, *pc == NULL and then return from the program with the
ENOMEM value right there ?

....SNIP..
here is what the code of get_words() looks like, which is supposed to
create a dynamic array of pointers pointing to different words:
int get_words( char*** pw, size_t* cnt )
{
int idx;
int mem_check;
char *pw_begin, *new_mem;
size_t arr_size;

arr_size = ARRSIZE;
mem_check = GW_ENOMEM;

**pw = calloc( arr_size, sizeof **pw );

if( **pw )
{
mem_check = GW_OK;
pw_begin = **pw;
}
else
{
mem_check = GW_ENOMEM;
return mem_check;
}

if( idx == arr_size )
{
new_mem = realloc( **pw, (2 * arr_size * sizeof new_mem));

if( new_mem )
{
pw_begin = new_mem;

}
else
{
mem_check = GW_ENORESIZE;
return mem_check;
}
Its nearly a duplicate of get_single_word, as the design is same. onlya
few things are confusing me. calloc() will return a pointer to allocated
space which we will assign to a pointer. But in this function we are
working with pointer to arrays or pointer to pointers. So how come get the
pointer to pointer as first element of the allocated space. Or calloc()
does it for us and we can do something like:
char*** pw;
*pw_begin = calloc( arr_size, sizeof(*pw_begin) );

--
www.lispmachine.wordpress.com
my email is @ the above blog.
Google Groups is Blocked. Reason: Excessive Spamming

Sep 18 '08 #124
William Pursell said:
On 17 Sep, 14:10, Richard Heathfield <r...@see.sig.invalidwrote:
>arnuld said:
>On Wed, 17 Sep 2008 09:37:47 +0000, Richard Heathfield wrote:
>Think about it. First satisfy yourself that this is correct:
>V = calloc(n, sizeof *V);
<SNIP>
Array elements in your example are of type V, not *V. This is what
confusing me.

V isn't a type. It's a pointer. Let them be of type T, instead. Okay?

Yes, V points to n elements, each of which is sizeof *V bytes in size.


V points to a single element, not n of them. The element that it
points to is the first element of an array of n elements.
Yes, you're right, careless of me. Thank you. s/to n/to the first of n/
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Sep 18 '08 #125
arnuld said:
>On Wed, 17 Sep 2008 14:06:52 +0000, James Kuyper wrote:
>In context, arnuld was using the term "academic" in reference to
Richard's statement 'If this is a mere learning exercise and the
learning task is not error recovery, then yes, by all means bomb out.
That's the "student solution"...'. I think that the contextual meaning
was clearly pejorative ("mere learning exercise"), whether or not he
meant it to be more generally pejorative.


I think you guys need to stop arguing and listen to me instead ;) .
Forget about pejorative or bombing out.
My meaning of academic means, "being not practical" . In Indian computer
education system, clrscr() is the function that belongs to a language
named TURBO C, which is better than C.
I've never heard such baloney. C is a language. Turbo C is an ancient
implementation, no longer supported, which runs on only one tiny class of
platforms.
There is *only* one good C and that is TURBO C.
Try telling that to the OS390 guys. How many C implementations did your
teachers use before arriving at this opinion?
Same for VC++ which, of course , is much better than
C++.
There's no "of course" about it. VC++ is an implementation of C++, with
extensions. I stopped bothering with MFC (a supposedly cool extension)
when I discovered that you couldn't make a CList of CLists - a stupid
restriction that forced me to come up with a workaround. C++ itself is a
language, not an implementation, and there are plenty of implementations
of C++.

How many C++ implementations did your teachers use before arriving at this
opinion?
Microsoft has created a better language than C.
What makes your teachers think so? And on what criteria are they judging?
And why do they dismiss the criteria on which they are not judging?

Thats *exactly* what I have been taught in my 3 years of graduation
A load of baloney.
and thats *exactly* what academic means.
No, it isn't. In academic circles, the truth is valued rather more highly
than that. What you have experienced is not an academic system but a
travesty.
I did not even told that TURBO C was
actually a proprietary compiler. I was told it was the C.
You were told wrong.
okay, enough of real rant.
It's hard to know what you're ranting against. If it's the apparent
incompetence of the teaching you are receiving, I sympathise.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Sep 18 '08 #126
arnuld said:
>On Wed, 17 Sep 2008 09:37:47 +0000, Richard Heathfield wrote:
> pc_begin[idx++] = ch;

So it is C programming style to do that ? I mean, whenever we get a ** or
a *** pointer in some function argument we should create a new * and
reference it to the original value.
No. I was doing so because you seemed to like it that way. In my own code
written for my own benefit, I would probably have used (*pc)[idx++]

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Sep 18 '08 #127
arnuld said:
>On Wed, 17 Sep 2008 09:37:47 +0000, Richard Heathfield wrote:
>...SNIP...
>Anyway, I finally got around to testing my code, and noticed some bugs.
Fixing those gives working code:

(Headers and #defines as before)

int get_single_word( char** pc )
{
int rc = GSW_ENOMEM; /* if we succeed, we'll update the status */
size_t idx = 0;
int ch;
char *pc_begin = NULL;
size_t cursize = AVERAGE_SIZE;
char *new = NULL;

*pc = calloc(cursize, sizeof **pc);
if(*pc != NULL)
{
rc = GSW_OK; /* so far so good */
pc_begin = *pc;
>.....SNIP...

This whole program is based on that condition of *pc != NULL. Why don't
we put a line like, *pc == NULL and then return from the program with the
ENOMEM value right there ?
Lots of people /would/ write it like that. In *my* code, I consider an
"early return" like that to be a bug that I should fix, because in *my*
code I want every function and every loop to have *one* entry point and
*one* exit point. I find that this makes my programs much easier to read
and thus to maintain.

Clearly, lots of people disagree with that, including some whose opinion I
value rather highly. Nevertheless, I have tried writing code both ways,
and found "my" way to be best for me.
here is what the code of get_words() looks like, which is supposed to
create a dynamic array of pointers pointing to different words:
int get_words( char*** pw, size_t* cnt )
{
int idx;
int mem_check;
char *pw_begin, *new_mem;
size_t arr_size;

arr_size = ARRSIZE;
mem_check = GW_ENOMEM;

**pw = calloc( arr_size, sizeof **pw );
Surely you mean *pw = calloc( arr_size, sizeof **pw );

Oh, by the way - I don't see the bit where you point the array's elements
to words. Why isn't get_words calling get_single_word?

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Sep 18 '08 #128
On Thu, 18 Sep 2008 09:14:41 +0000, Richard Heathfield wrote:
>arnuld wrote:
Lots of people /would/ write it like that. In *my* code, I consider an
"early return" like that to be a bug that I should fix, because in *my*
code I want every function and every loop to have *one* entry point and
*one* exit point. I find that this makes my programs much easier to read
and thus to maintain.
Will not that make the program less efficient as program has to go till it
finds the return ?
> **pw = calloc( arr_size, sizeof **pw );
Surely you mean *pw = calloc( arr_size, sizeof **pw );

you say that calloc() will automatically return a pointer to pointer ?

Oh, by the way - I don't see the bit where you point the array's
elements to words. Why isn't get_words calling get_single_word?

because I did not wrote it yet ;) . I wanted to remove some confusions
first and then proceed ahead.
--
www.lispmachine.wordpress.com
my email is @ the above blog.
Google Groups is Blocked. Reason: Excessive Spamming

Sep 18 '08 #129
arnuld said:
>On Thu, 18 Sep 2008 09:14:41 +0000, Richard Heathfield wrote:
>>arnuld wrote:
>Lots of people /would/ write it like that. In *my* code, I consider an
"early return" like that to be a bug that I should fix, because in *my*
code I want every function and every loop to have *one* entry point and
*one* exit point. I find that this makes my programs much easier to read
and thus to maintain.

Will not that make the program less efficient as program has to go till
it finds the return ?
Only if the compiler is really brain-damaged.

Let's say the code is:

if(ptr != NULL) /* A */
{
/* lots of code, translating to 500 bytes of assembly instructions */
}

return ptr; /* B */

The compiler will do something like this:

CMP ptr, 0
JE _B
(500 bytes of assembly instructions here)
_B:
MOV RR, ptr

On the second pass, JE _B will be translated into a jump to a specific
(relocatable) address, and the jump will consist simply of changing the
instruction pointer to have that new value. The program doesn't have to
"go till it finds the return" - it simply has to assign a new value to the
instruction pointer, and it doesn't give tuppence whether that value is
close to the value it had before or not.
>> **pw = calloc( arr_size, sizeof **pw );
>Surely you mean *pw = calloc( arr_size, sizeof **pw );


you say that calloc() will automatically return a pointer to pointer ?
No, calloc returns void * - and I don't see the relevance of your question
to the point I made.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Sep 18 '08 #130
On Thu, 18 Sep 2008 11:16:13 +0000, Richard Heathfield wrote:
Only if the compiler is really brain-damaged.

Let's say the code is:

if(ptr != NULL) /* A */
{
/* lots of code, translating to 500 bytes of assembly instructions */
}

return ptr; /* B */

The compiler will do something like this:

CMP ptr, 0
JE _B
(500 bytes of assembly instructions here)
_B:
MOV RR, ptr

hey.. thats assembly :)
On the second pass, JE _B will be translated into a jump to a specific
(relocatable) address, and the jump will consist simply of changing the
instruction pointer to have that new value. The program doesn't have to
"go till it finds the return" - it simply has to assign a new value to the
instruction pointer, and it doesn't give tuppence whether that value is
close to the value it had before or not.
Nobody taught me that way on comp.lang.c++. Seems like C is very closer to
assembly language.
No, calloc returns void * - and I don't see the relevance of your
question to the point I made.

I quoted the wrong code. See this code:

char*** pw;
*pw = calloc( arr_size, sizeof **pw );
*pw means pointer to pointer. I want to dynamically allocate an array of
pointers. but calloc() gives void* in return not void**. So how can
I dynamically allocate an array of pointers. The array elements (pointers)
will point to words ,which again are pointers.
This is going to be base for get_words function, which will be passed the
address of a pointer to pointer, making the 3 levels of indirection coming
into the picture.


--
www.lispmachine.wordpress.com
my email is @ the above blog.
Google Groups is Blocked. Reason: Excessive Spamming

Sep 18 '08 #131
arnuld said:
>On Thu, 18 Sep 2008 11:16:13 +0000, Richard Heathfield wrote:
>Only if the compiler is really brain-damaged.

Let's say the code is:

if(ptr != NULL) /* A */
{
/* lots of code, translating to 500 bytes of assembly instructions */
}

return ptr; /* B */

The compiler will do something like this:

CMP ptr, 0
JE _B
(500 bytes of assembly instructions here)
_B:
MOV RR, ptr


hey.. thats assembly :)
When we're talking about efficiency (and it was you who raised the
subject), the language definition is no longer adequate, because it
doesn't have anything to say about efficiency, so we have to look at
typical characteristics of implementations, knowing that what we say is no
longer universally true. Note that the assembly language above was only
mildly modelled on real assembly languages, and probably won't do you much
good if you try to insert it into your own program.
>On the second pass, JE _B will be translated into a jump to a specific
(relocatable) address, and the jump will consist simply of changing the
instruction pointer to have that new value. The program doesn't have to
"go till it finds the return" - it simply has to assign a new value to
the instruction pointer, and it doesn't give tuppence whether that value
is close to the value it had before or not.

Nobody taught me that way on comp.lang.c++.
Well, nobody would have taught you that way on comp.lang.c either, except
that you raised the subject of efficiency and suggested that a particular
style is inefficient. To demonstrate that it isn't could not be done from
within the context of the language itself.
Seems like C is very closer to assembly language.
Yes, except that there really isn't any such thing as "assembly language" -
rather, there are many different assembly languages.
char*** pw;
*pw = calloc( arr_size, sizeof **pw );
*pw means pointer to pointer. I want to dynamically allocate an array of
pointers. but calloc() gives void* in return not void**.
Right. (So do malloc and realloc.) Why would you need void **?
So how can
I dynamically allocate an array of pointers.
T **p;
p = malloc(n * sizeof *p);
if(p != NULL)
{
p[0] through p[n - 1] are now pointers to T, with indeterminate values

If you are passing p via a function parameter, you will need an additional
level of indirection, so take it as T ***p and do:

*p = malloc(n * sizeof **p);
if(*p != NULL)
{
(*p)[0] through (*p)[n - 1] are now pointers to T...

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Sep 18 '08 #132
On Thu, 18 Sep 2008 09:14:41 +0000, Richard Heathfield wrote:
...SNIP..
Surely you mean *pw = calloc( arr_size, sizeof **pw );

Oh, by the way - I don't see the bit where you point the array's elements
to words. Why isn't get_words calling get_single_word?

Okay here is my new code:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
enum { WORD_SIZE = 28, ARRSIZE = 10 };

enum { GSW_OK, GSW_ENOMEM, GSW_ENORESIZE } ;

enum { GW_OK, GW_ENOMEM, GW_ENORESIZE };
int get_words( char***, size_t* );
int get_single_word( char** );
int main( void )
{
char** pword; /* pw means pointer to word */
size_t word_count;
int num;

pword = NULL;
word_count = 0;

num = get_words( &pword, &word_count );

printf("words = %d, num = %d\n", (int) word_count, num);

free(pword);

return 0;
}
int get_words( char*** pw, size_t* cnt )
{
size_t idx;
int mem_check;
char **pw_begin, **new_mem;
char* pword;
size_t arr_size;

arr_size = ARRSIZE;
mem_check = GW_ENOMEM;

*pw = calloc( arr_size, sizeof **pw );
pw_begin = *pw;

if( *pw )
{
mem_check = GW_OK;
pw_begin = *pw;
for( idx = 0; (! get_single_word( &pword )) && *pword; ++idx )
{
if( idx == arr_size )
{
new_mem = realloc( **pw, (2 * arr_size * sizeof new_mem));

if( new_mem )
{
pw_begin = new_mem;
}
else
{
mem_check = GW_ENORESIZE;
}
}

if( GSW_OK == mem_check )
{
pw_begin++ = &pword;
}
}

pw_begin = NULL;

}

*cnt = idx;

return mem_check;
}


int get_single_word( char** pc )
{
int mem_check;
unsigned idx;
int ch;

size_t curr_size;
char *new_mem;
char *pc_begin;

mem_check = GSW_ENOMEM; /* will updat eit on first use */
curr_size = WORD_SIZE;

*pc = calloc(curr_size, sizeof(**pc));

if( (! *pc) )
{
mem_check = GSW_ENOMEM;
return mem_check;
}
else
{
mem_check = GSW_OK;
pc_begin = *pc;
}

while( (ch = getchar()) && (isspace( (unsigned char) ch)) )
{
continue; /* skip leading white space */
}
if( EOF != ch )
{
*pc_begin++ = ch;
}

while( (GSW_OK == mem_check) &&
((ch = getchar()) != EOF) &&
(! isspace( (unsigned char) ch)) )
{
if( idx == curr_size )
{
new_mem = realloc( pc_begin, (2 * curr_size * sizeof(*new_mem)));

if( new_mem )
{
pc_begin = new_mem;
curr_size *= 2;
}
else
{
mem_check = GSW_ENORESIZE; /* error, couldn't not enlarge */
*pc_begin = '\0';
return mem_check;
}
}

if( GSW_OK == mem_check )
{
*pc_begin++ = ch;
}

}
*pc_begin = '\0';
return mem_check;
}

======================= OUTPUT ========================
[arnuld@dune ztest]$ gcc -ansi -pedantic -Wall -Wextra sort-input.c
sort-input.c: In function `get_words':
sort-input.c:79: error: invalid lvalue in assignment
[arnuld@dune ztest]$

Line 79: pw_begin++ = &pword;

I don't understand why I am getting this error.

--
www.lispmachine.wordpress.com
my email is @ the above blog.
Google Groups is Blocked. Reason: Excessive Spamming

Sep 18 '08 #133
arnuld said:

<snip>
Line 79: pw_begin++ = &pword;

I don't understand why I am getting this error.
The assignment operator requires a modifiable lvalue as its left operand.
The ++ operator yields a value as its result. The above is equivalent in
spirit to a statement such as: 6 = &pword; which simply makes no sense.
The implementation is obliged to diagnose this, and has done so.

What you meant to write is:

*pw_begin++ = pword;

This is legal because * has higher precedence than = so what happens is
that ++ yields the old value of pw_begin, * gives us the object to which
that old value points, and = now assigns to the object. Since pw_begin has
type char **, pw_begin++ has type char **, *pw_begin++ has type char * and
is a real object, so we can assign a char * value to it. pword is one such
value.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Sep 18 '08 #134
arnuld wrote:
....
> *pc = calloc(cursize, sizeof **pc);
if(*pc != NULL)
{
....
This whole program is based on that condition of *pc != NULL. Why don't
we put a line like, *pc == NULL and then return from the program with the
ENOMEM value right there ?
If you return from the program, the fact that errno contains ENOMEM has
no further significance.
Sep 18 '08 #135
Richard Heathfield wrote:
....
The compiler will do something like this:

CMP ptr, 0
JE _B
(500 bytes of assembly instructions here)
_B:
MOV RR, ptr

On the second pass, JE _B will be translated into a jump to a specific
(relocatable) address, and the jump will consist simply of changing the
instruction pointer to have that new value. The program doesn't have to
"go till it finds the return" - it simply has to assign a new value to the
instruction pointer, and it doesn't give tuppence whether that value is
close to the value it had before or not.
It depends upon the assembly language; I've written assembly in
languages where a short jump used a faster instruction than a long jump.
However, it was only a little bit faster; not enough to justify worrying
about in C code.
Sep 18 '08 #136
Richard Heathfield wrote:
arnuld said:
....
>My meaning of academic means, "being not practical" . In Indian computer
education system, clrscr() is the function that belongs to a language
named TURBO C, which is better than C.

I've never heard such baloney. C is a language. Turbo C is an ancient
implementation, no longer supported, which runs on only one tiny class of
platforms.
>There is *only* one good C and that is TURBO C.

Try telling that to the OS390 guys.
I would imagine, since he prefaced his statement with "In Indian
computer education system ...", that this would imply that the specified
system doesn't have any OS390 guys. He wasn't making a more general
statement. The wording of his statement leaves open the possibility that
there are implementations of C which are better than the ones he listed,
they just don't happen to be available in that system. If this is the
case, he has my sympathy - I thought the Indians were more advanced than
that.

However, India is a huge place, and I doubt that arnuld has seen the
entire "Indian computer education system". I suspect that he's
describing the attitude of one particular piece (of unknown size) of
that system. However, his description of that piece of the system might
be perfectly accurate.
Sep 18 '08 #137
arnuld <su*****@invalid.addresswrites:
>On Thu, 18 Sep 2008 09:14:41 +0000, Richard Heathfield wrote:
<snip>
Okay here is my new code:
A few comments.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
enum { WORD_SIZE = 28, ARRSIZE = 10 };

enum { GSW_OK, GSW_ENOMEM, GSW_ENORESIZE } ;

enum { GW_OK, GW_ENOMEM, GW_ENORESIZE };
int get_words( char***, size_t* );
int get_single_word( char** );
int main( void )
{
char** pword; /* pw means pointer to word */
size_t word_count;
int num;

pword = NULL;
word_count = 0;

num = get_words( &pword, &word_count );

printf("words = %d, num = %d\n", (int) word_count, num);

free(pword);

return 0;
}
int get_words( char*** pw, size_t* cnt )
{
size_t idx;
int mem_check;
char **pw_begin, **new_mem;
char* pword;
size_t arr_size;

arr_size = ARRSIZE;
mem_check = GW_ENOMEM;

*pw = calloc( arr_size, sizeof **pw );
pw_begin = *pw;

if( *pw )
{
mem_check = GW_OK;
pw_begin = *pw;
for( idx = 0; (! get_single_word( &pword )) && *pword; ++idx )
I find this counter-intuitive. I had to go check what get_single_word
returns for success (GSW_OK) and then go check that this was indeed
zero so ! of it was true. I'd write
for( idx = 0; get_single_word( &pword ) == GSW_OK; ++idx )
and try hard to make sure that there is no need for the extra check
on *pword. I have not checked if you need it.
{
if( idx == arr_size )
{
new_mem = realloc( **pw, (2 * arr_size * sizeof new_mem));

if( new_mem )
{
pw_begin = new_mem;
Surely not? The next words has to go after the existing ones in the new
memory not at the start.
}
else
{
mem_check = GW_ENORESIZE;
}
}

if( GSW_OK == mem_check )
This looks wrong. You set mem_check only once and that is to GW_OK.
Now GW_OK == GSW_OK (probably) but why test it anyway since we are in
an the if where it was set? I.e. you get to this test unless
mem_check is GW_OK.
{
pw_begin++ = &pword;
}
}
I find this a gruesome waste of space, but that is only style! You go
with what feels right.
pw_begin = NULL;

}

*cnt = idx;

return mem_check;
}


int get_single_word( char** pc )
{
int mem_check;
unsigned idx;
int ch;

size_t curr_size;
char *new_mem;
char *pc_begin;

mem_check = GSW_ENOMEM; /* will updat eit on first use */
curr_size = WORD_SIZE;

*pc = calloc(curr_size, sizeof(**pc));

if( (! *pc) )
{
mem_check = GSW_ENOMEM;
return mem_check;
}
else
{
mem_check = GSW_OK;
pc_begin = *pc;
}

while( (ch = getchar()) && (isspace( (unsigned char) ch)) )
Ah! The cast is wrong here. Not just unneeded, but wrong. I'll
gladly say why but I think you get way more out of it if you can work
out why for yourself. It won't actually fail o any system that I can
recall but it is, technically, not portable.
{
continue; /* skip leading white space */
}
if( EOF != ch )
{
*pc_begin++ = ch;
}

while( (GSW_OK == mem_check) &&
((ch = getchar()) != EOF) &&
(! isspace( (unsigned char) ch)) )
And here it is unneeded but can't, even theoretically, cause a
problem.
{
if( idx == curr_size )
{
new_mem = realloc( pc_begin, (2 * curr_size * sizeof(*new_mem)));

if( new_mem )
{
pc_begin = new_mem;
Again, is this right? New characters need to go after the ones that
are there already.
curr_size *= 2;
}
else
{
mem_check = GSW_ENORESIZE; /* error, couldn't not enlarge */
*pc_begin = '\0';
return mem_check;
}
}

if( GSW_OK == mem_check )
{
*pc_begin++ = ch;
}

}
*pc_begin = '\0';
return mem_check;
}
--
Ben.
Sep 18 '08 #138
arnuld <su*****@invalid.addresswrites:
>On Thu, 18 Sep 2008 09:14:41 +0000, Richard Heathfield wrote:
[...]
>> **pw = calloc( arr_size, sizeof **pw );
>Surely you mean *pw = calloc( arr_size, sizeof **pw );


you say that calloc() will automatically return a pointer to pointer ?
[...]

No, calloc() returns a void*. The assignment implicitly converts that
void* result to the type of the left side; in this case, whatever type
*pw has.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 18 '08 #139
arnuld wrote:
On Thu, 18 Sep 2008 09:04:49 +0000, Richard Heathfield wrote:
I've never heard such baloney. C is a language. Turbo C is an
ancient implementation, no longer supported, which runs on only one
tiny class of platforms.

I did not know that TURBO C is an ancient compiler. As of 2008, the
Indian Computer Education system still rely on TURBO C compiler.

That's because it's free.


Brian
Sep 18 '08 #140
Andrew Poelstra wrote:
On 2008-09-17, arnuld <su*****@invalid.addresswrote:

My meaning of academic means, "being not practical" . In Indian
computer education system, clrscr() is the function that belongs to
a language named TURBO C, which is better than C. There is only one
good C and that is TURBO C. Same for VC++ which, of course , is
much better than C++. Microsoft has created a better language than
C.

Well, TURBO C is not C, and VC++ is not C++. Microsoft should not have
named their products so similarly to those real languages.
Then you should the same complaint about gcc and almost every other C
implementation. Almost all offer some sort of extensions.

Turbo C contained a nearly conforming C89 compiler. I believe I've
heard that there were a few bugs, but I don't recall what they were.
The manual had a portability statement for every library function
included that specified whether it was ANSI C, UNIX, or
platform-specific.

Oh, and Turbo C was Borland, not Microsoft.


Brian
Sep 18 '08 #141
Richard Heathfield wrote:
arnuld said:
This whole program is based on that condition of *pc != NULL. Why
don't we put a line like, *pc == NULL and then return from the
program with the ENOMEM value right there ?

Lots of people would write it like that. In my code, I consider an
"early return" like that to be a bug that I should fix, because in my
code I want every function and every loop to have one entry point and
one exit point. I find that this makes my programs much easier to
read and thus to maintain.
Our company coding standard now allows early return for initial
parameter checking. In the old days, the usual method was something
like:

int func(int a, int b)
{
returnval = 0;

if (a 10)
{
returnval = -1;
}
else if (b 20)
{
returnval = -2;
}

if (returnval == 0)
{
/* do the real work and set returnval appropriately */
}

return returnval;
}

Now you can do:

int func(int a, int b)
{
returnval = 0;

if (a 10)
{
return -1;
}
if (b 20)
{
return -2;
}

/* do the real work and set returnval appropriately */

return returnval;
}
I don't know if it's better, worse, or just differently-abled.

Brian
Sep 18 '08 #142
On Thu, 18 Sep 2008 22:46:07 +0500, arnuld wrote:
You are wrong. Most Indian students say that you need Windows to run a
computer, without Windows you can not use a computer. I have yet to meet
a person who uses Linux as his daily use OS.
Off topic, but what the hell. I, living in Southern California, have yet
to meet anybody who uses linux. Besides myself, and people I have given
computers to. I work in construction, and have been in many offices, and
have seen nothing but window and mac boxes. Eventually, if my children
let me have some free time, I will join a LUG.

sf
Sep 19 '08 #143
On Fri, 19 Sep 2008 05:20:08 +0000, jellybean stonerfish wrote:
Off topic, but what the hell. I, living in Southern California, have yet
to meet anybody who uses linux. Besides myself, and people I have given
computers to. I work in construction, and have been in many offices, and
have seen nothing but window and mac boxes. Eventually, if my children
let me have some free time, I will join a LUG.
Thats what *exactly* I am telling. Indian students and users are same as
American students or users. People wrongly believe that Indian guys are
much more computer literate. Like US or Germany, most don't even
understand the difference between OS and Windows.

--
www.lispmachine.wordpress.com
my email is @ the above blog.
Google Groups is Blocked. Reason: Excessive Spamming

Sep 19 '08 #144
On Fri, 19 Sep 2008 10:35:57 +0500, arnuld wrote:
>On Fri, 19 Sep 2008 05:20:08 +0000, jellybean stonerfish wrote:
>Off topic, but what the hell. I, living in Southern California, have
yet to meet anybody who uses linux. Besides myself, and people I have
given computers to. I work in construction, and have been in many
offices, and have seen nothing but window and mac boxes. Eventually,
if my children let me have some free time, I will join a LUG.

Thats what *exactly* I am telling. Indian students and users are same as
American students or users. People wrongly believe that Indian guys are
much more computer literate. Like US or Germany, most don't even
understand the difference between OS and Windows.
In other words, stupidity has no boundaries.

sf
Sep 19 '08 #145
arnuld wrote, On 19/09/08 06:35:
>On Fri, 19 Sep 2008 05:20:08 +0000, jellybean stonerfish wrote:
>Off topic, but what the hell. I, living in Southern California, have yet
to meet anybody who uses linux. Besides myself, and people I have given
computers to. I work in construction, and have been in many offices, and
have seen nothing but window and mac boxes. Eventually, if my children
let me have some free time, I will join a LUG.

Thats what *exactly* I am telling. Indian students and users are same as
American students or users.
It varies in India, America and the US. There are definitely people in
Silicon Valley who know about and use Linux. The majority of people
outside IT don't know and don't care.
People wrongly believe that Indian guys are
much more computer literate.
I have talked to other people involved in SW outsourcing to India and
I've yet to meet people who believe that. Don't get me wrong, I'm not
saying Indian people are less intelligent, just that the people I've met
involved in doing outsourcing SW to India do it because the staff are
cheap enough that you can hire enough to make up for the staff being
*less* able. This is one reason why certain key parts of the SW
development are kept in the UK/USA/wherever.
Like US or Germany, most don't even
understand the difference between OS and Windows.
For most people the computer should just be an appliance. They want to
do word processing, play games, browse the web etc. It is US who should
be making it possible to do that *without* knowing or caring about the
OS. Of course, the OS needs to be locked down for people like that so
that they can't break it (cue OS wars). People in IT and SW development
are and should be different.
--
Flash Gordon
Sep 19 '08 #146
On Thu, 18 Sep 2008 13:25:51 +0000, Richard Heathfield wrote:
...SNIP...
What you meant to write is:

*pw_begin++ = pword;

This is legal because * has higher precedence than = so what happens is
that ++ yields the old value of pw_begin, * gives us the object to which
that old value points, and = now assigns to the object. Since pw_begin has
type char **, pw_begin++ has type char **, *pw_begin++ has type char * and
is a real object, so we can assign a char * value to it. pword is one such
value.

I understood completely the *pw_begin++ part, the confusion remains in
in the Right Hand Side, the pword has triple levels of indirection ***.
while pw_begin has two **. So dereferencing pw_begin gives me single level
of indirection. SO it looks like this:

* = ***
thats what confusing me an din that confusion I did &pword :(

--
www.lispmachine.wordpress.com
my email is @ the above blog.
Google Groups is Blocked. Reason: Excessive Spamming

Sep 19 '08 #147
arnuld said:

<snip>
I understood completely the *pw_begin++ part, the confusion remains in
in the Right Hand Side, the pword has triple levels of indirection ***.
No, it doesn't. Read the code again: pword is of type char *.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Sep 19 '08 #148
CBFalconer <cb********@yahoo.comwrote:
Richard Bos wrote:
There is also the catch that strtok() scribbles over its
parameter, meaning that you cannot use it to tokenise either a
string literal, or data you want to keep. This is something that
catches out a lot of less well-informed newbies.

Try this:
No thanks; I've already written my own, several times for several
different situations, and I don't think a single solution would do.
Besides, it's such a simple thing to write a basic version of, with such
opportunity for a variety of approaches, that I believe this is one of
those problems which it does a newbie good to attempt his own instead of
using someone else's almost-perfect-enough solution.

Richard
Sep 19 '08 #149
On Fri, 19 Sep 2008 08:55:41 +0000, Richard Heathfield wrote:
>arnuld said:
I understood completely the *pw_begin++ part, the confusion remains in
in the Right Hand Side, the pword has triple levels of indirection ***.
No, it doesn't. Read the code again: pword is of type char *.
Eh.. I think I am overwhelmed by the power pointers and arrays provide, as
with great power comes great responsibility, like Spiderman said. Anyway,
I have created little edited version of get_single_word and I wrote it
fully without taking a single look at the clc posted solutions. I am
posting it here as now it contains my own style of programming. See if you
notice something god or bad. This is final version and after that we will
start discussing get_words() and next:
/* A program that takes a single word from input
* it uses a while loop and dynamic memory allocation to take
* continuous input form user
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
enum { WORD_SIZE = 28 };
enum { GSW_OK, GSW_ENOMEM, GSW_ENORESIZE } ;
int get_single_word( char** );

int main( void )
{
char* pword;
while( (GSW_OK == get_single_word(&pword)) && ( *pword != 0) )
{
printf("You entered: [%s]\n", pword);
}
return 0;
}


int get_single_word( char** ppc )
{
unsigned idx;
int ch;
size_t arr_size;
char* pw_begin;
char* new_mem;

arr_size = WORD_SIZE;
*ppc = malloc(arr_size * sizeof(**ppc));
pw_begin = *ppc;
if( NULL == ppc )
{
return GSW_ENOMEM;

}
while( (EOF != (ch = getchar())) && isspace(ch) )
{
continue; /* trailing whitespace */
}
if( EOF != ch )
{
*pw_begin++ = ch;
}
for( idx = 0; (EOF != (ch = getchar())) && (! isspace(ch)); ++idx )
{
if( WORD_SIZE == idx )
{
new_mem = realloc( *ppc, (2 * WORD_SIZE * sizeof **ppc) );
*ppc = new_mem;

if( NULL == new_mem )
{
return GSW_ENORESIZE;
}
}

*pw_begin++ = ch;
}
*pw_begin = '\0';

return GSW_OK;
}


--
www.lispmachine.wordpress.com
my email is @ the above blog.
Google Groups is Blocked. Reason: Excessive Spamming

Sep 19 '08 #150

This discussion thread is closed

Replies have been disabled for this discussion.

By using this site, you agree to our Privacy Policy and Terms of Use.