Counting chars in C on Mac OS X - c

I am running an example from The C Programming Language by Kernighan and Ritchie.
#include <stdio.h>
main() {
long nc;
nc = 0;
while (getchar() != EOF)
++nc;
printf("%ld\n", nc);
}
I'm on Mac OS X, so I compile it, run it, type in "12345", press enter for newline (I believe newline is the sixth character?) and then press ctrl-D to send an EOF.
It prints out "6D".
Why is the "D" there?
How do I write a program to just count the 5 chars in "12345" and not the newline?
Should I just subtract one at the end?
How do I get it to stop printing the "D"?

What happens is that the terminal actually echoes your control-D (and prints it out as ^D) when you type it, but then your program overwrites that line with a number and a line-feed. So your one-digit number overwrites the ^, but the D stays there.
If you enter more than 10 characters, or if change the code by adding a space at the end of your format string ("%ld \n"), then your program would overwrite the ^D (though it would still have been echoed by your terminal)

The program is working correctly: it's printing 6.
You see 6D because the terminal window printed ^D then went back to the beginning of the line, and your program prints 6 over the ^ leaving the following D. Try redirecting the output to a file, or giving it enough input that the answer has more than one digit, and you won't see the D.
The answer is 6 instead of 5 because of the newline, yes. If you don't want to count the newline at the end, subtract 1. If you don't want to count any newlines, subtract 1 whenever you see a newline.

Related

Little character counter program using getchar() returns twice as much as the expected result

