Reading and Writing in C - c

so I was messing with the read functions fgets and scanf and with the printing functions write and printf with the following code:
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[])
{
printf("Enter an integer: ");
int n = 0; scanf("%d",&n);
printf("The input number is: %d\n", n);
printf("Please enter a string now: ");
char buffer[200];
read(0,buffer,200);
printf("The input string is: %s", buffer);
printf("which is: %s\n", buffer);
printf("Now please enter another message: ");
fgets(buffer,200,stdin);
write(1,buffer,200);
return 0;
}
I would get these errors:
1-After the first scanf, it won't just show me the message to input the string.
2-What I write now it's what it's going to be saved in the string.
3-It will skip the last fgets...
An example of output:
Which doesn't make any sense at all; I would like to get an output like this:
Enter an integer: 15
The input number is: 15
Please enter a string now: This is the message1
The input string is: This is the message1 which is: This is the message1
Now please enter another message: This is the message2
This is the message2
Thanks for your help!

Interesting question. Mixing standard I/O (scanf(), fgets()) and file descriptor I/O (read()) on the same underlying file descriptor (0 aka standard input; stdin as a file stream) is at best problematic. You will get odd-ball effects.
At the file stream level, there is some synchronization between stdin and stdout when the input comes from a terminal; pending output on stdout is often flushed by the library. When you use read(), there is no such synchronization. That's why the prompt doesn't appear until after you hit return.
When you type 1 for the number, you also supply a newline. Standard I/O buffers the newline; it is kept so that the next file stream operation can read it. Then you read a line with read(). This does not know about the standard I/O buffer, so it waits for a new line of input from the terminal. You need to capture how much data was read because the input was not null terminated; that's a service provided by the standard I/O library, not the low-level read() function.
When you then call fgets(), it reads the newline that was buffered (not processed by scanf() when reading the integer) and returns with the empty line.
Note that if you had any buffered output waiting on standard output (e.g. you had used printf("Beginning of line: "); with no newline), then the output from write() would appear before the information buffered on stdout.
Using fread() and fwrite() would give you direct binary I/O (no null termination, for example), but would use the same I/O buffers as functions such as printf() and fgets(). You get hybrid behaviour when using these — it is normally best to use either fread()/fwrite() or the text I/O functions on a single file stream, and not both, but mixing them is permissible, relatively simple to understand, and occasionally useful.
So, what you see is all explainable, but it is hard work doing the explaining. It is also a clear indication of why you should not, in general, mix file stream and file descriptor I/O on the same underlying file descriptor — especially not standard input.

Why not use scanf with some better formatting:
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[]) {
int n, i;
char buffer[200], ch;
printf("Enter an integer: ");
scanf("%d",&n);
printf("The input number is: %d\n", n);
printf("Please enter a string now: ");
scanf(" %[^\t\n]s",buffer);
printf("The input string is: %s", buffer);
printf("which is: %s\n", buffer);
printf("Now please enter another message: ");
scanf(" %[^\t\n]s",buffer);
printf("%s", buffer);
return 0;
}

read(0,buffer,200);
reads up to 200 characters but it won't add a terminating null character to buffer. Hence the following call to printf results in undefined behavior.
You need to add code to capture the return value of the function and make sure to null terminate the string.
int n = read(0, buffer, 199); // Leave one for the terminating null character
if ( n == -1 )
{
// Deal with the error.
}
else
{
// null terminate the string.
buffer[n] = '\0';
}

Related

How can i detect just the new line input using scanf, and printing directory, like terminal

