मैं एक फाइल सिस्टम पेड़ को पार करने की कोशिश कर रहा हूँ। जब मैं एक निश्चित एक्सटेंशन वाली फ़ाइल में आता हूं तो मैं फ़ाइल खोलना चाहता हूं और फिर फ़ाइल में लाइनों की गणना करना चाहता हूं। ऐसा लगता है कि मुझे सेगमेंटेशन गलती मिल रही है, मेरा मानना है कि यह फ़ाइल खोलने के बाद/जब मैं लाइनों को गिनने का प्रयास करता हूं। यह सीजी फॉल्टिंग क्यों है इस पर कोई मदद की सराहना की जाएगी।
संपादित करें: मैंने पुराना कोड हटा दिया है क्योंकि मैंने seg गलती को ठीक कर दिया है। अब मैंने कमांड लाइन पर फीड किए जाने वाले डेटा को बदल दिया है। लेकिन ऐसा लगता है कि या तो फाइलें नहीं खुल रही हैं या यह लाइनों की सही गिनती नहीं कर रही है क्योंकि जब मैं इसे चलाता हूं तो प्रोग्राम हमेशा 0 लाइनें लौटाएगा।
यहाँ अद्यतन कोड है:
#include <unistd.h>
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
const char *get_filename_ext(const char *filename) {
const char *dot = strrchr(filename, '.');
if(!dot || dot == filename) return "";
return dot + 1;
}
int printdir(char *dir, char *targetFileExt, int depth)
{
DIR *dp;
struct dirent *entry;
struct stat statbuf;
int spaces = depth*4;
int totalLines=0;
if((dp = opendir(dir)) == NULL) {
fprintf(stderr,"cannot open directory: %s\n", dir);
return -1;
}
chdir(dir);
while((entry = readdir(dp)) != NULL) {
lstat(entry->d_name,&statbuf);
if(S_ISDIR(statbuf.st_mode)) {
/* Found a directory, but ignore . and .. */
if(strcmp(".",entry->d_name) == 0 || strcmp("..",entry->d_name) == 0){
continue;
}
printf("%*s%s/\n",spaces,"",entry->d_name);
/* Recurse at a new indent level */
totalLines = printdir(entry->d_name, targetFileExt, depth+1);
}
else {
printf("%*s%s\n",spaces,"",entry->d_name);
char *currentFileExt = get_filename_ext(entry->d_name);
if(*currentFileExt == *targetFileExt){
//open the file for reading
FILE *fPtr = fopen(entry->d_name, "r");
//traverse the file
while(!feof(fPtr)){
//if there is a new line character
int temp = fgetc(fPtr);
if(temp=='\n'){
//add a line to the total amount of lines
totalLines++;
}
}
//close the file
fclose(fPtr);
fPtr=NULL;
}
}
}
chdir("..");
closedir(dp);
return totalLines;
}
int main(int argc, char* argv[])
{
char *topdir, pwd[2]=".";
char *ext;
if (argc < 2 || argc > 3)
topdir=pwd;
else if(argc == 2){
topdir=argv[1];
}
else if(argc == 3){
topdir=argv[1];
ext=argv[2];
}
printf("Directory scan of %s\n",topdir);
int lines = printdir(topdir, ext, 0);
printf("You have written %d lines of %s code!\n", lines, ext);
return 0;
}
1 उत्तर
सबसे पहले, फ़ाइल नाम एक्सटेंशन की जांच करें: if(*currentFileExt == *targetFileExt)
केवल एक वर्ण वाले फ़ाइल एक्सटेंशन के लिए काम करेगा। ".com" के लिए खोज करने पर विचार करें, और आप एक ".c" फ़ाइल का सामना करते हैं। get_filename_ext()
डॉट के बाद पहले अक्षर के लिए एक पॉइंटर लौटाएगा। तब आप 'c' == 'c' की तुलना कर रहे होंगे। इसके बजाय strcmp()
का उपयोग करने पर विचार करें, और सुनिश्चित करें कि targetFileExt
में प्रमुख बिंदु नहीं है, क्योंकि आपका कोड इस प्रकार सेट किया गया है।
दूसरा, printdir()
अपने वर्तमान स्वरूप में उपनिर्देशिकाओं से लाइन काउंट जमा नहीं करता है। परिदृश्य पर विचार करें:
- हम .c फ़ाइलें खोज रहे हैं।
- आप जिस निर्देशिका में खोज रहे हैं, उसमें दो उपनिर्देशिकाएँ हैं, A और B, और कुछ नहीं।
- A में 10 LOC .c फ़ाइल है, और B में 20 LOC .c फ़ाइल है।
जब आप कोड चलाते हैं:
- आप
printdir()
कोmain()
से कॉल करते हैं, मान लें कि आपका कोड पहले A से मिलता है - फ़ंक्शन स्वयं को पुनरावर्ती रूप से कॉल करता है और 10 देता है, इसलिए
totalLines
को 10 का मान दिया जाता है। - अगले लूप पुनरावृत्ति पर फ़ंक्शन का सामना B से होता है।
- फ़ंक्शन स्वयं को पुनरावर्ती रूप से कॉल करता है, 20 देता है, इसलिए
totalLines
को 20 का मान दिया जाता है। - आपने पहले लूप पुनरावृत्ति से 10 लाइनें खो दी हैं।
इसे ठीक करने के लिए, आपके पास तीन विकल्प हैं:
फंक्शन सिग्नेचर को इसमें बदलें:
int printdir(char *dir, char *targetFileExt, int depth, int totalLines);
औरint totalLines=0;
को हटा दें। फ़ंक्शन में इसे इस तरह कॉल करें:totalLines = printdir(entry->d_name, targetFileExt, depth+1, totalLines);
इसेmain()
से कॉल करें जो कुललाइन के लिए 0 पास कर रहा है।एक लाइन काउंट वेरिएबल के लिए पॉइंटर को स्वीकार करने के लिए फ़ंक्शन सिग्नेचर में बदलें, और जब आप लाइनों का सामना करते हैं तो इसे बढ़ाएँ। (निहितार्थ। गृहकार्य के रूप में छोड़ दिया गया)
वैश्विक लाइन गणना चर का प्रयोग करें। (निहितार्थ। गृहकार्य के रूप में छोड़ दिया गया)