由perror scanf通过管道引起的无限循环

时间:2017-05-22 06:15:21

标签: c linux pipe stdin infinite-loop

我一直在编写一个c程序,它将数据从一个文件传输到下一个文件但是它已经无限循环。

到目前为止我发现了什么。无限循环是在文件c1.c上引起的,其中perror(或stderr)跳过scanf。如果scanf确实有效。程序无限循环沿轨道向下打印出perror,即使它已超过该部分!

我的代码在

下面

controller.c

#include<stdio.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<unistd.h>

int main(int ac, char**av)
{
int pipez[2];
int piped[2];
int status;
pid_t pid;

if (pipe (pipez) == -1){
perror("could not make pipe");
return 1;
}

if ((pid = fork()) == -1){
perror("fork");
return 1;
}

if(pid == 0){
close(pipez[1]);
dup2(pipez[0],0);
close(pipez[0]);
execvp("./c1",av);
perror("demo);
_exit(1);
}
else{
close(pipez[0]);
dup2(pipez[1],1);
close(pipez[1]);
execvp("./c2",av);
perror("demo");
exit(1);
}

waitpid(pid,&status,0);
if(WIFEXITED(status)){
printf("[%d] TERMINATED (Status: %d)\n", pid, WEXITSTATUS(status));
}

if(pipe (piped) == -1){
perror("could not make pipe");
return 1;
}

if((pid = fork()) == -1){
perror("fork");
return 1;
}

if (pid == 0){
close(piped[1]);
dup2(piped[0],0);
close(piped[0]);
execvp("./c2", av);
perror("demo");
_exit(1);
}
else{
close(piped[0]);
dup2(piped(piped[1],1);
close(piped[1]);
execvp("./c3",av);
perror("demo");
exit(1);
}

waitpid(pid, &status, 0);
if (WIFEXITED(status)){
printf("[%d] TERMINATED (Status: %d)\n", pid, WEXITSTATUS(status));
}

return 0;
}

c1.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUFSIZE 256

//This program is causing infinite loop, tried fflush and fgets and scanf
// It will run independently but will loop via the pipe

int main(int a, char**av){
char store[BUFSIZE];
memset(store, '\0', sizeof(store));
while(strcmp(store, "exit!") != 0){

perror("Please enter next line of input (type 'exit!' to stop) \n"); //This repeats itself infinitely
fgets(store, BUFSIZE, stdin);
printf("%s",store); // This also repeats itself dependant on where i put 
//fflush or another printf. Repeated outputs occur in blocks
}

return 0;
}

c2.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUFSIZE 256

char *strlwr(char *str);

int main(int ac, char**av){
char store[BUFSIZE];

while(strcmp(store, "exit!") != 0){
scanf("%s", store);
printf("%s", strlwr(store));
}

return 0;
}

char *strlwr(char *str){
unsigned char *p = (unsigned char *)str;

while(*p){
*p = tolower((unsigned char)*p);
p++;
}

return str;

}

c3.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUFSIZE 256

int main(int ac, char**av){
char store[BUFSIZE];
int n = 0;

while(strcmp(store, "exit!") != 0{
scanf("%s",store);
printf("Line %d: %s\n",n,store);
n++;

}

return 0;
}

1 个答案:

答案 0 :(得分:0)

fgets'\n'缓冲区中留下store个字符,因此最简单的方法是将'\n'添加到比较字符串中:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUFSIZE 256

//This program is causing infinite loop, tried fflush and fgets and scanf
// It will run independently but will loop via the pipe

int main(int a, char**av)
{
    char store[BUFSIZE];
    memset(store, '\0', sizeof(store));
    while (strcmp(store, "exit!\n") != 0)
    {

        perror("Please enter next line of input (type 'exit!' to stop) \n"); //This repeats itself infinitely
        fgets(store, BUFSIZE, stdin);
        printf("%s", store); // This also repeats itself dependant on where i put
                             // fflush or another printf. Repeated outputs occur in blocks
    }

    return 0;
}

此外,正如您所看到的,初始值'/ 0'是不可接受的;它必须是'\ 0'。您的编译器可能会告诉您类似

的内容
test.c: In function ‘main’:
test.c:242:16: warning: multi-character character constant [-Wmultichar]
  memset(store, '/0', sizeof(store));
                ^

BTW memset,在这种情况下没用,因为fgets完成了所有工作,但无论如何,如果你想要缓冲区设置为nul,只需声明:

char store[BUFSIZE] = {0};

使用fgets的最佳解决方案(显然)始终管理左侧的换行符:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUFSIZE 256

//This program is causing infinite loop, tried fflush and fgets and scanf
// It will run independently but will loop via the pipe

int main(void)
{
    char store[BUFSIZE] = {0};
    char *pos;
    while (strcmp(store, "exit!") != 0)
    {

        perror("Please enter next line of input (type 'exit!' to stop) \n"); //This repeats itself infinitely
        fgets(store, BUFSIZE, stdin);

        if ((pos = strchr(store, '\n')) != NULL)
            *pos = '\0';
        else
            fprintf(stderr, "String too long!\n");

        printf("%s", store); // This also repeats itself dependant on where i put
                             // fflush or another printf. Repeated outputs occur in blocks
    }

    return 0;
}