Programeer opdrachtenOpdracht : opdr3_marvin.txt

Terug naar de inzendingen
Opdracht 3,Marvin Raaijmakers
23 Feb 2005
 Zo die van mij is ook weer klaar: http://linux-box.nl/~marvin/src/foto's/
 1 
*****rename_pictures.h*****
  
 2/*-------------------------------------------------------------------------------------
 3Name               : rename_pictures.h
 4Author             : Marvin Raaijmakers
 5Description        : Header file for rename_pictures
 6Date of last change: 24-January-2005
 7
 8    Copyright (C) 2005 Marvin Raaijmakers
 9
 10    This program is free software; you can redistribute it and/or modify
 11    it under the terms of the GNU General Public License as published by
 12    the Free Software Foundation; either version 2 of the License, or
 13    any later version.
 14
 15    This program is distributed in the hope that it will be useful,
 16    but WITHOUT ANY WARRANTY; without even the implied warranty of
 17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 18    GNU General Public License for more details.
 19
 20    You should have received a copy of the GNU General Public License
 21    along with this program; if not, write to the Free Software
 22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 23
 24    You can contact me at: marvin_raaijmakers(at)linux-box(dot)nl
 25    (replace (at) by @ and (dot) by .)
 26---------------------------------------------------------------------------------------*/
 27#define RENAME_PREFIX   ("foto")
 28#define CAMERA_PREFIX   ("IMG_")
 29
 30#define NUM_EXTENSIONS  (3)
 31#define MIN_DIGITS      (4)
 32#ifdef INT_MAX /* If limits.h was not included */
 33#       ifndef NAME_MAX /* If the maximum lenght of a file name was not
 34#       defined */
 35#               define NAME_MAX (200)
 36#       endif
 37#endif
 38
 39#define ACCESS_OK       (0)
 40#define RENAME_OK       (0)
 41#define EQUAL           (0)
 42
 43typedef int Boolean;
 44
 45#define TRUE    (1)
 46#define FALSE   (0)
 1 
