cat breaks the program, manual stdin input doesn't - c

I have this small program:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
int orig = 1;
for (int i = 0; (i != 3) && orig; ++i) {
orig = orig && fork();
}
if (orig) {
for (int i = 0; i != 3; ++i) {
wait(NULL);
}
} else {
int num;
scanf("%8d", &num);
printf("%d\n", num*num);
}
}
Which is supposed to simply square three numbers that it reads from stdin. And if I type the numbers in myself, it works:
akiiino$ ./out.out
12345678
12345678
12345678
260846532
260846532
260846532
but if I use cat for the same purpose, it does not work as expected:
akiiino$ cat in.txt
12345678
12345678
12345678
akiiino$ cat in.txt | ./out.out
260846532
0
0
What is the reason behind this weird behavior and is it fixable? I've always assumed cating files was no different from typing them into stdin.

The difference is that when you type the 3 numbers by hand, you are reading from a terminal and low level reads are terminated on newlines. Let's look what happens under the hood.
manual input:
the 3 child have started and are waiting for input
you type one number and a new line
the underlying read call is terminated by the newline because you read from a terminal
first child (the one that got the read) has its scanf call decode the input an does its processing
Ok, we iterate the same for the 2 other childs
reading from a file or a pipe
the 3 child have started and are waiting for input
the 3 numbers and the newlines are immediately available
the underlying read of first child reads and consumes all the input in the stdio buffer
first child (the one that got the read) has its scanf call decode the (first part of the) input an does its processing
But now the 2 other childs are reading from a file/pipe positioned at end of file. Their scanf returns 0 but you fail to control it, and they let the initial undeterminated value in num.
You can control that it is not a problem of race condition by adding a sleep(10) before the loop, starting the program an inputting by hand 3 numbers before first child begins to read. As the low level reads will be newline terminated (special tty case) you still get same output of the first case, even if the 3 lines are available before the first read.

Already said by #Some programmer dude, problem is with the fork command.
If you try ./out.out < in.txt, it should work fine.

Related

Print number for each second

#include <stdio.h>
#include <wiringPi.h>
#include <softPwm.h>
int main(void)
{
wiringPiSetupGpio();
for(int i = 0 ; i <50; i++)
{
if ( i%10 == 1)
{
printf("\n");
}
printf("%d ", i);
delay(1000);
}
return 0;
}
I'm working in rasberry pi environment.
I want to print a number for each 1 second. But this code did not print a number one by one but
print 10 numbers for each 10 seconds. This code gives 10 numbers in line at once. What's the problem??
The stdout channel is line buffered by default. This means that data sent to stdout won't necessarily appear until a newline character is printed.
If you call fflush(stdout), any buffered output will be immediately printed.
printf("%d ", i);
fflush(stdout);
in order to print the values at the running time using printf you need to add \n so try this may work.
#include <stdio.h>
#include <wiringPi.h>
#include <softPwm.h>
int main(void)
{
wiringPiSetupGpio();
for(int i = 0 ; i <50; i++)
{
if ( i%10 == 1)
{
printf("\n");
}
// a `\n` added at the end of the string!
printf("%d \n", i);
delay(1000);
}
return 0;
}
for more info read this question's answer
The problem is probably that the output stream is not being flushed. I suggest that you call fflush( stdout ); before the delay(1000); function call. This will ensure that all printed data actually becomes observable, before the program enters a wait state.
Normally, it is not necessary to explicitly flush an output stream, because the output will become visible sooner or later. For example, the output buffer will usually get implicitly flushed whenever you read input or when the program ends. Also, if your program is writing output to the user's screen (in contrast to, for example, writing output to a file), then the output stream is probably line-buffered, which means that the output stream will get implicitly flushed whenever a newline character is written.
However, in this case, it appears that the implicit flushing mentioned above is not sufficient. Therefore, you will have to revert to explicit flushing using the function fflush, as mentioned above.

My fgetc is not returning a desired output. (C programming beginner)

