I have a program that reads data from stdin. This data is a sequence of bytes. If there is a byte describing a new line in it (in hex: 0x0A), scanf stops reading.
Can I mask this byte, so that scanf continues to read the whole sequence?
It is important that the memory, that is written by scanf contains the newline-byte.
Without seeing your code, I can't make a precise recommendation. But if your goal is take the input "as-is", I'll recommend read() as an alternative to scanf(). See this question for someone who had the exact opposite issue.
scanf("%[^`]s", str);
You can use some thing like this. `\n will now be the terminating sequence of characters. You can replace ` using any other character or even a group of them and input will end with that character followed by a \n.
Related
I would like to read text files line by line in c.
I saw some examples using fgets. But I don't know if the fgets reads the caracteres until the end of the line, or it will read the amunt of chactrers specified (without stoping at the end of the line).
Best regards.
For future, if you're using a vim editor, try using man fgets. It'll give you some basic info on the function and its parameters. You can use this on literally any function that you're unsure about and it may help to clear some things up (although in my experience it confused things a bit more sometimes since I'm also a beginner)
fgets reads until either a null-byte (basically '\0'), the new line character or until it reaches the end of the file.
One of many references located here.
fgets - char * fgets ( char * str, int num, FILE * stream );
Reads characters from stream and stores them as a C string into str until (num-1) characters have been read or either a newline or the end-of-file is reached, whichever happens first.
A newline character makes fgets stop reading, but it is considered a
valid character by the function and included in the string copied to
str.
Many code examples out there.
This question already has answers here:
Why does scanf ask twice for input when there's a newline at the end of the format string?
(7 answers)
Closed 4 years ago.
Here's a simple example: I have an array of 3 characters, I write an input on terminal and I want to check immediately what i scanned, like this:
scanf("%3s\n",array);
printf("%s",array);
What i want to know is: why, after running the program, if I write on terminal "abc", to make it print out the array I have to put another input, like writing another letter or a number?
If I write "abcd" and then press ENTER then it immediately prints, but if I just write "abc" and press ENTER many times it still doesn't go to the next instruction (which is printf).
I know that it has to do with how \n makes scanf read the string, but I cant quite get it.
It is not the printf (as the first version of your now edited title implied) which needs the additional input, it is the scanf.
Your format string contains a "\n".
That happens to be a white space.
Any whitespace in that position will tell scanf to consume any number of whitespace following the three characters (e.g. "abc").
As long as you continue adding whitespace (including returns), the scanf is not done consuming "all following whitespace".
As soon as you enter any non-whitespace (e.g. "d") it knows "aha, all whitespace done". Then, and not before, it can complete. Leaves the non-whitespace in the input stream and returns.
Note (credits to chux) that with a (commonly, to the point of almost always if you did not intentionally change that) line buffered input, you need to enter such a non-whitespace with a return/newline following it somewhere.
Note, as mentioned in comments, you need 4 characters of space in your target array, to also accomodate the always written "\0" at the end of the string. If you only have three characters space, then the last 0 will be written beyond causing undefined behaviour.
I am not sure how to solve your problem, because I cannot tell what the purpose of your "\n" is. But I think you should try the behaviour if you move the "\n" out of scanf() and maybe into the printf(). A following scanf() call starting with a conversion specifier (except "[", "c", and "n") consumes any leading whitespace anyway, including any remaining newlines/returns from this one.
int main() {
char one[50]; char two[50];
while (scanf("%10s %10s",one,two) == 2){
printf("%s %s\n",one,two);
}
}
The function won't let me leave the loop
Charanas-MacBook-Pro:Testing zone Charana$ ./a.out
first second
first second
one two
one two
one
two
one two
leave
Any idea how to fix this so that I can leave the scanf when I go to a new line, or only enter one word into terminal, not two?
The scanf() function skips white space before reading a string via %s. Newlines are white space. Therefore, it continues reading until it gets the second string. Similarly with numbers; if you ask for two numbers, scanf() won't stop reading until it gets two numbers, or it comes across a character that can't be a part of a number — it reads across newlines quite happily.
If you want line-based input, do not use scanf(); use the fgets() from standard C or
getline() from POSIX, coupled with
sscanf(). Then you can get sane behaviour.
As it stands, the scanf() function is working exactly as it is intended to work; it won't complete until it has a second string. You can interrupt the program, but that's usually not what you want. You can signal EOF (e.g. by typing Control-D on Unix-like platforms or Control-Z on Windows), but that can lead to further problems — you have to clear the EOF condition before you can get further input, for example.
Using fgets() and sscanf() has many advantages — go with it.
If the code is
scanf("%s\n",message)
vs
gets(message)
what's the difference?It seems that both of them get input to message.
The basic difference [in reference to your particular scenario],
scanf() ends taking input upon encountering a whitespace, newline or EOF
gets() considers a whitespace as a part of the input string and ends the input upon encountering newline or EOF.
However, to avoid buffer overflow errors and to avoid security risks, its safer to use fgets().
Disambiguation: In the following context I'd consider "safe" if not leading to trouble when correctly used. And "unsafe" if the "unsafetyness" cannot be maneuvered around.
scanf("%s\n",message)
vs
gets(message)
What's the difference?
In terms of safety there is no difference, both read in from Standard Input and might very well overflow message, if the user enters more data then messageprovides memory for.
Whereas scanf() allows you to be used safely by specifying the maximum amount of data to be scanned in:
char message[42];
...
scanf("%41s", message); /* Only read in one few then the buffer (messega here)
provides as one byte is necessary to store the
C-"string"'s 0-terminator. */
With gets() it is not possible to specify the maximum number of characters be read in, that's why the latter shall not be used!
The main difference is that gets reads until EOF or \n, while scanf("%s") reads until any whitespace has been encountered. scanf also provides more formatting options, but at the same time it has worse type safety than gets.
Another big difference is that scanf is a standard C function, while gets has been removed from the language, since it was both superfluous and dangerous: there was no protection against buffer overruns. The very same security flaw exists with scanf however, so neither of those two functions should be used in production code.
You should always use fgets, the C standard itself even recommends this, see C11 K.3.5.4.1
Recommended practice
6 The fgets function allows properly-written
programs to safely process input lines too long to store in the result
array. In general this requires that callers of fgets pay attention to
the presence or absence of a new-line character in the result array.
Consider using fgets (along with any needed processing based on
new-line characters) instead of gets_s.
(emphasis mine)
There are several. One is that gets() will only get character string data. Another is that gets() will get only one variable at a time. scanf() on the other hand is a much, much more flexible tool. It can read multiple items of different data types.
In the particular example you have picked, there is not much of a difference.
gets - Reads characters from stdin and stores them as a string.
scanf - Reads data from stdin and stores them according to the format specified int the scanf statement like %d, %f, %s, etc.
gets:->
gets() reads a line from stdin into the buffer pointed to by s until either a terminating newline or EOF, which it replaces with a null byte ('\0').
BUGS:->
Never use gets(). Because it is impossible to tell without knowing the data in advance how many characters gets() will read, and because gets() will continue to store characters past the end of the buffer, it is extremely dangerous to use. It has been used to break computer security. Use fgets() instead.
scanf:->
The scanf() function reads input from the standard input stream stdin;
BUG:->
Some times scanf makes boundary problems when deals with array and string concepts.
In case of scanf you need that format mentioned, unlike in gets. So in gets you enter charecters, strings, numbers and spaces.
In case of scanf , you input ends as soon as a white-space is encountered.
But then in your example you are using '%s' so, neither gets() nor scanf() that the strings are valid pointers to arrays of sufficient length to hold the characters you are sending to them. Hence can easily cause an buffer overflow.
Tip: use fgets() , but that all depends on the use case
The concept that scanf does not take white space is completely wrong. If you use this part of code it will take white white space also :
#include<stdio.h>
int main()
{
char name[25];
printf("Enter your name :\n");
scanf("%[^\n]s",name);
printf("%s",name);
return 0;
}
Where the use of new line will only stop taking input. That means if you press enter only then it will stop taking inputs.
So, there is basically no difference between scanf and gets functions. It is just a tricky way of implementation.
scanf() is much more flexible tool while gets() only gets one variable at a time.
gets() is unsafe, for example: char str[1]; gets(str)
if you input more then the length, it will end with SIGSEGV.
if only can use gets, use malloc as the base variable.
I want to know if there is a way to know when fscanf reads a whitespace or a new line.
Example:
formatting asking words italic
links returns
As fscanf read a string till it meets a newline or a whitespace(using %s), it'll read formatting and the space after it and before a. The thing is, is there a way to know that it read a space? And after it entered the second line is there is a way to know that it read a carriage return?
You can instruct fscanf to read whitespace into your variable instead of reading and discarding whitespace. Use something like [ \n\r\t]* but you need to include more characters in that expression. Depending on the locale and some features of the runtime character set, you might want to write a separate function to compute the appropriate format string once before using it.
If you need to distinguish \n from other kinds of whitespace, you have your variable containing the whitespace that you just finished reading. You might want to count all of the \n characters in it, depending on your needs.