Code to consume input buffer not working as espected - c

I have this code that is supposed to cut the string the user inputs at 256 characters and prevent it from "spilling" into susequent fgets() functions.
It worked perfectly up until today.
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include <ctype.h>
#include <string.h>
int main(){
printf("\nEnter a new string.\n");
char string[256];
do
{
fgets(string,256,stdin);
} while (strlen(string) > 0 && string[strlen(string) - 1] != '\n');
printf("\n\n stringa %s\n", string);
}
So for example if I input a string longer than 256 characters like
Qwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnm
i would expect it to print:
Qwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxc
but instead it prints:
cvbnmqwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnm
Why is this? How can I fix it?

fgets will read until the buffer is full or it hits EOL (\n).
The loop in your code will call fgets until the result includes the EOL.
So: first time through it reads the buffer until full, and then continues
the loop; second time through it reads from the current point until it hits the EOL. That's what's in the result.
You should always check the return value of fgets. The loop will never exit if the input doesn't contain an EOL.
the buffer size passed to fgets includes the returned \0 so you are reading 255 characters, not 256.
If you want to read 256 characters and then throw away input until \n, then do that:
char string[257]; /* room for 256+\0 */
string[0] = 0; /* set string empty in case of no input */
if (fgets(string, sizeof(string), stdin)) { /* read */
if (!strchr(string, '\n')) { /* didn't pick up EOL */
do {
int c = fgetc(stdin); /* get characters */
} while (c >= 0 && c != '\n'); /* until EOL or EOF */
}
}

Related

