Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #72851 > unrolled thread
| Started by | Alla _ <modelling.data@gmail.com> |
|---|---|
| First post | 2015-10-14 08:59 -0700 |
| Last post | 2015-10-15 08:20 +0000 |
| Articles | 9 — 7 participants |
Back to article view | Back to comp.lang.c
While loop with bool, same issue Alla _ <modelling.data@gmail.com> - 2015-10-14 08:59 -0700
Re: While loop with bool, same issue Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-10-14 13:31 -0400
Re: While loop with bool, same issue August Karlstrom <fusionfile@gmail.com> - 2015-10-14 20:11 +0200
Re: While loop with bool, same issue Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-10-14 14:26 -0400
Re: While loop with bool, same issue Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-14 20:44 +0100
Re: While loop with bool, same issue Siri Cruz <chine.bleu@yahoo.com> - 2015-10-14 10:45 -0700
Re: While loop with bool, same issue Keith Thompson <kst-u@mib.org> - 2015-10-14 13:15 -0700
Re: While loop with bool, same issue Keith Thompson <kst-u@mib.org> - 2015-10-14 11:42 -0700
Re: While loop with bool, same issue Jorgen Grahn <grahn+nntp@snipabacken.se> - 2015-10-15 08:20 +0000
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2015-10-14 08:59 -0700 |
| Subject | While loop with bool, same issue |
| Message-ID | <96769962-2192-444e-a738-01306756e949@googlegroups.com> |
Hello!
I have decided to create a new topic, although
with the issue that I have already raised previously
(previous one is clear to me now).
/** Counting words in a piece of text **/
#include <stdio.h>
#include <stdbool.h>
bool alphabetic (const char c)
{
if ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') )
return true;
else
return false;
}
void read_line (char buffer [])
{
char character;
int i = 0;
do
{
character = getchar();
buffer[i] = character;
i++;
}
while (character != '\n');
buffer[i - 1] = '\0'; // i - 1 because the index character was incremented one extra time inside the loop the last time it was executed
}
int count_words (const char string[])
{
int i;
int word_count = 0;
bool look_for_word = true;
for (i = 0; string[i] != '\0'; i++)
if (alphabetic (string [i]))
{
if (look_for_word)
{
word_count++;
look_for_word = false;
}
}
else
look_for_word = true;
return word_count;
}
int main (void)
{
char text[81];
int total_words = 0;
bool end_of_text = false;
printf ("Type in your text.\n");
printf ("When done, press 'RETURN'.\n\n");
while ( !end_of_text )
{
read_line (text);
if (text[0] == '\0')
end_of_text = true;
/** tests the input line that is stored
inside the text array to see if just the Enter (or Return)
key was pressed; if so, then the buffer contains the null
string, in which case the flag end_of_text is set to true
to signal that all of the text has been entered **/
else
total_words += count_words (text);
}
printf ("\nThere are %i words in the above text.\n", total_words);
return 0;
}
The part that I am not sure I understand correctly:
while ( !end_of_text )
{
read_line (text);
if (text[0] == '\0')
end_of_text = true;
/** tests the input line that is stored
inside the text array to see if just the Enter (or Return)
key was pressed; if so, then the buffer contains the null
string, in which case the flag end_of_text is set to true
to signal that all of the text has been entered **/
else
total_words += count_words (text);
}
The program has assigned a false value to end_of_text.
Hence, the condition in the while loop should mean
end_of_text is true.
This is how I read each line of the code:
Before the user has typed in his string, end_of_text
is true (no text exists); therefore, while (end_of_text is true),
get the text from the user (read_line(text).
If the user has only pressed Enter, set end_of_ text to true.
Isn't end_of_text already true because we are inside the loop with
that exact condition; and also because read_line(text) ends
with the NULL character, thus indicating the end of the text?
Otherwise, set end_of_text to false and compute total_words.
I am not sure I understand why while loop is required.
Thank you!
[toc] | [next] | [standalone]
| From | Eric Sosman <esosman@comcast-dot-net.invalid> |
|---|---|
| Date | 2015-10-14 13:31 -0400 |
| Message-ID | <mvm3e9$fjs$1@dont-email.me> |
| In reply to | #72851 |
On 10/14/2015 11:59 AM, Alla _ wrote:
> Hello!
>
> I have decided to create a new topic, although
> with the issue that I have already raised previously
> (previous one is clear to me now).
>
> /** Counting words in a piece of text **/
>
> #include <stdio.h>
> #include <stdbool.h>
>
> bool alphabetic (const char c)
> {
> if ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') )
> return true;
> else
> return false;
> }
Aside: The `if' is unnecessary. You could simply do
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
instead. (I mention this mostly because you seem to use this
silly pattern frequently. It's not "wrong," just silly.)
> void read_line (char buffer [])
> {
> char character;
> int i = 0;
>
> do
> {
> character = getchar();
> buffer[i] = character;
> i++;
> }
> while (character != '\n');
>
> buffer[i - 1] = '\0'; // i - 1 because the index character was incremented one extra time inside the loop the last time it was executed
> }
Aside: This is, more or less, a re-implementation of the
COMPLETELY UNSAFE gets() function, a function SO BAD that it has
been removed from the latest C Standard. (I say "more or less"
because there are errors: See question 12.1 on the comp.lang.c
FAQ page at <http://www.c-faq.com/> for one of them, and you'll
learn about the other if you ever type your system's end-of-input
keystroke -- maybe CTRL-D or CTRL-Z -- at the keyboard.)
> int count_words (const char string[])
> {
> int i;
> int word_count = 0;
> bool look_for_word = true;
>
> for (i = 0; string[i] != '\0'; i++)
> if (alphabetic (string [i]))
> {
> if (look_for_word)
> {
> word_count++;
> look_for_word = false;
> }
> }
>
> else
> look_for_word = true;
>
> return word_count;
> }
>
> int main (void)
> {
> char text[81];
> int total_words = 0;
> bool end_of_text = false;
>
> printf ("Type in your text.\n");
> printf ("When done, press 'RETURN'.\n\n");
>
> while ( !end_of_text )
> {
> read_line (text);
>
> if (text[0] == '\0')
> end_of_text = true;
> /** tests the input line that is stored
> inside the text array to see if just the Enter (or Return)
> key was pressed; if so, then the buffer contains the null
> string, in which case the flag end_of_text is set to true
> to signal that all of the text has been entered **/
> else
> total_words += count_words (text);
> }
>
> printf ("\nThere are %i words in the above text.\n", total_words);
>
> return 0;
>
> }
>
> The part that I am not sure I understand correctly:
>
> while ( !end_of_text )
> {
> read_line (text);
>
> if (text[0] == '\0')
> end_of_text = true;
>
> /** tests the input line that is stored
> inside the text array to see if just the Enter (or Return)
> key was pressed; if so, then the buffer contains the null
> string, in which case the flag end_of_text is set to true
> to signal that all of the text has been entered **/
>
> else
> total_words += count_words (text);
> }
>
> The program has assigned a false value to end_of_text.
To start with, yes. (Actually, it's an initialization, not an
assignment, but that's a nitpick.)
> Hence, the condition in the while loop should mean
> end_of_text is true.
Did you miss the leading `!' character? Have you learned
yet what the `!' means?
> This is how I read each line of the code:
>
> Before the user has typed in his string, end_of_text
> is true (no text exists); therefore, while (end_of_text is true),
> get the text from the user (read_line(text).
No; see the remark about `!' above.
> If the user has only pressed Enter, set end_of_ text to true.
> Isn't end_of_text already true because we are inside the loop with
> that exact condition; and also because read_line(text) ends
> with the NULL character, thus indicating the end of the text?
No.
> Otherwise, set end_of_text to false and compute total_words.
The variable is initialized to false, but is never set false
thereafter. The only value assigned to it after initialization
is true.
> I am not sure I understand why while loop is required.
How many lines of input could you process if there were no loop?
--
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM
[toc] | [prev] | [next] | [standalone]
| From | August Karlstrom <fusionfile@gmail.com> |
|---|---|
| Date | 2015-10-14 20:11 +0200 |
| Message-ID | <mvm5td$o3e$1@speranza.aioe.org> |
| In reply to | #72861 |
On 2015-10-14 19:31, Eric Sosman wrote: > Aside: The `if' is unnecessary. You could simply do > > return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); Or maybe return isalpha(c); after including ctype.h. -- August
[toc] | [prev] | [next] | [standalone]
| From | Eric Sosman <esosman@comcast-dot-net.invalid> |
|---|---|
| Date | 2015-10-14 14:26 -0400 |
| Message-ID | <mvm6lk$srb$1@dont-email.me> |
| In reply to | #72865 |
On 10/14/2015 2:11 PM, August Karlstrom wrote:
> On 2015-10-14 19:31, Eric Sosman wrote:
>> Aside: The `if' is unnecessary. You could simply do
>>
>> return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
>
> Or maybe
>
> return isalpha(c);
>
> after including ctype.h.
I think that's been mentioned elsethread. Also, note that
you need
return isalpha((unsigned char) c);
... thanks to some unfortunate "hysterical raisins."
--
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2015-10-14 20:44 +0100 |
| Message-ID | <87d1wh9qvr.fsf@bsb.me.uk> |
| In reply to | #72861 |
Just an FYI post...
Eric Sosman <esosman@comcast-dot-net.invalid> writes:
> On 10/14/2015 11:59 AM, Alla _ wrote:
>> Hello!
>>
>> I have decided to create a new topic, although
>> with the issue that I have already raised previously
>> (previous one is clear to me now).
>>
>> /** Counting words in a piece of text **/
>>
>> #include <stdio.h>
>> #include <stdbool.h>
>>
>> bool alphabetic (const char c)
>> {
>> if ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') )
>> return true;
>> else
>> return false;
>> }
>
> Aside: The `if' is unnecessary. You could simply do
>
> return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
>
> instead. (I mention this mostly because you seem to use this
> silly pattern frequently. It's not "wrong," just silly.)
Sadly, it's from the book.
>> void read_line (char buffer [])
>> {
>> char character;
>> int i = 0;
>>
>> do
>> {
>> character = getchar();
>> buffer[i] = character;
>> i++;
>> }
>> while (character != '\n');
>>
>> buffer[i - 1] = '\0'; // i - 1 because the index character was incremented one extra time inside the loop the last time it was executed
>> }
>
> Aside: This is, more or less, a re-implementation of the
> COMPLETELY UNSAFE gets() function, a function SO BAD that it has
> been removed from the latest C Standard. (I say "more or less"
> because there are errors: See question 12.1 on the comp.lang.c
> FAQ page at <http://www.c-faq.com/> for one of them, and you'll
> learn about the other if you ever type your system's end-of-input
> keystroke -- maybe CTRL-D or CTRL-Z -- at the keyboard.)
Again, it's from the textbook though with a slight name change and a
comment added.
Dorothy Parker comes to mind... "This is not a book to be cast aside
lightly. It should be thrown with great force." (paraphrased)
No book on C should be cavalier about buffer overruns.
<snip>
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Siri Cruz <chine.bleu@yahoo.com> |
|---|---|
| Date | 2015-10-14 10:45 -0700 |
| Message-ID | <chine.bleu-B63CFA.10453814102015@88-209-239-213.giganet.hu> |
| In reply to | #72851 |
In article <96769962-2192-444e-a738-01306756e949@googlegroups.com>,
Alla _ <modelling.data@gmail.com> wrote:
> bool alphabetic (const char c)
> {
> if ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') )
> return true;
> else
> return false;
> }
(1) Letters are not guaranteed contiguous. In EBCDIC they are not.
(2) Don't be afraid of using the library.
(3) Eventually char may be a 16 bit integer carrying Unicode. Letters are not
contiguous in Unicode.
#include <ctype.h>
bool alphabetic (const char c) {return isalpha(c);}
> void read_line (char buffer [])
> {
> char character;
> int i = 0;
>
> do
> {
> character = getchar();
> buffer[i] = character;
> i++;
> }
> while (character != '\n');
>
> buffer[i - 1] = '\0'; // i - 1 because the index character was
> incremented one extra time inside the loop the last time it was executed
> }
(1) If you passed in the buffer size, you could check for buffer overrun.
(2) and you could use fgets.
(3) Pretend end of file is an empty line so the function client doesn't have to
deal with that.
void read_line (char buffer [], size_t n) {
if (n==0) {
;
}else if (fgets(buffer, n, stdin)) {
char *nl = strchr(buffer, '\n');
if (nl) *nl = 0;
}else {
*buffer = 0
}
}
> int count_words (const char string[])
> {
> int i;
> int word_count = 0;
> bool look_for_word = true;
>
> for (i = 0; string[i] != '\0'; i++)
> if (alphabetic (string [i]))
> {
> if (look_for_word)
> {
> word_count++;
> look_for_word = false;
> }
> }
>
> else
> look_for_word = true;
>
> return word_count;
> }
>
> int main (void)
> {
> char text[81];
> int total_words = 0;
> bool end_of_text = false;
>
> printf ("Type in your text.\n");
> printf ("When done, press 'RETURN'.\n\n");
>
> while ( !end_of_text )
> {
> read_line (text);
>
> if (text[0] == '\0')
> end_of_text = true;
> /** tests the input line that is stored
> inside the text array to see if just the Enter (or Return)
> key was pressed; if so, then the buffer contains the null
> string, in which case the flag end_of_text is set to true
> to signal that all of the text has been entered **/
> else
> total_words += count_words (text);
> }
>
> printf ("\nThere are %i words in the above text.\n", total_words);
>
> return 0;
>
> }
>
> The part that I am not sure I understand correctly:
>
> while ( !end_of_text )
> {
> read_line (text);
>
> if (text[0] == '\0')
> end_of_text = true;
>
> /** tests the input line that is stored
> inside the text array to see if just the Enter (or Return)
> key was pressed; if so, then the buffer contains the null
> string, in which case the flag end_of_text is set to true
> to signal that all of the text has been entered **/
>
> else
> total_words += count_words (text);
> }
>
> The program has assigned a false value to end_of_text.
>
> Hence, the condition in the while loop should mean
> end_of_text is true.
On the first iteration end_of_text==false, !end_of_text==true, the loop
condition is true, and the iteration continues.
> This is how I read each line of the code:
! means not. The loop condition is while end_of_text is false.
> I am not sure I understand why while loop is required.
If you want to read more than one line, you need some kind of iteration.
--
:-<> Siri Seal of Disavowal #000-001. Disavowed. Denied. Deleted.
'I desire mercy, not sacrifice.'
When is a Kenyan not a Kenyan? When he's a Canadian.
That's People's Commissioner Siri Cruz now. Punch!
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2015-10-14 13:15 -0700 |
| Message-ID | <lntwpt6wc9.fsf@kst-u.example.com> |
| In reply to | #72862 |
Siri Cruz <chine.bleu@yahoo.com> writes:
[...]
> (3) Eventually char may be a 16 bit integer carrying Unicode.
16 bits is not enough to represent all Unicode characters.
> Letters are not contiguous in Unicode.
No, but a-z and A-Z are. Depending on the program's requirements, you
might actually want to check whether a character is one of the 52 Latin
letters, rather than whether it's a "letter" in any more general sense.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2015-10-14 11:42 -0700 |
| Message-ID | <lnfv1d8f7q.fsf@kst-u.example.com> |
| In reply to | #72851 |
Alla _ <modelling.data@gmail.com> writes:
> I have decided to create a new topic, although
> with the issue that I have already raised previously
> (previous one is clear to me now).
>
> /** Counting words in a piece of text **/
>
> #include <stdio.h>
> #include <stdbool.h>
>
> bool alphabetic (const char c)
> {
> if ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') )
> return true;
> else
> return false;
> }
This is more simply written as:
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
Strictly speaking the parentheses aren't necessary, but they do make it
clearer.
There's not much point in defining the parameter as "const". It has no
meaning to the caller.
> void read_line (char buffer [])
> {
> char character;
> int i = 0;
>
> do
> {
> character = getchar();
getchar() returns an int, but you're assigning it to a char. That means
you can't reliably detect EOF ...
> buffer[i] = character;
> i++;
> }
> while (character != '\n');
... which you're not trying to do anyway. It *is* possible for
getchar() to return EOF in the middle of a line. If it does, you have
an infinite loop.
> buffer[i - 1] = '\0'; // i - 1 because the index character was incremented one extra time inside the loop the last time it was executed
> }
> int count_words (const char string[])
> {
> int i;
> int word_count = 0;
> bool look_for_word = true;
I suggest that "looking_for_word" would be a clearer name.
> for (i = 0; string[i] != '\0'; i++)
> if (alphabetic (string [i]))
> {
> if (look_for_word)
> {
> word_count++;
> look_for_word = false;
> }
> }
>
> else
> look_for_word = true;
>
> return word_count;
> }
>
> int main (void)
> {
> char text[81];
> int total_words = 0;
> bool end_of_text = false;
>
> printf ("Type in your text.\n");
> printf ("When done, press 'RETURN'.\n\n");
>
> while ( !end_of_text )
> {
> read_line (text);
`text` is just 81 characters long. Your read_line function will read as
many characters as you give it. If your cat stands on the space bar,
you'll have undefined behavior.
[snip]
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Jorgen Grahn <grahn+nntp@snipabacken.se> |
|---|---|
| Date | 2015-10-15 08:20 +0000 |
| Message-ID | <slrnn1uof2.5q5.grahn+nntp@frailea.sa.invalid> |
| In reply to | #72871 |
On Wed, 2015-10-14, Keith Thompson wrote:
> Alla _ <modelling.data@gmail.com> writes:
...
>> bool alphabetic (const char c)
>> {
>> if ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') )
>> return true;
>> else
>> return false;
>> }
> There's not much point in defining the parameter as "const". It has no
> meaning to the caller.
For the benefit of the OP, a clarification:
Not much point in /this/ function, but if it had been more complex
the const could help detect errors where you modify 'c' by accident.
/Jorgen
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c
csiph-web