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 [.
Related
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char file(FILE *fh, char c[45]);
int lejiko(FILE *lh);
void split(FILE *fh);
int main() {
int choice;
char c[45];
FILE *fh;
FILE *lh;
file(fh, c);
lejiko(lh);
split(fh);
return 0;
}
char file(FILE *fh, char c[45]){
fh = fopen("test.txt", "r");
if (fh != NULL) {
printf("Loaded File");
/* while ((c = fgetc(fh)) != EOF)
putchar(c); */
} else
printf("ERROR");
fclose(fh);
return c;
}
int lejiko(FILE *lh) {
int count = 0;
char t;
lh = fopen("englishWords.txt", "a+");
if (lh != NULL) {
printf("\nLoaded Dictionary");
}
for (t = getc(lh); t != EOF; t = getc(lh))
if (t == '\n')
count = count + 1;
printf("\nYparxoun %d lejeis sto lejiko.\n", count);
return count;
}
void split(FILE *fh) {
char array[45];
char *spl;
fh = fopen("test.txt", "r");
if (fh == NULL)
perror("Error opening file");
else {
while (fgets(array, 45, fh) != NULL) {
printf("%s\n", array);
spl = strtok(array, " ");
while (spl != NULL) {
printf("%s\n", spl);
spl = strtok(NULL, " ");
}
}
fclose(fh);
}
return 0;
}
FILE:I dont know what this is.im.just.testing.out.
Output:
I
dont
know
what
this
is.im.just.testing.out
.
.
This is what I have accomplished so far. I think that the way this will work is by storing every word from the text file and the dictionary in to two matrices and from there by comparing the elements of the matrices.So far i have managed to separate each word whenever there is a space, but when there is punctuation in the text it doesn't seem to work. I have tried multiple ways to remove punctuation from the text, but I cannot get it to work. Also dont mind the functions that just print their names, they will be used for later versions.
Program should read list of filenames, open these files and put their handles in the array of structure, then read strings and print consecutive lines of strings to smallest files by using handles contained in array of structures.
My program puts data from all lines to only one file which is initially the smallest which is false because it should the one which is smallest with every time it prints data into the file. This is my program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <math.h>
struct file_t
{
FILE* f;
int size;
}t[5];
void close_file(struct file_t* f) {
if (f == NULL || f->f == NULL) {
}
else {
fclose(f->f);
}
}
int open_file(struct file_t* f, const char* filename) {
if (f == NULL || filename == NULL) {
return 1;
}
FILE* fp;
fp = fopen(filename, "ab");
if (fp == NULL) {
return 2;
}
long int res = ftell(fp);
fclose(fp);
f->size = res;
f->f = fopen(filename, "ab+");
if (fp == NULL) {
return 2;
}
return 0;
}
struct file_t* find_min(const struct file_t* files, int size) {
if (files == NULL || size <= 0) {
return NULL;
}
int x = (files + 0)->size, i = 0, index = 0;
for (i = 0; i < size; i++) {
if ((files + i)->size <= x) {
x = (files + i)->size;
index = i;
}
}
return (struct file_t*)(files + index);
}
int main() {
puts("Input files' names:");
char tab[100];
int num = 0;
while(1==1){
if(fgets(tab, 100, stdin)==NULL||*tab=='\n'){
if (num == 0) {
printf("Couldn't open file");
return 4;
}
break;
}
int index=strlen(tab);
*(tab+index-1)='\x0';
if (strlen(tab) > 30) {
*(tab + 30) = '\x0';
}
if (open_file((t + num), tab) > 0) {
}
else {
num++;
}
}
if (num == 0) {
printf("Couldn't open file");
return 4;
}
char str[1000];
printf("Input text:");
*str = '\x0';
while (fgets(str, 1000, stdin)==NULL||*str!='\n') {
int index=strlen(str);
*(str+index-1)='\x0';
struct file_t* p = find_min(t, num);
fwrite(str, sizeof(char), strlen(str), p->f);
}
for (int i = 0; i < num; i++) {
close_file(t + i);
}
printf("File saved");
return 0;
}
There are some critical bugs that you need to resolve.
fseek(stdin, 0, SEEK_END) -- fseek normally only work on a disk file, or something reasonably similar. Please refer to this link Using fseek with a file pointer that points to stdin
As a matter of fact even fflush() won't work. fflush is something that is designed for flushing output streams, and its behavior with input streams is implementation-dependent. Please refer to this link for more details stdinflush
scanf("%[^\n]s", tab)
If you are using this in a loop or multiple times, only the first read will succeed. The reason being, the \n character is left out from the previous input, and as said earlier fflush() might not be successful in removing that \n. The further calls to scanf() will simply return without reading anything.
'\0x' If you are intending to use this as string terminator then this is not it. It is a multi-character constant with an integer value 120. Below is a vague test run
Code
#include <stdio.h>
int main()
{
if ('\0' == '\0x' )
printf("both are same\n");
printf("%d",'\0x');
}
Compilation Warnings
test.c: In function ‘main’:
test.c:5:14: warning: multi-character character constant [-Wmultichar]
5 | if ('\0' == '\0x' )
| ^~~~~
test.c:8:14: warning: multi-character character constant [-Wmultichar]
8 | printf("%d",'\0x');
| ^~~~~
Output
120
fseek(fp, 0, SEEK_END); ftell(fp); -- This should not be used to determine the file sizes. The behavior of the fseek() with SEEK_END is undetermined in the case of binary files. Please refer to this link Do not use fseek() and ftell() to compute the size of a regular file
Some Logic Errors
1) You should compute the file size every time in find_min() as it gets changed whenever you write data to the file.
2) fwrite()won't actually dump the data to file immediately. you need to call fflush().
After resolving the above issues, this is the modified code.
Code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <math.h>
#include <sys/stat.h>
struct file_t
{
FILE* f;
int size;
}t[5];
void close_file(struct file_t* f) {
if (f == NULL || f->f == NULL) {
}
else {
fclose(f->f);
}
}
int open_file(struct file_t* f, const char* filename) {
if (f == NULL || filename == NULL) {
return 1;
}
f->f = fopen(filename, "a");
if (f->f == NULL)
return 2;
struct stat statbuf;
fstat(fileno(f->f), &statbuf);
f->size = statbuf.st_size;
return 0;
}
struct file_t* find_min(const struct file_t* files, int size) {
if (files == NULL || size <= 0) {
return NULL;
}
struct stat statbuf;
fstat(fileno(files->f), &statbuf);
int x = statbuf.st_size, i = 0, index = 0;
for (i = 0; i < size; i++) {
fstat(fileno((files+i)->f), &statbuf);
if (statbuf.st_size < x) {
x = statbuf.st_size;
index = i;
}
}
return (struct file_t*)(files + index);
}
int main() {
puts("Input files' names:");
char tab[100];
int num = 0;
while(1){
int c;
while (1) {
c = getc(stdin);
if (c == EOF || c == ' ')
goto user_input;
if(c != '\n')
break;
}
tab[0] = c;
if (scanf("%[^\n]s", tab+1) == EOF)
break;
if (*tab == '\0') {
if (num == 0) {
printf("Couldn't open file");
return 4;
}
break;
}
if (strlen(tab) > 30) {
*(tab + 30) = '\0';
}
if (open_file((t + num), tab) > 0) {
}
else {
num++;
}
*tab = '\0';
}
user_input:
if (num == 0) {
printf("Couldn't open file");
return 4;
}
fflush(stdin);
char str[1000];
printf("Input text:\n");
*str = '\0';
while(1) {
int c;
while(1) {
c = getc(stdin);
if (c == EOF)
goto main_exit;
if (c != '\n')
break;
}
str[0] = c;
if (scanf("%[^\n]s", str+1) == EOF)
break;
struct file_t* p = find_min(t, num);
fwrite(str, sizeof(char), strlen(str), p->f);
fflush(p->f);
}
main_exit:
for (int i = 0; i < num; i++) {
close_file(t + i);
}
printf("File saved");
return 0;
}
Terminal Session
$ ./a.out
Input files' names:
test file1.txt
test file2.txt
' '(NOTE: Space character inputted before pressing enter.)
Input text:
this is
stackoverflow
File saved
test file1.txt
this is
test file2.txt
stackoverflow
Note for breaking from the first loop (Files input). You need to enter space and then press enter (You can tweak around this).
Where are you updating the file_t->size when you write into a file?
You are calling this:
fwrite(str, sizeof(char), strlen(str), p->f);
But after that you should do p->size += strlen(str) to update its size, otherwise all file sizes are set to initial values, and hence all strings get written to a single file.
As for getting garbage data, try printing the string you are reading from scanf in the while loop.
You are using scanf to read characters until '\n', but you are not reading the '\n' itself. You need a fseek(stdin, 0, SEEK_END); in that loop as well.
Finally, why are you using syntax like this:
(files + i)->size
When you can call it more cleanly like this:
files[i].size
You code is really hard to read because of this.
What i need to do, is to take a file of n lines, and for every x lines, create a new file with the lines of the original file. An example would be this:
Original File:
stefano
angela
giuseppe
lucrezia
In this case, if x == 2, 3 file would be created, in order:
First file:
stefano
angela
Second FIle:
giuseppe
lucrezia
Third File:
lorenzo
What i've done so far is this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 10
int getlines(FILE *fp)
{
int c = 0;
int ch;
do{
ch = fgetc(fp);
if(ch == '\n')
{
c++;
}
}while(ch != EOF);
fseek(fp, 0 , SEEK_SET);
return c;
}
int ix = 0;
void Split(FILE *fp, FILE **fpo, int step, int lines, int *mem)
{
FILE **fpo2 = NULL;
char * filename = malloc(sizeof(char)*64);
char * ext = ".txt";
char number[2];
for(int i = ix; i < *mem; i++)
{
itoa(i+1, number,10);
strcpy(filename, "temp");
strcat(filename, number);
strcat(filename, ext);
if(!(fpo[i] = fopen(filename, "w")))
{
fprintf(stderr, "Error in writing\n");
exit(EXIT_FAILURE);
}
}
char ch;
int c = 0;
do{
ch = fgetc(fp);
printf("%c", ch);
if(ch == '\n')
{
c++;
}
if(c >= step)
{
c = 0;
ix++;
if(ix >= *mem && (ix*step) <= lines)
{
*mem = *mem + 1;
fpo2 = realloc(fpo, sizeof(FILE*)*(*mem));
Split(fp, fpo2, step, lines, mem);
}
}
putc(ch, fpo[ix]);
}while(ch != EOF);
}
int main()
{
FILE * fp;
if(!(fp = fopen("file.txt", "r")))
{
fprintf(stderr, "Error in opening file\n");
exit(EXIT_FAILURE);
}
int mem = N;
int lines = getlines(fp);
int step = lines/N;
FILE **fpo = malloc(sizeof(FILE *)*N);
Split(fp, fpo, step, lines, &mem);
exit(EXIT_SUCCESS);
}
I'm stack with segmentation error, i couldn't find the bug doing
gdb myprogram
run
bt
I really appreciate any help.
EDIT:
I've changed some things and now it works, but it creates an additional file that contains strange characters. I need to still adjust some things:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 10
int getlines(FILE *fp)
{
int c = 0;
int ch;
do{
ch = fgetc(fp);
if(ch == '\n')
{
c++;
}
}while(ch != EOF);
fseek(fp, 0 , SEEK_SET);
return c;
}
int ix = 0;
void Split(FILE *fp, FILE **fpo, int step, int lines, int *mem)
{
FILE **fpo2 = NULL;
char * ext = ".txt";
for(int i = ix; i < *mem; i++)
{
char * filename = malloc(sizeof(char)*64);
char * number = malloc(sizeof(char)*64);
itoa(i+1, number,10);
strcpy(filename, "temp");
strcat(filename, number);
strcat(filename, ext);
if(!(fpo[i] = fopen(filename, "w")))
{
fprintf(stderr, "Error in writing\n");
exit(EXIT_FAILURE);
}
free(number);
free(filename);
}
char ch;
int c = 0;
do{
ch = fgetc(fp);
printf("%c", ch);
if(ch == '\n')
{
c++;
}
if(c >= step)
{
c = 0;
ix++;
if(ix >= *mem && ((ix-1)*step) <= lines)
{
*mem = *mem + 1;
fpo2 = realloc(fpo, sizeof(FILE*)*(*mem));
Split(fp, fpo2, step, lines, mem);
}
}
putc(ch, fpo[ix]);
}while(ch != EOF);
}
int main()
{
FILE * fp;
if(!(fp = fopen("file.txt", "r")))
{
fprintf(stderr, "Error in opening file\n");
exit(EXIT_FAILURE);
}
int mem = N;
int lines = getlines(fp);
int step = lines/N;
FILE **fpo = malloc(sizeof(FILE *)*N);
Split(fp, fpo, step, lines, &mem);
exit(EXIT_SUCCESS);
}
There are a few problems in your code. But first I think you need to fix the most important thing
int step = lines/N;
Here step is 0 if your input file has less than N lines of text. This is because lines and N both are integer and integer division is rounding down.
I won't fix your code, but I'll help you with it. Some changes I
suggest:
Instead of getlines, use getline(3) from the standard
library.
fseek(fp, 0 , SEEK_SET) is pointless.
In char * filename = malloc(sizeof(char)*64), note that
both arguments to malloc are constant, and the size is arbitrary.
These days, it's safe to allocate filename buffers statically,
either on the stack or with static: char filename[PATH_MAX].
You'll want to use limits.h to get that constant.
Similarly you have no need to dynamically allocate your FILE
pointers.
Instead of
itoa(i+1, number,10);
strcpy(filename, "temp");
strcat(filename, number);
strcat(filename, ext);
use sprintf(filename, "temp%d%s", i+1, ext)
get familiar with err(3) and friends, for your own convenience.
Finally, your recursive Split is -- how shall we say it? -- a nightmare. Your whole program
should be something like:
open input
while getline input
if nlines % N == 0
create output filename with 1 + n/N
open output
write output
nlines++
I tried to change all random lowercase letters to uppercase letters in this program.First of all, I have initialized in lowercase.txt AkfsASlkALfdk.Then I read from it and changing all the lowercase letters into capital ones.The problem is,when I opened the capital.txt is ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌAKFSASLKALFDK.Where did the error come from?I couldn't find it yet and I decided to ask you.
#pragma warning(disable:4996)
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
#include <conio.h>
int main()
{
int i;
char s[100];
char k[100];
FILE *kp;
kp = fopen("lowercase.txt", "r");
if (kp == NULL)
{
printf("Error in opening file.\n");
system("pause");
exit(1);
}
FILE *temp;
temp = fopen("capital.txt", "w");
if (kp == NULL)
{
printf("Error in opening file.\n");
system("pause");
exit(2);
}
printf("Opening file is successful.\n");
if (fscanf(kp, "%s", &s) != EOF)
{
for (i = 0; i < 100; i++)
{
if (s[i] >= 97 && s[i] <= 122)
{
s[i] -= 32;
}
}
}
fprintf(temp, "%s", k);
getch();
return 0;
}
Multiple issues in your code which together cause the issues
You are storing the opened FILE* in temp, but checking kp. I think that is because you copy pasted the check from above. Can be easily fixed by changing the variable
You perform the capitalization operation outside what was set by scanf. As suggested by #MOehm, change the loop condition to s[i]
Finally you are converting the string in place in s but are saving k in the file. k is never modified. Change fprintf(temp, "%s", k); to fprintf(temp, "%s", s);
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
char *append(const char *s, char c) {
int len = strlen(s);
char buf[len+2];
strcpy(buf, s);
buf[len] = c;
buf[len + 1] = 0;
return strdup(buf);
}
int main(int argc, char **argv)
{
char ch;
FILE *fp;
if (argc != 2)
return (0);
if ((fp = fopen(argv[1], "r")) == NULL)
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
char *res;
while((ch = fgetc(fp)) != EOF)
{
res = append(res, ch);
}
fclose(fp);
int i = 0;
while (i < strlen(res))
{
if (res[i] >= 97 && res[i] <= 122)
res[i] = res[i] - 32;
i++;
}
printf("%s\n", res);
return 0;
}
here is a quick example
read the file char by char and add each char in a char *. Then for each character lowercase char, sub 32 to get the uppercase char and write it then print. Give the filename as first parameter when you start the programm
I want to read a file which looks like this:
Name=José, Age=21
Name=Antonio, Age=26
Name=Maria, Age=24
My problem is how can i read the names and ages from different positions and different lines and put in an array names[size] and the same thing for the ages ages[size].
I have this at the moment:
#include <stdio.h>
#define size 100
int main()
{
char ch = 0;
int i = 0;
char names[size];
char ages[size];
FILE *fp1;
fp1 = fopen("data.txt", "r");
if(fp1 == NULL)
{
printf("Error!");
return 1;
}
while((ch=fgetc(fp1)) != '=');
while((ch=fgetc(fp1)) != ',')
{
fscanf(fp1, "%s", names);
i++;
}
fclose(fp1);
printf("Names = %s", names);
return 0;
}
Can anyone explain me what is the best way to do it?
you need 2D-Array. E.g names[number of record][max length size + 1]
a way sample like this
#include <stdio.h>
#define size 100
int main(void){
int i = 0;
char names[size][128];
char ages[size][4];
FILE *fp1;
fp1 = fopen("data.txt", "r");
if(fp1 == NULL){
printf("Error!\n");
return 1;
}
while(i < size && 2 == fscanf(fp1, "Name=%127[^,], Age=%3[0-9]\n", names[i], ages[i])){
i++;
}
fclose(fp1);
int n = i;
for(i = 0; i < n; ++i)
printf("Names = %s, Ages = %s\n", names[i], ages[i]);
return 0;
}