2014-10-16 60 views
0

我是C編程新手。我做了一個很短的程序來合併文件夾中的所有文件。 該程序運行併產生正確的輸出,但執行後它掛起,我不得不手動殺死它。 任何想法爲什麼?C程序執行後掛起

這裏最重要的功能是scandirappend_to_file

/* 
MERGE: Merges text files. Gives the ability to merge a list of files or all files in a 
directory with specified extension. 
*/ 
#include <stdio.h> 
#include <dirent.h> 
#include <stdbool.h> 
#include <string.h> 
#include <stdlib.h> 

/* Function prototypes */ 
int append_to_file(const char *filename, const char *outfilename); // Appends the contents of filename to outfilename 
int scandir(char dirname[], char const *ext, char outfile[]); // Scans a directory for files of a specific extension and merges them 
bool has_extension(char const *name, char const *ext); 
void usage(); // Prints out usage information (help) to the console 
void path_combine(char *dest, const char *path1, const char *path2); // Combines a directory name and filename to a single filepath 

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

    int i, // Counters 
     nfiles; // Number of files merged 

    if (argc == 4) 
    { 
     nfiles = scandir(argv[1], argv[2], argv[3]);  
     printf("Merged %s files\n", nfiles); 

     return 0; 
    } 
    else 
    { 
     printf("Wrong input, quitting"); 
     return 1; 
    } 

} 

int append_to_file(const char *filename, const char *outfilename) 
{ 
    FILE *infile, *outfile; 
    char ch; 
    infile = fopen(filename, "r"); 
    outfile = fopen(outfilename, "a"); 

    if (infile == NULL) 
    { 
     printf("Input file is empty, skipping...\n"); 
     return 1; 
    } 

    while ((ch = fgetc(infile)) != EOF) 
     fputc(ch, outfile); 

    fclose(infile); 
    fclose(outfile); 

    return 0; 

} 

int scandir(char dirname[], char const *ext, char outfile[]) 
/* Scans a directory and merges all files of given extension */ 
{ 
    DIR *d = NULL; 
    struct dirent *dir = NULL; 
    char filepath[strlen(dirname) + 255]; 
    int i = 0; 

    d = opendir(dirname); 

    if (d) 
    { 
     while ((dir = readdir(d)) != NULL) 
     { 
      if (has_extension(dir->d_name, ext)) 
      { 

       path_combine(filepath, dirname, dir->d_name); 
       printf("%s\n", filepath); 
       append_to_file(filepath, outfile); 
       i++; 
      } 

     } 
     closedir(d); 
    } 
    return i; 
} 


bool has_extension(char const *name, char const *ext) 
{ 
    size_t len = strlen(name); 
    return len > 4 && strcmp(name+len-4, ext) == 0; 
} 


void path_combine(char *dest, const char *path1, const char *path2) 
{ 
    const char *last_char = path1; 
    int append_sep = 0; 
    char sep[] = "/"; 

#ifdef WIN32 
    sep[0] = '\\'; 
#endif 

    /* Find the last character in the first path*/ 
    while(*last_char != '\0') 
     last_char++; 

    /* If the last character is not a seperator, we must add it*/ 
    if (strcmp(last_char, sep) !=0) 
    { 
     append_sep = 1; 
    } 

    strcpy(dest, path1); 
    if (append_sep) 
     strcat(dest, sep); 
    strcat(dest, path2);  

} 


void usage() 
{ 
    printf("\t=================\n"); 
    printf("\t  MERGE\n"); 
    printf("\t=================\n"); 
    printf("Merge two or more text files\n"); 
    printf("Usage:\n"); 
    printf("\tCall merge with a directory name and desired extension:\n"); 
    printf("\tmerge DIRNAME .csv OUTPUTFILE\n\n"); 

}; 
+2

嘗試運行GDB下的程序(調試器)。當你按下control-c時,它會告訴你什麼在運行 – Maz 2014-10-16 14:31:27

+0

啊!我以爲我使用的是調試器('gcc main.c -g -o main'),但我還需要將'-Wall'和'-Werror'標誌放在上面! – jramm 2014-10-16 14:37:24

+1

這不是調試器。調試器是gdb,而不是gcc。 – Maz 2014-10-16 14:38:52

回答

-1

啊。 我還以爲是使用調試器,通過編譯時指定-g

gcc main.c -g -o main.exe 

,但它仍掛。

如果我包含標記-Wall-Werror它很快告訴我,我有一個字符串格式錯誤。

printf("Merged %s files\n", nfiles)需要更改爲printf("Merged %d files\n", nfiles)

用-Wall和-Werror編譯很快指出了這個錯誤。

+0

你應該用'gcc -Wall -g'進行編譯。這產生一個帶有調試信息的可執行文件你應該改進你的程序,直到你沒有任何警告。然後你應該使用'gdb'調試器(或其他的)。 – 2014-10-16 14:40:56

+1

@jramm,這應該是一個評論,而不是一個答案。 – 2014-10-16 14:51:38

+1

我不明白這是怎麼回答我的問題,因爲我確切地回答了什麼是錯的。不過,爲了更加清晰,我編輯了它。 – jramm 2014-10-16 15:40:45

2

當編譯器警告過你(如果你有gcc -Wall -g編譯),下面一行:

printf("Merged %s files\n", nfiles); 

是錯誤的,因爲nfilesint。您可能想要

printf("Merged %d files\n", nfiles); 

閱讀關於undefined behavior。你有一個。請仔細閱讀您正在使用的每項功能的文檔,從printf(3) & fopen(3) & perror(3) & exit(3)。不要忘記處理失敗,例如:

FILE *infile, *outfile; 
char ch; 
infile = fopen(filename, "r"); 
outfile = fopen(outfilename, "a"); 

if (infile == NULL) { 
    printf("failed to open %s (%s), skipping...\n", 
      filename, strerror(errno)); 
    return 1; 
} 
if (outfile == NULL) { 
    perror(outfilename); 
    exit(EXIT_FAILURE); 
} 

瞭解如何使用調試器(gdb)。如果在Linux上,也使用strace(1)valgrind