Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » Rätselecke » Zeilenleser

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 < [ 2 ] [ 3 ]
000
07.08.2004, 21:33 Uhr
mike
Pinguinhüpfer
(Operator)


Zu schreiben ist ein Programm zeilenausg welches bestimmte Zeilen einer Datei ausgibt.
Bsp. (test ist die zu ausgebende Datei)
$ zeilenausg 3,4-9,12,14- test
Gibt Zeile 3,4 bis 9,12 und 14 bis zum Ende aus

$ zeilenausg 2-10 test
Gibt Zeile 2-10 aus

$ zeilenausg -20,50- test
Gibt Zeile 1 bis 20 aus und 50 bis Ende

$ zeilenausg test
Gibt alle Zeilen aus

Gewonnen hat das "schönste" Programm (Länge ist egal)

mfg
PS: ich fande diese Übung eines Buches interessant - muss aber zugeben, dass mein Programm ein paar Bugs hatte
--

Dieser Post wurde am 07.08.2004 um 21:34 Uhr von mike editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
07.08.2004, 22:02 Uhr
Pablo
Supertux
(Operator)


@mike: du als modi solltest da nicht posten, sondern in Rätselecke

aber echt schönes Ziel
--
A! Elbereth Gilthoniel!
silivren penna míriel
o menel aglar elenath,
Gilthoniel, A! Elbereth!

Dieser Post wurde am 07.08.2004 um 22:02 Uhr von Pablo editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
08.08.2004, 11:32 Uhr
mike
Pinguinhüpfer
(Operator)


Schande Jetzt sehe ichs. Habs unter Ideen & Projekte gepostet lol Das sollte natürlich ein Rätsel werden - sorry
--
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
08.08.2004, 15:54 Uhr
virtual
Sexiest Bit alive
(Operator)



C++:
#include <sstream>
#include <string>
#include <stdexcept>
#include <list>
#include <fstream>
#include <iostream>
#include <iterator>


class range {
    int from;
    int to;   // -1 means to last line
public:
    range(const std::string& str) {
        std::string::size_type pos = str.find('-');
        std::stringstream sstr(str);
        if (pos==std::string::npos) {
            sstr>>to;
            from = to;
        }else if (pos==0) {
            sstr>>to;
            from = 1;
        }else if (pos==str.length()-1) {
            sstr>>from;
            to = -1;
        }else {
            sstr>>from;
            sstr>>to;
            to = -to;
        }
        if (!sstr) {
            throw std::runtime_error("Bad range \""+str+"\"");
        }
    }

    bool contains(int line) const {
        return line>=from && (line<=to || to==-1);
    }
};


class range_list {
    std::list<range> ranges;
public:
    range_list(char** strs, int count) {
        for(int i=0; i<count; ++i) {
            ranges.push_back(range(strs[i]));
        }
    }

    bool contains(int line) const {
        for(std::list<range>::const_iterator i=ranges.begin(); i!=ranges.end(); ++i) {
            if (i->contains(line)) {
                return true;
            }
        }
        return ranges.size()==0;
    }
};


template<typename L>
class line_filter {
    int line;
    range_list ranges;

public:
    line_filter(const range_list& rangesp)
        :line(0), ranges(rangesp) {
    }

    L operator () (L content) {
        return ranges.contains(++line) ? content:L();
    }
};


int main(int argc, char** argv) {
    std::list<std::string> content;

    try
    {
        // Command line issues
        if (argc<2) {
            std::cerr<<"Bad command line"<<std::endl
                     <<"usage: zeilenfilter [line-patterns ...] file"<<std::endl;
            return 1;
        }

        std::ifstream in(argv[argc-1]);

        // Read in file
        std::list<std::string> content;
        std::string buffer;
        while (std::getline(in, buffer)) {
            content.push_back(buffer+"\n");
        }

        // Filter
        range_list ranges(argv+1, argc-2);
        std::transform(content.begin(),
                       content.end(),
                       std::ostream_iterator<std::string>(std::cout),
                       line_filter<std::string>(ranges));
    }
    catch(std::exception e)
    {
        std::cerr<<"Unexpected error: "<<e.what()<<std::endl;
        return 1;
    }
}



