Gå til innhold

problem med char*


Anbefalte innlegg

Har et lite problem med en oppgave vi har fått på skolen. Skal lage et "tail" program som skriver ut de n siste linjene i en fil. Det skal skrives i C++. Jeg har fått laget programmet og alt fungerer, men det jeg har problemer med er;

 

n = argv[2]; // antall linjer som skal skrives ut

 

char** p = new char*[n];

 

for ( int i = 0; i < n; i++ )

{

p = new int[1024]; // her ligger problemet.

}

 

og det er her problemet kommer. Det er vanskelig å vite om en linje ikke inneholder mer enn 1024 char...og hvordan løser jeg problemet?.

Jeg bruker dobbel pekeren ( p ) som en sirkulær kø.

 

 

NB! Vi får ikke lov til å lese en linje mer enn 1 gang! og heller ikke lese mer enn n linjer i minnet. Får heller ikke lov til å bruke noen av funksjonene i STL ( som vector, string og tilsvarende )...

 

Mvh

 

- Amir-

Lenke til kommentar
Videoannonse
Annonse
  • 4 uker senere...
men i stedet lese inn f.eks. ett og ett tegn om gangen?

 

Å lese inn en linje som inneholder 1024 tegn krever 1 system call.

Å lese inn denne linjen ett og ett tegn om gangen krever 1024 system calls.

 

Det finnes grenser for hvor mye ressurser man trenger å sløse.

 

Jalemo

Lenke til kommentar

Ta en titt på getline(3) funksjonen, dersom du får bruke denne - den leser en linje av gangen, og allokerer minne selv. Den er imidlertid en GNUting, og finnes ikke i Windows. (Uten å bruke libiberty, altså.)

 

Ellers kunne du bruke read(2)-kallet, lese 1024 bokstaver ad gangen og utvide strengen etterhvert. Du kunne også lage en lenket liste bestående av strenger på 1024 chars. read(2) returnerer antall tegn lest, men stopper ikke ved linjeskift; du må bufre det selv.

 

For å stoppe ved linjeskift *må* du enten lese ett tegn av gangen, eller (bedre) bruke ikke-blokkerende IO - men da kan du få linjeskiftet + litt av neste setning, og må bufre. Standard libc har ingen funksjoner for dette, derfor bruken av read-systemkallet; oppførselen til fgetc(3) kan innvolvere et systemkall per kall - ingen garantier der.

 

Hvis du velger å utvide strengen du leser til etterhvert bør du forøvrig doble den hver gang; da får du O(N log N) hastighet, mens en konstant økning vil gi O(N^2).

Lenke til kommentar
For å stoppe ved linjeskift *må* du enten lese ett tegn av gangen, eller (bedre) bruke ikke-blokkerende IO

 

    The fgets() function reads at most one less than the number of characters
    specified by size from the given stream and stores them in the string
    str.  Reading stops when a newline character is found, at end-of-file or
    error.  

 

fgets() kan lese fra alle FILE *streams.

 

read() tar en file descriptor som argument, og det er null problem å få gjort om denne fd'en til en FILE *stream med fdopen() eller lignende.

 

En annen mulighet er å lese inn alt i en dynamisk allokert char peker og så dele opp denne strengen etter newlines.

 

Det er ikke så vanskelig å få til noe her, det dummeste man gjør er å lese inn en fil char for char, det er lite trivelig med store filer.

 

Jale

Lenke til kommentar

Jeg fant at et lite tail program jeg lagde en gang, så her er det:

 

Gikk litt fort og gæli men jaja, gidder ikke fikse så mye på det...

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

#define BUFFERSIZE 4096

static int fd;
int printwholefile = 0;

int print_tail(int);

int main(int argc, char **argv)
{
       int pos = 0;
       if( argc < 2) {
               printf("Usage: %s <filename>\n", argv[0]);
               exit(1);
       }

       if( (fd = open(argv[1], O_RDONLY)) == -1) {
               perror(argv[1]);
               exit(1);
       }

       print_tail(10);
       close(fd);
       return 0;
}

int print_tail(int lin)
{
       int     num_bytes, lines, bytesfrombuf, line, i, printfromhere;
       num_bytes = lines = bytesfrombuf = line = i = printfromhere = 0;
       char    buffer[BUFFERSIZE];

       while( (num_bytes = read(fd, buffer, BUFFERSIZE)) > 0)
       {
               for(bytesfrombuf = 0; bytesfrombuf < num_bytes; bytesfrombuf++)
               {
                       if(buffer[bytesfrombuf] == '\n')
                               lines++;
               }
               buffer[0] = '\0';
       }
       printf("Lines in file: %d\n", lines);

       lseek(fd, 0, SEEK_SET);
       if(lines < lin)
               while( read(fd, buffer, BUFFERSIZE) > 0)
                       printf("%s", buffer);

       while( (num_bytes = read(fd, buffer, BUFFERSIZE)) > 0)
       {
               if( !printfromhere )
               {
                       for( bytesfrombuf = 0; bytesfrombuf < num_bytes; bytesfrombuf++)
                       {
                               if( buffer[bytesfrombuf] == '\n')
                               {
                                       line++;
                                       if( line == (lines-lin)) {
                                               printfromhere = 1;
                                               for ( i  = bytesfrombuf; i < num_bytes; i++ ) {
                                                       printf("%c", buffer[i]);
                                               }
                                               break;
                                       }
                               }
                       }
               }
               else
                       printf("%s", buffer);

               buffer[0] = '\0';     
       }

       return 0;
}

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...