470,874 Members | 1,474 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

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

Reading input problem

I have a function named getword that read every single input from std.
input.

WHAT I WANTED: I want it read the word if it has less than or equal to 30
characters. Anything else beyond that should be discarded and it should
ask the user for new input. Ctrl-D should exit from the program.

WHAT I GOT: It reads anything beyond 30 characters as the next word :\ and
I have to press Ctrl-D two times to exit from the program.
/* This program will simply create an array of pointers to integers
* and will fill it with some values while using malloc to create
* pointers to fill the array and then will print the values pointed
* by those pointers
*
* version 1.1
*
*/

#include <stdio.h>
#include <ctype.h>
enum { MAX = 30 };

int getword( char *, int );
int main( void )
{
char word[MAX];

while( getword( word, MAX ) )
{
printf( "---------- %s\n", word );
}

return 0;
}

/* A program that takes a single word as input. It will discard
* the whole input if it contains anything other than the 26 alphabets
* of English. If the input word contains more than 30 letters then only
* the extra letters will be discarded . For general purpose usage of
* English it does not make any sense to use a word larger than this size.
* Nearly every general purpose word can be expressed in a word with less
* than or equal to 30 letters.
*
*/
int getword( char *word, int max_length )
{
int c;
char *w = word;
while( isspace( c = getchar() ) )
{
;
}

if( isalpha( c ) )
{
*w++ = c;
}

while( --max_length && (c = getchar()) )
{
if( isalpha( c ) )
{
*w++ = c;
}
else if( isspace( c ) || c == EOF)
{
*w = '\0';
break;
}
else
{
return 0;
}
}
*w = '\0';
return word[0];
}

================ OUTPUT =====================
[arnuld@raj C]$ gcc -ansi -pedantic -Wall -Wextra test.c
[arnuld@raj C]$ ./a.out
like
---------- like
this
---------- this
lllllllllllllllpppppppppppppqqqqqqqqqqqqqqqqqqqqqq qqqqqqqqqqqqqqqqqqqpppppppppppdddddddddddddddddddd dddddd
---------- lllllllllllllllpppppppppppppqq
---------- qqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
---------- qqqqqqqqqpppppppppppdddddddddd
---------- dddddddddddddddd
[arnuld@raj C]$


--
http://lispmachine.wordpress.com/
my email ID is @ the above blog.
just check the "About Myself" page :)

Jun 27 '08 #1
24 1797
arnuld <su*****@see.sigs.invalidwrites:
I have a function named getword that read every single input from std.
input.

WHAT I WANTED: I want it read the word if it has less than or equal to 30
characters.
Be careful with your counts. Most people would say that a 30
character words needs a 31 character array to store it. I'd say
your code accepts words up to and including 29 characters.
Anything else beyond that should be discarded and it should
ask the user for new input. Ctrl-D should exit from the program.
This is underspecified. At least in one sense, if "anything else
beyond" has been discarded, how can there be any more input? Maybe
you want to throw away any more input on that line?
WHAT I GOT: It reads anything beyond 30 characters as the next word :\ and
I have to press Ctrl-D two times to exit from the program.
You can't change the Ctrl-D behaviour without resorting to some
serious OS-specific code. You may need a screen library like ncurses
if you go much further.

--
Ben.
Jun 27 '08 #2
arnuld wrote:
>
I have a function named getword that read every single input from
std. input.

WHAT I WANTED: I want it read the word if it has less than or
equal to 30 characters. Anything else beyond that should be
discarded and it should ask the user for new input. Ctrl-D should
exit from the program.

WHAT I GOT: It reads anything beyond 30 characters as the next
word :\ and I have to press Ctrl-D two times to exit from the
program.
Try this. To generate EOF press ctl-D at line beginning.

/* Get the next word consisting of alpha chars */
/* Return the terminating character (or EOF) */
/* Downshift the acquired word */
static int nextword(FILE *f, char *buffer, int max)
{
int i, ch;

while ((!isalpha(ch = getc(f))) && (ch != EOF)) continue;
if (EOF != ch) {
i = 0; max--;
do {
if (i < max) buffer[i++] = tolower(ch);
} while (isalpha(ch = getc(f)));
buffer[i] = '\0'; /* terminate string */
}
return ch;
} /* nextword */

