When I run the code below, it executes correctly but adds an extra iteration before I can input again. Not sure why. I am going to be using it for fork and pipe parent process to children. That step will come after the user inputs # of processes.
Code:
#include <stdio.h>
int main(void) {
int num_processes;
int running = 1;
do {
printf ("How many processes do you want? (1, 2 or 4) \n");
num_processes = getchar();
num_processes -= '0';
if(num_processes == 1 || num_processes == 2 || num_processes == 4){
int temp = num_processes - 1;
printf("\n1 Parent and %d child processes\n", temp);
printf("----------------------------------\n");
running = 0;
} else {
printf("Invalid Input, please try again.\n");
}
} while(running == 1);
// Do important stuff
return(0);
}
Out:
How many processes do you want? (1, 2 or 4)
3
Invalid Input, please try again.
How many processes do you want? (1, 2 or 4)
Invalid Input, please try again.
How many processes do you want? (1, 2 or 4)
2
1 Parent and 1 child processes
----------------------------------
Think what happens when you give your first input. You type 3, and then you hit Enter.
Now, in the Standard input buffer, there are two items awaiting to be consumed, 3 and \n (which is Enter).
You enter the body of the loop for the very first time, 3 is consumed. Now next in line awaits the \n...
When you enter the loop's body again (for the second time), the next character to be read by the Standard input buffer is \n, and that's what the second getchar() happily returns to you.
Here is a quick fix:
do {
printf ("How many processes do you want? (1, 2 or 4) \n");
// Eat trailing newline character, if any
do {
num_processes = getchar(); // read a character
} while(num_processes == '\n'); // if it was the newline character, repeat
// until `num_processes` is not the newline character
// Continue with your logic..
num_processes -= '0';
Output:
How many processes do you want? (1, 2 or 4)
3
Invalid Input, please try again.
How many processes do you want? (1, 2 or 4)
2
1 Parent and 1 child processes
----------------------------------
PS: As #Barmar commented, if you want to read lines, then use fgets(). Read more here: How to use fgets() to control the execution of while loop through user input in c?
Related
I have to solve the following problem as homework: create two processes with popen. The parent process will read from stdin lines of at most 30 chars and give the first child the digits from the line and give the second child the letters from the line, which will transform them to uppercase. Both processes will then print these things to the parent's stdout.
So basically i want something similar to running the "tee" command. Read a line, write some output and repeat until ctrl-d
Here is my attempt:
#include <stdio.h>
#include <ctype.h>
int main() {
FILE *digits, *letters;
char string[31];
if ((digits = popen("tee", "w")) == NULL) {
perror("can't create pipe for digits");
return 1;
}
if ((letters = popen("tr a-z A-Z", "w")) == NULL) {
perror("can't create pipe for letters");
return 1;
}
while(!feof(stdin)) {
fgets(string, 31, stdin);
for (char* c = string; *c != '\0'; c++)
if (isdigit(*c))
fputc(*c, digits);
else if (isalpha(*c))
fputc(*c, letters);
fputc('\n', digits);
fputc('\n', letters);
}
pclose(digits);
pclose(letters);
return 0;
}
But after I write a line and press enter, the program expects input again, without printing anything. It prints all of the output at the end, after pressing ctrl-d. And I don't understand why. It reads the line correctly, then it feeds the correct characters to each child, followed by a new line. Why don't these processes immediately print their output? Is the actual command ran when pclose is called? Because I couldn't find any information about that. Also, is writing '\n' to a child's stdin the same as pressing enter? And what's even weirder is that the last line from the output of each child is printed twice.
For example, here is how I would like it to work:
(input)
1a2b3c
(output)
123
ABC
(input)
4d5e6f
(output)
456
DEF
(ctrl-d)
But I get this:
(input)
1a2b3c
(input)
4d5e6f
(ctrl-d)
(output)
123
456
456
ABC
DEF
DEF
I need to repeat a process and I'm using a while. I need to do antoher process when enter key is pressed and I'm using if(getchar()). The problem is that the while "pauses" when it gets to the if because it's checking if getchar() it's true. I need to know how to keep looping the while whithout it stopping to check if there's an enter.
I'm making a game in which you have 1 minute to guess as much names as you can. So the purpose of the while() is to countdown from 60 to 0 seconds (clears the screen and prints the new second and the name you're actually guessing every second). So I want it to keep running the while() so the timer keeps running, but if enter is pressed it only changes the guessed name to a new name and the timer keeps running. (I don't know if I was clear but this is the idea)
//program in c
while(//specific condition)
{
/*- here goes the code for a timer that every second it clears the
- terminal and prints the next number (in seconds).
-
-
-*/
if(getchar()) //the current program stops here and keeps running the loop
//until enter is pressed
{
//second process
}
}
I expect the while to keep looping until there's an enter. When that happens I want it to enter the if, exit the if and keep looping.
char buffer[100];
while (fgets(buffer, sizeof(buffer), stdin))
{
if (strlen(buffer) == 1)
break;
if (sscanf(buffer, "%f", &f) == 1)
{
total += f;
printf("Enter another number: ");
}
}
if you have conio.h available in your environment you can use kbhit
while(//specific condition)
{
/*--process to do
-
-
-
-*/
if(kbhit())
{
if (getchar() == 0x0d)
{
break;
}
}
//second process
}
In this loop, the second process will run without checking the enter key and only exit if enter key is pressed.
You cannot use if(getchar()=='\n')
so the program runs until an enter key is pressed
because buffer value of '\n' will be present and it'll alter the next iteration
char a;
printf("Enter charecter or press enter to exit:");
scanf("%c",&a);
while(1)
{
//process 1 loop
if (a == '\n')
{
// process 2 here, if process two has loop make it's own loop here
printf("we are in process 2\n");
break;
}
getchar();
printf("Enter charecter or press enter to exit:");
scanf("%c",&a);
}
You did't give enough code to understand what input stream you are working with but something like this will do it, if it's file stream or string do it accordingly by replacing scanf with fgets, or file stream inputs like fscanf or fread.
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.
Here's the situation, I have a code that reads values until the user inputs Ctrl+D, the problem though is I have to input it TWICE for it to successfully exit the loop, I figured it had to do with the fact that the Ctrl+D was being inserted into the string along with the remainings of the buffer and therefore didn't register as EOF and simply another character inside the string and only the second Ctrl+D which would be saved in an int variable, actually stopped the reading loop. To solve this I added while(getchar() != '\n') to see if it fixed the problem, but to no end.
Here's my code:
typedef struct {
char nome[50];
int tempo;
int ncertas;
} equipa;
int ler_equipas(equipa *resultados)
{
int x, r1, r2 ,r3 ,r4, r11, r22, r33 ,r44, rcertas = 0, i = 0;
scanf ("%d %d %d %d", &r1, &r2, &r3, &r4);
while (scanf ("%s %d %d %d %d %d", resultados[i].nome, &resultados[i].tempo, &r11, &r22, &r33, &r44 ) == 6 )
{
i++;
if (r1 == r11) rcertas++;
if (r2 == r22) rcertas++;
if (r3 == r33) rcertas++;
if (r4 == r44) rcertas++;
resultados[i-1].ncertas = rcertas;
rcertas = 0;
while((x=getchar()) != '\n');
}
return i;
}
The input/output was as follows (">>" means output):
1 2 3 4
>> correct answers are 1 2 3 4
Team1 234 1 2 3 4
>> values inputed for team time and answers: Team1 234 1 2 3 4
>> getchar value was (ASCII): 10
>> Next read:
Team2 400 1 3 2 4
>> values inputed for team time and answers: Team2 400 1 3 2 4
>> getchar value was (ASCII): 10
>> Next read:
>>
^D
^D
>> return i was reached
>> Number of teams: 2
>> Team "Team1" took 234 seconds and answered 4 questions correctly
>> Team "Team2" took 400 seconds and answered 2 questions correctly
Since you are using windows, you shall use ctrl+z for emulating EOF
See https://stackoverflow.com/a/16136924/4386427
When you use ctrl+d, the first ctrl+d matches the initial %s so the scan continues.
The second ctrl+d will not match %d so the scan terminates. Since the number of scanned elements isn't 6, the while loop terminates.
Consequently two ctrl+d terminates the function. A single ctrl+z will also terminate the program.
I did not try this yet. But i remember having the same Problems...
Try this: How to clear input buffer in C?
while ((c = getchar()) != '\n' && c != EOF) { }
This is a way to clear the input buffer. But this after a scanf(); call to clear the input Buffer.
Best regards
I have a while loop that scans in an input set of integers. It scans and prints all of the numbers with "..." at the end and skips to the next line. However, the script does not: execute past the while loop and print TEST.
For example, I enter:
3 44 62 1
It prints:
3...
44...
62...
1...
When it should print:
3...
44...
62...
1...
TEST
while(scanf("%d", &n) != -1) {
x[i] = n;
i++;
printf("%d", n);
printf("...\n");
}
printf("TEST");
What am I doing wrong?
scanf("%d", &n) != 1 is wrong. It should be scanf("%d", &n) == 1.
You're expecting the loop to end just because you hit enter? As written, your program will only stop if scanf fails to read a number due to reaching the end of the input file. If you're on Unix, you can signal EOF from the terminal by hitting Ctrl-D. If you're on Windows, it's Ctrl-Z Enter. (Also, don't rely on EOF being -1; it's not portable.)