I wanna reproduce the terminal behavior when the input is just a new line (keeps printing the same string), but don't know how to do it.
Example: When the user just inputs a new line, the terminal keeps printing the directory, until a real command is inserted
int main()
{
char userInput[1024];
while (1)
{
printf("directory »» ");
scanf("%[^\n]" , userInput); // This scanf doesn't work
while (userInput[0] == '\n') // If the input is only a new line char, keep asking for more inputs and printing the directory
{
printf("directory »» ");
scanf(" %[^\n ]" , userInput); // This scanf doesn't work
}
//Input isn't a NewLine, process the input
process_Input_Function(userInput); //Isn't empty, search for my created commands
}
}
At the first enter press, it enters the loop, reproduce 1 time, and then the scanf doesn't detect new lines anymore, it just skips and waits to a real string.
What can i type inside of the scanfto detect a new line input and keep printing that string till a real command is inserted?
I tried with scanf("%c"...) but the problem with a char, is that i can't process the whole string command, if isn't empty
First of all, your two scanf calls are different. The first one is
scanf("%[^\n]", userInput);
which looks for anything that's not a newline, as you wish to do.
But the second one is
scanf(" %[^\n ]", userInput);
which is also looking for a space before the input, followed by any character that is also not a newline or a space. Thus, scanf is waiting for the space.
IMHO, the best way to recreate this behavior is going to be in the parsing step, after you have gotten the command from the command line. Essentially, your command input loop would look like this:
char *userInput = NULL;
size_t n = 0;
while (true) {
// print the prompt
printf(">");
// get the line
ssize_t userInputLength = getline(&userInput, &n, &stdin);
// parse the input, using a function you wrote elsewhere
parse(userInputLength, userInput);
}
(Note the use of POSIX getline() instead of scanf. This is a more recent standard library function that does exactly the task of getting a line of user input, and also allocates the buffer using malloc and realloc so that you don't have to care about buffer overflows or even sizing the buffer at all.)
The user input function wouldn't care that the userInput portion was blank. The function that would care is the parse function, which will simply interpret a blank userInput string as "do nothing" and continue on its merry way.
Hmm, the code I gave pretty much does that with one exception, it doesn't display a prompt each time...
Is this what you mean:
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // For the memset()
int main() {
char userInput[1024];
while (1) {
printf("»»» ");
fgets(userInput, 1024, stdin);
while (userInput[0] == '\n')
{
printf(">>> ");
memset(userInput, '\0', 1024);
fgets(userInput, 1024, stdin);
}
// Your command can be accessed from here //
printf("Command entered: %s\n", userInput);
printf("Input isn't a NewLine\n");
}
}
I changed the scanf() to fgets() to read from stdin so that we don't overwrite the buffer.

Why does scanf pass the value to my function, dont want scanf to send value to callee [duplicate]

This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
Closed 5 years ago.
I am aware of scanf() usage and is not encouraged. But I've the problem, where scanf sends the stdin value to the next function stdin. I'm wondering why it's doing like this.
code:
#include <stdio.h>
void ffgets() {
char name[40];
printf("What's your name? ");
if (fgets(name, 40, stdin)) {
printf("Hello %s", name);
}
}
int main(int argc, char **argv) {
int a;
printf("enter a number: ");
int res = scanf("%d", &a);
if (res > 0) {
printf("Valid Integer %d.\n", a);
} else {
printf("It's not a number\n");
}
ffgets();
return 0;
}
Output:
Test case 1:
Why the function doesn't ask for stdin, it just print empty string
./a.out
enter a number: 23
Valid Integer 23.
What's your name? Hello
Test case 2: I entered the string with the special character that is passed name.
./a.out
enter a number: random##¤
It's not a number
What's your name? Hello random##¤
I dont want stdin value from main passed to the function, how to do that?
If you input something that scanf can not match to the format specification then it will stop immediately and leave the input in the input buffer for the next input function.
Also, when using scanf it will not consume the trailing newline in the input buffer, also leaving it for the next input function.
To solve both problems consider using fgets to get the whole line from the input, and then use sscanf to parse the string.
I am aware of scanf() usage and is not encouraged.
This is exactly the issue that comes from scanf() (namely, that input not used by scanf is left in the input buffer, contrary to what the user expected). So, as you seem to already know, the solution is to not use the function.
It's not that hard to make a function to read a complete line of input, and parse an int from there with sscanf() or strtol or friends:
#include <stdio.h>
#include <limits.h>
int getint(void)
{
char buffer[120] = {0}; /* arbitrary limit */
fgets(buffer, 120, stdin);
int a;
if (sscanf(buffer, "%d", &a) == 1) {
return a;
}
return INT_MIN;
}
(Of course INT_MIN is a valid number to enter, so you might want to have some better way of returning errors. And perhaps consider what to do with garbage following the number.)
The reason is that in the first case, the matching input is consumed by scanf() but the newline \n is present in the input buffer. That makes a valid input and terminator for fgets() in the first case.
Related , quoting C11, chapter §7.21.6.2
Trailing white space (including new-line characters) is left unread unless matched by a
directive. [....]
In the second case, the matching failure happens, which makes the entire input to be available in the input buffer at the time of fgets() call, so fgets() reads the whole thing.

Reading from stdin, and clearing stdin afterward

Here is a loop that repeatedly gets two characters from stdin and outputs them.
char buf[2];
while (1)
{
printf("give me two characters: ");
fflush(stdout);
read(0, buf, 2);
printf("|%c%c|\n", buf[0], buf[1]);
}
The problem is that when the ENTER key is struck on the terminal, a newline character is inserted and remains in the stdin buffer, and will be grabbed on the next call to read. Ideally, I would like to have a clear stdin buffer ever time I call read, with none of the previous garbage left over. Can you recommend a good solution to this?
I have tried various library calls such as fgets, however they encounter the same issue. I was considering using fpurge to clear the buffer manually, but I was told this was not a good solution.
The issue here is that leftover input should be treated as garbage, and thrown away. However when I make the next call to read I have no way of distinguishing the leftover input from the new input.
Thanks for the input.
You can add getchar(); to read the more '\n':
#include <stdlib.h>
#include <stdio.h>
char buf[2];
main() {
while (1)
{
printf("give me two characters: ");
fflush(stdout);
read(0, buf, 2);
getchar();
printf("|%c%c|\n", buf[0], buf[1]);
}
}
give me two characters: ab
|ab|
give me two characters: xy
|xy|

Program output in wrong order

I working on a C project in Eclipse environment the code is correct and executable but the output
lines are not in order the program ask user to
enter a number from 1-5 then asks for a name then street
but nothing appear on console screen unless i entered these values
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char name[20], address[30];
char c;
printf("How do you feel on a scale of 1-5?");
c = getchar();
printf("Enter name: ");
scanf("%s", &name);
printf("Enter your address: ");
scanf("%s", &address);
printf("Entered Name: %s\n", name);
printf("Entered address:%s\n", address);
printf("You said you feel: ");
putchar(c);
return EXIT_SUCCESS;
}
The problem is that stdout is line buffered (when going to a console), so unless you print a newline character, the output will remain buffered and not be displayed (OK, there's going to be a maximum size that can be buffered put that's just detail, your small amount of output will remain in buffer).
The two solutions that occur to me are, use fflush (stdout); after your first 3 printf calls, this will cause the stdout buffer to be flushed to the console, and should resolve your problems.
You could also turn off buffering of stdout, see setvbuf for how to do this, but I think, placing this call near the start of main (before any output) should work (untested):
setvbuf (stdout, NULL, _IONBF, 0);
The problem is your second scanf is capturing the \n character of the previous input, try to use fgets in order to avoid this behaviour.