(It's part of wdfreq.c, in the hashlib package.)

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
** Posted from http://www.teranews.com **
Jun 27 '08 #3
On Wed, 07 May 2008 12:35:35 -0400, CBFalconer wrote:

Try this. To generate EOF press ctl-D at line beginning.
... SNIP...

since I do not have any FILE* so I changed it a little bit:

int main( void )
{
char word[MAX];

while( getword2( word, MAX ) )
{
printf( "---------- %s\n", word );
}

return 0;
}

static int getword2(char *buffer, int max)
{
int i, ch;

while ( (!isalpha(ch = getchar())) && (ch != EOF) )
{
continue;
}

if (EOF != ch)
{
i = 0;
--max;

do {
if( i < max )
{
buffer[i++] = ch;
}

} while ( isalpha(ch = getchar()) );
buffer[i] = '\0'; /* terminate string */
}
return ch;
}

================ OUTPUT ======================

[arnuld@raj C]$ gcc -ansi -pedantic -Wall -Wextra test.c
test.c:125: warning: 'getword3' defined but not used
[arnuld@raj C]$ ./a.out
likethis
---------- likethis
and about
---------- and
---------- about
pppppppppppppppppllllllllllllllllllqqqqqqqqqqqqqq
---------- pppppppppppppppppllllllllllll
like2
---------- like
lik678uyt
---------- lik
---------- uyt
---------- uyt
---------- uyt
---------- uyt
---------- uyt
---------- uyt
---------- uyt
CB^%~!~%!++))::"?<Falconer
---------- CB
---------- Falconer

[arnuld@raj C]$

you see the output. It has 3 problems:

1.) it does not discard the words containing anything else than
letters. Rather it discards everything else and read the letters. I simply
want to discard the *whole* word if it contains anything else than 26
letters of English. See the last input where I input your name with junk
between CB and Falconer and it read them :(
2.) Ctrl-D does not do any exit but prints the last word it read :(

3.) thats good point, it discards the letters beyond MAX length :)

--
http://lispmachine.wordpress.com/
my email ID is @ the above blog.
just check the "About Myself" page :)

Jun 27 '08 #4
On Wed, 07 May 2008 12:35:35 -0400, CBFalconer wrote:
Try this. To generate EOF press ctl-D at line beginning.

/* Get the next word consisting of alpha chars */
/* Return the terminating character (or EOF) */
/* Downshift the acquired word */
static int nextword(FILE *f, char *buffer, int max)
{
...SNIP...
one more nit, why use static int instead of int as return value ?


--
http://lispmachine.wordpress.com/
my email ID is @ the above blog.
just check the "About Myself" page :)

Jun 27 '08 #5
On Wed, 07 May 2008 10:58:41 +0100, Ben Bacarisse wrote:

Be careful with your counts. Most people would say that a 30
character words needs a 31 character array to store it. I'd say
your code accepts words up to and including 29 characters.
oh.. I even forgot this fact. I changed it to 30 + 1
This is underspecified. At least in one sense, if "anything else
beyond" has been discarded, how can there be any more input? Maybe
you want to throw away any more input on that line?
yes, exactly

You can't change the Ctrl-D behaviour without resorting to some
serious OS-specific code. You may need a screen library like ncurses
if you go much further.

I will accept it.


--
http://lispmachine.wordpress.com/
my email ID is @ the above blog.
just check the "About Myself" page :)

Jun 27 '08 #6
arnuld wrote:
>On Wed, 07 May 2008 12:35:35 -0400, CBFalconer wrote:


>Try this. To generate EOF press ctl-D at line beginning.

/* Get the next word consisting of alpha chars */
/* Return the terminating character (or EOF) */
/* Downshift the acquired word */
static int nextword(FILE *f, char *buffer, int max)
{
...SNIP...

one more nit, why use static int instead of int as return value ?
The function is declared static, not the int!

--
Ian Collins.
Jun 27 '08 #7
arnuld wrote:

By the way, your clock appears to be rather fast.

Date: Fri, 09 May 2008 02:36:41 +0500

It's only Thursday afternoon here and no one is ahead of us!

--
Ian Collins.
Jun 27 '08 #8
On Thu, 08 May 2008 17:00:03 +1200, Ian Collins wrote:
The function is declared static, not the int!
oops!

So, is it a good practice or or a C style to make every function/variable
static if I have only source file ?


--
http://lispmachine.wordpress.com/
my email ID is @ the above blog.
just check the "About Myself" page :)

Jun 27 '08 #9
On Wed, 07 May 2008 10:58:41 +0100, Ben Bacarisse wrote:
Be careful with your counts. Most people would say that a 30
character words needs a 31 character array to store it. I'd say
your code accepts words up to and including 29 characters.
with maxlength = 30, my function reads 30 characters plus the '\0':