Noch nicht ganz schön, aber das wird noch...
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
08.08.2004, 17:52 Uhr
0xdeadbeef
Gott
(Operator)


Ich hatte mangels Compiler auf dieser Kiste leider keine Gelegenheit das zu testen, aber ich denke, die Idee sollte klar werden:

C++:
#include <algorithm>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>

#include "boost/tokenizer.hpp"

int main(int argc, char *argv[]) {
  /* Code zum Abfangen etwaiger Eingabefehler (Datei nicht vorhanden, zu wenig
   * Parameter etc)  kann sich der geneigte Leser selbst schreiben. */


  std::vector<std::string> lines;
  std::ifstream fin(argv[2]);

  lines.push_back(""); // Indices nicht von 0-basiert auf 1-basiert transformieren
  while(fin) {
    std::string s;
    std::getline(std::cin, s);
    lines.push_back(s);
  }

  boost::tokenizer<> tok(argv[1], boost::char_separator<char>(","));
  for(tokenizer::iterator tok_iter = tok.begin(); tok_iter != tok.end(); ++tok) {
    int x1, x2;
    switch(sscanf(tok_iter->c_str(), "%d-%d", &x1, &x2)) {
    case 1:
      if(x1 < 0)
        for(int i = 1; i <= -x1; ++i)
          std::cout << lines[i] << std::endl;
      else if((*tok_iter)[tok_iter->size() - 1] == '-')
        for(int i = x1; i < lines.size(); ++i)
          std::cout << lines[i] << std::endl;
      else
        std::cout << lines[x1] << std::endl;
      break;
    case 2:
      for(int i = x1; i <= x2; ++i)
        std::cout << lines[i] << std::endl;
    }
  }

  return 0;
}


--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
08.08.2004, 18:21 Uhr
FloSoft
Medialer Over-Flow
(Administrator)


muss


C++:
while(fin) {
    std::string s;
    std::getline(std::cin, s);
    lines.push_back(s);
  }



nicht


C++:
while(fin) {
    std::string s;
    std::getline(fin, s);
    lines.push_back(s);
  }



heißen?
--
class God : public ChuckNorris { };
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
08.08.2004, 18:29 Uhr
0xdeadbeef
Gott
(Operator)


Ja, ja, ja. Wie gesagt - kein Compiler, keine Testmöglichkeit.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
08.08.2004, 20:31 Uhr
Pablo
Supertux
(Operator)


Ok, meins ist ein bisschen groß geworden, aber gibt alle Zeilen in der richtigen Reihenfolge aus, wenn man supercat 5-3 bla.txt macht, dann werden die Zeilen 3 5 und 5 in dieser Reihenfolge ausgebeben


C++:
/* fun-soft.de Rätsel super cat
Synopsis:

Zu schreiben ist ein Programm zeilenausg welches bestimmte Zeilen einer Datei ausgibt.
Bsp. (test ist die zu ausgebende Datei)
$ zeilenausg 3,4-9,12,14- test
Gibt Zeile 3,4 bis 9,12 und 14 bis zum Ende aus

$ zeilenausg 2-10 test
Gibt Zeile 2-10 aus

$ zeilenausg -20,50- test
Gibt Zeile 1 bis 20 aus und 50 bis Ende

$ zeilenausg test
Gibt alle Zeilen aus

*/


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

#define MAX_LENGTH 4096
#define FM_A_B 1
#define FM_A_ 2
#define FM__A 3
#define FM_A 4
#define FM_ERROR 5

int comp(const void* z1, const void* z2)
{
        return( *(int *)z1 - *(int *)z2 );
}

void fehl_meldung(const char *fmt, va_list az)
{
    char puffer[MAX_LENGTH];

    vsprintf(puffer, fmt, az);
    fprintf(stderr, "%s", puffer);
}