*****rename_pictures.c*****
  
 2/*-------------------------------------------------------------------------------------
 3Name               : rename_pictures.c
 4Author             : Marvin Raaijmakers
 5Description        : Renames pictures in the current directory according to
 6the
 7                     specifications you can find at:
 8                     http://pascal.nedlinux.nl/cgi-bin/opdrachten.pl?opdracht=opdr3.txt
 9Date of last change: 24-January-2005
 10
 11    Copyright (C) 2005 Marvin Raaijmakers
 12
 13    This program is free software; you can redistribute it and/or modify
 14    it under the terms of the GNU General Public License as published by
 15    the Free Software Foundation; either version 2 of the License, or
 16    any later version.
 17
 18    This program is distributed in the hope that it will be useful,
 19    but WITHOUT ANY WARRANTY; without even the implied warranty of
 20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 21    GNU General Public License for more details.
 22
 23    You should have received a copy of the GNU General Public License
 24    along with this program; if not, write to the Free Software
 25    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 26
 27    You can contact me at: marvin_raaijmakers(at)linux-box(dot)nl
 28    (replace (at) by @ and (dot) by .)
 29---------------------------------------------------------------------------------------*/
 30#include 
 31#include 
 32#include 
 33#include 
 34#include 
 35#include 
 36#include 
 37#include 
 38
 39#include 
 40
 41
 42static const char *extensions[NUM_EXTENSIONS] = {"png", "jpg", "gif"};
 43
 44
 45char
 46*get_extension (char *file_name)
 47/*
 48Input:
 49        file_name       - The file name to check
 50Output:
 51        -
 52Global:
 53        extensions
 54Returns:
 55        The pointer to the extension if file_name's extension is correct,
 56otherwise NULL.
 57Description:
 58        This function checks the if the extension of file_name matches one of
 59the strings
 60        in the global array extensions. If it does, a pointer to the string
 61(located in
 62        extensions) will be returned, otherwise it returns NULL. This
 63functions ignores
 64        the case of the characters in the extension.
 65*/
 66{
 67        int count;
 68        char *ext;
 69        
 70        /* The extension occurs after the last occurrence of '.' in the file
 71 * name */
 72        ext = strrchr(file_name, '.');
 73        if (ext != NULL) /* If a extension ('.' actually) was found */
 74        {
 75                ext++;
 76                for (count = 0; count < NUM_EXTENSIONS; count++)
 77                {
 78                        /* If we found a matching extension */
 79                        if ( strcasecmp(ext, extensions[count]) == EQUAL )
 80                        {
 81                                ext = extensions[count];
 82                                break;
 83                        }
 84                }
 85                if (ext != extensions[count])
 86                {
 87                        ext = NULL;
 88                }
 89        }
 90        return (ext);
 91}
 92
 93
 94Boolean
 95check_name (    char    *file_name,
 96                char    *prefix      )
 97/*
 98Input:
 99        file_name       - The file name to check
 100        prefix          - A correct file name should start with this.
 101Output:
 102        -
 103Returns:
 104        TRUE if file_name is correct, otherwise FALSE.
 105Description:
 106        This function checks the correctness of file_name, according to the
 107following syntax:
 108        prefixX.ext
 109        where X should be at least MIN_DIGITS digits an ext is one of the
 110possible extensions
 111        in the global array extension.
 112*/
 113{
 114        int count, prefix_len;
 115        
 116        prefix_len = strlen(prefix);
 117        if (strncmp(prefix, file_name, prefix_len) != EQUAL)
 118        {
 119                return (FALSE);
 120        }
 121        for (count = prefix_len; file_name[count] != '.' && file_name[count]
 122!= '\0'; count++)
 123        {
 124                if ( !isdigit(file_name[count]) )
 125                {
 126                        return (FALSE);
 127                }
 128        }
 129        if (count < MIN_DIGITS || !(file_name[count] == '.' &&
 130get_extension(file_name) != NULL))
 131        {
 132                return (FALSE);
 133        }
 134        return (TRUE);
 135}
 136
 137
 138Boolean
 139file_ok (struct dirent *file)
 140/*
 141Input:
 142        file    - This file will be checked whether it should be renamed.
 143Output:
 144        -
 145Returns:
 146        TRUE if file should be renamed, otherwise FALSE.
 147Description:
 148        This function checks if file should be renamed.
 149*/
 150{
 151        /* If the file is a regular file,
 152         * not a already renamed file,
 153         * not a camera file
 154         * and the extension is ok
 155         */
 156        if ( file->d_type == DT_REG &&                          /* If the file
 157is a regular file,       */
 158             !check_name(file->d_name, RENAME_PREFIX) &&        /* not a
 159already renamed file,          */
 160             !check_name(file->d_name, CAMERA_PREFIX) &&        /* not a
 161camera file                    */
 162             get_extension(file->d_name) != NULL )              /* and the
 163extension is ok.             */
 164        {
 165                return (TRUE);
 166        }
 167        return (FALSE);
 168}
 169
 170
 171void
 172create_file_name (      char    *new_name,
 173                        char    *prefix,
 174                        int     index,
 175                        char    *extension  )
 176{
 177        snprintf (new_name, NAME_MAX, "%s%.*d.%s", prefix, MIN_DIGITS, index,
 178extension);
 179}
 180
 181
 182Boolean
 183file_exists (int index)
 184/*
 185Input:
 186        index           - The index of the renamed file to check
 187Output:
 188        -
 189Globals:
 190        extensions      - All possible extensions for a renamed file
 191Returns:
 192        TRUE if a renamed file with index index exists, otherwise FALSE.
 193Description:
 194        This function checkes if a renamed file with index index exists.
 195*/
 196{
 197        int count;
 198        char file_name[NAME_MAX];
 199        
 200        /* For every extension */
 201        for (count = 0; count < NUM_EXTENSIONS; count++)
 202        {
 203                /* OK, doing this for every extension is a litlle ineffecient
 204 * */
 205                create_file_name (file_name, RENAME_PREFIX, index,
 206extensions[count]);
 207                if ( access(file_name, F_OK) == ACCESS_OK ) /* If the file
 208exists */
 209                {
 210                        return (TRUE);
 211                }
 212        }
 213        return (FALSE);
 214}
 215
 216
 217void
 218rename_files (  struct dirent   **file_list,
 219                int             num_files    )
 220/*
 221Input:
 222        file_list       - The list of files to rename
 223        num_files       - The number of files to rename
 224Output:
 225        -
 226Returns:
 227        -
 228Description:
 229        This function renames all files in file_list. A new file name will
 230look like:
 231        .
 232         consists of, at least, NUM_DIGITS digits.  will be
 233the same
 234        as the original one.
 235*/
 236{
 237        int count, index;
 238        char new_file_name[NAME_MAX];
 239        
 240        index = 0;
 241        /* For every file to rename */
 242        for (count = 0; count < num_files; count++)
 243        {
 244                while ( file_exists(index) )
 245                {
 246                        index++;
 247                }
 248                create_file_name (new_file_name, RENAME_PREFIX, index,
 249get_extension(file_list[count]->d_name));
 250                /*printf ("%s > %s\n", file_list[count]->d_name,
 251 * new_file_name);*/
 252                if (  rename(file_list[count]->d_name, new_file_name) !=
 253RENAME_OK ) /* If renaming failed */
 254                {
 255                        /* If access to the file was denied */
 256                        if ( access(file_list[count]->d_name, W_OK) !=
 257ACCESS_OK )
 258                        {
 259                                printf ("Permission denied: Could not rename
 260'%s' to '%s'.\n",
 261                                        file_list[count]->d_name,
 262new_file_name);
 263                        }
 264                        else
 265                        {
 266                                printf ("Rename error: Could not rename '%s'
 267to '%s' for an unknown reason.\n",
 268                                        file_list[count]->d_name,
 269new_file_name);
 270                        }
 271                }
 272        }
 273}
 274
 275
 276int
 277main (void)
 278{
 279        int num_files;
 280        struct dirent **file_list;
 281        
 282        /* Get the files in the current directory to rename */
 283        num_files = scandir ("./", &file_list, file_ok, alphasort);
 284        rename_files (file_list, num_files);
 285        exit (0);
 286}
 
 
Mijn commentaar
 
 Wat in deze wederom voortreffelijk verzorgde inzending meteen opvalt,
 is de voor deze opdracht wel heel ongebruikelijke keuze van de taal C.
 Uit diverse opmerkingen in de opdracht viel wel op te maken dat een scripttaal
 in de lijn der verwachtingen lag.
 Ik vermoed een klein bugje in je programma.
 Ik ben er n.l. niet helemaal zeker van wat er gebeurd als je het herhaaldelijk
 uitvoerd waarbij je tussendoor bestanden met lagere nummers verwijderd.
 Het kost me nu gewoon ff teveel tijd om dat te controleren.
 Ik ben verder heel tevreden over je werkwijze.
 Een opmerking echter.
 De taal C is niet heilig Marvin, er zijn er meerdere.
 Soms zijn andere talen gewoon praktischer voor een opdracht.