Zeile in einer Datei editieren (ich schon wieder...)



  • Wow bist Du schnell!

    Kannst Du mir da CODE-mässig ein bisl unter die Arme greifen? Bin doch noch so'n NOOB...



  • dazu brauchst du dynamische speicherverwaltung.

    #define BUFFSIZE 512
    
    char **ppLines = NULL;
    char buffer[BUFFSIZE];
    int nElements=0;
    

    Einlesen:

    while (fgets(buffer, BUFFSIZE, fp) != NULL)
    {
        nElements++;
        // speicher für das pointerarray allokieren
        ppLines = (char**) realloc (ppLines, nElements*sizeof(char*));
    
        // speicher für den string allokieren
        ppLines[nElements-1] = (char*) malloc ((strlen(buffer)+1)*sizeof(char));
        strncpy(ppLines[nElements-1], buffer, strlen(buffer));
    }
    

    Dann arbeite mit den Datensätzen und schreibe sie wieder in datei

    am ende freigeben nicht vergessen

    if (ppLines)
    {
        for (int i=0; i<nElements; i++)
        {
            if (ppLines[i])
            {
                free (ppLines[i]);
                ppLines[i] = NULL;
            }
        }
    
        free (ppLines);
        ppLines = NULL;
    }
    


  • "fp" in fgets ist der Verweis auf meine Datei, richtig??

    Sieht ja alles schon ganz gut aus... Kannst Du mir noch zeigen, wie ich dann in den Daten rumschreiben kann und das ganze dann in die Datei zurückschreiben kann??

    Ich versteh zwar was Du mir da gepostet hast, aber ich würde nie selber auf sowas kommen... 🙂

    Danke!!!



  • Doom5000 schrieb:

    "fp" in fgets ist der Verweis auf meine Datei, richtig??

    Richtig

    Doom5000 schrieb:

    Ich versteh zwar was Du mir da gepostet hast, aber ich würde nie selber auf sowas kommen... 🙂

    das glaub ich dir nicht 🙄

    was machst du den mit deiner funktion fwrite()?

    habe mir gerade noch mal deinen post angeschaut, glaubst du nicht es ist besser alles in eine Struktur zu packen?



  • fwrite schreibt mir eine Zeile in die Datei. Aber eben unten dran...

    Ich bin jetzt schon soweit, dass er den dynamischen Speicher richtig aufbaut, dann die richtige Zeile raussucht, jetzt muss ich nur noch das mit dem Überschreiben hinkriegen. Insgesamt scheint das aber zu klappen!

    Wenns läuft werde ich das hier nochmal posten, vielleicht kann man dann ja noch das ein oder andere "hübsch" machen... 🙂



  • wie kann ich denn vor dem schreiben am besten die Datei wieder ganz leer machen?? Ich hab schon die verschiedenen Modes beim fwrite durchprobiert aber ich bekomm immer noch so komisches Zeug vor meinen eigentlichen Werten. Das Überschreiben an sich scheint aber zu funktionieren...

    ύݻ̐Û	þ/Ï›œË¾‘ÛŒÿ/ÏœË¾‘Û?yÒÿèþ/ùœ’ÝÓÍïú/Ϥ™ÀÀ’Üüü/Ϟ¸Á‘Ú¿ý/Ï‹œÍ”Ø?yÒÿµû/ùÝ›
    Òÿµû/ùÝ›œŒÝÓ¯ø/ÏÝ›ÁÄœÚù/Ïœ–Á˘Ûÿý/Ïš‘ƾÛ?yÒÿØþ/ùÝ”’“ÝÓßú/Ïš‘¶Ä’ÛŸü/Ï—£¶»‰ßŸþ/Ï
    
     02 WOO.V \   QB03 Q W ` f lumme ]VR0508002 020000 000000 
    ‡ áÒN‡ep Tÿ ð€ ðoï ð  À	£‡oï ðoï ðoï ðoï ðš áÒep \‡Mø ðÍÎI‡9ç ð:ÈéÎ(
    
    썆ì÷P&ÿw&ÿwšÿÿ  †ì÷ŒVþ‰Fü‹Fþ‹Vü‰Fú‰Vø3öé¨ ÿvþÿvü¸~ Pšÿÿ  ‰Vú‰FøFúué‹ Ä^ø&Æ †Ò÷
    QB0306004 001000 5500   0 4 Testblatt Zeile:1 Spalte:1 Nummer:1                   (ENDE)
    VQ0577000 009000 000000 1 4 Testblatt Zeile:1 Spalte:2 Nummer:2                         
    VR0508002 020000 000000 0 5 Testblatt Zeile:1 Spalte:3 Nummer:3                         
    QB0306003 100000 000000 0 6 Testblatt Zeile:2 Spalte:1 Nummer:4                         
    VQ0576000 900000 000000 1 6 Testblatt Zeile:2 Spalte:2 Nummer:5
    


  • habs schon....

    mit "wt+" hats gut geklappt!



  • So, das funktioniert jetzt alles schon ziemlich gut. Problematisch wirds aber, wenn ich meine Original-Zählerdatei teste: Sie hat knapp 1000 Zeilen, womit diese dynamische Speicherverwaltung anscheinend nicht klarkommt... Kann man das irgendwie noch aufbohren, oder muss ich das anders machen?

    Die ganze Geschichte funktioniert, aber um die richtige Nummer im Speicher zu finden braucht er gut 2 Minuten... (auf dem Handheld)

    Gibts da noch irgendeine andere Möglichkeit das zu realisieren??

    Hier nochmal der aktuelle Code:
    (nur die collect_data-Funktion)

    void collect_data(void)
    {
    	#define BUFFSIZE 90
    	int ks, rc; /* ks=Keystroke, rc=ReturnCharacter  */
    	int collect_flag = 1;
    	char file_buffer[95];  /* Puffer fr die Daten aus der Datei */
    
    	char **ppLines = NULL;
    	char buffer[BUFFSIZE];
    	int nElements = 0;
    	int i;
    	char zSuch_buffer[10]; //Puffer zum Speichern der gesuchten Z-Nr.
    
    	while(collect_flag)
    	{
    
    		memset(zNr,0,sizeof(zNr));  /* Variablen werden mit Nullwerten gefllt */
    		memset(oldStd,0,sizeof(oldStd));
    		memset(newStd,0,sizeof(newStd));
    		memset(ueber,0,sizeof(ueber));
    		memset(anzSt,0,sizeof(anzSt));
    		memset(einbau,0,sizeof(einbau));
    
    		inv_menu(); // Inventurmen zeigen
    
    		rc = get_scan_input(zNr,10,7,1,0);  // Nummer einlesen
    
    		if(rc == -1)  // ESC wurde gedrckt
    		{
    			collect_flag = 0;
    			break;
    		}
    
    		trim_spaces(zNr);
    
    		if(*zNr)
    		{
    
    			if((inv_file = fopen(INVFILE, "r")) == NULL)
    			{
    				clrscr();
    				gotoxy(2,1);
    				printf("Dateifehler");
    				delay(1000);
    			}
    
    			if(lookup())
    			/* Nummer in der Datei suchen
    			   Variablen setzen */
    			{
    
    				// Z-Nummer gefunden, Daten ausgeben:
    
    				gotoxy(14,2);
    				printf("%s",oldStd);
    
    				gotoxy(10,4);
    				printf("%s", anzSt);
    
    				if(strcmp(ueber,"1") == 0)
    				//šberlauf anzeigen
    				{
    					gotoxy(13,4);
    					printf("šberlauf");
    				}
    
    				gotoxy(1,6);
    				printf("%s",einbau);
    
    				gotoxy(14,3);
    				shift_lock(1);
    
    				//Aufbau des dynamischen Speichers
    				fseek(inv_file, 0, SEEK_SET);
    				nElements = 0;
    				while(fgets(buffer, BUFFSIZE, inv_file) != NULL)
    				{
    					nElements++;
    					//Speicher fr Pointerarray allokieren
    					ppLines = (char**) realloc (ppLines, nElements*sizeof(char*));
    
    					//Speicher fr den String allokieren
    					ppLines[nElements-1] = (char*) malloc ((strlen(buffer)+1)*sizeof(char));
    					strncpy(ppLines[nElements-1], buffer, strlen(buffer));
    				}
    
    				if(strcmp(newStd, "000000") != 0)
    				// Neuer ZS wurde schon eingegeben:
    				{
    					gotoxy(14,3);
    					printf("%s", newStd);
    					gotoxy(14,3);
    
    					// evtl. Editieren des neuen Standes:
    					ks = dgetch(NOECHO);
    					if(ks == ESC || ks == BS)
    					{
    						// Abbruch durch ESC oder BkSp
    					}
    					else
    					{
    						// Neuen ZS annehmen:
    						memset(newStd,0,sizeof(newStd));
    						gotoxy(14,3);
    						printf("      ");
    
    						get_kybrd_input(newStd,7,14,3,NUMLOCK);
    
    						for(i=0; i<nElements;i++)
    						{
    
    							//Z„hlernummer zum Suchen kopieren
    							strncpy(zSuch_buffer, ppLines[i], 9); //9 Zeichen der Zeile in den Buffer
    							zSuch_buffer[9] = '\0';
    
    							if(strcmp(zNr, zSuch_buffer) == 0)
    							{
    								//Zeile im Speicher erneuern
    								sprintf(ppLines[i],"%-10s%-7s%-7s%-2s%-2s%-61s", zNr, oldStd, newStd, ueber, anzSt, einbau);
    							}
    						}
    					}
    				}//Ende von If "ZS lag schon vor"
    
    				else
    				// Neuer ZS liegt noch nicht vor:
    				{
    					memset(newStd,0,sizeof(newStd));
    					// Eingabe des neuen Standes
    					get_kybrd_input(newStd,7,14,3,NUMLOCK);
    
    					//richtige Zeile suchen
    
    					for(i=0; i<nElements;i++)
    					{
    
    						//Z„hlernummer zum Suchen kopieren
    						strncpy(zSuch_buffer, ppLines[i], 9); //9 Zeichen der Zeile in den Buffer
    						zSuch_buffer[9] = '\0';
    
    						if(strcmp(zNr, zSuch_buffer) == 0)
    						{
    							//Zeile im Speicher erneuern
    							sprintf(ppLines[i],"%-10s%-7s%-7s%-2s%-2s%-61s", zNr, oldStd, newStd, ueber, anzSt, einbau);
    						}
    					}
    
    				}//Ende von Else "ZS lag noch nicht vor"
    
    				//Datei erstmal wieder zu machen
    				fclose(inv_file);
    
    				//Datei mit anderem Mode wieder aufmachen
    				if((inv_file = fopen(INVFILE, "wt+")) == NULL)
    				{
    					clrscr();
    					gotoxy(2,1);
    					printf("Dateifehler");
    					delay(1000);
    				}
    
    				// Zurckschreiben in Datei:
    				for(i=0; i<nElements; i++)
    				{
    					fwrite(ppLines[i],88,1,inv_file);
    					fputs("\n",inv_file);
    				}
    
    				//OutFile dicht machen
    				fclose(inv_file);
    
    				//dynamischen Speicher wieder freigeben
    				if(ppLines)
    				{
    					for(i=0; i<nElements; i++)
    					{
    						if(ppLines[i])
    						{
    							free(ppLines[i]);
    							ppLines[i] = NULL;
    						}
    					}
    
    					free(ppLines);
    					ppLines = NULL;
    				}
    
    			}//Ende von If "Z-Nummer gefunden"
    
    			else
    			// Z„hlernummer nicht in Datei vorhanden
    			{
    				clrscr();
    				gotoxy(3,3);
    				printf("nicht gefunden...");
    				delay(1500);
    			}
    
    		}//Ende von if(*zNr)
    	}// Ende von while(collect_flag)
    }//Ende von collect_data()
    


  • MOIN!
    so, bin jetzt schon mal ne ganze Ecke weiter: Ich lasse den dyn. Speicher jetzt einfach am Anfang der Routine einmal erzeugen, dann wird damit gearbeitet beim Verlassen der Funktion wird dann alles zurück in die Datei geschrieben.
    Dieses Zurückschreiben dauert allerdings SEHR lange auf meinen Handhelds... (Ca. 4 min)
    Kann man das irgendwie noch schneller lösen?? Das Einlesen der Datei dauert auch nur ein paar Sekunden...

    So wirds bei mir zurückgeschrieben:

    if((inv_file = fopen(INVFILE, "wt+")) == NULL)
    		{
    			clrscr();
    			gotoxy(2,1);
    			printf("Dateifehler");
    			delay(1000);
    		}
    
    	// dyn. Speicher zurückschreiben in Datei:
    	for(j=0; j<nElements; j++)
    	{
    		fwrite(ppLines[j],88,1,inv_file);
    		fputs("\n",inv_file);
    		clrscr();
    		gotoxy(1,1);
    		printf("Datei wird geschrieben\n");
    		printf("Zähler-Nr.: %d", j);
    	}
    
    	//File dicht machen
    	fclose(inv_file);
    


  • gibst du den speicher auch wieder frei?



  • Ja, der Speicher wird beim Beenden des Programmes wieder freigegeben. Dies erfolgt erst so spät, weil ich für andere Bereiche der Anwendung die Daten auch noch brauche. Funktioniert bis jetzt auch alles prima. Im Prinzip kann man damit jetzt schon ganz gut arbeiten. Das Rückschreiben in die Datei ist zwar etwas nervig, aber man kann sich darauf einstellen.

    Falls jemand noch Verbesserungsvorschläge hat, gerne her damit... 🙂

    Chris

    Dies erfolgt am Ende der Main-Methode:

    // dynamischen Speicher wieder freigeben
       if(ppLines)
       {
    	for(j=0; j<nElements; j++)
    	{
    		if(ppLines[j])
    		{
    			free(ppLines[j]);
    			ppLines[j] = NULL;
    		}
    	}
    
    	free(ppLines);
    	ppLines = NULL;
       }
    

Anmelden zum Antworten