How come this little program returns twice as much as the expected result ?
int counter=0;
while(getchar()!=EOF)++counter;
printf("%d\n",counter);
The goal of this program is to print the number of input characters it gets from the keyboard until EOF signal is received ( I'm using unix so ctr+D). However this is the result on my terminal after I start the program, input inside it a 'c' character from the keyboard and then give it the ctr+D signal :
c
2D
As you see the counter is unexpectedly 2. Moreover what that D stands for ?
Well, I'm going to guess that your input was:
:
C
2
^D
which would be ":\nC\n2\n^D". The newlines would account for the extra chars.
If you did actually send ^D that would be the same as 13 (0xD) aka carriage return or \r. When you print the carriage return the cursor goes to the beginning of the line and then you print your character count over whatever char was there.
Terminals usually get input lines from the user, and pass them on to programs. A line of text is terminated by the end-of-line byte, \n. So you, as a user, have to press Enter and send this end-of-line byte to your program, if you want your program to get any input at all. Your program then counts this byte as a normal byte.
Try supplying 9 bytes of input to your program by typing something. Your program will wait for your input, and then get 10 bytes in a quick succession: s, o, m, e, t, h, i, n, g, \n.
One way to send just 1 byte to your program is to redirect its standard input:
program <input.txt
where the file input.txt contains just one byte.

C, why does printf add a "D" after a single digit long?

I'm working through the K&R C book and one of the example programs is this:
#include <stdio.h>
int main() {
long nc;
nc = 0;
while (getchar() != EOF) {
++nc;
}
printf("%ld", nc);
return 0;
}
When I run this program, it mostly behaves as I expect. So for an input like This is a sentence, it prints 19.
However, if I input anything under 10 characters (including EOF), there is a capital D appended to the output number.
E.g. for input hello, the output is 6D.
Why is there a D appended to an integer value and what does it mean?
Note: This occurs with cc, gcc and clang.
It turns out that D is part of the ^D that gets printed to the console when I input an EOF (control + D on Unix). Because there is no \n at the start of the printf statement, a single-digit number will overwrite the ^, while a double-digit number will overwrite the entire ^D, which is what gave the impression of some weird behaviour.
What version of gcc are you using? I ran the exact same code using gcc and it runs fine. Maybe it's an artifact left over by your terminal where it's trying to print the Ctrl-D for end of file

C programming — loop

I am following the exercises in the C language book. I am in the first chapter where he introduces loops. In this code:
#include <stdio.h>
/* copy input to output; 1st version */
int main() {
int c, n1;
n1 = 0;
while ((c = getchar()) != EOF) {
if (c == '\n') {
++n1;
}
printf("%d\n", n1);
}
}
In here I am counting the number of lines. When I just hit enter without entering anything else I get the right number of lines but when I enter a character then hit enter key the loop runs twice without asking for an input the second time. I get two outputs.
this how the output looks like:
// I only hit enter
1
// I only hit enter
2
// I only hit enter
3
g // I put char 'g' then hit enter
3
4
3 and 4 print at the same time. why is 4 printing after the loop has been iterated already? I thought the loop would restart and ask me for input before printing 4.
The getchar function reads one character at a time. The number of lines will be printed for every character in the input read by getchar, whether that character is newline or not, but the counter will only be incremented when there is a newline character in the input.
When you enter g then the actual input that goes to the standard input is g\n, and getchar will read this input in two iterations and that's the reason it is printing number of lines twice.
If you put the print statement inside the if block then it will print only for newline characters. If you put the print statement outside the loop, then it will only print the count of the number of lines at the end of the input.
To be clear this is the terminal that you are dealing with.
By default, the terminal will not get input from the user \n is entered. Then the whole line is placed in the stdin.
Now as I said earlier here the program is not affected by the buffering of stdin. And then the characters will be taken as input and it is processed as you expect it to be. The only hitch was the terminals buffering - line buffering.
And here from standard you will see how getchar behaves:-
The getchar function returns the next character from the input stream pointed to by stdin. If the stream is at end-of-file, the end-of-file indicator for the stream is set and getchar returns EOF. If a read error occurs, the error indicator for the stream is set and getchar returns EOF.
Now what are those characters - those charaacters include \n - the \n is what you put in the terminal and then to stdin via pressing the ENTER. Here earlier you were entering the characters earlier which were \n. This time you entered two characters. That's why the behavior you saw.

Understanding getchar() in the character counting program in C

This is a follow-up question of my previous question. There is already a similar question asked(question). But I don't get what I want to know from that answer.
From the previous question I come to know that if I type a lot of characters, then they are not made available to getchar(), until I press Enter. So at the very point when I press Enter, all the characters will be made available to getchar()s. Now consider the following program for character counting:
#include<stdio.h>
main()
{
long nc;
nc=0;
while(getchar()!=EOF)
++nc;
printf(" Number of chars are %ld ",nc);
}
If I input characters from the command line in the following sequence: {1,2,3,^Z,4,5,Enter}, then in the next line {^Z,Enter}. The output that I expect is: Number of chars are 6. But the output that I am getting is Number of chars are 4.
This answer explains that when we input1,2,3,^Z, then ^Z acts like Enter and 1,2,3 are sent to getchar()s. The while loop of the above written code runs three times. ^Z is not given to getchar(), so the program doesn't terminate yet. My input was {1,2,3,^Z,4,5,Enter}. After ^Z I had pressed 4,5 and then Enter. Now when I press Enter the characters 4,5 and Enter, should be given to getchar()s and the while loop should execute three times more. Then in the last line I input {^Z,Enter}, since there is no text behind ^Z, it is consider as a character and when I press Enter, this ^Z is given as the input to getchar() and the while loop terminates. In all this, the while loop has executed 6 times, so the variable nc should become 6.
Why am I getting 4 as the value of nc, rather than 6.
Adding some output will help you:
#include <stdio.h>
int
main (void)
{
int c, nc = 0;
while ((c = getchar ()) != EOF)
{
++nc;
printf ("Character read: %02x\n", (unsigned) c);
}
printf ("Number of chars: %d\n", nc);
}
The Windows console views the ^Z input as "send input before ^Z to stdin, discard remaining input on the line (including the end-of-line delimiter), and send ^Z" unless it is at the beginning of a line, in which case it sends EOF instead of ^Z:
123^Z45
Character read: 31
Character read: 32
Character read: 33
Character read: 1a
^Z12345
Number of chars: 4
Also, Windows always waits for the Enter/Return key, with the exception of very few key sequences like ^C or ^{Break}.
^Z, or Ctrl-Z, means end-of file for text files (old MS-DOS). getchar() is equivalent to fgetc(stdin) and is often a macro. "fgetc returns the character read as an int or returns EOF to indicate an error or end of file."
See also _set_fmode, however, I am not sure if that changes the behaviour right away or whether you have to close/reopen the file. Not sure either if you can close/reopen stdin (don't do much console programming anymore).

C: Problems with scanf and printf

I'm having issues with accepting user input and the printing its ascii value in C. I'm tasked with writing a program that simply takes a single char as input and prints out its ascii value, and only stops when the user inputs 0 (the ascii value of 0 is 48). My problem is that if the the printf seems to function one loop behind scanf.
while(x == 1){
scanf("%c\n",&thisChar);
ascii = thisChar;
if(ascii == 48){
x = -1;
}
printf("Ascii: %d\n", ascii);
}
For example, when I run this from the command line, I get something like this:
f
0
Ascii: 102
f
Ascii: 48
and then the program ends. With those same inputs, I want the output to be:
f
Ascii: 102
0
Ascii: 48
and then end there. What is the error in my logic?
\n character is the root cause of your problem.
Change
scanf("%c\n",&thisChar);
to
scanf(" %c",&thisChar);
EDIT: OP asked why a space before %c in scanf matters in output?
When you inputs the data to a program and press Enter key, an extra character \n is passed to the input buffer along with the input data. For Ex: If you want to enter f in your program then on pressing Enter key, input buffers contains f\n. On first iteration of loop, character f is read by scanf leaving behind the \n in the buffer. On next iteration of loop, this \n is read by the scanf causing unexpected output.
To solve this issue you need to consume this \n before next read. Placing a space before %c specifier in scanf can consume any number of new-line characters.
Did you consider using just getchar(3) ? (Perhaps fflush(3) could be needed)... Also stdin in a terminal is a complex beast. See tty demystified.
The kernel (not only the libc) is sort of buffering each tty lines (see line discipline).
See also ncurses and GNU readline.
Dont use \n in scanf() .
Remove "\n" and execute

Resources