Is it possible to use scanf("%d" &i) and use the first number inputted only, and nothing else?

First off, I am not familiar with c at all. It would be great if you treated me like a total beginner, which I am.
So, the problem I have is that I don't seem to be able to make it so that the program only takes the information of one number, uses it, then disregards any other information.
At the moment I have something similar to this:
#include <stdio.h>
#include <string.h>
int main(){
int i, ret;
char c, type;
do
{
printf("Convert ASCII # to character\n");
printf("q: Quit.\n");
scanf("%c", &type);
/* I use the " if(type== 'n'); " a number of times. */
/* I left the others out to simplify what my problem is. */
if(type=='1'){
printf("ASCII NUMBER -> CHAR \n");
printf("\t Please input one ASCII code \n");
int ret = scanf("%d", &i);
/* My aim here is to get the amount of integers the user inputs,*/
/* and use that to categorize, but I think I am failing to do so. */
if(ret==1){
printf("\t The character for ASCII code %d is -> '%c' \n\n", i, i);
break;
}
else{
printf("Please input one number./n/n");
break;
}
}
}
while(type=='q');
return 0;
/* A problem I face a lot is where the program would terminate*/
/* even when the while conditions weren't met. */
}
I hope you could understand what I'm trying to do by looking at the code above.
Any help would be greatly appreciated!
the program ends because of the character [enter] left in the input buffer.
You give input value for type then for i and press [enter]. this [enter] is a character left in the input buffer which will be read by next
scanf("%c",type);
so the loop exits. Therefore use getchar() after
int ret = scanf("%d", &i);
To clear the input buffer. and the loop will not end unexpectedly.
Make these changes,
printf("\t Please input one ASCII code \n");
int ret = scanf("%d", &i);
getchar(); //this will read the [enter] character in input buffer
/* My aim here is to get the amount of integers the user inputs,*/
/* and use that to categorize, but I think I am failing to do so. */
if(ret==1){
In general, I find it better to use fgets() (alternatively, if you are using C99, gets_s() -- although I still prefer fgets() for maximum portability to older compiler environments) for all user-based input, then if necessary use sscanf(), strtol(), and the like to convert the string into other data types, as this will read data by line in a way that is buffer-safe and you won't have to worry about things left in the input buffer. This is especially true for user-based input which is never well-formed (due to typos, etc). scanf() really only works well when reading from well-formed input files.
See the comp.lang.c FAQ which describes some of the problems that often occur when using scanf() in detail, including the problem you are seeing above, where inputs seem to be getting skipped:
http://c-faq.com/stdio/scanfprobs.html
http://c-faq.com/stdio/scanfhang.html
http://c-faq.com/stdio/scanfinterlace.html
http://c-faq.com/stdio/scanfjam.html
To find out more about any C standard library function, at a linux command prompt (or Google) type: man 3 fgets and so on.
fgets: http://linux.die.net/man/3/fgets
sscanf: http://linux.die.net/man/3/sscanf
strtol: http://linux.die.net/man/3/strtol
Example:
char buffer[256], type;
fgets( buffer, sizeof(buffer), stdin );
if( sscanf( buffer, "%c", &type ) == 1 ) {
// Was able to read a char from the buffer, now you can use it.
}
else {
// Wasn't able to read a char from the buffer. handle it if required.
}

Resources