2016-09-11 9 views
0

Следующий код должен работать следующим образом: распечатать список файлов в каталоге и распечатать содержимое каждого .c файла. он отлично работает при выполнении в UNIX для того же каталога: ./a.out ./Открытие файла с использованием относительного пути

Однако я не смог заставить его работать ./a.out ../differentDir.

Я знаю, что если абсолютный путь предоставляется в качестве аргумента, я мог бы использовать для этого argv [1]. Однако, когда он предоставляется в виде относительного пути, я теряюсь.

#include <sys/types.h> 

#include <dirent.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <string.h> 

#define BUFFSIZE 32768 

int main(int argc, char **argv) { 

    char buf[BUFFSIZE]; 
    DIR *dp; 
    struct dirent *dirp; 
    char filename[80]; 
    int name_length; 
    FILE *fp; 

    if (argc != 2) { 
     fprintf(stderr, "usage: %s dir_name\n", argv[0]); 
     exit(1); 
    } 

    if ((dp = opendir(argv[1])) == NULL) { 
     fprintf(stderr, "can't open '%s'\n", argv[1]); 
     exit(1); 
    } 

     while ((dirp = readdir(dp)) != NULL){ 
      printf("%s\n", dirp->d_name); 
      memset(filename, '\0', sizeof(filename)); 
      strcpy(filename, dirp->d_name); 
      printf(" ** %s ", filename); 
      name_length = strlen(filename); 
      printf(" name_length=%d \n", name_length); 
      if (findC(filename)) // checking if the file has a .c extension 
      { 
       fp=fopen(filename, "r"); 
       if (fp == NULL) 
        fprintf(stderr, "Can't open .C file!\n"); 
       else 
        {// if the file was opened successfuly: 
         do 
         { 
          fgets(buf,BUFFSIZE,fp); // reading each line until buffer is full or until reaching whitespace 
          buf[strlen(buf)-1]='\0'; // removing the trailing whitespace from the buffer 
          puts(buf); 
         } 
         while (!feof(fp)); 
        printf("\n\n"); 
        fclose(fp); 
        } 
      } 
     } 
    closedir(dp); 
    return(0); 
} 

/*FindC method gets a c-string that represents a file name; returns 1 if the file ends with .C extension, else returns 0*/ 
int findC(char * name) 
{ 
    int len = strlen(name); 
    if (len>=2 && name[len-2]=='.' && tolower(name[len-1])=='c') 
     return 1; 
    return 0; 
} 
+0

Боковые проблемы: 'fgets (buf, BUFFSIZE, fp); buf [strlen (buf) -1] = '\ 0'; 'может привести к неопределенному поведению. 1) проверьте результат 'fgets()' перед использованием 'buf'. 2) Зафиксируйте 'strlen (buf)> 0' перед использованием' buf [strlen (buf) -1] = '\ 0''. (Это редко необходимо, но предотвращает UB). – chux

+0

Спасибо, хорошая точка! Таким образом, было бы лучше: if (fgets (buf, BUFFSIZE, fp)! = NULL) { buf [strlen (buf) -1] = '\ 0'; puts (buf); } – DR29

+0

Код не работает, потому что 'fopen (filename ...' не учитывает 'argv [1]'. – chux

ответ

0

Вы можете использовать realpath(argv1 ...), как в этом примере. realpath вернет абсолютный путь для относительного пути.

#include <stdlib.h> 
#include <stdio.h> 
#include <limits.h> 
int main(int argc, char **argv) { 
    char *path = "../.."; 
    char buff[PATH_MAX + 1]; /* not sure about the "+ 1" */ 
    char *res = realpath(path, buff); 
    if (res) { 
     printf("This source is at %s.\n", buff); 
    } else { 
     perror("realpath"); 
     exit(EXIT_FAILURE); 
    } 
    return 0; 
} 

Чтобы включить желаемое поведение в вашей программе, вы можете использовать realpath в коде:

