The program is supposed to get user first name and last name and then print them as last name, first name. The program stops immediately after the second input. I tried fflush (stdout) but that didn't seem to work (I might have done it incorrectly).
#include "stdafx.h"
#include <iostream>
using namespace System;
using namespace std;
int main()
{
char First[30], Last[30];
printf("Please type in your First Name: ");
scanf("%s",&First);
fflush(stdout);
printf("Please type in your Last Name: ");
scanf("%s",&Last);
printf("%s %s", Last, First);
printf("pause");
return 0;
}
C++ version of your program :
#include <iostream>
using namespace std;
int main()
{
string first, last;
cerr << "Please type in your First Name: ";
if (! (cin >> firs))
return -1;
cerr << "Please type in your Last Name: ";
if (! (cin >> last))
return -1;
cout << last << ' ' << first << endl;
return 0;
}
Compilation and execution :
pi#raspberrypi:/tmp $ g++ -pedantic -Wextra i.cc
pi#raspberrypi:/tmp $ ./a.out
Please type in your First Name: aze
Please type in your Last Name: qsd
qsd aze
pi#raspberrypi:/tmp $
I check names was enter (no EOF), I use cerr to be sure to flush the messages without writing endl
And the C version :
#include <stdio.h>
int main()
{
char first[30], last[30];
fprintf(stderr, "Please type in your First Name: ");
if (scanf("%29s", first) != 1)
return -1;
fprintf(stderr, "Please type in your Last Name: ");
if (scanf("%29s", last) != 1)
return -1;
printf("%s %s\n", last, first);
return 0;
}
Compilation and execution:
pi#raspberrypi:/tmp $ gcc -pedantic -Wextra i.c
pi#raspberrypi:/tmp $ ./a.out
Please type in your First Name: aze
Please type in your Last Name: qsd
qsd aze
I limit the size in the scanf to not write out of the arrays, I check scanf was able to read the names, I also use stderr to be sure to flush the message without writing '\n'
first and last are array, it is useless to use '&' in the scanf to give their address
Note these versions do not allow to enter composed names using spaces, to allow that all the line need to be read
It helps to think about the purpose of the fflush() call. There is pending data that you want the user to see so they know what to type.
Let us consider the first query (printf, scanf, flush). The printf() puts data into a buffer. The scanf() then reads the user's response. The flush() won't execute until after the user has typed something.
Those three calls are in the wrong order. I'll leave fixing that as an exercise for the reader.
Now consider the next query (printf, scanf). The printf() puts data into a buffer. The scanf() reads the user's response, but the user won't yet have seen the "... Last Name:" prompt.
Clearly there is also an error in that block. Again, I'll leave fixing that as an exercise for the reader. Hint: if you fixed the first error that should help you understand the second.
By the way, scanf() doesn't guard against overflowing the First[] and Last[] arrays. That isn't necessary to answer your original question, but I mention it because even after you have fixed the code it will remain unsafe.
The fflush(stdout); you have doesn't help because it's too early in the code as it doesn't help with flushing the latter printfs.
You could use \n to flush as well. But this may not work if your output device isn't interactive e.g. redirected to a file.
You also have another problem with scanf() format specifiers: First and Last, being arrays, decay into pointers when passed to scanf. So you are passing the wrong type of arguments to scanf - just drop the &'s from scanf calls.
So your program could simply be:
#include <stdio.h>
int main(void)
{
char First[30], Last[30];
printf("Please type in your First Name: ");
scanf("%s", First);
fflush(stdout);
printf("Please type in your Last Name: ");
scanf("%s", Last);
fflush(stdout);
printf("%s %s\n", Last, First);
fflush(stdout);
getchar();
return 0;
}
All the fflush(stdout) calls may not be necessary if you could use \n in all printf calls because you're likely using an interactive terminal.
If you are using C++, you should really be using iostream for I/O. If nothing else, scanf is a terrible, has many problems, and should be avoided.
Related
I have make a program that take a number and a separator. If the user press enter, then the program will print the total of the number.
example input: 2[space]3[enter] will print "total = 5", 1[space]2[space]3[enter] will print "total = 6", but if I input 2a3[enter], the program will get terminated and exit instead of printing "error!" and the "press ENTER..." message. Previously, I use the system("PAUSE") function and there was no problem(the error message appear). And then I know that it is not standard, so I replace it with 2 lines of code(you can see it in the code) and the problem occur.
My input:
2[space]3[enter] --> print "total = 5"
2a3[enter] --> the program gets terminated instead of printing "error!" and the "press ENTER..." message
#include <stdio.h>
#include <stdlib.h>
int main()
{
int num, total;
char separator;
for(;;)
{
scanf("%d%c", &num, &separator);
total += num;
if(separator == '\n')
{
printf("total = %d\n", total);
break;
}
else if(separator == ' ')
{
//do nothing
}
else
{
printf("error!\n");
break;
}
}
printf("press ENTER to exit..."); //this
getchar(); //two lines
//previously, I use system("PAUSE"), and there is no problem.
return 0;
}
I use gcc 10.3.0 and Windows 10 OS.
Can anyone explain to me why this problem occur?
Input buffer fun.
When you hit the break; statement after the printf("error!"), there is a "3\n" in the input buffer; thus getchar() finds something to read immediately and thus your program appears to terminate immediately. The missing newline after error causes the line to be gobbled on Windows because the command prompt moves the cursor left first rather than starting the command prompt mid-line.
It is not recommended to use scanf to parse keyboard input but rather to use fgets() or getline() and parse yourself to avoid input buffer stuff like this.
Use of total like that is undefined, but it is improbable that you are using a processor that's going to fault here and I disregarded it.
I want to get date of birth in one line:
#include <stdio.h>
int main()
{
int BirthYear,BirthMonth,BirthDay;
printf("Please enter your birth date: ");
scanf("%d",&BirthYear);
printf("/");
scanf("%d",&BirthMonth);
printf("/");
scanf("%d",&BirthDay);
return 0;
}
This is my output:
Please enter your birth date: YYYY
/MM
/DD
But I want to get something like this:
Please enter your birth date: YYYY/MM/DD
In output, it goes to next line after each scanf() without using \n.
I use VS Code for IDM.
Here is a workaround using ansi control characters. I would not do like this, but just to show that it is possible:
#define PREVLINE "\033[F"
#define MSG "Please enter your birth date: "
int main(void) {
int BirthYear,BirthMonth,BirthDay;
printf(MSG);
scanf("%d",&BirthYear);
printf(PREVLINE MSG "%d/", BirthYear);
scanf("%d",&BirthMonth);
printf(PREVLINE MSG "%d/%d/", BirthYear, BirthMonth);
scanf("%d",&BirthDay);
printf("You entered: %d/%d/%d\n", BirthYear, BirthMonth, BirthDay);
}
Please note that this is not portable. The terminal needs to support this in order to work. AFAIK there's no 100% portable way to achieve this.
If you want to do this stuff for real, then I recommend taking a look at the ncurses library
Note:
Always check the return value for scanf to detect errors.
Note2:
It may be a good idea to add fflush(stdout); after each printf statement.
I actually wrote another answer today about ascii control characters. It might be interesting: https://stackoverflow.com/a/64549313/6699433
You can explicitly specify that the three input numbers should be separated by a '/' character by adding that character in the format specifier for the scanf function.
Then, you can ensure that the user gave valid input by checking the value returned by scanf (which will be the number of items successfully scanned and assigned); if that value is not 3, then you will (probably) need to clear any 'leftover' characters in the input buffer, using a getchar() loop until a newline (or end-of-file) is found:
#include <stdio.h>
int main()
{
int BirthYear, BirthMonth, BirthDay;
int nIns = 0, ch;
while (nIns != 3) {
printf("Enter D.O.B. (as YYYY/MM/DD): ");
nIns = scanf("%d/%d/%d", &BirthYear, &BirthMonth, &BirthDay);
while ((ch = getchar() != '\n') && (ch != EOF))
; // Clear remaining in-buffer on error
}
printf("Entered data were: %d %d %d!\n", BirthYear, BirthMonth, BirthDay);
return 0;
}
Expanding on my comment...
The problem you're running into is that you have to hit Enter for each input, which writes a newline to the terminal screen. You can't avoid that.
And unfortunately, you can't overwrite the newline on the screen with a '\b'; you can only backspace up to the beginning of the current line, not to a previous line.
You basically can't do what you want with vanilla C - the language only sees byte streams, it has no concept of a "screen".
There are some terminal control sequences you can play with to reposition the cursor after sending the newline; I don't know how well those will work for you.
Beyond that, you'll need to use a library like ncurses.
#include <stdio.h>
int main()
{
int BirthYear,BirthMonth,BirthDay;
printf("Please enter your birth date: ");
scanf("%d/%d/%d",&BirthYear,&BirthMonth,&BirthDay);
return 0;
}
You can take multiple values from scanf which are then separated by any text you like (in this case /s).
You could use fflush(3) (in particular before all calls to scanf(3)) like in
printf("Please enter your birth date: ");
fflush(NULL);
but you should read this C reference website, a good book about C programming such as Modern C, and the documentation of your C compiler (perhaps GCC) and debugger (perhaps GDB).
Consider enabling all warnings and debug info in your compiler. With gcc that means compiling with gcc -Wall -Wextra -g
Be aware that scanf(3) can fail.
Your code and problem is surely operating system specific.
On Linux consider using ncurses (for a terminal interface) or GTK (for a graphical interface). Read also the tty demystified, then Advanced Linux Programming and syscalls(2) and termios(3).
You might also consider using ANSI escape codes, but be aware that in 2020 UTF-8 should be used everywhere.
I'm writing a program called split.c that takes from the stdin an input.txt file as input and then sends every other word within the input file to stdout and stderr.
My current codes is as follows:
#include <stdio.h>
int main(){
int input;
// keep getting characters until end-of-file
while ((input = fgetc(stdin)) != EOF){
// prints to stdout
fprintf(stdout, "%d", input);
if(input == " ")
printf("\n"); // encounters whitespace so print new line
// prints to stderr
fprintf(stderr, "%d", input);
if(input == " ")
printf("\n"); // encounters whitespace so print new line
}
return 0;
}
In ubuntu I run make then the command ./split < test/input.txt > myout.txt 2> myerr.txt
The expected output should be, for example.
If input.txt has the following: "Is my code working?"
The output should be:
In myout.txt:
"Is
code
In myerr.txt:
my
working?"
Instead I get the following in both files, a huge number:
6511032731101001051181051001179710...............
Any idea was to what may be wrong with the code? Is my thought process wrong? The idea is that it gets the input file, reads each character and then, when a whitespace is found, it prints a new line in stdout, then does the same thing, but now printing to stderr until it reaches EOF.
I'm still learning the in's and out's (pun intended :) ) of using stdin/out/err so I'm not surprised if I'm not coding correctly. Any guidance is appreciated!
You are using the %d specifier that interprets the corresponding argument as a number. You should be using %c to interpret the corresponding argument as a character.
This is the code:
#include <stdio.h>
int main()
{
int i = 0;
while(getchar() != '\n') {
printf("\n%d\n", i);
i++;
}
printf("second printf: %d\n", i);
return 0;
}
The expected ouput after I press enter only is:
second printf: 0
instead of:
0
second printf: 1
Why is this happening ?
I am on linux Ubuntu MATE.
So I got some information about anas firari's environment by reading his other questions. This involves some measure of physic debugging.
You are getting input of \r\n when you type a newline because your terminal is in raw mode. Older shells used to choke on this by treating \r as something that isn't whitespace, but newer ones actually work ok.
I know the program I am posting is very basic but I am unable to find the error. I rechecked everything but despite no compilation error, the output is not coming.
#include<stdio.h>
#include <stdlib.h>
int main()
{
int i;
while(1)
{
if((scanf("%d",&i))!=42)
{
printf("%d",i);
}
else
{
break;
}
}
return 0;
}
Thank You for your time and consideration.
scanf does not return the value entered. It returns the number of inputs matched. So your check for 42 is incorrect. It will return 1 if an integer was assigned to i, or 0 if there was invalid input. If you want to exit the loop when the user enters 42, you should explicitly test if (i == 42).
As simonc mentioned, The reason you're not getting any output is because printf("%d",i); is not printing a newline "\n" after the number, and the standard out (stdout) stream is line-buffered. That means the standard library is going to continue to buffer up your printfs until a newline is encountered. At this point the buffer will be flushed to the console.
The solution is to add the newline (which is probably what you desire anyway): printf("%d\n",i); Alternatively, you could call fflush(stdout) to tell the std library to flush the buffered content to the console immediately. Or, writing to stderr will output immediately, because it is unbuffered.
This should demonstrate:
#include <stdio.h>
int main()
{
int i;
while(1) {
fprintf(stderr, "Enter a number (or 42 to quit): ");
if((scanf("%d",&i)) != 1) {
fprintf(stderr, "Invalid input.\n");
continue;
}
if (i==42)
break;
printf("Number provided: %d\n", i);
}
return 0;
}
Output:
$ ./a.exe
Enter a number (or 42 to quit): 17
Number provided: 17
Enter a number (or 42 to quit): 42
$
You are comparing the scanf function's return value to 42, not the variable i's value.
maybe you should read this
http://www.cplusplus.com/reference/cstdio/scanf/?kw=scanf