for schleifen vereinfachen



  • kann mir irgendwer kurz helfen folgende 3 for schleifen zu vereinfachen, ohne das die funktionalität verloren geht?

    for (i=3; buffer[i]!= ('\n' || ' '); i++)						
    	{
    		if (buffer[i]== '#')
    		{
    			while (buffer[i]!='\n')
    			{
    				i++;
    			}
    		}
    		header[j] = buffer[i];
    		j++;
    		header= (char*)realloc(header, j+sizeof(char));
    	}
    	header[i+1] = '\0';
    	pic.width = atoi(header);
    	j = 0;
    	for (; buffer[i]!= ('\n' || ' '); i++)
    	{
    		if (buffer[i]== '#')
    		{
    			while (buffer[i]!='\n')
    			{
    				i++;
    			}
    		}
    		header[j] = buffer[i];
    		j++;
    		header=(char*)realloc(header, j+sizeof(char));
    	}
    	header[i+1]='\0';
    	pic.height = atoi(header);
    	j=0;
    	for (; buffer[i]!= ('\n' || ' '); i++)
    	{
    		if (buffer[i]== '#')
    		{
    			while (buffer[i]!='\n')
    			{
    				i++;
    			}
    		}
    		header[j] = buffer[i];
    		j++;
    		header=(char*)realloc(header, j+sizeof(char));
    	}
    	header[i+1]='\0';
    	pic.maxcolor = atoi(header);
    


  • Bearbeite bitte deinen Beitrag und verwende die [cpp]-Code-Tags.
    Siehe http://www.c-plusplus.net/forum/viewtopic.php?t=129036

    Edit: Und achte auch auf saubere Einrückung.



  • for (i=3; buffer[i]!= ('\n' || ' '); i++)

    kann schonmal überhaupt nicht machen, was es soll.

    buffer[i]!= ('\n' || ' ') ist fehlerhaft.

    Wenn dann

    buffer[i] != '\n' && buffer[i] != ' '



  • Oh! danke! und wie kann ich die 3 schleifen möglichst effizient zusammenpacken?
    es geht darum dass der code kürzer werden soll.



  • Marla666 schrieb:

    Oh! danke! und wie kann ich die 3 schleifen möglichst effizient zusammenpacken?
    es geht darum dass der code kürzer werden soll.

    Wieso fragst du in den Schleifen '\n' und ' ' ab ? Vielleicht solltest du mal nen Beispielstring mit gewünschtem Ergebnsi posten.
    So kann man teilweise nur raten, was deine Zeilen machen sollen.



  • Sind die beiden Schleifen nicht identisch auser :

    header[i+1] = '\0';
        pic.width = atoi(header); //DIES
        j = 0;
        for (; buffer[i]!= ('\n' || ' '); i++)
        {
            if (buffer[i]== '#')
            {
                while (buffer[i]!='\n')
                {
                    i++;
                }
            }
            header[j] = buffer[i];
            j++;
            header=(char*)realloc(header, j+sizeof(char));
        }
        header[i+1]='\0';
        pic.height = atoi(header); // DAS
        j=0;
        for (; buffer[i]!= ('\n' || ' '); i++)
        {
            if (buffer[i]== '#')
            {
                while (buffer[i]!='\n')
                {
                    i++;
                }
            }
            header[j] = buffer[i];
            j++;
            header=(char*)realloc(header, j+sizeof(char));
        }
    


  • Also die schleifen sollen einen header einer ppm datei durchgehen und eben wenn ein Newline oder ein leerzeichen kommt rausspringen und den teil der bis dahin war in 'header' schreiben und dann von ascii in int in ein struct namens pic.'...' schreiben.
    das problem ist dass die schleifen immer am ende der vorigen anschliessen. und deshalb befürchte ich, wenn man sie zusammenfast, könnte der sinn der schleifen verloren gehen, aber es wäre der übersichthalber besser sie zu komprimieren.
    Kann mir da wer helfen?



  • wie öffnest du die datei mit fopen?
    nomal kannst du dann jede zeile in ein buffer einlesen. Msust nich nach '\n' suchen?

    vlt. postest mal den gesamten code, und man kann das ganz anders machen



  • Naja es is so, dass die header information von einem ppm in 3 teile aufgeteilt ist, die ich brauche. in einem anderen teil meines programms schau ich ob auch P6 (identifikation für eine eche ppm binär) am anfang steht und dann muss ich natürlich auch eventuelle kommentare überspringen also sucht es nach zeichenketten die mit # beginnen, nachdem aber ein kommentar auch leerzeichen enthalten kann, erkenn ich nur am newline dass das kommentar zuende ist.
    die infos die ich wirklich brauche, sind höhe, breite und maxcolor. und das machen meine schleifen.



  • Marla666 schrieb:

    ...
    die infos die ich wirklich brauche, sind höhe, breite und maxcolor. und das machen meine schleifen.

    Hi !
    Was spricht gegen ein gewöhnliches fgets/fread ?
    Wer seine Pixelmapzeilen breiter als die vorgeschriebenen 70 Zeichen macht, hat selber schuld. Dann kann er/sie sich seine Bilder allein angucken 😃 :p

    #include <stdio.h>
    #include <string.h> // strerror
    #include <stdlib.h> // errno
    
    struct ppmPic
    {
    	char type[4];
    
    	unsigned width,
    			 height,
    			 maxcolour,
    			 bpc; // Byte pro Farbkomponente, ( byte per colourvalue )
    	void* data; // Pixeldaten. char* oder short*, abhängig von bpc
    };
    
    int ErrClose( char* s, FILE* fp )
    {
    	fprintf( stderr, "%s\n", s );
    	fclose(fp);
    	return 1;
    }
    
    int Err( char* s )
    {
    	fprintf( stderr, "%s\n", s );
    	return 1;
    }
    
    int Msg( char* s )
    {
    	fprintf( stdout, "%s\n", s  );
    	return 0;
    }
    
    int RdChk( FILE* fp ) // Prüfung auf Lesefehler.
    {
    	if( ferror( fp ) )
    		return ErrClose( strerror(errno), fp );
    	else 
    		return 0;
    }
    
    int ChkFormat( char* s )
    {
    	if ( *s != 'P' ) 
    		return Err( "Invalid PPM format." );
    
    	if ( *(s+1) == '3' ) 
    		return Msg(  "Ascii format." ); // Nur mal so zum Gucken.
    
    	if ( *(s+1) == '6' ) 
    		return Msg( "Binary format." );	// Dito.
    
    	return Err( "Format not supported." ); // PBM, PGM, etc.
    }
    
    void SetBpc( struct ppmPic* Pic, unsigned maxcolour )
    {
    	maxcolour <= 255 ? Pic->bpc = 1: Pic->bpc = 2;
    }
    
    int PpmReader( struct ppmPic* Pic, char* file )
    {
    	char buf[100] =	{0};
    	FILE *fp = NULL;
    
    	if ( NULL == ( fp = fopen ( file, "rb" )) )
    	{
    		sprintf( buf, "%s not found.", file );
    		return Err( buf );
    	}
    
    	fgets ( buf, sizeof(buf), fp ) ; // Identifikation.
    
    	if ( RdChk( fp ) )
    		return 1;
    
    	if ( ChkFormat( buf ) )
    		return ErrClose( "Failed on read ppm file.", fp );
    
    	strncpy( Pic->type, buf, 2 ); // Format kopieren.
    
    	do
    	{
    		fgets( buf, sizeof( buf ), fp ); 
    
    		if ( RdChk( fp ) )
    			return 1;
    	}
    	while ( buf[0] == '#' ); // Kommentare ingorieren.
    
    	// Breite, Höhe.
    	if ( 2 != sscanf ( buf, "%u %u", &Pic->width, &Pic->height ) )
    		return ErrClose( "Failed on read ppm file ( width, height ).", fp );
    
    	fgets( buf, sizeof( buf ), fp ); 	// Maximalwert der Farbkomponente.
    
    	if ( RdChk( fp ) )
    		return 1;
    
    	if ( 1 != sscanf ( buf, "%u", &Pic->maxcolour ) )
    		return ErrClose( "Failed on read ppm file ( maxcolour ).", fp );
    
    	SetBpc( Pic, Pic->maxcolour ); // Byte pro Farbwert setzen.
    
    // Fertig mit Header einlesen.
    
    /* Pixeldaten einlesen. Bei grossen Bildern eventuell mit fread weiter arbeiten.
    Pic->data = malloc( ... to be written ...
    	while( fgets( buf, sizeof( buf ), fp ) )
    	{
    		if ( RdChk( fp ) )
    			return 1;
    		fputs( buf, stdout );
    	}
    */
    	if( fclose(fp) )
    		return Err( "Failed on fclose." );
    
    	return 0;
    }
    
    void ShowPpmInfo( struct ppmPic* Pic )
    {
    	fprintf( stdout, "Type: %s\n", Pic->type );
    	fprintf( stdout, "Width: %u\n", Pic->width );
    	fprintf( stdout, "Height: %u\n", Pic->height );
    	fprintf( stdout, "Maxcolour: %u\n", Pic->maxcolour );
    	fprintf( stdout, "Byte per colour value: %u\n", Pic->bpc );
    }
    
    int main()
    {
    	char* file = "background.ppm";
    	struct ppmPic Pic = {0};
    
    	if ( PpmReader( &Pic, file ) )
    		return 1;
    	else
    		ShowPpmInfo( &Pic );
    
    	return 0;
    }
    


  • WOW! 😮
    hast du das grade geschrieben? das is ja genial! Danke!!



  • *grins*
    ja, bitte 🙂



  • Ich will ja nicht unverschämt sein, aber könntest du mir bei einem weiteren problem helfen? Kann auch verstehen wenn du das nicht willst.
    Ich muss nämlich das ppm in ein unkomprimiertes 24bpp 'bottom up' bmp verwandeln. ich sitz schon seit tagen daran und weiss nicht wie ich das machen soll.



  • Das ppm ? Welches denn, das Ascii, das binäre oder beide?
    In beiden Fällen brauchst du für das bmp Format die beiden Header:
    http://www.pohlig.de/Unterricht/Inf2003/Tag45/25.11_Das_bmp_Format.htm

    Du kannst dir also zwei Strukturen schreiben, oder irgendwo kopieren :D.
    Das sind dann deine Header.
    Microsoft nennt die in ihrer WindowsApi BITMAPINFOHEADER und BITMAPFILEHEADER.

    Man könnte das auch in eine Struktur schreiben, aber das wäre vllt. etwas unübersichtlich.
    Die beiden Header schreibst du ganz an den Anfang der Datei. Vorher natürlich mit den richtigen Werten initialisieren.
    Die Anzahl der Ebenen gleich 1 setzen, sonst zeigt z.B. Paint die Bilder nicht an. Kompression setzt du gleich 0, sowie die X-Auflösung, Y-Auflösung, Anzahl genutzter Farben, Anzahl wichtiger Farben ebenfalls auf 0.
    Das bmp Format verlangt, das sich die Zeilen in Byte gerechnet, ohne Rest durch vier teilen lassen. Hast du also z.B. ein 24 Bit/Pixel Bild, mit zwei Pixeln pro Zeile, dann musst du noch zwei Byte nachfüllen(Füllbyte, Ausrichtung auf 4 Byte-Grenzen).
    Ich glaube, der Grund dafür ist ein Geschwindigkeitsgewinn beim Zugriff auf die Pixel.
    Die Größe der Pixeldaten ohne die beiden Header kannst du mit dieser Zeile berechnen lassen:
    size_image = height * ((((width * bit_count) + 31) & ~31) >> 3);
    Das nette an dieser etwas monströs aussehenden Zeile ist, das sich dann deine Zeilen durch 4 teilen lassen.
    Die Höhe und die Breite kannst du ja jetzt aus der ppm lesen, bit_count hast du ja auf 24 festgelegt.
    Die Größe der kompletten Datei ist sizeof(Header1) + sizeof(Header2) + size_image.
    Falls du noch eine Farbpalette brauchst, muss die noch mit einbezogen und zwischen Header2 und den Pixeldaten gespeichert werden, ist aber bei 24 Bits/Pixel nicht üblich.

    Nagut, bei einer binären ppm brauchst du also nur die Header auszutauschen und eventuell Bytes nachzufüllen. Bei einer Ascii ppm müsstest du noch die Whitespaces rausfiltern. Die Pixeldaten schreibst du in beiden Fällen direkt hinter die Header.



  • Du bist Spitze!! 👍 Einfach genial! 👍 Ich danke dir!
    Du hast ja keine ahnung wie lang ich schon an diesem dämlichen programm sitze!



  • routine routine routine;)


Anmelden zum Antworten