#include <stdlib.h> 
#include <stdio.h> 
#include <limits.h> 
#include <ctype.h> 
#include <dirent.h> 
#include <string.h> 

#define BUFFSIZE 32768 

int main(int argc, char **argv) { 

    char buf[BUFFSIZE]; 
    DIR *dp; 
    struct dirent *dirp; 
    char filename[80]; 
    int name_length; 
    FILE *fp; 
    char buff[PATH_MAX + 1]; /* not sure about the "+ 1" */ 

    if (argc != 2) { 
     fprintf(stderr, "usage: %s dir_name\n", argv[0]); 
     exit(1); 
    } 
    char *res = realpath(argv[1], buff); 
    if ((dp = opendir(res)) == NULL) { 
     fprintf(stderr, "can't open '%s'\n", argv[1]); 
     exit(1); 
    } 

    while ((dirp = readdir(dp)) != NULL){ 
     printf("%s\n", dirp->d_name); 
     memset(filename, '\0', sizeof(filename)); 
     strcpy(filename, dirp->d_name); 
     printf(" ** %s ", filename); 
     name_length = strlen(filename); 
     printf(" name_length=%d \n", name_length); 
     if (findC(filename)) // checking if the file has a .c extension 
     { 
      fp=fopen(filename, "r"); 
      if (fp == NULL) 
       fprintf(stderr, "Can't open .C file!\n"); 
      else 
      {// if the file was opened successfuly: 
       do 
       { 
        fgets(buf,BUFFSIZE,fp); // reading each line until buffer is full or until reaching whitespace 
        buf[strlen(buf)-1]='\0'; // removing the trailing whitespace from the buffer 
        puts(buf); 
       } 
       while (!feof(fp)); 
       printf("\n\n"); 
       fclose(fp); 
      } 
     } 
    } 
    closedir(dp); 
    return(0); 
} 

/*FindC method gets a c-string that represents a file name; returns 1 if the file ends with .C extension, else returns 0*/ 
int findC(char * name) 
{ 
    int len = strlen(name); 
    if (len>=2 && name[len-2]=='.' && tolower(name[len-1])=='c') 
     return 1; 
    return 0; 
} 
+1

Я не уверен, что с ним не так, но когда я скомпилирую, я получаю «неопределенную ссылку на realpath». – DR29

+0

@ DR29 Это может зависеть от вашей среды и os. Я тестировал его с Ubuntu Linux. Вы включили 'stdlib.h'? –

+1

Да, я это сделал. Я на самом деле пишу его в Windows и пытаюсь запустить код на сервере unix ssh. – DR29

1

При открытии файла для чтения, файл путь к файлу должен быть относительным.

// Form prefix for complete relative file name 
    char filename[MAXPATH]; 
    strcpy(filename, argv[1]); 
    // append '/' if directory path does not end in '/' 
    if (TBD_code(filename)) { 
     strcat(filename, "/"); 
    } 
    char *end = filename[strlen(filename)]; 

    while ((dirp = readdir(dp)) != NULL){ 
     printf("%s\n", dirp->d_name); 
     if (findC(dirp->d_name)) { 
     // append filename to prefix 
     strcpy(end, dirp->d_name); 
     fp=fopen(filename, "r"); 
     ... 
+0

Я выполнил вашу рекомендацию аналогичной версией, однако, когда я запускаю ее по относительному пути, он не может открыть файлы. Выход для $ ./lsc ../dir '**. name_length = 1 .. ** .. name_length = 2 b.html ** b.html name_length = 6 practice.txt ** practice.txt name_length = 12 А.c ** A.c name_length = 3 Невозможно открыть файл .C! ' – DR29

+0

@ DR29 Каково значение' filename', когда 'fp = fopen (имя файла,« r »);' fail? – chux

+0

«../dir/file.txt» - это значение (я добавил оператор puts, чтобы убедиться в этом). – DR29

Смежные вопросы