Terminating a c program when the user enters a blank line - c

Hi i am writing a program to count the number of lines the user enters, i have this code:
#include <stdio.h>
#include <string.h>
int readline(char line[], int max);
/* count lines in input */
main() {
int c, nl,max, i;
max = 99;
char line[100];
nl = 0;
while (( readline(line, max) != 0)){
++nl;
}
printf("%d\n", nl);
}
/* readline: read a line from standard input, return its length or 0
*/
int readline(char line[], int max)
{
if (fgets(line, max, stdin) == NULL)
return 0;
else
return strlen(line);
}
but i am not sure how to terminate the program and have "nl" printed to the screen, i am using the cygwin64 terminal to write and execute the program.
Thanks

size_t n;
while(fgets(line,max,stdin))
{
n = strlen(line);
if( n == 1 && line[n-1] == '\n')
{
//This is a empty line
}
}
Basically fgets() comes with a newline character and you can use this to confirm whether there was any input in the line or just a newline character was entered.
readline returns the text of the line read. A blank line returns
the
empty string. If EOF is encountered while reading a line, and the line
is empty, NULL is returned. If an EOF is read with a non-empty line,
it is treated as a newline.
So you can check for empty string.

Change the condition into like this,
while (( readline(line, max) <= 1)){
...
}
When you enter the empty new line then that new line will be placed in that array.
So it gives the strlen as 1.

Related

How to find the length of every word in a string?