My .txt file I have created before running the code looks like the following:
/*
I am Jason and I love horses hahaha/n
This is amazing, How much I love horses, I think I am in love/n
how many people love horses like I do?/n/n
this is quite a horsed up paragraph
*/
//I also manually wrote '\0' character at the end of my string//
And the output that I am wanting for this program is the same as above, and the code is the following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *filepointer;
int buck;
int counter=1 ;
filepointer = fopen("inoutproj.txt","r");
while(buck=fgetc(filepointer),buck!=EOF)
{
if(buck=='\n')
{
++counter;
}
printf("%c",fgetc(filepointer));
}
printf("\nThere are %d lines in the text file\n\n",counter);
counter=1;
rewind(filepointer);
for(buck=fgetc(filepointer);buck<175;++buck)
{
if(fgetc(filepointer)=='\n')
{
++counter;
}
printf("%c",fgetc(filepointer));
}
printf("\nThere are %d lines in the text file\n",counter);
fclose(filepointer);
return 0;
the output is the following:
mJsnadIlv osshhh
Ti saaig o uhIlv oss hn mi oe o aypol oehre ieId?
hsi ut osdu aarp�
There are 3 lines in the text file
a ao n oehre aaa hsi mzn,Hwmc oehre,ItikIa nlv
hwmn epelv osslk o
ti sqieahre pprgah���������������
There are 3 lines in the text file
As you can see I tried two different approaches with fgetc (While loop and a for loop), but the output is still coming out broken. I have read some archived Macbook Pro document that the loops are reading the pushed back input from the input stream, and it seems to persistently do that for my code too (or maybe I am wrong).
Can someone tell me what is wrong with the code I have written and why my computer is not outputting the .txt file as I desire?
I am currently running Cygwin GCC on VSCode.
My system is a Macbook Pro 16in 2019
You are reading 2 characters for every one you print. The first character was read by "buck=fgetc(filepointer)" as an argument in the while statement. The second character was read by "printf("%c",fgetc(filepointer));".
So essentially your program first reads a character from the file and stores it in "buck", then reading another character and printing it out, resulting in the output missing characters.
You can do something like this:
FILE *filepointer;
int buck;
int counter=1 ;
filepointer = fopen("inoutproj.txt","r");
while(buck=fgetc(filepointer),buck!=EOF)
{
if(buck=='\n')
{
++counter;
}
printf("%c",buck);
}
printf("\nThere are %d lines in the text file\n\n",counter);
To simply print buck for every scan.
Good luck!
What #SSORshen says is correct, but you also have a similar problem in the for loop, following the rewind. But here you call fgetc three times per iteration, so you only print every third character. Also note that buck contains the character read, not a count. If you want to count how many characters are read, you'll need to use a separate counter variable, such as i below. Your second loop should look more like this:
counter=1;
rewind(filepointer);
for(int i=0;i<175;++i)
{
buck=fgetc(filepointer);
if(buck=='\n')
{
++counter;
}
printf("%c",buck);
}

Strange behavior with read()

I discovered the function read(), but I don't understand everything.
Here is my code:
#include <unistd.h>
#include <stdio.h>
int main(void)
{
char array[10];
int ret;
printf("read : ");
fflush(stdout);
array[sizeof(array) - 1] = '\0';
ret = read(STDIN_FILENO, array, sizeof(array) - 1);
printf("array = %s\n", array);
printf("characters read = %d\n", ret);
//getchar();
return (0);
}
Here is an example of the running program :
$> ./a.out
read : hi guys how are you
array = hi guys h
characters read = 9
$> ow are you
zsh: command not found: ow
$>
Why is it launching a shell command after the end of the program?
I noticed that if I uncomment the getchar() line, this strange behavior disappears. I'd like to understand what is going on, if someone has an idea :)
Your call to read is reading in the first 9 characters of what you've type. Anything else will be left in the input buffer so that when you program exits, your shell will read it instead.
You should check the return value of read so you know how much has been read as it's not guaranteed that it'll be the amount you ask for and also the value returned is used to indicate an error.
The string read in won't be null-terminated either, so you also should use the return value (if positive) to put the NUL character in so that your string is valid.
If you want to read in the whole line, you'll need to put in a loop and identify when there is an end of line character (most likely '\n').
You typed about 20 characters, but you only read 9 characters with read(). Everything after that was left in the terminal driver's input buffer. So when the shell called read() after the program exited, it got the rest of the line, and tried to execute it as a command.
To prevent this, you should keep reading until you get to the end of the line.

C Read in bash : stdin and stdout