void error(const char *fmt, ...)
{
    va_list az;

    va_start(az, fmt);
    fehl_meldung(fmt, az);
    va_end(az);
    exit(1);
}


void print_lines(const char* filename, size_t len, int* lines, int eof)
{
        char buffer[MAX_LENGTH];
        FILE* file;
        int counter=0, current=0;

        if (NULL==(file = fopen(filename, "r")))
        {
                free(lines);
                error("File '%s' cannot be opened\n", filename);
        }


        while(fgets(buffer, MAX_LENGTH, file) && ++current)
        {
                //printf("Printing counter=%d %s", counter, buffer);
                if(counter<len) {
                        /* man kann in lines lesen */
                        if(lines[counter]!=current)
                                buffer[0]=0;
                        else counter++;

                }  else if(!eof) buffer[0]=0;

                printf("%s", buffer);
        }

}

int type(const char* arg, int* x, int* y)
{
        if (sscanf(arg, "%d-%d", x, y)==2) return FM_A_B;
        if (sscanf(arg, "%d-", x)==1 && arg[strlen(arg)-1]=='-') return FM_A_;
        if (sscanf(arg, "-%d", x)==1 && arg[0]=='-') return FM__A;
        if (sscanf(arg, "%d", x)==1) return FM_A;

        return FM_ERROR;
}

void prepare_lines(int** lines, int flag, int x, int y, size_t* len, int* eof)
{
        int* tmp;
        if (flag==FM_ERROR) return;
        int bereich; /* anzahl der neue Felder in *lines */
        int i;
        switch(flag)
        {
                case FM_A_B:
                        bereich = abs(x-y)+1;
                        if (y<x) {
                            x ^= y;
                            y ^= x;
                            x ^= y;
                        }
                        break;
                case FM_A_:
                        bereich = 1;
                        *eof |= 1;
                        break;
                case FM__A:
                        bereich = x;
                        x=1;
                        break;
                case FM_A:
                        bereich = 1;
                        break;
                case FM_ERROR:
                default:
                        error("The format is incorrect\n");
        }


        if (!*len)
        {
                /* speicher initialisieren */
                tmp = (int*) malloc(sizeof(int)*bereich);
                if (!tmp) error("Not enough memory\n");


        } else {
                /* speicher vergrößern */
                tmp = *lines;
                realloc(tmp, sizeof(int) * (*len+bereich));
        }

        for(i=0; i<bereich; ++i)
                tmp[*len+i] = x+i;

        *len += bereich;
        *lines = tmp;

}

int parse_argv(int argc, char** argv, int** lines, size_t* len, int* eof)
{
        int x,y,typ;
        char* token;

        if (argc==2) {
                /* Verhalten von cat */
                *len=0;
                *eof=1;
                return 1;
        }

        *len = 0;
        *eof = 0;

        token = strtok(argv[1], ",");

        typ = type(token, &x, &y);
        prepare_lines(lines, typ, x,y,len,eof);

        while (NULL != (token=strtok(NULL, ",")))
        {
                typ = type(token, &x, &y);
                prepare_lines(lines, typ, x,y,len,eof);
        }

        return 2;
}

int main(int argc, char** argv)
{
        int* lines, eof, filename;
        size_t len;

        if (argc==1)
                error("usage: %s [lines] textfile\n\
[line]\t\tThe format of the lines. 3,4-9,12,14- means\n\
\t\trow 3, row 4 to 9, row 12, row 14 to eof. Format -3 means\n\
\t\trow 1 to 3\n"
, argv[0]);


        filename = parse_argv(argc, argv, &lines, &len, &eof);

        /* array sortieren */
        qsort(lines, len, sizeof(int), comp);

        print_lines(argv[filename], len, lines, eof);

        free(lines);


        return 0;
}


--
A! Elbereth Gilthoniel!
silivren penna míriel
o menel aglar elenath,
Gilthoniel, A! Elbereth!