int getword( char *word, int max_length )
{
int c;
char *w = word;
while( !( isalpha( c = getchar() ) ) && EOF != c )
{
continue;
}

do {
if( isalpha( c ) )
{
*w++ = c;
}
else if( isspace( c ) || c == EOF)
{
*w = '\0';
break;
}
else
{
return 0;
}

} while( --max_length && (c = getchar()) );
*w = '\0';
return word[0];
}

--
http://lispmachine.wordpress.com/
my email ID is @ the above blog.
just check the "About Myself" page :)

Jun 27 '08 #10
arnuld wrote:
>On Thu, 08 May 2008 17:00:03 +1200, Ian Collins wrote:
>The function is declared static, not the int!

oops!

So, is it a good practice or or a C style to make every function/variable
static if I have only source file ?
There's no harm in doing so.

--
Ian Collins.
Jun 27 '08 #11
Ian Collins said:
arnuld wrote:
>>On Thu, 08 May 2008 17:00:03 +1200, Ian Collins wrote:
>>The function is declared static, not the int!

oops!

So, is it a good practice or or a C style to make every
function/variable static if I have only source file ?
There's no harm in doing so.
....except for main, of course!

--
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
Jun 27 '08 #12
arnuld wrote:
I have a function named getword that read every single input from std.
input.

WHAT I WANTED: I want it read the word if it has less than or equal to 30
characters. Anything else beyond that should be discarded and it should
ask the user for new input.
Try this:

/* BEGIN fscanf_input.c */
/*
** There are only three different values
** that can be assigned to the int variable rc,
** from the fscanf calls in this program;
** They are:
** EOF
** 0
** 1
** If rc equals EOF, then the end of file was reached,
** or there is some other input problem;
** ferror and feof can be used to distinguish which.
** If rc equals 0, then an empty line
** (a line consisting only of one newline character)
** was entered, and the array contains garbage values.
** If rc equals 1, then there is a string in the array.
** Up to LENGTH number of characters are read
** from a line of a text stream
** and written to a string in an array.
** The newline character in the text line is replaced
** by a null character in the array.
** If the line is longer than LENGTH,
** then the extra characters are discarded.
*/
#include <stdio.h>

#define LENGTH 30
#define str(x) # x
#define xstr(x) str(x)

int main(void)
{
int rc;
char array[LENGTH + 1];

puts("The LENGTH macro is " xstr(LENGTH) ".");
do {
fputs("Enter any line of text to continue,\n"
"or just hit the Enter key to quit:", stdout);
fflush(stdout);
rc = fscanf(stdin, "%" xstr(LENGTH) "[^\n]%*[^\n]", array);
if (!feof(stdin)) {
getc(stdin);
}
if (rc == 0) {
array[0] = '\0';
}
if (rc == EOF) {
puts("rc equals EOF");
} else {
printf("rc is %d. Your string is:%s\n\n", rc, array);
}
} while (rc == 1);
return 0;
}

/* END fscanf_input.c */

--
pete
Jun 27 '08 #13
arnuld <su*****@see.sigs.invalidwrites:
>On Wed, 07 May 2008 10:58:41 +0100, Ben Bacarisse wrote:
>Be careful with your counts. Most people would say that a 30
character words needs a 31 character array to store it. I'd say
your code accepts words up to and including 29 characters.

with maxlength = 30, my function reads 30 characters plus the '\0':
Neither you nor I are in doubt about what the function does -- I was
just asking that you be careful in your comments. For example, the
above remark is again vague:

(a) the function may read many more than 30 characters;
(b) it does not read the '\0';
(c) it may store up to 30 chars;
(d) the result may be a string as long as 29.

Lots of errors can come from readers believing a program's incorrect
comments or from misunderstanding an ambiguous comment. I was just
suggesting that you take care when writing them.

--
Ben.
Jun 27 '08 #14
arnuld <su*****@see.sigs.invalidwrites:

<snip>
while( getword2( word, MAX ) )
{
printf( "---------- %s\n", word );
}
<snip>
static int getword2(char *buffer, int max)
{
int i, ch;
<snip>
return ch;
}
getword2 is unlikely to every return 0. It returns either EOF or the
last character read. I don't think that helps you. You want it to
return an indication that there is, or is not, a word to be processed.

