For example, I am writing a C function that replace a substring s1 in string source with a new string s2. But I am having trouble with reading the input from stdin. I also want it to end until an EOF is met.
I search a lot about "read until EOF" and "read a string containing whitespace", but I didnt make it to work.
#include <stdio.h>
{
char source[120], s1[20], s2[20];
...
//what ever to input multiple cases of source, s1, and s2 until EOF is met
replace(source, s1, s2);
printf("%s\n",source);
return 0;
}
You might like to do something like this:
char buffer[1234];
while (NULL != fgets(buffer, 1234, stdin))
{
/* Do something with the 0-terniated content of buffer. */
}
if (ferror(stdin))
{
/* An error occurred reading from stdin. */
}
For reference:
man fgets
man ferror
If you cannot define an upper limit for the number of characters until a new-line, the getline() function might be of interest, as it is capable to allocate as much memory as necessary to hold all characters until the next new-line.
You can use feof function.
while(!feof(stdin)) {
//read data with scanf, gets, fgets, etc...
}
To send an EOF press CTRL+D.
View the manual for more information about feof function. (man feof on terminal)
Check this and give me your opinion :
#include <stdio.h>
int Replace_Function(String[] s1,String[] s2){
String source[120], s1[20], s2[20];
//This is what u want????
while (getchar() != EOF)
{
S1=S2;
}
return 0;
}
I think this piece of code may help you:
int c;
while ((c = getchar()) != EOF) {
// do smt
}
We must declare c to be a big enough to hold any value that getchar return. So we don't use char since
c must be big enough to hold EOF (which is integer defined in <stdio.h>)
Related
I have this program:
#include <stdio.h>
#define SIZE 19
int main(){
char string[SIZE];
while (string[0] != 'A'){
printf("\nEnter a new string.\n");
fgets(string,SIZE,stdin);
int storage = 0;
while (storage != '\n')
{
storage = getchar();
}
}
}
The nested while loop with getchar() exists in case the inputted string exceeds the maximum number of characters string[] can hold. If that is not there, inputting a string with, say, 20 characters, would cause the output to be:
Enter a new string.
12345123451234512345
Enter a new string.
Enter a new string.
The problem is that this requires me to press enter twice in order to enter a new string: once for 'fgets' and one for the nested while loop (this is my understanding of what's going on).
Is there a way to change this so I only have to press 'Enter' once, or possibly a way to change the entire while loop into something more elegant?
If the buffer that receives from fgets contains a newline, you know it read everything that was inputted so you don’t need to do anything else. If not, then you use the extra loop to flush the buffer.
You are thinking correctly, you just need to think through how and when you need to empty the input buffer a bit further.
All line-oriented input functions (fgets and POSIX getline) will read, and include, the trailing '\n' in the buffers they fill (fgets only when sufficient space is provided in the buffer).
When using fgets, you have only two possible returns, (1) a pointer to the buffer filled, or (2) "NULL on error or when end of file occurs while no characters have been read."
In case fgets returns a valid pointer, then it is up to you to determine whether a complete line of input was read, or whether the input exceeds the buffer size, leaving characters in the input buffer unread.
To make that determination, you check whether the last character in the buffer is '\n' and if not, whether the buffer contains SIZE-1 characters indicating that characters remain in the input buffer. You can do that a number of ways, you can use strchr (to get a pointer to the '\n'), strcspn (to get an index to it) or good old strlen (to get the length of the string) and then check the character at len-1.
(a note on preference, you can use whatever method you like, but in either case of strcspn or strlen, save the index or length so it can be used to validate whether the input exceeded the buffer size or whether the user ended input by generating a manual EOF. You save the index or length to prevent having to make duplicate function calls to either)
It is also helpful to create a simple helper-function to clear the input buffer to avoid placing loops everywhere you need the check. A simple function will do the trick, e.g.
/* simple function to empty stdin */
void empty_stdin (void)
{
int c = getchar();
while (c != '\n' && c != EOF)
c = getchar();
}
of if you prefer the more-compact, but arguably less readable version, a single for loop will do, e.g.
void empty_stdin (void)
{
for (int c = getchar(); c != '\n' && c != EOF; c = getchar()) {}
}
The remainder of your example can be structured to complete each of the tests described above to provide input handling as you have described (although using the 1st character of the buffer being 'A' to control the loop is a bit strange), e.g.
#include <stdio.h>
#include <string.h>
#define STRSIZE 19
/* simple function to empty stdin */
void empty_stdin (void)
{
int c = getchar();
while (c != '\n' && c != EOF)
c = getchar();
}
int main (void) {
char string[STRSIZE] = ""; /* initialize string all 0 */
while (*string != 'A') { /* up to you, but 'A' is a bit odd */
size_t len = 0; /* variable for strlen return */
printf ("enter a string: "); /* prompt */
if (!fgets (string, STRSIZE, stdin)) { /* validate read */
putchar ('\n'); /* tidy up with POSIX EOF on NULL */
break;
}
len = strlen (string); /* get length of string */
if (len && string[len-1] == '\n') /* test if last char is '\n' */
string[--len] = 0; /* overwrite with nul-character */
else if (len == STRSIZE - 1) /* test input too long */
empty_stdin(); /* empty input buffer */
}
return 0;
}
An arguably more useful approach is to have the loop exit if nothing is input (e.g. when Enter alone is pressed on an empty line). The test would then be while (*string != '\n'). A better approach rather is simply controlling your input loop with while (fgets (string, STRSIZE, stdin)). There, you have validated the read before entering the loop. You can also wrap the whole thing in a for (;;) loop and control the loop exit based on any input condition you choose.
Those are all possibilities to consider. Look things over and let me know if you have further questions.
fgets() does read the newline IF (and only if) the buffer is long enough to reach and contain it, along with a trailing nul terminator.
Your sample input is 20 characters, which will be followed by a newline, and then a nul terminator. That won't go into a buffer of 19 characters.
The simple way is to use fgets() in a loop, until the newline is included in the buffer.
printf("\nEnter a new string.\n");
do
{
fgets(string,SIZE,stdin);
/*
handle the input, noting it may or may not include a trailing '\n'
before the terminating nul
*/
} while (strlen(string) > 0 && string[strlen(string) - 1] != '\n');
This loop will clear input up to and including the first newline, and also allow you to explicit handle (discard if needed) ALL the input received. It is therefore not necessary to use a second loop with getchar().
You haven't checked if fgets() returns NULL, so neither have I. It is advisable to check, as that can indicate errors on input.
I have trouble finishing a while loop using '\0' in c programming language, the c code is the following
#include<stdio.h>
char r;
int main()
{
do
{
scanf("%c", &r );
printf("%c", r);
}
while (r!='\0');
return 0;
}
My problem is that the program never finishes at the final character of typed string line, the while loop is always in waiting mode because of the scanf and never go to return 0. I do not know why this happen.
The output of this program is like this:
1234
2345
4556
7788
2345, 4556, 7788
Those are numbers I typed, but the program never finish (never go to return 0), I want to print just one string and I want the program ends.
Typical user input is a line, a sequence of characters up to and including a final '\n'.
As a part of user input, '\0' is just another character. It is often difficult to key in. Some keyboards allow it with CtrlShift# or other ways #user3629249
Very rarely is a string (a sequence of characters up to and including a final '\0') used on input.
To handle user input, a simply approach is to use fgets() to read a line of user input. That input will be saved as a string by fgets(buf) by appending a null character '\0' to the characters read: all saved in buf.
#include<stdio.h>
int main(void) {
char buf[100];
if (fgets(buf, sizeof buf, stdin) == NULL) {
puts("End-of-file or error encountered");
} else {
// maybe lop off the potential trailing \n from buf
buf[strcspn(buf, "\n")] = '\0';
printf("User input was <%s>\n", buf);
}
return 0;
}
To end user input, the usual approach is to signal the "end-of-file", see recognise return as EOF on the console
If code must use scanf();, check the return value to detect end-of-file or input error. #user3629249
if (scanf("%c", &r ) != 1) {
puts("End-of-file or error encountered");
}
My code goes something like this:
char k[1000];
while(1){
scanf("%s",&k);
if(k[0] == '\n'){
exit(0);}
/* Do some processing on k */
memset(k,0,1000);
}
My intention is to process user input per normal and terminate when user inputs empty string or new line. This doesn't seem to work.
Could you guys help on what went wrong?
On related note, I also want to terminate if it is the end of file, how should I do it for EoF?
Thank you in advance for all the help.
First off -- don't use scanf for user input. It is a minefield of subtle issues just waiting to bite new C programmers, instead use a line-oriented input function like fgets or POSIX getline. Both read up to (and including) the trailing '\n' every time (as long as you provide a buffer of sufficient size for fgets -- otherwise it just keep reading blocks of characters of its buffer size until it encounters a '\n' or EOF)
So to read user input until an empty-string or EOF is encountered, you could simply do something like the following:
#include <stdio.h>
#include <string.h>
#define MAXC 1000
int main (void) {
char k[MAXC] = "";
for (;;) { /* loop until empty-string of EOF */
printf ("input: "); /* prompt for input */
if (fgets (k, MAXC, stdin)) { /* read line (MAXC chars max) */
if (*k == '\n') { /* test for empty-string */
fprintf (stderr, "empty-string! bye.\n");
break;
}
size_t l = strlen (k); /* get length of string */
if (l && k[l - 1] == '\n') /* check if last char is '\n' */
k[--l] = 0; /* overwrite with nul-terminator */
printf ("got input: %s\n", k);
}
else { /* got EOF */
fprintf (stderr, "EOF -- bye.\n");
break;
}
}
return 0;
}
Example Use/Output
>bin\fgets_user_input.exe
input: this
got input: this
input: is some
got input: is some
input: input
got input: input
input:
empty-string! bye.
>bin\fgets_user_input.exe
input: this is more
got input: this is more
input: ^Z
EOF -- bye.
>bin\fgets_user_input_cl.exe
input: it works the same
got input: it works the same
input: compiled by gcc
got input: compiled by gcc
input: or by cl.exe (VS)
got input: or by cl.exe (VS)
input:
empty-string! bye.
(note: for Linux Ctrl+d generates the EOF, I just happened to be on windoze above)
Like ever so often, the problem here is inappropriate usage of scanf(). scanf() is not for reading input but for parsing it and the format-string tells it how to parse.
In your case, %s is looking for a sequence of non-whitespace characters (IOW, a word) and it skips any leading whitespace. \n (newline) is just a whitespace character, so it is always skipped -- your scanf() will just wait for more input until it can parse %s.
For more information on scanf() pitfalls, I recommend you my beginners' guide away from scanf(). As a rule of thumb, with interactive input (which is the default), scanf() is almost always wrong.
There's another huge problem with scanf("%s", ...): It will happily overflow any buffer you provide it, as long as the input contains non-whitespace characters, just like gets() which was even removed from C for exactly that reason: Buffer overflows are extremely dangerous! Therefore always use a field-width, in your case scanf("%999s", ...). This parses a maximum of 999 characters, leaving one for the necessary 0 byte terminating a string.
But now for how to do it correctly: There are several functions in C that are indeed for reading input and one of them is for reading a line of input: fgets(). In your code, it would look like this:
char k[1000];
while(fgets(k, 1000, stdin)){
if(k[0] == '\n'){
exit(0);
}
/* Do some processing on k */
memset(k,0,1000);
}
I used your original code here, still some further remarks:
It would be better to define a macro instead of using the magic number 1000, e.g. #define INPUTSIZE 1000 and use this instead, like char k[INPUTSIZE];, fgets(k, INPUTSIZE, stdin) etc.
Clearing the whole array is not needed, so to avoid unnecessary work, replace the memset() with just k[0] = '\0'; or similar. A C string ends at the first 0 byte, so this is enough to make k hold an empty string. If your program does nothing more than shown here, you could even get rid of this completely, as the next fgets() call overwrites the array anyways (or returns NULL on error, which would stop the loop).
Also note that fgets() reads the whole line including the newline character at the end, so keep this in mind when processing the contents of k.
This one is guaranteed to give everything except newlines (and EOFs) for you:
char k[1000];
scanf("%[^\n]", k);
And when it returns, the next character is guaranteed to be either a newline, or non-existent at all (EOF reached). Get it like this:
int next_char = getcgar();
if (next_char == EOF){
your_eof_process();
}
else if (nexr_char == '\n'){
your_newline_process();
}
Personally, I would do it using only getchar():
char k[1000];
int ind, tempc;
for (ind = 0; ind < sizeof k; ind ++){
tempc = getchar();
if (tempc == '\n'){
// Some stuff
}
else if (tempc == EOF){
// Other stuff
}
else {
k[ind] = tempc;
}
}
k[sizeof(k)-1] = '\0';
I have a program that is meant to take commands the first question is the format the commands will be taken in command line or file by typing c or f
if neither is typed the while loop repeats without allowing input equal to the number of characters in the incorrect input instead of stopping and allowing scanf to grab input again. I don't use it's return values at any point so I am at a loss as to why this happens. correctly entering 'f' or 'c' does not cause the problem.
any help would be greatly appreciated
#include<stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#define true 1
#define false 0
typedef int bool;
double **temp_array;
double temp1d_array[36];
char consolep[100];
char *fp1;
FILE *fp;
char string_IO1[50];
char string_temp[50];
char buffer[50];
char current_command[10];
int halt = 0;
char *strtodptr;
void main(){
printf("welcome \n");
char IO;
char read[250];
char file_console;
int IO_method = 0;
char command[10];
char type_IO;
char type_of_var_IO;
char dim_IO[3];
char array_string_IO[40];
//console or file
//decide IO Method loop 1
while (IO_method==0)
{
printf("please type 'c'for console or 'f' for file to select input type\n");
scanf("%c", &file_console);
//if console
if(file_console =='c')
{
IO_method=1;
printf("method is console\n");
}
//if file
else if(file_console=='f')
{
IO_method=2;
printf("method is file\n");
printf("please enter a file directory\n");
scanf("%s",&string_IO1);
}
else
{
printf("invalid entry\n");
file_console=NULL;
IO_method=0;
}
}}//code here continues but i compiled it without and has no bearing on the error.
The calls to scanf() in the posted code leave characters behind in the input stream. If, for example, the user enters g at the first prompt, pressing ENTER after, the \n character is left behind. If the user enters more than one character, the extra characters are left behind. The later calls to I/O functions will pick up these unexpected characters, causing the program to misbehave.
One solution is to write a little function to clear the input stream after such I/O function calls:
void clear_input(void)
{
int c;
while ((c = getchar()) != '\n' && c != EOF) {
continue;
}
}
This function discards any characters that remain in the input stream (up to and including the first newline character). Note that c must be an int to ensure that EOF is handled correctly. Also note that this function should only be called when the input stream is not empty; an empty input stream will cause the call to getchar() to block, waiting for input.
For example, after the first call to scanf() you know that there is at least a \n character still in the input stream (maybe more characters preceding the newline); just call clear_input() to clean the input stream before the next I/O call:
scanf("%c", &file_console);
clear_input();
The value returned by scanf() should be checked in robust code; the number of successful assignments made is returned, or EOF in rare the event of an error. This can help to validate input.
A better option would be to use fgets() to read from stdin and fetch a line of input to a buffer, and then use sscanf() to parse the buffer. One advantage here is that fgets() will read all characters up to, and including, a newline character, provided there is adequate space in the buffer. So, allocate a generous buffer[] to make it likely that no reasonable input can fail to be contained in the buffer. If you need to be more careful, you can check the input buffer for a \n character (using strchr(), for example). If the \n character is found in the buffer, then the input stream is empty, otherwise there are extra characters left behind, and the clear_input() function can be called to clean things up:
#include <stdlib.h>
#include <string.h>
...
char buffer[1000];
char end;
while (IO_method==0)
{
printf("please type 'c'for console or 'f' for file to select input type\n");
if (fgets(buffer, sizeof buffer, stdin) == NULL) {
/* Handle input error */
perror("Error in fgets()");
exit(EXIT_FAILURE);
}
/* May need to clear input stream, if input is too large */
if (strchr(buffer, '\n') == NULL) {
clear_input();
}
/* Input again if input is not as expected */
if (sscanf(buffer, "%c%c", &file_console, &end) != 2 || end != '\n') {
continue;
}
...
Here, buffer[] is declared with a generous size to hold all reasonable inputs. fgets() places the input in buffer, up to and including the newline (space-permitting). Note that the return value from fgets() is checked; a null pointer is returned if there is a rare I/O error. Next, strchr() is used to check for the \n in buffer; it is expected to be present, but if not, a null pointer is returned, signalling that there are still characters in the input stream to be cleared. Next, sscanf() is used to parse the buffer. Here, note that end is used store the character after the user-input character. In expected input, this is a \n character. If the user enters too many characters, testing end will reveal this, and input is taken again.
Also note that in the posted code, string_IO1 was not declared (and not a great name, since the characters in IO1 are difficult to distinguish on a screen); if this is a character array, then the call to scanf() should have looked like:
scanf("%s",string_IO1);
And, file_console has been declared as a char, so the assigment file_console = NULL; is wrong, since NULL is the null pointer macro, not an integer type.
My objective is to change the delimiter of scanf to "\n".
I tried using scanf("%[^\n]s",sen); and works fine for single inputs.
But when i put the same line inside a for loop for multiple sentences it gives me garbage values.
Does anyone know why?
Here's my code:
char sen[20];
for (i=0;i<2;i++)
{
scanf("%[^\n]s",sen);
printf("%s\n",sen);
}
Consider this (C99) code:
#include <stdio.h>
int main(void)
{
char buffer[256];
while (scanf("%255[^\n]", buffer) == 1)
printf("Found <<%s>>\n", buffer);
int c;
if ((c = getchar()) != EOF)
printf("Failed on character %d (%c)\n", c, c);
return(0);
}
When I run it and type in a string 'absolutely anything with spaces TABTABtabs galore!', it gives me:
Found <<absolutely anything with spaces tabs galore!>>
Failed on character 10 (
)
ASCII (UTF-8) 1010 is newline, of course.
Does this help you understand your problem?
It works in this case (for a single line) but if I want to take multiple lines of input into an array of arrays then it fails. And I don't get how scanf returns a value in your code?
There are reasons why many (most?) experienced C programmers avoid scanf() and fscanf() like the plague; they're too hard to get to work correctly. I'd recommend this alternative, using sscanf(), which does not get the same execration that scanf() and fscanf() do.
#include <stdio.h>
int main(void)
{
char line[256];
char sen[256];
while (fgets(line, sizeof(line), stdin) != 0)
{
if (sscanf(line, "%255[^\n]", sen) != 1)
break;
printf("Found <<%s>>\n", sen);
}
int c;
if ((c = getchar()) != EOF)
printf("Failed on character %d (%c)\n", c, c);
return(0);
}
This reads the line of input (using fgets() which ensures no buffer overflow (pretend that the gets() function, if you've heard of it, melts your computer to a pool of metal and silicon), then uses sscanf() to process that line. This deals with newlines, which are the downfall of the original code.
char sen[20];
for (i=0;i<2;i++)
{
scanf("%[^\n]s",sen);
printf("%s\n",sen);
}
Problems:
You do not check whether scanf() succeeded.
You leave the newline in the buffer on the first iteration; the second iteration generates a return value of 0 because the first character to read is newline, which is the character excluded by the scan set.
The gibberish you see is likely the first line of input, repeated. Indeed, if it were not for the bounded loop, it would not wait for you to type anything more; it would spit out the first line over and over again.
Return value from scanf()
The definition of scanf() (from ISO/IEC 9899:1999) is:
§7.19.6.4 The scanf function
Synopsis
#include <stdio.h>
int scanf(const char * restrict format, ...);
Description
2 The scanf function is equivalent to fscanf with the argument stdin interposed
before the arguments to scanf.
Returns
3 The scanf function returns the value of the macro EOF if an input failure occurs before
any conversion. Otherwise, the scanf function returns the number of input items
assigned, which can be fewer than provided for, or even zero, in the event of an early
matching failure.
Note that when the loop in my first program exits, it is because scanf() returned 0, not EOF.
%[^\n] leaves the newline in the buffer. %[^\n]%*c eats the newline character.
In any case, %[^\n] can read any number of characters and cause buffer overflow or worse.
I use the format string %*[^\n]%*c to gobble the remainder of a line of input from a file. For example, one can read a number and discard the remainder of the line by %d%*[^\n]%*c. This is useful if there is a comment or label following the number, or other data that is not needed.
char sen[20];
for (i=0;i<2;i++)
{
scanf("%[^\n]s",sen);
printf("%s\n",sen);
getchar();
}
Hope this helps ... actually "\n" remains in stream input buffer... Ee need to flush it out before scanf is invoked again
I know I am late, but I ran into same problem after testing C after a long time.
The problem here is the new line is considered as input for next iteration.
So, here is my solution, use getchar() to discard the newline the input stream:
char s[10][25];
int i;
for(i = 0; i < 10; i++){
printf("Enter string: ");
scanf("%s", s[i]);
getchar();
}
Hope it helps :)
While using scanf("%[^\n]", sen) in a loop, the problem that occurs is that the \n stays within the input buffer and is not flushed. As a result next time, when the same input syntax is used, it reads the \n and considers it as a null input. A simple but effective solution to address this problem is to use:
char sen[20];
for (i=0;i<2;i++)
{
scanf("%[^\n]%*c",sen);
printf("%s\n",sen);
}
%*c gets rid of the \n character in the input buffer.