Why doesn't it wait for me to input string after I exit the loop using CTRL+D

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char c, char_array[100];
int i = 0;
printf("Enter characters (press CTRL+D to end):\n");
while(fgets(char_array+i,sizeof(char_array)-i,stdin)) {
i = i + strlen(char_array+i);
if(char_array[i-1] == EOF)
break;
}
char_array[i-1] = '\0';
strtok(char_array,"\n");
printf("\nEnter a string:\n");
char string[100];
fgets(string,sizeof(string),stdin);
printf("\nCharacter Array: %s\n", char_array);
printf("String: %s\n", string);
return 0;
}
This is the code and I have tried many different variations(simpler) but it always has the same problem... I enter the characters, press CTRL+D and it ends without waiting for me to input a string. please help
I tried everything I could but I just cant make it work and my friends cant too... I have and exam and I need this to be done in 3 days max so I need all the help I can get.
fgets() returns NULL when the stream is closed. On Linux Ctrl-D will flush the terminal buffer if it's not empty (but fgets() will not return as it remains line buffered), and a 2nd Ctrl-D is required to trigger the EOF state of the stream.
You also want to terminate the loop if the array is full otherwise it's an infinite loop:
#define ARRAY_LEN 100
//...
while(i < ARRAY_LEN - 1 && fgets(char_array + i, ARRAY_LEN - i,stdin)) {
fgets() will not emit EOF as part of the string being read, so this is simply incorrect, and as stdin is line buffered the last character is either \n or whatever if the last character was read if the buffer is full which could be -1 or 0xff (whatever char is signed or not but that's still wrong):
if(char_array[i-1] == EOF)
break;
The next line:
char_array[i-1] = '\0';
strips the last character which is either \n or whatever we read last if the array is full (i.e. data loss).
As the input stream is in the EOF state the 2nd fgets() will return NULL. You can clear that state with clearerr(stdin) before calling fgets() to get the 2nd string. If the stream indeed ended, as in, echo "hello world" | ./your_program, the 2nd fgets() with return NULL again of course.
I suggest you use a blank line to signify end of input:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ARRAY_LEN 100
int main() {
printf("Enter characters (empty line to end):\n");
char char_array[ARRAY_LEN];
for(size_t i = 0; i < ARRAY_LEN - 1; i += strlen(char_array)) {
if(!fgets(char_array + i, ARRAY_LEN - i, stdin)) {
printf("fgets() failed\n");
return 1;
}
if(char_array[i] == '\n') {
char_array[i] = '\0';
break;
}
}
strtok(char_array, "\n");
printf("Enter a string:\n");
char string[ARRAY_LEN];
char *rv = fgets(string,sizeof(string),stdin);
printf("Character Array: %s\n", char_array);
printf("String: %s\n", string);
}
and example session:
Enter characters (empty line to end):
hello
world
Enter a string:
friend
Character Array: hello
String: friend
With stdio streams, error/eof is sticky -- that is, once an error or eof condition has occurred, further operations on the FILE * will continue to return EOF or NULL (depending on the function), rather than trying to read or write anything further.
To reset the eof state on the FILE *, you need to call clearerr(stdin). Once you do that, you can read additional input from the terminal.

C reading lines from stdin

My goal is to read every line from a piped .txt file with the getline() function, but I somehow get a error every time I use this function:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
int Chars;
int size = 10;
char *string;
printf("Please enter a string: ");
string = (char*) malloc(size);
Chars = getline(&string, &size, stdin);
if (Chars == -1)
{
puts("ERROR!");
}
else
{
puts("You entered the following string: ");
puts(string);
printf("\nCurrent size for string block: %d", Chars);
}
return 0;
}
I always get the errorcode: [Error] Id retruned 1 exit status
I've reproduced the linking error on DevC++, in which getline() seems to be missing even after forcing recent C revisions with gcc compiler options such as -std=c11.
So I've rewritten your code using fgets():
char *fgets(char *s, int size, FILE *stream);
It is for sure more portable than getline but has a few differences:
It reads up to size-1 characters if the newline is not encountered before this limit (it automatically appends the string terminator). So it doesn't manage buffer reallocation
The resulting string contains the '\n' character, if found
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_STR_SIZE 32
int main( void )
{
int len = 0;
char *str;
printf("Please enter a string: ");
str = malloc(MAX_STR_SIZE); /* (1) */
while( 1 )
{
size_t newline_pos;
fgets( str, MAX_STR_SIZE, stdin );
/* (2) */
if( len == 0) /* (3) */
{
puts("You entered the following string: ");
}
newline_pos = strcspn(str, "\n" );
str[newline_pos] = '\0';
len += strlen(str); /* (4) */
fputs(str, stdout);
if(newline_pos < MAX_STR_SIZE-1) /* (5) */
break;
}
printf("\n\nCurrent size for string block: %d", len);
free( str ); /* (6) */
return 0;
}
So, basically, I just use fgets to read from stdin, iterating until the '\n' character is found. In order to understand is this condition is met, I use strcspn() function, and I use the same function to remove the newline from the resulting string.
A few notes/assumptions (check the corresponding number in code section):
Casting the result of malloc is required only if you are compiling with a C++ compiler. It can be omitted in C
Removed fgets error check: it returns NULL in case of error (no chars read before EOF is found. It won't happen reading from stdin)
Checking for len==0 we make sure that the "You entered the following string: " is printed only once
The length of the string is calculated by summing the length of the strings read in every iteration
The break condition is met when the string contains '\n'. Otherwise strcspn's return value will be MAX_STR_SIZE
Even if the OS will release all the dynamic memory used by the program, on return, it is a good habit always freeing it anyway

C: The first element of a char cannot be detected

I am learning getting inputs from key board. I want the user create a or more strings from the input, each string is considered as a line, the program will not terminate until a specified char is pressed. Then store these strings to the buffer.
However, when I print out the buffer, the first few elements of the string are always missing. Here is my code:
#include<stdio.h>
int main(void){
printf("Please type the string:\n");
char buffer[1000];
int c;
while( (c = getchar()) != ' ' ) {
fgets(buffer, sizeof(buffer), stdin);
printf("The output string is: \n%s\n", buffer);
if((c = getchar())== ' '){
printf("A space is detected!\n");
break;
}
}
}
The output is:
Please type the string:
abcdefg
The output string is:
bcdefg
hijklmn
The output string is:
jklmn
opqrst
The output string is:
qrst
A space is detected!
Program ended with exit code: 0
Which part did I go wrong? Any hints are very much appreciated.
The problem you are having is both getchar(), and fgets in your code are reading from stdin. Since you call getchar() first in your test, it was consuming the first character of your string, when you called it again, another character disappeared...
You don't need getchar() at all to end your loop. All you care about for breaking your loop as you have explained is whether the user enters a space as the first character. fgets does not skip leading whitespace, so any leading space entered by the user will be captured at the beginning of buffer. So to satisfy your loop-exit condition, all you need to do is check if the first character of buffer is a space.
How? The simple way is to just derererence buffer, e.g. *buffer returns the first character in buffer. How? In pointer notation, buffer + 0 is the offset you want in buffer, so to get the character at that location, you dereference, e.g. *(buffer + 0), which of course is just *buffer, which is the equivalent of buffer[0].
So, putting it altogether, and getting rid of getchar(), and adding strlen to properly validate that the string fit in buffer and to get the location for the trailing '\n' read and included in buffer by fgets (which leaves you with the length of trimmed string as a benefit), you could do something similar to:
#include <stdio.h>
#include <string.h>
#define MAXC 1000 /* if you need a constant, define one (or more) */
int main (void) {
char buffer[MAXC] = ""; /* initialize strings zero (good practice) */
for (;;) { /* loop continually taking input */
size_t len; /* variable for buffer length */
printf ("\nenter string: "); /* prompt */
if (!fgets (buffer, sizeof buffer, stdin)) /* read input */
break; /* exit if user cancels input */
len = strlen (buffer); /* get length */
if (len && buffer[len-1] == '\n') /* check if last char is \n */
buffer[--len] = 0; /* overwrite with nul-char */
else { /* otherwise string too long */
fputs ("error: string too long.\n", stderr);
return 1;
}
if (*buffer == ' ') /* check if 1st char of buffer is ' ' */
break;
printf ("buffer: %s (%zu chars)\n", buffer, len); /* output */
}
}
Example Use/Output
$ ./bin/fgetsspace
enter string: my dog has fleas
buffer: my dog has fleas (16 chars)
enter string: my cat has none
buffer: my cat has none (15 chars)
enter string: bye
(note: a space was entered before bye above, e.g. " bye")
Look things over and let me know if you have further questions.
Separating Words with strtok
To separate each line into individual words you can use strtok. The first argument is the buffer (for the 1st call), the second parameter is a list of characters to use as delimeters between the words (e.g. if you want to separate on space include a space, to not include the '.' at the end of a sentence include that as well -- and include the '\n'). After the 1st call to strtok all subsequent calls to get the remaining words uses NULL in place of buffer, e.g.
#include <stdio.h>
#include <string.h>
#define MAXC 1000 /* if you need a constant, define one (or more) */
int main (void) {
char buffer[MAXC] = ""; /* initialize strings zero (good practice) */
for (;;) { /* loop continually taking input */
size_t len; /* variable for buffer length */
char *delim = " .\n", /* delmiters for strtok */
*p = buffer; /* pointer to buffer for strtok */
printf ("\nenter string: "); /* prompt */
if (!fgets (buffer, sizeof buffer, stdin)) /* read input */
break; /* exit if user cancels input */
len = strlen (buffer); /* get length */
if (len && buffer[len-1] == '\n') /* check if last char is \n */
buffer[--len] = 0; /* overwrite with nul-char */
else { /* otherwise string too long */
fputs ("error: string too long.\n", stderr);
return 1;
}
if (*buffer == ' ') /* check if 1st char of buffer is ' ' */
break;
printf ("buffer: %s (%zu chars)\n", buffer, len); /* output */
p = strtok (buffer, delim); /* 1st call to strtok uses buffer */
while (p != NULL) {
printf (" %s\n", p);
p = strtok (NULL, delim); /* subsequent calls use NULL */
}
}
}
(note: the original buffer is modified, so make a copy if you need to preserve the original)
Example Use/Output
$ ./bin/fgetsspace
enter string: my dog has fleas
buffer: my dog has fleas (16 chars)
my
dog
has
fleas
enter string: my cat has none
buffer: my cat has none (15 chars)
my
cat
has
none
enter string: bye
getchar swallows up a character. Your first iteration gets one character swallowed up by the initial call in the while, and then successive iterations get two characters swallowed up, one by the getchar you use to detect a space and then again the one in the while.
Answering in addition to my initial comment and the issue:
First, quoting myself:
I believe that when using getChar(), you efficiently remove the character from stdin buffer.
As stated since then by other people, the problem is that your call to getchar function consume and input, efficiently removing it from stdin buffer.
See Jim Buck's answer for detailed informations on the precise behavior of your application.
Now, what should you do ?
First, the if inside the while loop is not necessary, and using your application right now must be pretty odd. Try doing :
#include<stdio.h>
int main(void){
printf("Please type the string:\n");
char buffer[1000];
int c;
while( (c = getchar()) != ' ' ) {
fgets(buffer, sizeof(buffer), stdin);
printf("The output string is: \n%s\n", buffer);
}
printf("A space is detected!\n");
}
Instead to prevent unnecessary user inputs. Your loop is basically an infinite loop so there is no need to check at the end of every iteration if the loop should terminate, the while statement is already doing that pretty damn well. :P
Now, to prevent the input from being taken out of buffer, I would consider using the buffer's first element instead of "c" variable.
Like so :
#include<stdio.h>
int main(void){
printf("Please type the strings:\n");
char buffer[1000];
while( (buffer[0] = getchar()) != ' ' ) { // Now reads directly into buffer
fgets(buffer + 1, sizeof(buffer), stdin); // + 1 prevents overriding the char we just read.
printf("The output string is: \n%s\n", buffer);
}
printf("A space is detected!\n");
}
Have a nice day!

I am trying to write a program that determines if the sequence of characters is valid or invalid [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
If the user enters any character other than ACGT (sequence does not matter) then it should print "INVALID". The user just keeps entering the sequence not more than 250 characters.
#include <stdio.h>
#include <string.h>
int main(void)
{
char dna[250];
int i;
for(i=0; i<250; i++)
{
scanf("%c", dna[i]);
}
fgets(*dna, 250, scanf("%c", dna));
int k;
for(k=0; k<250; k++)
{
if(dna[k] == 'A' || 'C' || 'G'|| 'T')
{
i++;
//printf("%c\n", dna[0])
}
}
if(i > 0)
{
printf("VALID sequence \n");
}
else
{
printf("INVALID sequence \n");
}
}
like this
#include <stdio.h>
int main(void){
char dna[250+1], rest;
if(scanf("%250[ACGT]%c", dna, &rest) == 2 && rest == '\n')
printf("VALID sequence \n");
else
printf("INVALID sequence \n");
}
There are a large number of ways to approach the problem. You can use scanf with character classes as shown, or you can use any other method to read the input (e.g. getchar, fgets, POSIX getline) and then simply analyze the characters entered for anything other than "ACGT".
Additionally, in your problem statement you state "The user just keeps entering the sequence not more than 250 characters". Obviously you will need to loop to handle entry of multiple strings, but beyond that, you will also need to protect against and handle the remainder of any strings greater than 250 characters. It is unclear whether in that case, you want to keep the first 250 valid characters entered (seems logical you would), and then discard any over the 250 character limit.
Your tools for validating the input are, in the case of using character-oriented input (e.g. using getchar) are simply to check each character input against your ACGT. When using line-oriented input, (e.g. fgets or getline) the C library provides a number of tools to check for characters within a string, or substrings within a string (strchr is applicable here) or you can simply walk a pointer down the entire string of input checking each character. (you also need to check for, and remove the '\n' the line-oriented functions read and include in the buffer)
Putting the pieces together into a short example using fgets for input and strchr to check whether each character is one of ACGT, you could do something like the following. Here the user can enter as many strings as desired. The program terminates when EOF is read (manually generated with Ctrl + D on Linux, Ctrl + Z on windoze). In the event an invalid string is entered, the code identifies the position of the first invalid character in the entry:
#include <stdio.h>
#include <string.h>
#define MAXC 250
int main (void) {
char str[MAXC+1] = "", *valid = "ACGT";
printf ("Enter sequences [ctrl+d] to quit:\n");
while (fgets (str, MAXC+1, stdin)) /* read input */
{
size_t len = strlen (str), good = 1; /* get length, set flag */
char *p = str; /* pointer to str */
int c;
if (str[len-1] == '\n') /* trim '\n' char */
str[--len] = 0; /* overwrite with nul */
else /* line > 250, discard extra */
while ((c = getchar()) != '\n' && c != EOF) {}
for (; *p; p++) /* for each char in str */
if (!strchr (valid, *p)) { /* check against valid */
good = 0; /* not found - invalid */
break;
}
if (good)
printf ("VALID\n");
else
fprintf (stderr, "INVALID ('%c' at character '%ld'\n", *p, p - str);
}
return 0;
}
Example Use/Output
$ ./bin/acgtvalid
Enter sequences [ctrl+d] to quit:
ACGTTTGGCCCATTAGGC
VALID
ACCGGTTCCGGAITT
INVALID ('I' at character '12')

Ending a while loop when user hits enter, cannot use #include <string.h>

In this scenario, user input is taken from stdin using fgets. Normally to end a while loop when a user hits enter I would use strcmp between the fgets value and \n, but we are not allowed to use #include <string.h> in this particular assignment. Using C99.
You can't, since the fgets() function returns when it finds an \n
I'm assuming you mean when the user input a single \n and nothing else. Itmight be a better idea to use fgetc() instead, which will return the \n.
This means you need to buffer the inout yourself, something like this:
char inputBuffer[120] = "";
char ch;
char chCount = 0;
while (1) {
ch = fgetc(stdin);
if (ch == '\n') {
/* Empty buffer? */
if (inputBuffer[0] == '\0')
/* Oui! */
break;
/* Buffer isn't empty - do something with it... */
fprintf(stdout, "Input buffer: %s\n", inputBuffer);
/* Clear the buffer for the next line of input and reset the
* counter. */
inputBuffer[0] = '\0';
chCount = 0;
}
else {
if (chCount < 119) {
/* Add the byte to the buffer. */
inputBuffer[chCount++] = ch;
inputBuffer[chCount] = '\0';
}
}
}
The above loop will output any input string or break if a single \n is entered.

Resources