<snip>
1.) it does not discard the words containing anything else than
letters. Rather it discards everything else and read the letters. I simply
want to discard the *whole* word if it contains anything else than 26
letters of English. See the last input where I input your name with junk
between CB and Falconer and it read them :(
I doubt anyone will write this for you. It is a rather specific input
routine and you will just have to work out a way to do it yourself.
Do you plan using pseudo-code before starting to write the C? You
will need to, I think, because such an input routine is quite
complex.

--
Ben.
Jun 27 '08 #15
arnuld wrote:
>CBFalconer wrote:
>Try this. To generate EOF press ctl-D at line beginning.

/* Get the next word consisting of alpha chars */
/* Return the terminating character (or EOF) */
/* Downshift the acquired word */
static int nextword(FILE *f, char *buffer, int max)
{
...SNIP...

one more nit, why use static int instead of int as return value ?
The return value is int, not static int. The static applies to the
function. If you read your C text you will see that it makes the
function local to the source file in which it occurs.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
** Posted from http://www.teranews.com **
Jun 27 '08 #16
arnuld wrote:
>
.... snip ...
>
CB^%~!~%!++))::"?<Falconer
---------- CB
---------- Falconer

[arnuld@raj C]$

you see the output. It has 3 problems:

1.) it does not discard the words containing anything else than
letters. Rather it discards everything else and read the letters.
I simply want to discard the *whole* word if it contains anything
else than 26 letters of English. See the last input where I input
your name with junk between CB and Falconer and it read them :(
No. Your own demo shows that it reads and discards them.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
** Posted from http://www.teranews.com **
Jun 27 '08 #17
On Thu, 08 May 2008 11:45:24 +0100, Ben Bacarisse wrote:

Neither you nor I are in doubt about what the function does -- I was
just asking that you be careful in your comments. For example, the
above remark is again vague:

(a) the function may read many more than 30 characters;
(b) it does not read the '\0';
(c) it may store up to 30 chars;
(d) the result may be a string as long as 29.

Lots of errors can come from readers believing a program's incorrect
comments or from misunderstanding an ambiguous comment. I was just
suggesting that you take care when writing them.

that was a nice advice. That is my mistake that I ignored this thing.

Thanks :)

--
http://lispmachine.wordpress.com/
my email ID is @ the above blog.
just check the "About Myself" page :)

Jun 27 '08 #18
On Thu, 08 May 2008 11:54:31 +0100, Ben Bacarisse wrote:

I doubt anyone will write this for you. It is a rather specific input
routine and you will just have to work out a way to do it yourself.
Do you plan using pseudo-code before starting to write the C? You
will need to, I think, because such an input routine is quite
complex.
yes, it is complex *only* in C, I guess:

I can discard the words containing anything else than characters:
/* version 1.4 */

int getword( char *word, int max )
{
int c, in_word;
char *w, *w_begin;

w_begin = word;
w = word;
in_word = 0;

while( isspace( c = getchar() ))
{
continue;
}
if( isalpha( c ))
{
*w++ = c;
}

for( ; ( (c = getchar()) != EOF ) && --max ; ++w )
{
if( isalpha(c) )
{
in_word = 1;
*w = c;
}
else if( c == EOF || isspace( c ) )
{
*w = '\0';
in_word = 0;
return 1;
}
else
{
if( in_word )
{
while( w != w_begin )
{
*w-- = '\b';
}
*w-- = '\b';
}
}
}

*w = '\0';

return word[0];
}
============= OUTPUT ==============
[arnuld@raj C]$ gcc -ansi -pedantic -Wall -Wextra getword.c
[arnuld@raj C]$ ./a.out
Ben9
---------->
9Ben
---------- Ben
Be9n
---------- n
[arnuld@raj C]$

now only 2 things have remained:

1.) it does not discard the whole-word if the non-character comes as 1st
element or within the word like 9Ben or Be9n but it will discard Ben9
completely. So it is juts a half-implementation yet.
2.) as usual, does not discard characters more than 30 .
any ideas on that ?

--
http://lispmachine.wordpress.com/
my email ID is @ the above blog.
just check the "About Myself" page :)

Jun 27 '08 #19
arnuld wrote:

look "arnuld"

Your clock is in the future!

Please fix the clock of your machine.

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Jun 27 '08 #20
On Fri, 09 May 2008 10:20:33 +0200, jacob navia wrote:
look "arnuld"

Your clock is in the future!

Please fix the clock of your machine.
oh.. NO.. not again ...
actually, it changes every time the machine boots, so I have to change it
back to normal time at every boot. I have tried changing the cell on the
motherboard but it still gives problems.


--
http://lispmachine.wordpress.com/
my email ID is @ the above blog.
just check the "About Myself" page :)

