can';第一次进入do while后无法获取输入
我正在尝试分叉一个子进程,每当用户输入一行文本以打印输入的行数时,将其置于睡眠状态并将其唤醒 我的代码运行良好。但奇怪的是,我发现我必须使用两个get(str)语句,如果我没有这样做,用户只会被提示一次 如果运行代码并注释one get(str),您将知道我的意思 谢谢你的帮助。谢谢can';第一次进入do while后无法获取输入,c,linux,string,C,Linux,String,我正在尝试分叉一个子进程,每当用户输入一行文本以打印输入的行数时,将其置于睡眠状态并将其唤醒 我的代码运行良好。但奇怪的是,我发现我必须使用两个get(str)语句,如果我没有这样做,用户只会被提示一次 如果运行代码并注释one get(str),您将知道我的意思 谢谢你的帮助。谢谢 #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <wait.h> #in
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <wait.h>
#include <unistd.h>
#include <signal.h>
main () {
int n;
char ch;
pid_t child;
int erret;
char str[20];
int c = 0;
if ((child = fork ()) < 0) {
perror ("fork");
exit (0);
}
else {
//waitpid(child,NULL,0);
do {
waitpid (child, NULL, 0);
printf ("Enter a line(s) \n");
//funn();
//fflush(stdin);
//scanf("%d",&n);
gets (str);
gets (str);
erret = kill (child, SIGCHLD);
printf ("Signal %d\n", erret);
if (erret >= 0) {
c++;
printf ("You have entered : %d line(s)\n", c);
//pause();
//waitpid(child,NULL,0);
}
else {
kill (child, SIGKILL);
exit (0);
}
printf ("\nPress 9 to exit :");
fflush (stdin);
scanf ("%d", &n);
fflush (stdin);
} while (n != 9);
kill (child, SIGKILL);
}
}
#包括
#包括
#包括
#包括
#包括
#包括
主要(){
int n;
char ch;
pid_t儿童;
INTERRET;
char-str[20];
int c=0;
如果((child=fork())<0){
佩罗尔(“福克”);
出口(0);
}
否则{
//waitpid(子级,NULL,0);
做{
waitpid(子级,NULL,0);
printf(“输入一行)\n”);
//funn();
//fflush(stdin);
//scanf(“%d”和“&n”);
获取(str);
获取(str);
erret=kill(child,SIGCHLD);
printf(“信号%d\n”,erret);
如果(erret>=0){
C++;
printf(“您已经输入了%d行)\n”,c);
//暂停();
//waitpid(子级,NULL,0);
}
否则{
杀死(孩子,SIGKILL);
出口(0);
}
printf(“\n按9退出:”;
fflush(stdin);
scanf(“%d”和“&n”);
fflush(stdin);
}而(n!=9);
杀死(孩子,SIGKILL);
}
}
在您尝试输入时,有许多方法可以获得重复的字符串输入。标准方法之一是收集输入,直到用户发出信号表示没有更多数据可输入。(在Linux上,EOF
由终端使用ctrl+d
生成)。在不更改逻辑和不评论fork、waitpid等实现的情况下,
以下是一种处理为程序收集字符串输入的方法,直到用户通过按键盘上的ctrl+d
发送EOF
:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <wait.h>
#include <unistd.h>
#include <signal.h>
int main () {
pid_t child;
int erret;
int c = 0;
ssize_t nread = 0; /* number of chars read by getline */
char *lineptr = NULL; /* string read by (NULL forces getline to allocate) */
size_t nbytes = 0; /* number of bytes to read (ignored with lineptr = NULL) */
if ((child = fork ()) < 0) {
perror ("fork");
exit (0);
}
else
{
waitpid (child, NULL, 0);
printf ("\nEnter line(s) of text (ctrl+d to exit):\n\n");
while (printf (" Input: ") && (nread = getline (&lineptr, &nbytes, stdin) != -1))
{
erret = kill (child, SIGCHLD);
printf ("\n Signal %d\n", erret);
if (erret >= 0) {
c++;
printf (" You have entered : %d line(s)\n\n", c);
}
else
{
kill (child, SIGKILL);
exit (0);
}
}
kill (child, SIGKILL);
}
return 0;
}
你的概念是有缺陷的,你没有明确说明巴拉特和孩子做了什么。因此,您在
获取时有一个竞赛条件。这是因为在fork
调用之后,运行了两个代码副本,一个由父级复制,一个由子级复制。因此,解决方法是添加一个swich
或else if
语句,将代码分为子代码段和父代码段。顺便说一句,如前所述,使用fgets
switch(fork()):
case -1:
//Error
case 0:
// Child code
default:
// Parant code
编写代码时有一定的标准级别。更具体地说,缩进帮助人们更有效地阅读代码。不要使用get
它不再是C标准的一部分。使用fgets
或(更好)getline
(是的,它在stdin
上工作。fflush(stdin)不会清理输入缓冲区。此外,gets
容易发生缓冲区溢出。希望这不是接受标准输入的任意用户输入的网络程序的一部分。
switch(fork()):
case -1:
//Error
case 0:
// Child code
default:
// Parant code