Formatted input in C
Declare friend1
& friend2
as char array
if you want to store names
into them as below
char friend1[50];/** take the char array of required size **/
char friend2[50];
And while scanning you no need to provide &
in scanf
if friend1
is declared as char array
, because char array
name itself address.
printf("Please enter name of your friend...\n");
scanf("%s", friend1);
Apply the same for friend2
. Also while printing don't use &
if you want to print value of average
.
Replace
printf("Average age of your friends %s and %s is %4.2f years old\n" ,&friend1,&friend2,&average);
with
printf("Average age of your friends %s and %s is %4.2f years old\n" ,friend1,friend2,average);
Why do C++ standards introduce more output methods without input counterparts?
std::format
and std::print
are already quite a big library addition in itself and I could image that the limited resources for the standard committee to consider the addition of additional features didn't allow them to consider an input equivalent at the same time.
It might also be that the committee wanted to collect more experience with std::format
/std::print
first before adding an input equivalent or that there are objections to such an addition in principle, in the proposed implementation details or the priority of such an addition.
I couldn't find any definitive statements pointing towards any of these directions and I have no insider knowledge.
Anyway, the committee is still considering a std::scan
proposal as follow-up to the std::format
proposal, see https://github.com/cplusplus/papers/issues/493 for a log of the procedure the proposal has gone through so far. You can also see there polls on design directions, etc. There seems to not have been much activity since 2019, but I am not sure whether this really means anything or not.
In a reddit thread here from March 2022, Elias Kosunen, one of the authors of the proposal and author of scnlib mentions that there are still some unsure design questions that need to be made sure of before going forward with the proposal, hoping to be able to target C++26, but acknowledging that a farther delay would be preferable to adding a "half-baked" design to the standard.
Using scanf() in C++ programs is faster than using cin?
Here's a quick test of a simple case: a program to read a list of numbers from standard input and XOR all of the numbers.
iostream version:
#include <iostream>
int main(int argc, char **argv) {
int parity = 0;
int x;
while (std::cin >> x)
parity ^= x;
std::cout << parity << std::endl;
return 0;
}
scanf version:
#include <stdio.h>
int main(int argc, char **argv) {
int parity = 0;
int x;
while (1 == scanf("%d", &x))
parity ^= x;
printf("%d\n", parity);
return 0;
}
Results
Using a third program, I generated a text file containing 33,280,276 random numbers. The execution times are:
iostream version: 24.3 seconds
scanf version: 6.4 seconds
Changing the compiler's optimization settings didn't seem to change the results much at all.
Thus: there really is a speed difference.
EDIT: User clyfish points out below that the speed difference is largely due to the iostream I/O functions maintaining synchronization with the C I/O functions. We can turn this off with a call to std::ios::sync_with_stdio(false);
:
#include <iostream>
int main(int argc, char **argv) {
int parity = 0;
int x;
std::ios::sync_with_stdio(false);
while (std::cin >> x)
parity ^= x;
std::cout << parity << std::endl;
return 0;
}
New results:
iostream version: 21.9 seconds
scanf version: 6.8 seconds
iostream with sync_with_stdio(false): 5.5 seconds
C++ iostream wins! It turns out that this internal syncing / flushing is what normally slows down iostream i/o. If we're not mixing stdio and iostream, we can turn it off, and then iostream is fastest.
The code: https://gist.github.com/3845568
Disadvantages of scanf
The problems with scanf are (at a minimum):
- using
%s
to get a string from the user, which leads to the possibility that the string may be longer than your buffer, causing overflow. - the possibility of a failed scan leaving your file pointer in an indeterminate location.
I very much prefer using fgets
to read whole lines in so that you can limit the amount of data read. If you've got a 1K buffer, and you read a line into it with fgets
you can tell if the line was too long by the fact there's no terminating newline character (last line of a file without a newline notwithstanding).
Then you can complain to the user, or allocate more space for the rest of the line (continuously if necessary until you have enough space). In either case, there's no risk of buffer overflow.
Once you've read the line in, you know that you're positioned at the next line so there's no problem there. You can then sscanf
your string to your heart's content without having to save and restore the file pointer for re-reading.
Here's a snippet of code which I frequently use to ensure no buffer overflow when asking the user for information.
It could be easily adjusted to use a file other than standard input if necessary and you could also have it allocate its own buffer (and keep increasing it until it's big enough) before giving that back to the caller (although the caller would then be responsible for freeing it, of course).
#include <stdio.h>
#include <string.h>
#define OK 0
#define NO_INPUT 1
#define TOO_LONG 2
#define SMALL_BUFF 3
static int getLine (char *prmpt, char *buff, size_t sz) {
int ch, extra;
// Size zero or one cannot store enough, so don't even
// try - we need space for at least newline and terminator.
if (sz < 2)
return SMALL_BUFF;
// Output prompt.
if (prmpt != NULL) {
printf ("%s", prmpt);
fflush (stdout);
}
// Get line with buffer overrun protection.
if (fgets (buff, sz, stdin) == NULL)
return NO_INPUT;
// Catch possibility of `\0` in the input stream.
size_t len = strlen(buff);
if (len < 1)
return NO_INPUT;
// If it was too long, there'll be no newline. In that case, we flush
// to end of line so that excess doesn't affect the next call.
if (buff[len - 1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF))
extra = 1;
return (extra == 1) ? TOO_LONG : OK;
}
// Otherwise remove newline and give string back to caller.
buff[len - 1] = '\0';
return OK;
}
And, a test driver for it:
// Test program for getLine().
int main (void) {
int rc;
char buff[10];
rc = getLine ("Enter string> ", buff, sizeof(buff));
if (rc == NO_INPUT) {
// Extra NL since my system doesn't output that on EOF.
printf ("\nNo input\n");
return 1;
}
if (rc == TOO_LONG) {
printf ("Input too long [%s]\n", buff);
return 1;
}
printf ("OK [%s]\n", buff);
return 0;
}
Finally, a test run to show it in action:
$ printf "\0" | ./tstprg # Singular NUL in input stream.
Enter string>
No input
$ ./tstprg < /dev/null # EOF in input stream.
Enter string>
No input
$ ./tstprg # A one-character string.
Enter string> a
OK [a]
$ ./tstprg # Longer string but still able to fit.
Enter string> hello
OK [hello]
$ ./tstprg # Too long for buffer.
Enter string> hello there
Input too long [hello the]
$ ./tstprg # Test limit of buffer.
Enter string> 123456789
OK [123456789]
$ ./tstprg # Test just over limit.
Enter string> 1234567890
Input too long [123456789]
Is there an equivalent method to C's scanf in Java?
Take a look at this site, it explains two methods for reading from console in java, using Scanner
or the classical InputStreamReader
from System.in.
Following code is taken from cited website:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class ReadConsoleSystem {
public static void main(String[] args) {
System.out.println("Enter something here : ");
try{
BufferedReader bufferRead = new BufferedReader(new InputStreamReader(System.in));
String s = bufferRead.readLine();
System.out.println(s);
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
--
import java.util.Scanner;
public class ReadConsoleScanner {
public static void main(String[] args) {
System.out.println("Enter something here : ");
String sWhatever;
Scanner scanIn = new Scanner(System.in);
sWhatever = scanIn.nextLine();
scanIn.close();
System.out.println(sWhatever);
}
}
Regards.
Why does scanf appear to skip input?
When you enter a
, then cin >> i
fails to read it because the type of i
is int
to which a character cannot be read. That means, a
remains in the stream forever.
Now why i
prints 0
is a different story. Actually it can print anything. The content of i
is not defined once the attempt to read fails. Similar thing happens with scanf
as well.
The proper way to write it this:
do
{
++j;
if (!(cin>>i))
{
//handle error, maybe you want to break the loop here?
}
cout<<i<<" "<<j<<"\n";
}
while((i!=8) && (j<10));
Or simply this (if you want to exit loop if error occurs):
int i = 0, j = 0;
while((i!=8) && (j<10) && ( cin >> i) )
{
++j;
cout<<i<<" "<<j<<"\n";
}
Related Topics
How to Call a Cmake Function from Add_Custom_Target/Command
How to Open a Folder in %Appdata% with C++
Why There Is No Std::Copy_If Algorithm
What Does the "::" Mean in "::Tolower"
What Standard Clause Mandates This Lvalue-To-Rvalue Conversion
How to Output to the Console in C++/Windows
Locking Files in Linux with C/C++
Is It Legal to Modify the Result of Std::String::Op[]
Threadsafe Vector Class for C++
Conditionally Replace Regex Matches in String
The Cxx Compiler Identification Is Unknown
Pointer as Non-Type Template Argument
Clang-Omp in Xcode Under El Capitan
Should "Delete This" Be Called from Within a Member Method
Double Dispatch/Multimethods in C++
Spurious Warning About Binding Temporary to Reference Member in Constructor