I wrote a code that takes a sentence and outputs every each word in a line. But I also want to write the size of each word next to it.
Input:
Hi my name is
Current output:
Hi
my
name
is
Desired output:
Hi(2)
my(2)
name(4)
is(2)
My current Code:
#include <stdio.h>
#define MAX 100
int main(void) {
int c = 0;
size_t n = 0;
printf("\n Enter a sentence.\n\n input: ");
/* read up to 100 characters from stdin, print each word on a line */
while (n < MAX && (c = getchar()) != EOF && c != '\n')
{
if (c == ' ')
printf("\n");
else
printf("%c", c);
n++;
}
printf("\n");
if (n == MAX) /* read and discard remaining chars in stdin */
while ((c = getchar()) != '\n' && c != EOF);
return 0;
}
How can I do that?
For completeness a different approach reading the whole input in one call and then tokenising it:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX (100)
int main(void)
{
int result = EXIT_SUCCESS; /* Be optimistic. */
char s[MAX +1];
printf("\n Enter a sentence.\n\n input: ");
/* read up to 100 characters from stdin, print each word on a line */
if (NULL == fgets(s, sizeof s, stdin))
{
if (ferror(stdin))
{
perror("fgets() failed");
result = EXIT_FAILURE;
}
}
else
{
s[strcspn(s, "\r\n")] = '\0'; /* chop off carriage return, line feed, if any */
for (char * pc = strtok(s, " "); NULL != pc; pc = strtok(NULL, " "))
{
printf("%s (%zu)\n", pc, strlen(pc));
}
}
return result;
}
As the read buffer is never explicitly used the following variation is possible as well:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX (100)
int main(void)
{
int result = EXIT_SUCCESS; /* Be optimistic. */
printf("\n Enter a sentence.\n\n input: ");
{
/* read up to 100 characters from stdin, print each word on a line */
char * pc = fgets((char[MAX+1]), MAX+1, stdin);
if (NULL == pc)
{
if (ferror(stdin))
{
perror("fgets() failed");
result = EXIT_FAILURE;
}
}
else
{
pc[strcspn(pc, "\r\n")] = '\0'; /* chop off carriage return, line feed, if any */
for (pc = strtok(pc, " "); NULL != pc; pc = strtok(NULL, " "))
{
printf("%s (%zu)\n", pc, strlen(pc));
}
}
}
return result;
}
Have one more variable and print out when you hit space.
size_t len = 0;
/* read up to 100 characters from stdin, print each word on a line */
while (n < MAX && (c = getchar()) != EOF && c != '\n')
{
if (c == ' ') {
printf("(%u)\n", len);
len = 0;
}
else {
len++;
printf("%c", c);
}
n++;
}
In addition to the good answer by #kiranBiradar, you may want to add an additional variable that allows you to track whether you are in-a-word reading characters or outside-a-word reading whitespace. (using a simple int value as a flag set to 1 (true) for in-word or 0 (false) not-in-word is all you need) This will allow you to ignore leading whitespace, multiple included whitespace, or trailing whitespace in your input, e.g., if your input was similar to:
" my dog has fleas and my cat has none "
Unless you are keeping track of the state of your read, whether you are in-word / not-in-word, you will be outputting multiple occurrences of "(0)\n" each time a whitespace character is read. By keeping a flag of whether you are in / not-in a word and setting it zero when you encounter your first whitespace after being in-word reading non-whitespace characters allows you to only output the length once on the first whitespace encountered.
Additionally, conditioning your read on c != '\n' will skip outputting the length of the final word, unless you include additional code after you exit your read loop.
Also by including <ctype.h> you have the isspace() macro available to check for all whitespace (e.g, space, tab, newline, backspace, vertical-tab, etc...) It greatly simplifies your conditional checks.
Putting it altogether you could do:
#include <stdio.h>
#include <ctype.h> /* for isspace() */
int main (void) {
int c = 0, in = 0, len = 0; /* char, in/out flag, length */
fputs ("enter text: ", stdout); /* prompt for text */
fflush (stdout); /* (optional), but recommended */
while ((c = getchar()) != EOF) { /* loop reading chars until EOF */
if (isspace (c)) { /* if input is space */
if (in) { /* check if in-word */
printf ("(%d)\n", len); /* output (len) */
len = 0; /* reset len zero */
in = 0; /* set in flag zero (false) */
}
if (c == '\n') /* if space is \n */
break; /* break read loop */
}
else { /* if not whitespace */
putchar (c); /* output char */
len++; /* increment length */
in = 1; /* set in flag 1 (true) */
}
}
}
(note: there is no reason to limit your read to n < MAX unless you simply want to arbitrarily limit your read of characters to the first 100-characters. There is no array being filled or other storage being occupied by the character c (aside from it's one byte). You could read billions if your input contained them)
Example Use/Output
$ ./bin/getchar_word_len
enter text: my dog has fleas and my cat has none
my(2)
dog(3)
has(3)
fleas(5)
and(3)
my(2)
cat(3)
has(3)
none(4)
Look over both answers and let either of us know if you have further questions. If you are confused by the logic, take out an 8.5x11 sheet of paper and work through the logic of the loop for each character starting at the beginning of your input. It will make sense by the time you work through the first word.

Use and explanation of getchar() function

I am writing a program to read a user input statement and extract all integers from the input. For example, if I enter "h3ll0", the program will output "30". I have used the fgets function to read the user input.
However, I am currently reading about getchar() and would like to know what would be the best way to use getchar() in my program to read user input instead of fgets. I am not really clear on how getchar() works and what situations it can be useful in.
This question is related to a project that specifically asks for getchar() as the method of reading user input. As I was unclear on how getchar() works, I built the rest of the program using fgets to ensure it was working.
#include <stdio.h>
int main()
{
char user_input[100];
int i;
int j = 0;
printf("Please enter your string: ");
fgets(user_input ,100, stdin);
for(i = 0; user_input[i] ; i++)
{
if(user_input[i] >= '0' && user_input[i] <= '9')
{
user_input[j] = user_input[i];
j++;
}
}
user_input[j] = '\0';
printf("Your output of only integers is: ");
printf("%s\n", user_input);
return 0;
}
OP: unclear on how getchar() works
int fgetc(FILE *stream) typically returns 1 of 257 different values.
"If ... a next character is present, the fgetc function obtains that character as an unsigned char converted to an int C11 §7.21.7.1 2
On end-of-file or input error (rare), EOF, is returned.
OP: to use getchar() in my program to read user input instead of fgets.
Create your own my_fgets() with the same function signature and same function as fgets() and then replace.
char *fgets(char * restrict s, int n, FILE * restrict stream);
The fgets function reads at most one less than the number of characters specified by n from the stream pointed to by stream into the array pointed to by s. No additional characters are read after a new-line character (which is retained) or after end-of-file. A null character is written immediately after the last character read into the array. C11 §7.21.7.2 2
Return the same value
The fgets function returns s if successful. If end-of-file is encountered and no characters have been read into the array, the contents of the array remain unchanged and a null pointer is returned. If a read error occurs during the operation, the array contents are indeterminate and a null pointer is returned. §7.21.7.2 3
Sample untested code
#include <stdbool.h>
#include <stdio.h>
char *my_fgets(char * restrict s, int n, FILE * restrict stream) {
bool something_read = false;
int ch = 0;
char *dest = s;
// Room ("reads at most one less") and EOF not returned?
while (n > 1 && (ch = fgetc(stream)) != EOF) {
n--;
something_read = true;
*dest++ = (char) ch;
if (ch == '\n') {
break; // "No additional characters are read after a new-line character"
}
}
// Did code end the while loop due to EOF?
if (ch == EOF) {
// Was EOF due to end-of-file or rare input error?
if (feof(stream)) {
// "If end-of-file is encountered and no characters ... read into the array ..."
if (!something_read) {
return NULL;
}
} else {
// "If a read error ..."
return NULL; // ** Note 1
}
}
// room for \0?
if (n > 0) {
*dest = '\0'; //" A null character is written immediately after the last character"
}
return s;
}
Perhaps improve fgets() and use size_t for n.
char *my_fgets(char * restrict s, size_t n, FILE * restrict stream);
fgets() with n <= 0 is not clearly defined. Using size_t, an unsigned type, at least eliminates n < 0 concerns.
Note 1: or use s = NULL; instead of return NULL; and let the remaining code null terminate the buffer. We have that option as "array contents are indeterminate".
Something like this should work as a clunky replacement to fgets using only getchar. I don't guarantee the accuracy of the error handling.
I don't think you would ever want to use getchar over fgets in an application. Getchar is more limited and less secure.
#include <stdint.h>
void your_fgets(char *buffer, size_t buffer_size)
{
int i;
size_t j;
if (buffer_size == 0)
return ;
else if (buffer_size == 1)
{
buffer[0] = '\0';
return ;
}
j = 0;
while ((i = getchar()) != EOF)
{
buffer[j++] = i;
if (j == buffer_size - 1 || i == '\n')
{
buffer[j] = '\0';
return ;
}
}
buffer[j] = '\0';
}
I am baffled by the comments on this post suggesting that fgets is easier to use. Using fgets unnecessarily complicates the issue. Just do:
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
int
main(int argc, char **argv)
{
int c;
while( ( c = getchar() ) != EOF ) {
if(isdigit(c) && (putchar(c) == EOF)) {
perror("stdout");
return EXIT_FAILURE;
}
}
return ferror(stdin);
}
There is absolutely no reason to use any additional buffering, or read the input one line at a time. Maybe you'll want to output newlines as they come in, but that would be an implementation detail that is left unspecified in the question. Either way, it's utterly trivial (if(( c == '\n' || isdigit(c)) && (putchar(c) == EOF))). Just read a character and decide if you want to output it. The logic is much easier if you don't think about the input as being more complicated than it is. (It's not line-oriented...it's just a stream of bytes.)
If, for some unknown reason you want to make this tool usable only in an interactive setting and load up your output with excess verbosity, you can easily do something like:
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
int
main(int argc, char **argv)
{
int c;
do {
int want_header = 1;
printf("Please enter your string: ");
while( ( c = getchar() ) != EOF && c != '\n' ) {
if(! isdigit(c)) {
continue;
}
if(want_header) {
want_header=0;
printf("Your output of only integers is: ");
}
if(putchar(c) == EOF) {
perror("stdout");
return EXIT_FAILURE;
}
}
if( c == '\n')
putchar(c);
want_header = 0;
} while(c == '\n');
return ferror(stdin);
}
but, please, don't do that. (Imagine if grep started by emitting a prompt that said "please enter the regex you would like to search for"!)

how to take input till "only" newline character or a space is inputted ?Basically how to run loop till you enter nothing as input?

i am trying to create a looping which keeps looping till "only" newline charater is inputted or maybe just a space (until nothing is entered to the input line).
#include <stdio.h>
#include <stdlib.h>
int main()
{
int num;
while(1)
{
scanf("%d",&num);
if(num==NULL)
break;
printf("%d",num);
}
return 0;
}
You can't do that with scanf (at least not easily). If you want to process user input, scanf is a bad choice (in fact, in all my years of developing in C, I've never used scanf; I recommend you avoid it altogether).
num==NULL makes no sense: num is a number, but NULL is a pointer value. If you want to check whether scanf was successful, you need to check its return value.
I'd do something like:
char line[100];
while (fgets(line, sizeof line, stdin)) { // read input line by line
int num;
if (sscanf(line, "%d", &num) != 1) { // the line didn't start with a valid integer
break;
}
printf("%d\n", num);
}
If you want to check specifically for an empty string, not just something that doesn't look like a number, you could use strspn:
if (line[strspn(line, " \t\n")] == '\0') {
// line contains spaces / tabs / newlines only
There are other things that can be on a line other than an integer. Your code indicates an integer expected, but your text only indicates the line is blank or only contains a space.
Given your text in the question:
#include <stdio.h>
#include <string.h>
int main( void )
{
char line[1024];
while( fgets( line, sizeof( line ), stdin ) )
{
if( (strlen( line ) == 1 )
|| (strlen( line ) == 2 && line[0] == ' '))
{
// all done
break;
}
else
{
// process line
}
} // end while
}

delete trailing char in line without using string library C

started C this semester and struggling to convert knowledge of java into C. The code compiles and runs but not as I want it. The task is to write a code that read a text file line by line (I have a get line function) and outputs new text file keeping line formatting the same (meaning that if original file has 4 line output file has to have 4 line) but deleting trailing characters (space and \t). I've spend enormous amount of time pocking at this thing without success. Any help is appreciated.
hw2_execcise_1. program to remove trailing blanks and tabs from each line of input, and to delete entirely blank lines.
Pseudo::: while (there are lines to read)
find end of line1 (\n)
save length
going from the end of the line towards the beginning
find char that is not either space or tab
and insert \n following found char.
#include <stdio.h>
#define LINELIM 1000
int getLine(char s[], int lim);
int main (void){
int len, i;
char line1[100];
while ((len = getLine(line1, LINELIM)) >0){
for (i=len; i>=0; i--){
if ((line1[i] == ' ') || (line1[i] == '\t')){
line1[i] = '\n';
}
else break;
}
printf(" %s\n", line1);
}
return 0;
}
/*getline: read a line into s, return length*/
int getLine(char s[], int lim){
int c,i;
for (i=0; i<lim-1 && (c=getchar())!= EOF && c!='\n'; ++i)
s[i]=c;
if (c == '\n'){
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
while ((len = getLine(line1, LINELIM)) >0){
for (i=len-1; i>=0; i--){//-1 for 0 origin
if(line1[i] == ' ' || line1[i] == '\t' || line1[i] == '\n'){//add case of '\n'
line1[i] = '\0';//newline add print part
}
else break;
}
if(line1[0])//not blank line
printf("%s\n", line1);
}
the main logic problem with the code is
1) the getline function is terminating each input line with (either) '\n''\0' or with '\0'
2) the main function is not checking for the newline when it checks for space or tab. I.E. it needs to also check for newline --or-- getline() should not ever include the newline

getting output from a c program

I compiled the below program:
#include <stdio.h>
#define MAXLINE 1000 /* maximum input line length */
int getline(char line[], int maxline);
void copy(char to[], char from[]);
/* print the longest input line */
main()
{
int len; /* current line length */
int max; /* maximum length seen so far */
char line[MAXLINE]; /* current input line */
char longest[MAXLINE]; /* longest line saved here */
max = 0;
while ((len = getline(line, MAXLINE)) > 0)
if (len > max) {
max = len;
copy(longest, line);
}
if (max > 0) /* there was a line */
printf("%s", longest);
return 0;
}
/* getline: read a line into s, return length */
int getline(char s[],int lim)
{
int c, i;
for (i=0; i < lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
s[i] = c;
if (c == '\n') {
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
/* copy: copy 'from' into 'to'; assume to is big enough */
void copy(char to[], char from[])
{
int i;
i = 0;
while ((to[i] = from[i]) != '\0')
++i;
}
I tried to run it in bash shell:
gcc -o longest-line longest-line.c
./longest-line
And basically it turns into a running process (shows in result of ps aux) and the cursor just blinks. In the code, when the program is run and the getline function is called, it does 1000 iterations and the getchar is called each time to get input from the terminal in order to increment the counter if it's not end of file or newline. However, immediately there is no input in the terminal and when I start adding input and press the enter key:
$ ./longest-line
Hello World
Hello Again
Nothing happens. It's supposed to print the longest line.
The problem is that if you press '\n' from keyboard getline will always return 1 because of this statement
if (c == '\n') {
s[i] = c;
++i;
}
and the line while ((len = getline(line, MAXLINE)) > 0) will always be true.
But if you use a file as standard input it will work fine because of the EOF.
If you want it to work from keyboard input press Ctrl-D or Ctrl-Z to simulate an EOF.
So, on my compiler, I had to fix a few minor issues.
Generally, main should be written as int main() { ... } or int main(int argc, char **argv) { ... }.
getline() conflicts with a builtin function that gets pulled in from the #include <stdio.h>, so I simply renamed yours to getline_custom and also renamed all the usage points.
That being said, with these minor fixes, (which may not be required under your compiler), your program works correctly.
I believe your confusion is that the program won't print the longest line until after you've sent EOF. In bash, you can do this with CTRL+D.
Example:
[12:39pm][wlynch#watermelon /tmp] ./foo
test // Then I hit enter
longest line // Then I hit enter
short line // Then I hit enter
one more // Then I hit ctrl-D
longest line // This is output from the program.
Another Example:
If we use redirection, we can more easily see the difference between the input and output.
[12:42pm][wlynch#watermelon /tmp] printf "longest line\nshort line" | ./foo
longest line
or, using an input file:
[12:53pm][wlynch#watermelon /tmp] cat input.txt
longest line
short line
foo
blah
[12:53pm][wlynch#watermelon /tmp] cat input.txt | ./foo
longest line
On the other hand
If, on the other hand, you'd like the program to print the current longest line after each line of input, then we would need to change the code in this program.
Here's an example of that:
int main() {
int len = 0; /* current line length */
int max = 0; /* maximum length seen so far */
char line[MAXLINE]; /* current input line */
char longest[MAXLINE]; /* longest line saved here */
while ((len = getline(line, MAXLINE)) > 0) {
if (len > max) {
max = len;
copy(longest, line);
}
printf("Current longest line: %s", longest);
}
}

Resources