Pipe - wortweise lesen



  • Hello all.
    Ich hab ein kleines Beispielprogramm für Pipes in C programmiert, oder besser gesagt ich will.

    Die Funktion:
    Es gibt einen Vater und einen Kindprozess. Der Vaterprozess soll eine Datei einlesen und Wort für Wort in die Pipe schreiben.
    Der Kindprozess soll die Wörter aus der Pipe einlesen und auf dem Bildschirm ausgeben.

    Mein Problem hierbei ist nun, dass der Kindprozess nur das erste Wort ausgibt, und das 2 mal!

    Was mache ich hierbei falsch?

    Inhalt der lesen.txt:
    "Hallo dies ist ein Test"

    Ausgabe des Kindprozess:
    "HalloHallo"

    C-Code:

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    int main()
    {
    	pid_t pid;
    	FILE *datei;
    	char buffer[30], lesebuffer[30];
    	int fd[2], nbytes;
    
    	pipe(fd);
    	pid = fork();
    	switch(pid)
    	{
    		case 0: //Dies ist der Kindprozess
    			close(fd[1]);
    			do
    			{
    				nbytes = read(fd[0], lesebuffer, sizeof(lesebuffer));		
    				printf("%s", lesebuffer);
    			}
    			while(nbytes > 0);
    			close(fd[0]);	
    			break;
    
    		default: //Dies ist der Vaterprozess
    			close(fd[0]);
    			datei=fopen("lesen.txt", "r");
    			while((fscanf(datei, "%s", buffer))!=EOF)
    			{		
    				write(fd[1], buffer, strlen(buffer)+1);
    			}
    			close(fd[1]);
    			wait(NULL);
    			break;
    	}	
    return 0;
    }
    


  • Deine Abbruchbedingung bei do/while ist falsch, die läuft 1x zuviel und gibt somit den vorigen Bufferinhalt nochmals aus.



  • Wutz schrieb:

    Deine Abbruchbedingung bei do/while ist falsch, die läuft 1x zuviel und gibt somit den vorigen Bufferinhalt nochmals aus.

    Ok aber wie muss ich sie setzen, dass der Prozess nocheinmal von der Pipe liest.
    Sprich, wie muss ich es ändern damit ich den kompletten Text aus der Pipe herausbekomme?

    Egal wie ich die Abbruchbedingung der Pipe ändere, das höchste der Gefühle an Output ist "Hallo", was nur das erste Wort des Files ist. Der Vater schreibt jedoch mehrere Wörter in die Pipe.


  • Mod

    Die Leseschleife im Vaterprozess ist auch falsch. Guck mal, was (f)scanf zurück gibt.



  • Ich bin ein Stückchen weitergekommen, undzwar:

    Ich bekomme jetzt beim lesenden Kindprozess den kompletten Fileinhalt heraus. Nur ist das Problem, dass dieser im lesebuffer als ein einziger String erkannt wird. Sprich Leerzeichen, die im FIle enthalten sind, werden ignoriert.

    Der Output vom Kindprozess ist diese Wurst:
    "HallodiesisteinTest" anstatt "Hallo dies ist ein Test".

    Das Problem liegt nicht an der Ausgabe denn ich habe herausgefunden, dass der Vater zwar String für String in die Pipe schreibt aber das Kind einmal den kompletten Pipeinhalt in den Buffer speichert.

    Ich bräuchte jedoch die Wörter getrennt im Kindprozess, da ich bestimmte Wörter maskieren muss.

    Was ist hierfür nötig?

    aktueller Code:

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    int main()
    {
    	pid_t pid;
    	FILE *datei;
    	char buffer[300], lesebuffer[300];
    	int fd[2], nbytes;
    
    	pipe(fd);
    	pid = fork();
    	switch(pid)
    	{
    		case 0:
    			close(fd[1]);
    			do
    			{
    				nbytes = read(fd[0], lesebuffer, sizeof(lesebuffer));				
    				printf("%s\n", lesebuffer);
    			}
    			while(nbytes < 0);
    			close(fd[0]);	
    			break;
    
    		default:
    			close(fd[0]);
    			datei=fopen("lesen.txt", "r");
    			while((fscanf(datei, "%s", buffer))!=EOF)
    			{									
    				write(fd[1], buffer, strlen(buffer));
    			}
    			close(fd[1]);
    			wait(NULL);
    			break;
    	}	
    return 0;
    }
    


  • scanf überliest Whitespace (also auch Leerzeichen).
    Demnach werden keine gesendet.

    Füge die Leerzeichen im Kind ein. Du weißt ja, dass es einzelne Wörter sind.



  • Sorry, zu schnell geantwortet.

    Du musst den Schreibpuffer leeren.
    Such mal nach flush



  • Hey.
    Ich hab jetzt etliche Versuche unternommen die Wörter einzeln und nicht als einen ganzen String aus der Pipe herauszubekommen bin aber kläglich gescheitert.

    Meine Recherchen haben ergeben, dass bei write() nichts gebuffert wird.
    Ich wäre wirklich sehr dankbar falls jemand meinen existierenden Code so umändern könnte, dass jedes Wort getrennt durch "\n" im Kindprozess ausgegeben wird.

    Ich hoffe jemand findet sich, denn ich schaffs einfach nicht 😨

    Der obige Code von "Margusch", sorry ich vergaß mich einzuloggen, ist der Ausgangszustand.



  • int main()
    {
        pid_t pid;
        FILE *datei;
        char *p,buffer[300], lesebuffer[300];
        int fd[2], nbytes;
    
        pipe(fd);
        pid = fork();
        switch(pid)
        {
            case 0:
                close(fd[1]);
                while(1)
                {
                    nbytes=read(fd[0],lesebuffer,sizeof(lesebuffer));
                    if(nbytes<1) break;
                    lesebuffer[nbytes]=0;
                    for(p=strtok(lesebuffer," ");p;p=strtok(0," "))             
                        puts(p);
                }
                close(fd[0]);  
                break;
    
            default:
                close(fd[0]);
                datei=fopen("lesen.txt", "r");
                while(1==fscanf(datei, "%298s", buffer))
                {
                    strcat(buffer," ");                                 
                    write(fd[1], buffer, strlen(buffer));
                }
                fclose(datei);
                close(fd[1]);
                wait(NULL);
                break;
        }  
    return 0;
    }
    


  • Vielen vielen Dank!

    Doch ich verstehe die Zählschleife(p) nicht so recht.
    Würdest du mir die bitte erklären? (:



  • Du bekommst die Wärter durch Leerzeichen getrennt.
    Die Schleife* trennt den Text an den Leerzeichen wieder auf.
    Dafür benutzt sie strtok.
    Wenn kein Wort mehr da ist, gibt strtok eine NULL zurück.

    Evtl wird da klarer, wenn du die for-Schleife mal als while-Schleife aufschreibst.

    p=strtok(lesebuffer," ")
    while(p != NULL)            
    { puts(p);
      p=strtok(NULL," ");
    }
    

    *Da wird nix gezählt.


Log in to reply