So im writing a program to open a directory, get all the files inside, and then read the contents of each file. currently i successfully got all the file names in a string array. the print files[] loop shows all the file names, but the loop to check frequency does not read the files correctly. how do i successfully read an array of file names and then scan each of their contents?
//Open Directory
DIR *dr = opendir(path);
struct dirent *de;
if(dr == NULL){
printf("Could not open directory");
return 0 ;
}
const char* files[100];
int buffer=0;
//Read Directory Files
while((de = readdir(dr)) != NULL){
files[buffer] = de->d_name;
buffer++;
}
for(int x = 0; x <= buffer; x++){
printf("%s" , files[x]);
}
closedir(dr);
//Check Frequency
for(int i = 0; i <= buffer; i++){
int ch;
FILE *fp;
fp = fopen(files[i], "r");
if(fp == NULL)
continue;
ch = fgetc(fp);
while(ch != EOF){
ch = tolower(ch);
if(ch>=97 && ch<= 122){
alphabetfreq[ch-97]++;
}
ch = fgetc(fp);
}
fclose(fp);
There are multiple things wrong with the program. But the main reason why it is not reading the files is that you are just passing the file names to fopen(), so it is looking for them in current directory and returning null values. Also you are not handling the null results carefully. And the condition in the loop should x < buffer and not x <= buffer.
#include<stdio.h>
#include<dirent.h>
#include<stdlib.h>
#include<ctype.h>
#include<string.h>
int main()
{
int alphabetfreq[100], i;
for(i = 0; i < 100; i++){
alphabetfreq[i] = 0;
}
char path[] = "/home/path_to_directory/";
DIR *dr = opendir(path);
struct dirent *de;
if(dr == NULL){
printf("Could not open directory");
return 0 ;
}
const char* files[100];
int buffer=0;
//Read Directory Files
while((de = readdir(dr)) != NULL){
files[buffer] = de->d_name;
buffer++;
}
for(int x = 0; x < buffer; x++){
printf("%s" , files[x]);
}
closedir(dr);
printf("\n");
//Check Frequency
for(int i = 0; i < buffer; i++){
int ch;
FILE *fp;
char * file = malloc(strlen(path) + strlen(files[i]) + 1);
strcpy(file, path);
strcat(file, files[i]);
fp = fopen(file, "r");
if(fp == NULL)
{
printf("no file %s\n", file);
continue;
}
ch = fgetc(fp);
while(ch != EOF){
ch = tolower(ch);
if(ch>=97 && ch<= 122){
alphabetfreq[ch-97]++;
}
ch = fgetc(fp);
}
fclose(fp);
}
for(i = 0; i < 26; i++)
{
printf("%c %d\n", i+97, alphabetfreq[i]);
}
}
This is working for me.
Related
I have csv file with below format :
name,birthmonth,country,hobby
jack,jan,england,soccer
roben,july,germany,soccer
emma,dec,china,tennis
yannick,sep,france,music
alex,nov,england,cricket
thomas,apr,germany,tennis
mike,oct,netherlands,cycling
michelle,feb,france,poetry
yui,mar,japan,coding
feng,jun,china,reading
I want to parse this file using C, and put all the lines with same country name in a consecutive manner i.e shown below:
name,birthmonth,country,hobby
jack,jan,england,soccer
alex,nov,england,cricket
roben,july,germany,soccer
thomas,apr,germany,tennis
emma,dec,china,tennis
feng,jun,china,reading
yannick,sep,france,music
michelle,feb,france,poetry
mike,oct,netherlands,cycling
yui,mar,japan,coding
So far, I have tried this code below, however not able to match things properly and proceed further:
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<fcntl.h>
#include<string.h>
int main (int argc, char **argv) {
//int line;
char line[200];
char *inputFile = argv[1];
FILE *input_csv_file;
char a,b,c,d,e;
input_csv_file = fopen(inputFile, "rt");
if(input_csv_file ==0) {
printf("Can not open input file \n");
}
else {
//while((line = fgetc(input_csv_file)) != EOF) {
while(fgets(line, sizeof line, input_csv_file) != NULL) {
printf ("line = %s\n", line);
if(sscanf(line, "%s,%s,%s,%s,%s", a,b,c,d,e)) {
//if(sscanf(line, "%[^,], %[^,], %[^,], %[^,], %[^,]", a,b,c,d,e)) {
printf("d=%s\n",d);
}
}
}
return 0;
}
I am a newbie in C/C++. Any help would be much appreciated
Thanks.
I could write the code to get the required output. Below is the code:
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<fcntl.h>
#include<string.h>
int main(int argc, char ** argv)
{
struct filedata {
char nation[8];
char content[50];
};
char line[100];
char *inputFile = argv[1];
FILE *input_csv_file;
int iter = 0, c;
char * tok;
int count = 0;
char ch;
char country[] = "country";
char header_line[50];
input_csv_file = fopen(inputFile, "rt");
//count line numbers of the input csv
for(ch = getc(input_csv_file); ch!= EOF; ch=getc(input_csv_file))
if(ch == '\n')
count = count + 1;
fclose(input_csv_file);
count = count -1;
struct filedata * record[count];
input_csv_file = fopen(inputFile, "rt");
if(input_csv_file == 0)
{
printf("Can not open input file\n");
} else
{
while(fgets(line, sizeof line, input_csv_file) != NULL)
{
//printf("-- line = %s\n", line);
int s_line = sizeof line;
char dup_line[s_line];
strcpy(dup_line, line);
int h = 0;
int s_token;
tok = strtok(line, ",");
while(tok != NULL)
{
h++;
if(h == 3)
{
s_token = sizeof tok;
break;
}
tok = strtok(NULL, ",");
}
// skipping the line having column headers
if(compare_col(tok, country) == 0) {
strcpy(header_line, dup_line);
continue;
}
iter++;
c = iter - 1;
record[c] = (struct filedata*)malloc(sizeof(struct filedata));
strcpy(record[c]->nation, tok);
strcpy(record[c]->content, dup_line);
} //while
struct filedata * temp;
FILE * fptr;
fptr = fopen("nation_csv.txt", "w");
if(fptr == NULL)
{
printf("Error in opening the file to write\n");
exit(1);
}
// sorting the arr of struct nation wise
for(iter=1; iter < count; iter++)
for(c =0 ; c < count -1; c++) {
if(strcmp(record[c]->nation, record[c+1]->nation) > 0) {
temp = record[c];
record[c] = record[c+1];
record[c+1] = temp;
}
}
for(iter=0; iter < count; ++iter)
{
if(iter == 0) {
fprintf(fptr, "%s", header_line);
continue;
}
fprintf(fptr, "%s", record[iter]->content);
}
fclose(fptr);
}
fclose(input_csv_file);
}
int compare_col(char a[], char b[] )
{
int c = 0;
while(a[c] == b[c]) {
if(a[c] == '\0' || b[c] == '\0')
break;
c++;
}
if(a[c] == '\0' && b[c] == '\0')
return 0;
else
return -1;
}
Thanks for all your inputs. Any further inputs to make it better are much appreciated.
Thanks
I need to create a function that finds the most common letter in a file using C.
Can't figure out my problem, for some reason it always returns [.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
char commonestLetter(char* filename);
void main()
{
char str[101], ch;
FILE *fout;
fout = fopen("text.txt", "w");
if (fout == NULL)
{
printf("Can't open file\nIt's probably your fault, worked perfectly on my PC ;)\n");
fclose(fout);
}
printf("Enter string (to be written on file)\n");
gets(str);
fputs(str, fout);
ch = commonestLetter("text.txt");
printf("The most common letter is %c\n", ch);
fclose(fout);
}
char commonestLetter(char* filename)
{
char ch;
int i, count[26];
int max = 0, location;
FILE *f = fopen(filename, "r");
if (f == NULL)
{
printf("file is not open\n");
return;
}
for (i = 0; i < 26; i++)
count[i] = 0;
while ((ch = fgetc(f)) != EOF)
{
if (isalpha(ch))
count[toupper(ch) - 'A']++;
}
for (i = 0; i < 26; i++)
{
if (count[i] >= max)
{
max = count[i];
location = i + 1;
}
}
return location + 'A';
}
Do
location=i;
No need of i+1
As you are doing location+'A';
Suppose the location count[25] has the highest count, so the location becomes 25+1=26.
Now the return will be 26+65=91 which is of '['
The code of yours is slightly modified but the logic of your is kept
#include <stdio.h>
#include <string.h>
#include <ctype.h>
char commonestLetter(char* filename);
int main()
{
char str[101], ch;
FILE *fout;
fout = fopen("text.txt", "w");
if (fout == NULL)
{
printf("Can't open file\nIt's probably your fault, worked perfectly on my PC ;)\n");
return 0;
}
printf("Enter string (to be written on file): ");
fgets(str,sizeof(str),stdin);
fputs(str, fout);
fclose(fout);
ch = commonestLetter("text.txt");
printf("The most common letter is %c\n", ch);
return 0;
}
char commonestLetter(char* filename)
{
char ch;
int i, count[26];
int max = 0, location;
FILE *f = fopen(filename, "r");
if (f == NULL)
{
printf("file is not open\n");
return;
}
memset(&count,0,sizeof(count));
while ((ch = fgetc(f)) != EOF)
{
if (isalpha(ch))
count[toupper(ch) - 'A']++;
}
for (i = 0; i < 26; i++)
{
if (count[i] >= max)
{
max = count[i];
location = i;
}
}
fclose(f);
return location + 'A';
}
Input & Output:
Enter string (to be written on file): Gil this is a testing
The most common letter is I
The problem here is, in your code,
location = i + 1;
location is i+1 at the end, and you're returning location + 'A'; which is (because of your input, probably) (25+1) + 'A' , i.e., 26 + 'A' which is [.
In matlab we can do it using the code :
a= csvread('filename.csv');
But using C programming i used the following code but it doesnt works please help :
int main(){
int i,j,temp,m1=0,n=0;
//CSV file reading
int ch;
FILE *fp;
fp = fopen("filename.csv","r"); // read mode
if( fp == NULL )
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
while( ( ch = fgetc(fp) ) != EOF )
{printf("%d",ch);}
fclose(fp);
return 0;
}
mat[i][j] = ch;
int m1 = i;
int n = j;
}
Please help !
Ok this hasn't been extensively tested but it should read a csv file that has integer values and store them in an (n x m) matrix.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv){
//CSV file reading
int rowMaxIndex,columnMaxIndex;
int **mat;
int *matc;
int i,j,idx;
char part[1024];
char *token;
FILE *fp;
fp = fopen("filename.csv","r"); // read mode
if(fp == NULL){
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
// count loop
rowMaxIndex = 0;
columnMaxIndex = 0;
while(fgets(part,1024,fp) != NULL){
token = NULL;
while((token = strtok((token == NULL)?part:NULL,",")) != NULL){
if(rowMaxIndex == 0){ // only want to increment column count on first loop
columnMaxIndex++;
}
for(idx = 0;idx<strlen(token);idx++){
if(token[idx] == '\n'){ // this assumes there will be a \n (LF) at the end of the line
rowMaxIndex++;
break;
}
}
}
}
// allocate the matrix
matc = malloc(rowMaxIndex*columnMaxIndex*sizeof(int));
mat = malloc(rowMaxIndex*sizeof(int*));
for(idx = 0;idx<rowMaxIndex;idx++){
mat[idx] = matc+idx*columnMaxIndex;
}
// rewind the file to the beginning
rewind(fp);
// read loop
i = j = 0;
while(fgets(part,1024,fp) != NULL){
token = NULL;
while((token = strtok((token == NULL)?part:NULL,",")) != NULL){
mat[i][j] = atoi(token);
j = (j+1)%columnMaxIndex;
}
i++;
}
fclose(fp);
return 0;
}
This is part of the program I am working on, it is copying the file opened and then put it into an array (file1). However, I am getting a segmentation fault when I try to print out the content of the file1.
I had tried to set the MAX_MAC_ADD to 50 and BIG_NUM to 30000 such that it is big enough to sustain the file from fgets().
The file which I am opening has 4 parts, each separate by a 'tab'
e.g. 1one 1two 1three 1four
2one 2two 2three 2four
char file1[MAX_MAC_ADD][BIG_NUM];
int num_MAC = 0;
char *Programe_Name;
int saperate_fields1(char line[])
{
int i = 0;
int f = 0;
while(line[i] != '\0' && line[i] != '\n')
{
int c = 0;
while(line[i] != '\t' && line[i] != '\0' && line[i] != '\n')
{
file1[f][c] = line[i];
++c;
++i;
}
file1[f][c] = '\0';
++f;
if(f == (MAX_MAC_ADD-1))
{
break;
}
++i;
}
return f,i;
}
void read_file1(char filename[])
{
//OPEN FOR READING
FILE *fp = fopen(filename,"r");
if(fp == NULL)
{
printf("%s: cannot open '%s'\n", Programe_Name, filename);
exit(EXIT_FAILURE);
}
char line[BUFSIZ];
while(fgets(line, sizeof line, fp) != NULL)
{
saperate_fields1(line); //SAPERATE INTO FIELDS
num_MAC = num_MAC + 1;
printf("%d times\n", num_MAC);
}
fclose(fp);
printf("line is:\n%s\n", line); //TO CHECK WHERE DO THE PROGRAM STOP READING
printf("file1 is:\n%s\n", file1);
}
You pass a pointer to an array of chars to the format specifier %s which expects a pointer to a char. If you want to print your array of arrays of char you need to print the elements individually, e.g.:
for (int i = 0; i != end; ++i) {
printf("file1[%d]='%s'\n", i, file1[i]);
}
This code opens a directory, and for every file in the directory it loops through every line of data inside the file, and then parses it to do some calculations and outputs the resulting data into a new file.
The problem is that I can only output a maximum of around 1021 files. I'm closing all of the fopens after outputting all the data, so I'm not sure what I'm doing wrong.
Shouldn't fclose() be closing the open files therefore this not happening?
int main(int argc, char *argv[])
{
//sample data values
double lat;
double lon;
double convergence;
double pt_scale;
int zone = 54;
double major_axis = 6378137.0000;
double flattening = (1/298.2572);
double zoneWidth = 6;
double centMeridian = -177;
double falseEast = FALSE_EASTING;
double falseNorth = FALSE_NORTHING;
double scale = SCALE_FACTOR;
int max_size = 128;
int current_size = max_size;
char *pathStr = malloc(max_size);
char *outPathStr = malloc(max_size);
char coData[100]; //max length of line;
long firstTerm, secondTerm; //terms we will split the line into, lat, lon, elevation.
int counter = 0; //pos counter
int d = EOF; //end of file ASCII
char strIn[200];
char* elevation;
char strOut[200];
char dirOut[200]; //sprintf must use a actual defined buffer otherwise there will be a buffer overflow.
char* cchr;
int j;
_setmaxstdio(2048);
printf("Please enter the path of the files: \n");
getUserInput(pathStr, current_size, max_size);
printf("Please enter the output path of the files: \n");
getUserInput(outPathStr, current_size, max_size);
//loop through each file in the directory. Open the file, convert, then close it.
//we will use dirent.h as it is cross platform so we wont have to worry about sharing issues
DIR *dir; //new directory
struct dirent *ent;
dir = opendir(pathStr); //allcate it a path
if(opendir(pathStr) == NULL)
{ printf("Error: %d (%s)\n", errno, strerror(errno));}
int k;
if(dir != NULL)
{
while((ent = readdir(dir)) != NULL) //loop through each file in the directory.
{
//open the file and loop through each line converting it then outputing it into a new file
if((!strcmp(ent->d_name,"..") || !strcmp(ent->d_name,".")) == 1)
{
//dont want these directories
continue;
}
else
{
sprintf(strIn,"%s%s",pathStr,ent->d_name); //get the file n
FILE *fp = fopen(strIn, "r");
if(fopen(strIn, "r") == NULL) //for inputting file
{ printf("Error: %d (%s)\n", errno, strerror(errno));
getchar();
break; }
sprintf(dirOut,"%s%d%s",outPathStr,counter,".geo");
printf("%s \n",dirOut);
FILE *fp2 = fopen(dirOut, "w"); //for outputting file
if(fopen(dirOut, "w") == NULL)
{ printf("Error: %d (%s)\n", errno, strerror(errno));
getchar();
break; }
while(fgets(coData, 100, fp) != NULL)//loop through line by line, allocate into 2 doubles and a string, pass the two coordinates and convert
{
//extract terms from coData
char * pch; //pointer to array pos
char * pend;
pch = strtok(coData," ");
j = 0;
while(j <= 2) //We only want to split the first three parameters.
{
//convert char array to double for co-oridinate conversion
if(j == 0)
{
firstTerm = atof(pch); //latitude;
j++;
continue;
}
if(j == 1)
{
pch = strtok(NULL, " ");
secondTerm = atof(pch); //longitude
j++;
continue;
}
if(j == 2)
{
pch = strtok(NULL," ");
elevation = pch; //elevation doesnt need to be converted because it isnt used in the coordinate conversion.
break;
}
}
grid2spheroid(&lat,&lon,&convergence,&pt_scale,firstTerm,secondTerm,zone,0, major_axis,flattening,zoneWidth,centMeridian,falseEast,falseNorth,scale);
sprintf(strOut,"%f %f %s",lat,lon,elevation);
//printf("%d %d", lat, lon);
fputs(strOut,fp2);
} //end of while
fclose(fp2);
fclose(fp);
counter++;
}
}
closedir(dir);
}
free(pathStr); //finished using the path string so we can finish the
free(outPathStr);
getchar();
return 0;
}
void getUserInput(char *pathStr, int current_size, int max_size)
{
unsigned int i = 0;
if(pathStr != NULL)
{
int c = EOF;
//get the user input and reallocate the memory size if the input it too large.
while((c = getchar()) != '\n' && c != EOF) //WHILE NOT END OF FILE OR NEW LINE (USER PRESSED ENTER)
{
pathStr[i++] = (char)c;
if(i == current_size)
{
current_size = i+max_size;
pathStr = realloc(pathStr, current_size);
}
}
}
}
You aren't closing all the files ;-)
FILE *fp = fopen(strIn, "r");
if(fopen(strIn, "r") == NULL) //for inputting file
Same applies to your output.
I think you meant something more like:
FILE *fp = fopen(strIn, "r");
if(fp == NULL) //for inputting file
{
// error handling.
No, no! You're opening every file twice (and only closing once)!
/* Bad! */
dir = opendir(pathStr); //allcate it a path
if(opendir(pathStr) == NULL)
{ printf("Error: %d (%s)\n", errno, strerror(errno));}
int k;
/* Correct */
dir = opendir(pathStr); //allocate it a path
if(!dir) {
printf("Error: %d (%s)\n", errno, strerror(errno));
return;
}
You're also doing the same thing with fopen(). In both places :)
Just check the pointer; don't call "fopen()" a second time; don't call "opendir()" a second time!
Also: please don't put code on the same line as your opening brace. OK?
dir = opendir(pathStr); //allcate it a path
if(opendir(pathStr) == NULL)
(...)
FILE *fp2 = fopen(dirOut, "w"); //for outputting file
if(fopen(dirOut, "w") == NULL)
(...)
FILE *fp = fopen(strIn, "r");
if(fopen(strIn, "r") == NULL) //for inputting file
Here you open the file twice but only store the pointer once. Change these to:
FILE *fp = fopen(strIn, "r");
if(fp == NULL) //for inputting file
and the other one in the same way.