Jun 27 '08 #21
arnuld wrote:
>On Fri, 09 May 2008 10:20:33 +0200, jacob navia wrote:
>look "arnuld"

Your clock is in the future!

Please fix the clock of your machine.

oh.. NO.. not again ...
actually, it changes every time the machine boots, so I have to change it
back to normal time at every boot. I have tried changing the cell on the
motherboard but it still gives problems.

You are 1 day in the future. This will destroy any makefiles build
processes, and many other things in your system. It is a serious problem.
--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Jun 27 '08 #22
On 9 May 2008 at 11:33, jacob navia wrote:
You are 1 day in the future. This will destroy any makefiles build
processes, and many other things in your system. It is a serious
problem.
Not necessarily - as long as his clock consistently tells the wrong
time, he'll be OK.

Problems can arise when you're using make with source files stored on an
NFS mount, say - then the time make uses is the current time on your
machine, while the timestamps of the files are set by the time on the
NFS server. This can lead to annoying synchronization issues...

Jun 27 '08 #23
jacob navia <ja***@nospam.comwrites:
arnuld wrote:
>>On Fri, 09 May 2008 10:20:33 +0200, jacob navia wrote:
>>look "arnuld"

Your clock is in the future!

Please fix the clock of your machine.

oh.. NO.. not again ...
actually, it changes every time the machine boots, so I have to change it
back to normal time at every boot. I have tried changing the cell on the
motherboard but it still gives problems.


You are 1 day in the future. This will destroy any makefiles build
processes, and many other things in your system. It is a serious
problem.
No because all his files are relativey timed.
Jun 27 '08 #24
On Sat, 10 May 2008 00:08:14 +0500, arnuld <su*****@see.sigs.invalid>
wrote:
>On Thu, 08 May 2008 11:54:31 +0100, Ben Bacarisse wrote:

>I doubt anyone will write this for you. It is a rather specific input
routine and you will just have to work out a way to do it yourself.
Do you plan using pseudo-code before starting to write the C? You
will need to, I think, because such an input routine is quite
complex.

yes, it is complex *only* in C, I guess:

I can discard the words containing anything else than characters:
/* version 1.4 */

int getword( char *word, int max )
{
int c, in_word;
char *w, *w_begin;

w_begin = word;
w = word;
in_word = 0;

while( isspace( c = getchar() ))
{
continue;
}
if( isalpha( c ))
{
*w++ = c;
}

for( ; ( (c = getchar()) != EOF ) && --max ; ++w )
{
if( isalpha(c) )
{
in_word = 1;
*w = c;
}
else if( c == EOF || isspace( c ) )
{
*w = '\0';
in_word = 0;
return 1;
}
else
{
if( in_word )
{
while( w != w_begin )
{
*w-- = '\b';
}
*w-- = '\b';
The -- here invokes undefined behavior. You are not allowed to point
before the array that is passed to getword (if you originally pass the
start of the array).
> }
}
}

*w = '\0';
And you are now storing data in memory through a wild pointer, more
UB.

If you fix things so this stores a '\0' at the beginning of the array,
all the '\b' characters become irrelevant.
>
return word[0];
Your stream is left pointing at the character following the non-alpha.
Input of "ab cd9ef gh" would return words ab, '\0', ef, and gh. Do
you really want that ef?
>}
============= OUTPUT ==============
[arnuld@raj C]$ gcc -ansi -pedantic -Wall -Wextra getword.c
[arnuld@raj C]$ ./a.out
Ben9
---------->
9Ben
There is nothing in the code you showed that reorders the data.
>---------- Ben
Be9n
---------- n
[arnuld@raj C]$

now only 2 things have remained:

1.) it does not discard the whole-word if the non-character comes as 1st
element or within the word like 9Ben or Be9n but it will discard Ben9
completely. So it is juts a half-implementation yet.
Why even return when you find an unacceptable word.
>

2.) as usual, does not discard characters more than 30 .
More than 30 should be treated the same as non-alpha, simply
unacceptable. In both cases, continue reading (but not storing) until
you reach the end of the word.
>

any ideas on that ?

Remove del for email
Jun 27 '08 #25

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

2 posts views Thread by Dariusz | last post: by
1 post views Thread by fabrice | last post: by
3 posts views Thread by SB | last post: by
8 posts views Thread by Phil Slater | last post: by
7 posts views Thread by Shane | last post: by
6 posts views Thread by Charlie Zender | last post: by
10 posts views Thread by T Cordon | last post: by
5 posts views Thread by Scott M. Lyon | last post: by
6 posts views Thread by efrenba | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.