I have a simple C program with the read function and I don't understand the output.
//code1.c
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
int main()
{
int r;
char c; // In C, char values are stored in 1 byte
r = read ( 0, &c, 1);
// DOC:
//ssize_t read (int filedes, void *buffer, size_t size)
//The read function reads up to size bytes from the file with descriptor filedes, storing the results in the buffer.
//The return value is the number of bytes actually read.
// Here:
// filedes is 0, which is stdin from <stdio.h>
// *buffer is &c : address in memory of char c
// size is 1 meaning it will read only 1 byte
printf ("r = %d\n", r);
return 0;
}
And here is a screenshot of the result:
I ran this program 2 times as showed above and typed "a" for the first try and "aecho hi" for the second try.
How I try to explain the results:
When read is called it sees that stdin is closed and opens it (from my point of view, why? It should just read it. I don't know why it opens it).
I type "aecho hi" in the bash and press enter.
read has priority to process stdin and reads the first byte of "aecho hi" : "a".
I get the confirmation that read has processed 1 byte with the printf.
a.out has finished and is terminated.
Somehow the remaining data in stdin is processed in bash (the father of my program) and goes to stdout which executes it and for some reason the first byte has been deleted by read.
This is all hypothetical and very blurry. Any help understanding what is happening would be very welcome.
When you type at your terminal emulator, it writes your keystrokes to a "file", in this case an in-memory buffer that, thanks to the file system, looks just like any other file that might be on disk.
Every process inherits 3 open file handles from its parent. We are interested in one of them here, standard input. The program executed by the terminal emulator (here, bash), is given as its standard input the in-memory buffer described in the first paragraph.
a.out, when run by bash, also receives this same file as its standard input. Keep this in mind: bash and a.out are reading from the same, already-opened file.
After you run a.out, its read blocks, because its standard input is empty. When you type aecho hi<enter>, the terminal writes these characters to the buffer (<enter> becoming a single linefeed character). a.out only requests one character, so it gets a and leaves the rest of the characters in the file. (Or more precisely, the file pointer is still pointing at the e after a is read.)
After a.out completes, bash tries to read from the same file. Normally, the file is empty (i.e., the file pointer is at the end of the file), so bash blocks waiting for another command. In this case, though, there is input available already: echo hi\n. bash reads this now the same as if you had typed it after a.out completed.
Check this. As alk suggests stdin and stdout are already open with the program. Now you have to understand, once you type:
aecho hi
and hit return the stdin buffer is filled with all those letters (and space) - and will continue to be as long as you don't flush it. When the program exits, the stdin buffer is still full, and your terminal automatically handles a write into stdin by echoing it to stdout - this is what you're seeing at the end - your shell reading stdin.
Now as you point out, your code "presses return" for you so to speak - in the first execution adding an empty shell line, and in the second executing echo hi. But you must remember, you pressed return, so "\n" is in the buffer! To be explicit, you in fact typed:
aecho hi\n
Once your program exits the shell reads the remaining characters in the buffer, including the return, and that's what you see!

How to pause between functions in a program in C with GCC?

So my problem is my program runs too fast that I can't see how it behaves. It's supposed to make the text crawl along the edges of the terminal. I tried to use sleep() to make a short pause betweenprintf(...)s so that it I can see where the text us going while it prints.
This is what it looks like:
http://i.imgur.com/B6FFbNp.gif
So I put sleep() function after the printfs so that it will pause before starting the loop again and make the text move slowly. But what happens is it pauses the programs indefinitely before it even starts. This also happens with usleep and system("pause 1"). This is what it looks like:
http://i.imgur.com/krGW3lB.gif
==================================================================================
EDIT:
Okay, I figured it out on my own. It seems that sleep() only works if I put \n in my strings. I don't know why. I didn't even read this in the damn manuals.
So if you have
printf("HELLO\n");
sleep(3);
printf("HELLO\n");
sleep(3);
printf("HELLO\n");
It will result in:
HELLO
[pause for 3 seconds]
HELLO
[pause for 3 seconds]
HELLO
but if you remove the newline characters it will:
[pause for 9 seconds]
HELLO HELLO HELLO
I don't know why this happens but it just does
==================================================================================
EDIT:
This is how I wanted my program to work:
http://i.imgur.com/DXv7E60.gif
Thank you for your answers
Your observations do not due to sleep() not working, but to the fact that printf() uses stdout, which is line buffered. "line buffered" means, that what has been written to stdoutis buffered until the end of the line is reached before the buffer's content it is flushed out.
So after the first printf("HELLO"); the output does not go to the screen but stays in the buffer, then sleep(1); is executed and makes you wait. Then for the next printf("HELLO"); the output still does not go to the screen, but the following sleep(1); again makes you wait for 1 second ... and so on until a line end if reached by your program printing a '\n' or by the program's end, which implicitly flushes the output buffer to the console.
You can avoid the behaviour by flushing stdout's output buffer explicitly after every printf():
#include <stdio.h>
#include <unistd.h>
int main(void)
{
printf("HELLO");
fflush(stdout);
sleep(3);
printf("HELLO");
fflush(stdout);
sleep(3);
printf("HELLO");
/* fflush(stdout); */ /* not needed as buffers are implicitly flushed on the program's end */
return 0;
}
A quick hack I usually do is make some buffer array (eg. char buf[10]) and place an fgets() in between iterations, which forces the program to wait for a newline from the user. So, for example, if we had:
.
.
.
for(i = 0; i < 1000000; ++i)
printf("%d\n", i);
we could then do
.
.
.
char buf[10];
for(i = 0; i < 1000000; ++i){
printf("%d\n", i);
fgets(buf, 10, stdin);
}
and control the iterations with the enter key.
We could also stop every nth iteration by using a modulus. Using the above example, we will now stop every 100 iterations:
.
.
.
char buf[10];
for(i = 0; i < 1000000; ++i){
printf("%d\n", i);
if(i % 100 == 0)
fgets(buf, 10, stdin);
}
A more time consuming but effecient way is to use a dedicated debugger like GDB.

Resources