1. Homepage of Dr. Zoltán Porkoláb
    1. Home
    2. Archive
  2. Teaching
    1. Timetable
    2. Bolyai College
    3. C++ (for mathematicians)
    4. Imperative programming (BSc)
    5. Multiparadigm programming (MSc)
    6. Programming (MSc Aut. Sys.)
    7. Programming languages (PhD)
    8. Software technology lab
    9. Theses proposals (BSc and MSc)
  3. Research
    1. Sustrainability
    2. CodeChecker
    3. CodeCompass
    4. Templight
    5. Projects
    6. Conferences
    7. Publications
    8. PhD students
  4. Affiliations
    1. Dept. of Programming Languages and Compilers
    2. Ericsson Hungary Ltd

A 2020.12.16-i ZH megoldása

A feladat

A reverse parancs megvalósítása.

Ebben a feladatban megvalósítjuk a reverse parancsot: az argumentumként kapott fájlok tartalmát sorszámozva, fordított sorrendben, és a sorokat meg- fordítva (tükrözve) írjuk ki a standard outputra. Pl. ha a test.txt tartalma a következő:

alma
barack
szilva

. . . akkor a reverse parancs eredménye a következő:

3 avlizs
2 kcarab
1 amla

A megoldáshoz feltesszük, hogy bármely fájl teljes egészében elfér a memóriában. (Megjegyzés: a feladat alapja a rev Unix utility, amely a kapott bemenet(ek) tartalmát eredeti sorrendben, de sorszámozás nélkül és a sorokat megfordítva írja ki.)

A megoldás

A reverse.h fejlécállomány:

1
2
3
4
5
6
#ifndef REVERSE_H
#define REVERSE_H

void reverse( FILE *fp, char *name);

#endif /* REVERSE_H */

A main.c forrás:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
#include "reverse.h"

int main( int argc, char *argv[])
{
  if ( argc < 2 )
  {
    reverse( stdin, "stdin"); /* stdin */	  
  }
  else
  {
    int i;
    for ( i = 1; i < argc; ++i )  /* fájlnevek */	  
    {
      FILE *fp = fopen( argv[i], "r");
      if ( NULL != fp )
      {
         reverse( fp, argv[i]); /* fp-ről olvas */
         fclose(fp);
      }
      else
      {
        fprintf(stderr,"Can't open %s for read\n",argv[i]);	      
      }
    }
  }
  return 0;
}

A reverse.c forrás:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "reverse.h"

#define INITCAP 4     /* kezdeti pointer-tömb kapacitás */
#define BUFSIZE 1024  /* maximális sorhossz */

char **read( FILE *fp, int *pLines);
void   write( char **lines, int nLines, char *name);
void   revline( char *line);
void   allocfail( void *ptr);

/* egy fájl megfordítása */
void reverse( FILE *fp, char *name)
{
  int nLines = 0;
  char **lines = read( fp, &nLines);	
  write( lines, nLines, name); 
}

/* beolvas egy fájlt, a sorokat eltárolja a heap-ben    */
/* beírja a sorok számát a pLines által mutatott helyre */
/* visszaadja a sorok-ra mutató pointer tömb pointerét  */       
char **read( FILE *fp, int *pLines)
{
  int  capacity = INITCAP;   /* pointer-tümb kapacitása */
  int  nLines   = 0;         /* tényleges sorok száma   */
  char buffer[BUFSIZE]; /* buffer a sorok beolvasásához */

  /* kezdeti helyfoglalás */
  char **lines = (char **)malloc(capacity * sizeof(char*));
  allocfail(lines);
  while ( NULL != fgets(buffer, BUFSIZE, fp) ) /* sorok */
  {
    int len = strlen(buffer);    /* hány karakter a sor */
    if ( '\n' == buffer[len-1] )  /* '\n'-re végződott? */
    {
      buffer[len-1] = '\0';     /* sorvégi '\n' törlése */
    }
    if ( nLines == capacity )   /* teli a buffer? */
    {
      capacity *= 2;         /* duplájára növeljük */
      lines = realloc( lines, capacity * sizeof(char *));
      allocfail(lines);
    }
    lines[nLines] = (char *) malloc(len+1);    
    allocfail(lines[nLines]);
    strcpy( lines[nLines], buffer);      /* eltároljuk */
    ++nLines;
  }
  *pLines = nLines;  
  return lines;
}

/* Kiírja a fájlt az utolsó sortól kezdve visszafelé */
/* az egyes sorokat is visszafelé írja ki            */
void   write( char **lines, int nLines, char *name)
{
  int i;
  for ( i = nLines-1; i >= 0; --i)  /* sorok */
  {
    char *curr = lines[i];
    fprintf( stdout, "%s %d: ", name, i);
    revline(curr); 
    free( curr);
  }
  free(lines);
}

/* Egy sor kiírása visszafelé */
void revline( char *line)
{
  int len = strlen(line);	  
  while ( --len >= 0 )
  {
    fputc( line[len], stdout);	    
  }
  fputc( '\n', stdout);
}

/* Ha nincs elég memória, befejezzük a programot */
void allocfail( void *ptr)
{
  if ( NULL == ptr )
  {
    fprintf( stderr, "Out of memory\n");
    exit(1);    
  }	  
}