Dieser Post wurde am 08.08.2004 um 20:33 Uhr von Pablo editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
08.08.2004, 20:42 Uhr
Windalf
Der wo fast so viele Posts wie FloSoft...
(Operator)



Zitat:

Ja, ja, ja. Wie gesagt - kein Compiler, keine Testmöglichkeit.


und ich dachte ein Gott bräuchte keinen compiler um korrekten code zu posten
--
...fleißig wie zwei Weißbrote
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
08.08.2004, 21:46 Uhr
mike
Pinguinhüpfer
(Operator)


Ich hab hier auch noch eine Lösung (Lösung aus dem Buch )

C++:
#include   <string.h>
#include   <stdlib.h>
#include   <limits.h>
#include   "eighdr.h"

#define  MAX_ANGABEN   100

struct vonbis {
     long  von;
     long  bis;
};

int
main(int argc, char *argv[])
{
   FILE             *fz;
   char             *zgr, zeile[MAX_ZEICHEN];
   struct vonbis    kdozeil_nr[MAX_ANGABEN];
   int              i=0, j, zeilnr=1;

    /*------ Auswerten der Kommandozeilen-Argumente -------------------------*/
   if (argc!=2 && argc!=3)
      fehler_meld(FATAL, "usage:  %s [zeilenangaben] datei", argv[0]);

   if ( (fz=fopen(argv[argc-1], "r")) == NULL)
      fehler_meld(FATAL, "kann %s nicht eroeffnen", argv[argc-1]);

   if (argc > 2) {
      zgr = strtok(argv[1], ",");
      while (zgr != NULL) {
         if (*zgr == '-') {    /*--- Angabe wie -4           -----*/
            kdozeil_nr[i].von=1;
            if ( (kdozeil_nr[i].bis = labs(strtol(zgr, &zgr, 10))) == 0)
               fehler_meld(FATAL, "Unerlaubte Angabe: %s", zgr);
            if (*zgr != '\0')
               fehler_meld(FATAL, "Unerlaubte Angabe: %s", zgr);

         } else {              /*--- Angabe wie 12 oder 2-5 oder 3- */
            if ( (kdozeil_nr[i].von = strtol(zgr, &zgr, 10)) == 0)
               fehler_meld(FATAL, "Unerlaubte Angabe: %s", zgr);
            if (*zgr != '\0') {
               if (*zgr != '-')
                  fehler_meld(FATAL, "Unerlaubte Angabe: %s", zgr);
               if (*++zgr != '\0') {
                  if ( (kdozeil_nr[i].bis = strtol(zgr, &zgr, 10)) == 0)
                     fehler_meld(FATAL, "Unerlaubte Angabe: %s", zgr);
               } else
                  kdozeil_nr[i].bis = LONG_MAX;
            } else
               kdozeil_nr[i].bis = kdozeil_nr[i].von;
         }
         i++;
         zgr = strtok(NULL, ",");
      }
   } else {
      kdozeil_nr[i].von = 1;
      kdozeil_nr[i].bis = LONG_MAX;
      i++;
   }

    /*------ Ausgeben der entsprechenden Zeilen -----------------------------*/
   while (fgets(zeile, MAX_ZEICHEN, fz) != NULL) {
      for (j=0 ; j<i ; j++)
         if (zeilnr>=kdozeil_nr[j].von && zeilnr<=kdozeil_nr[j].bis) {
            fputs(zeile, stdout);
            break;
         }
      zeilnr++;
   }
   if (ferror(fz))
      fehler_meld(FATAL_SYS, "Fehler beim Lesen aus Datei %s", argv[argc-1]);
      
   fclose(fz);
   exit(0);
}



fehler_meld ist in einer eigenen *.h und entspricht in diesem Fall fprintf(stderr,...)
--

Dieser Post wurde am 08.08.2004 um 21:48 Uhr von mike editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 < [ 2 ] [ 3 ]     [ Rätselecke ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: