Finding the most frequent character of an input text file - c

I am trying to read an input txt file from command line and find the most frequent character in that file for a school project. I can open the txt file and print it without an issue with the following code. Also the funcion below freqcount(), works perfectly when I give it a string from the command line. But I can't seem to make them work together. I think I'm messing up something while setting up the dest array down below. Any help would be appreciated.
Also, for non static sized strings, which one is generally better to use, malloc or calloc?
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#define DEST_SIZE 26 // An arbitrary size but longest string to work is 24
char freqcount(char * str){
// Construct character count array from the input
// string.
int len = strlen(str);
int max = 0; // Initialize max count
char result; // Initialize result
int count[255] = {0};
// Traversing through the string and maintaining
// the count of each character
for (int i = 0; i < len; i++) {
count[str[i]]++;
if (max < count[str[i]]) {
max = count[str[i]];
result = str[i];
}
}
return result;
}
//////////////////////////////////////////////////////////////////////
int main(int argc,char ** argv){
int i=0;
char dest[DEST_SIZE] = {0};
if(argc !=2){
perror("Error: ");
return -1;
}
FILE * f = fopen(argv[1], "r");
if (f == NULL) {
return -1;
}
int c;
while ( (c=fgetc(f)) != EOF && i++<DEST_SIZE ) {
printf("%c",c);
dest[i]=c;
char cnt=freqcount(dest);
printf("%c",cnt);
}
return EXIT_SUCCESS;
}
Sorry I forgot to add, originally call was after the loop such as;
(omitted the first part)
while ( (c=fgetc(f)) != EOF && i++<DEST_SIZE ) {
printf("%c",c);
dest[i]=c;
}
/*int l;
for (l=0; l<DEST_SIZE;l++){
if (dest[i] != 0){
printf("%c\n",dest[l]); // burda da arrayi okuyor ama array 255 long oldugu icin cogu bos
}
}*/
char cnt=freqcount(dest);
printf("%s",cnt);
return EXIT_SUCCESS;
}
when it is like this, the code returns the following with the input "An example Of the input.
An example
Of the input.(null)

Move the call of freqcount to after the while loop:
while ( (c=fgetc(f)) != EOF && i++<DEST_SIZE ) {
printf("%c",c);
dest[i]=c;
}
dest[i]='\0'; // terminate
char cnt=freqcount(dest);
printf("%c",cnt);

Related

string of undetermined length c

Hi I was trying to create an array of string of an undetermined length in c.
This is my code :
int main()
{
int lineCount=linesCount();
char text[lineCount][10];
printf("%d",lineCount);
FILE * fpointer = fopen("test.txt","r");
fgets(text,10,fpointer);
fclose(fpointer);
printf("%s",text);
return 0;
}
I would like to replace 10 in
char text[lineCount][10];
My code reads out a file I already made the amount of lines dynamic.
Since the line length is unpredictable I would like to replace 10 by a something dynamic.
Thanks in advance.
To do this cleanly, we want a char * array rather than an 2D char array:
char *text[lineCount];
And, we need to use memory from the heap to store the individual lines.
Also, don't "hardwire" so called "magic" numbers like 10. Use an enum or #define (e.g) #define MAXWID 10. Note that with the solution below, we obviate the need for using the magic number at all.
Also, note the use of sizeof(buf) below instead of a magic number.
And, we want [separate] loops when reading and printing.
Anyway, here's the refactored code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
linesCount(void)
{
return 23;
}
int
main(void)
{
int lineCount = linesCount();
char *text[lineCount];
char buf[10000];
printf("%d", lineCount);
// open file and _check_ the return
const char *file = "test.txt";
FILE *fpointer = fopen(file, "r");
if (fpointer == NULL) {
perror(file);
exit(1);
}
int i = 0;
while (fgets(buf, sizeof(buf), fpointer) != NULL) {
// strip newline
buf[strcspn(buf,"\n")] = 0;
// store line -- we must allocate this
text[i++] = strdup(buf);
}
fclose(fpointer);
for (i = 0; i < lineCount; ++i)
printf("%s\n", text[i]);
return 0;
}
UPDATE:
The above code is derived from your original code. But, it assumes that the linesCount function can predict the number of lines. And, it doesn't check against overflow of the fixed length text array.
Here is a more generalized version that will allow an arbitrary number of lines with varying line lengths:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(void)
{
int lineCount = 0;
char **text = NULL;
char buf[10000];
// open file and _check_ the return
const char *file = "test.txt";
FILE *fpointer = fopen(file, "r");
if (fpointer == NULL) {
perror(file);
exit(1);
}
int i = 0;
while (fgets(buf, sizeof(buf), fpointer) != NULL) {
// strip newline
buf[strcspn(buf,"\n")] = 0;
++lineCount;
// increase number of lines in array
text = realloc(text,sizeof(*text) * lineCount);
if (text == NULL) {
perror("realloc");
exit(1);
}
// store line -- we must allocate this
text[lineCount - 1] = strdup(buf);
}
fclose(fpointer);
// print the lines
for (i = 0; i < lineCount; ++i)
printf("%s\n", text[i]);
// more processing ...
// free the lines
for (i = 0; i < lineCount; ++i)
free(text[i]);
// free the list of lines
free(text);
return 0;
}

Something weird using fgets

If I'm printing the whole string everything looks good, whitespace and indenting looks perfect (I'm loading the source file with this code).
But if I'm trying to print a single character in the buffer I'm getting letters where there are not supposed to be any.
For example, if I print buffer[2] I'm getting letters where it should be whitespace, but if I print the whole string the letters aren't there.
Here is my code that's not working:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void) {
char *buffer = (char*) malloc(100*sizeof(char));
FILE *myFile;
myFile = fopen("thisSourceFile.c", "r");
if (!myFile) {
printf("could not open file");
}
else {
while(fgets(buffer,100,myFile)) {
printf("%c \n",buffer[2]);
}
}
fclose(myFile);
free(buffer);
buffer = NULL;
return 0;
}
OUTPUT:
n
n
n
t
h
I
y
f
p
l
w
p
}
r
u
e
As you can se it is printing letters where it should by whitespace. Those letters are not there if I print the whole string.
If you're interested in parsing a source file and processing each character, this might be a solution.
But there are two constants; charsand num_lines_to_read.
M.M mentions in the comments below that isprint() isn't fully portable and comes with some quirks to be careful of.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void) {
const int chars = 100; /* Num chars per line to read */
const int num_lines_to_read = 3; /* Num lines to read */
char *buffer = (char*) malloc(chars*sizeof(char));
int i = 0, j = 0;
FILE *myFile;
myFile = fopen("thisSourceFile.c", "r");
if (myFile == NULL) {
printf("could not open file");
fclose(myFile);
return 1;
}
for(i=0; i<num_lines_to_read; i++)
{
if(fgets(buffer,chars,myFile) != NULL)
{
while(isprint((unsigned char) buffer[j]))
{
printf("%c", (buffer[j]));
j++;
}
j=0;
}
}
fclose(myFile);
free(buffer);
return 0;
}
Example output (itself!):
#include <stdio.h>#include <stdlib.h>#include <ctype.h>

How to save in a string the contents of a text file

This is the code why when I show in output the string I have all words but with in the final row a strange symbol , an ASCII random symbol...
My objective is to save in a string all words to operate with it.
For example I have this document:
Mario
Paul
Tyler
How can i save all words in a string??
#include <stdio.h>
#include <stdlib.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char *argv[]) {
int l,i=0,j=0,parole=0;
char A[10][10];
char leggiparola;
char testo[500];
FILE*fp;
fp=fopen("parole.txt","r");
if(fp!=NULL)
{
while(!feof(fp))
{
fscanf(fp,"%c",&leggiparola);
printf("%c", leggiparola);
testo[j]=leggiparola;
j++;
}
}
fclose(fp);
printf("%s",testo);
return 0;
}
Besides while(!feof(fp)) being "always wrong" you miss to 0-terminate the result string.
To do so place a
testo[j] = '\0'
just after the while-loop.
Instead of using fscanf, try with getc:
int leggiparola; /* This need to be an int to also be able to hold another
unique value for EOF besides 256 different char values. */
...
while ( (leggiparola = getc(fp)) != EOF)
{
printf("%c",leggiparola);
testo[j++] = leggiparola;
if (j==sizeof(testo)-1)
break;
}
testo[j] = 0;
Here's fslurp. I't a bit messy due to the need to grow the buffer manually.
/*
load a text file into memory
*/
char *fslurp(FILE *fp)
{
char *answer;
char *temp;
int buffsize = 1024;
int i = 0;
int ch;
answer = malloc(1024);
if(!answer)
return 0;
while( (ch = fgetc(fp)) != EOF )
{
if(i == buffsize-2)
{
if(buffsize > INT_MAX - 100 - buffsize/10)
{
free(answer);
return 0;
}
buffsize = buffsize + 100 * buffsize/10;
temp = realloc(answer, buffsize);
if(temp == 0)
{
free(answer);
return 0;
}
answer = temp;
}
answer[i++] = (char) ch;
}
answer[i++] = 0;
temp = realloc(answer, i);
if(temp)
return temp;
else
return answer;
}

How to include the spaces?

I am trying to write a program that takes the words from a file, and puts those in a dynamic array. However when I try to run my code the program copies it all except for the spaces. How do I fix this?
This is a test does it work?
But I get the following:
Thisisatestdoesitwork?
char** getWords(char* filename, int* pn){
char** tmp = (char**)malloc( 1000*sizeof(char));
int *temp=(int*)malloc(1000*sizeof(int);
int c;
int counter = 0;
FILE* fileInput = fopen(filename, "r");
if(fileInput == NULL){
return tmp; // return if file open fails
}
while((c=fgetc(fileInput)) != EOF){
result = fscanf(fileInput, "%c", &c); //try to read a character
if(isalpha(c)){ //chararect alphabetical
tmp[counter] = c; // safe int to array
counter ++;
printf("%c", c); fflush(stdout);
}
else{ // if read not succesfull
fscanf(fileInput, ""); // needs to scan anything not a character
}
if(counter > 100){ // to not exceed the array
break;
}
if(feof(fileInput)){ // to check if at the end of the file
break;
}
}
fclose(fileInput); // closing file
*pn = counter;
return tmp;}
My main Function:
int main(int argc, char* argv[]){
int n;
char** a = getWords("opdracht_4_5.c", &n);
if (a != NULL){
puts("gevonden woorden:");
for (int i = 0;i < n; i++){
printf("%3d %s\n",i,a[i]);
}
for (int i = 0;i < n; i++){
free(a);
}
free(a);
}
return (EXIT_SUCCESS);
}
There are quite a few problems with your code. Here's a start:
You don't test the return value of fopen().
You don't test the return value of malloc().
You assign the return value of fgetc() to a variable of type char. Plain char is compatible with either signed char or unsigned char. In order to make a distinction between a character and EOF (which is negative), the fgetc() function returns a character converted to unsigned char (or EOF). You need to test for EOF and then convert the value to a plain char.
The is...() function expects an int argument whose value is in the range of an unsigned char or EOF. If you have a plain char, you first have to cast it to unsigned char, or you can pass the return value of fgetc() straight to isalpha().
You attempt to append an zero-length char array (temp) to an uninitialized char array (s), and you do not test if there is enough room in the target array. This is broken for more reasons than than I care to enumerate.
You allocate memory for an array of 1000 pointers to char, but you never allocate memory for the char pointers themselves.
You try to append your buffer (s) to an uninitialized pointer (*tmp).
You call strlen() on something that is not null-terminated.
You never return the length of the array.
You call a number of functions that have not been declared.
This will read the file, put each word in an array
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
char** getWords(char* filename, int* pn){
char input[100]; // array to hold each word
char** tmp; // double pointer
int counter = 0;
int words = 0;
int c;
tmp = malloc( (*pn)*sizeof(char*)); // allocate pointers for number of words
if ( tmp == NULL) {
printf ( "malloc failed\n");
exit (1);
}
FILE* fileInput = fopen(filename, "r");
if(fileInput == NULL){
printf ( "file open failed\n");
*pn = 0; // no words entered
return tmp; // return if file open fails
}
while(( c = fgetc(fileInput)) != EOF){
if( isalnum(c)){ // is alpha or number
input[counter] = c; // save to array
input[counter + 1] = '\0'; // save a \0 to the end to make a string
counter ++;
}
else{ // not alpha or number
if ( counter > 0) { // if there are characters, save the word
tmp[words] = malloc ( strlen ( input) + 1); // memory for this word
strcpy ( tmp[words], input); // copy the word to the array
words++;
counter = 0;
if ( words >= *pn) { // got all the words wanted
break;
}
}
}
if(counter > 98){ // too many characters for input, start a new word
tmp[words] = malloc ( strlen ( input) + 1);
strcpy ( tmp[words], input);
words++;
counter = 0;
if ( words >= *pn) {
break;
}
}
}
fclose(fileInput); // closing file
*pn = words; // save number of words
return tmp;
}
int main(int argc, char* argv[]){
int n;
int i;
printf ( "enter the number of words to obtain\n");
scanf ( "%d", &n);
char** a = getWords("opdracht_4_5.c", &n);
if (a != NULL){
puts("gevonden woorden:");
for ( i = 0;i < n; i++){
printf("%3d %s\n",i,a[i]);
}
for ( i = 0;i < n; i++){
free(a[i]); // free each word
}
free(a); // free the pointer to the words
}
return (EXIT_SUCCESS);
}
The input file I used had these as the first two lines
#include<stdio.h>
#include<string.h>
I get this output:
enter the number of words to obtain
6
gevonden woorden:
0 include
1 stdio
2 h
3 include
4 string
5 h
This answer is as yet incomplete
Please allow me to finish this before commenting on it -- Thank you
There are a lot if issues with your code, I won't clean it up for you. However I would like to give you some hints on how your program SHOULD be coded:
Your main objective is to read a file and load the content word by word in an array.
Sorting is an incorrect use because that implies you want to sort them alphabetically or in some other order after loading it into an array.
Okay, so first things first, let's figure out the overall operation of our program. We'll call our program kitten, because it's not quite as powerful as cat.
To run our program we will assume that we give it the filename we want to read on the command-line as follows:
$ ./kitten somefile.txt
and expect the output to be:
word1
word2
word3
.
.
.
wordN
Total words: N
So, let's get started, first we make sure that our user specifies a filename:
#include <stdio.h>
int usage(const char *progname);
int main(int argc, char *argv[])
{
if (argc < 2) {
usage(argv[0]);
return -1;
}
return 0;
}
int usage(const char *progname)
{
fprintf(stderr, "Usage is:\n\t%s filename\n", progname);
}
Now that we know that our program can get a filename, let's try to open the text file, if there is an issue with it we use perror to display the error and exit the program, otherwise we are ready to use the file:
#include <stdio.h>
#include <errno.h>
int usage(const char *progname);
int main(int argc, char *argv[])
{
FILE *fp;
if (argc < 2) {
usage(argv[0]);
return -1;
}
fp = fopen(argv[1], "r");
if (!fp) {
perror(argv[1]); /* display system error, with the filename */
return -1;
}
/* TODO: file manipulation goes here */
fclose(fp); /* close the file */
return 0;
}
int usage(const char *progname)
{
fprintf(stderr, "Usage is:\n\t%s filename\n", progname);
}
Now in C each function should perform just one task. The task should make human sense. For example if the function is supposed to read words into an array, then that's all it should do, it should not open a file or close a file, which is WHY the code above does not create a function for opening the file the way you did. Your function should take in FILE * as the file to read.
Because we use the FILE * as input we'll start the function name with an f to keep with the stdio convention. Ideally, the function should take a pointer to char * (strings) to store the words in.
#include <stdio.h>
#include <errno.h>
int usage(const char *progname);
size_t fload(FILE *fp, char **wordlist_p);
int main(int argc, char *argv[])
{
FILE *fp;
if (argc < 2) {
usage(argv[0]);
return -1;
}
fp = fopen(argv[1], "r");
if (!fp) {
perror(argv[1]); /* display system error, with the filename */
return -1;
}
if(fload(fp, wordlist_p) < 0) {
fprintf(stderr, "Something went wrong\n")
}
fclose(fp); /* close the file */
return 0;
}
int usage(const char *progname)
{
fprintf(stderr, "Usage is:\n\t%s filename\n", progname);
}
size_t fload(FILE *fp, char **wordlist_p)
{
size_t rv = -1; /* return value */
return rv;
}
Now we run into a conceptual problem. How do we allocate memory for wordlist_p? I mean we don't have any idea about how big the file is, we also don't know how big the biggest word in the file is.
Crude approach
Let's first try an think about it the simple way:
Point to the beginning of the `wordlist_p` with a `tail_pointer`
Read the file line by line, (we assume no hyphenation)
For each line split the line up along white spaces,
Allocate space for the number of words in the `wordlist_p` array
For each word in the split line
Allocate space for the word itself
Save the pointer to the word at the tail_pointer
Advance wordlist_p tail_pointer
Next word
Next Line
Let's look at what the fload function would look like with these steps above,
More to come ##

Converting Greek words to uppercase

I have to create a function that reads a file called grwords.txt containing around 540000 words which are written in Greek letters.
I have to convert these words to uppercase and fill an array called char **words.
This is what I have so far.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <windows.h>
#include <ctype.h>
void fp();
int main(int argc, char *argv[]) {
SetConsoleOutputCP(1253);
fp();
return 0;
}
void fp(){
char **words;
words = malloc(546490 * sizeof(int *));
for (i = 0; i < 546490; i++)
words[i] = malloc(24 * sizeof(int));
FILE *file;
char *word;
size_t cnt;
file = fopen("grwords.txt", "rt");
if (file == NULL){
printf("File cannot be opened.\n");
exit(1);
}
cnt = 0;
while (1==fscanf(file, "%24s",word)){
if (cnt == 546490)
break;
strcpy(words[cnt++], word);
}
fclose(file);
}
I'm still trying to figure out pointers. I know that & makes a pointer from a value and * a value from a pointer. Updated the program and it successfully fills the array with the words from the file! I still have no idea how to convert Greek lowercase to uppercase.
Handling Greek words can be dependent on your platform.
First of all, you need to understand how file handling works. Here is what I wrote:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define bufSize 1024 // max lenght of word
// we are going to receive the .txt from cmd line
int main(int argc, char *argv[])
{
FILE *fp;
// Assume file has max 10 words
const size_t N = 10;
// Allocate a 2D array of N rows
// and bufSize columns.
// You can think of it like an array
// of N strings, where every string
// has, at most, bufSize length.
char buf[N][bufSize];
// make sure we got the .txt
if (argc != 2)
{
fprintf(stderr,
"Usage: %s <soure-file>\n", argv[0]);
return 1;
}
// open the file
if ((fp = fopen(argv[1], "r")) == NULL)
{ /* Open source file. */
perror("fopen source-file");
return 1;
}
// we will use that for toupper()
char c;
// counters
int i = 0, j;
while (fscanf(fp, "%1024s", buf[i]) == 1)
{ /* While we don't reach the end of source. */
/* Read characters from source file to fill buffer. */
// print what we read
printf("%s\n", buf[i]);
j = 0;
// while we are on a letter of word placed
// in buf[i]
while (buf[i][j])
{
// make the letter capital and print it
c = buf[i][j];
putchar (toupper(c));
j++;
}
i++;
printf("\ndone with this word\n");
}
// close the file
fclose(fp);
return 0;
}
For this test.txt file:
Georgios
Samaras
Γιώργος
Σαμαράς
the code would run as:
./exe test.txt
Georgios
GEORGIOS
done with this word
Samaras
SAMARAS
done with this word
Γιώργος
Γιώργος
done with this word
Σαμαράς
Σαμαράς
done with this word
As you can see, I could read the Greek words, but failed to convert them in upper case ones.
Once you got how file handling goes, you need to use wide characters to read a file with Greek words.
So, by just modifying the above code, we get:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <wchar.h>
#include <wctype.h>
#include <locale.h>
#define bufSize 1024
int main(int argc, char *argv[])
{
setlocale(LC_CTYPE, "en_GB.UTF-8");
FILE *fp;
const size_t N = 15;
wchar_t buf[N][bufSize];
if (argc != 2)
{
fprintf(stderr,
"Usage: %s <soure-file>\n", argv[0]);
return 1;
}
if ((fp = fopen(argv[1], "r")) == NULL)
{
perror("fopen source-file");
return 1;
}
wchar_t c;
int i = 0, j;
while (fwscanf(fp, L"%ls", buf[i]) == 1)
{
wprintf( L"%ls\n\n", buf[i]);
j = 0;
while (buf[i][j])
{
c = buf[i][j];
putwchar (towupper(c));
j++;
}
i++;
wprintf(L"\ndone with this word\n");
}
fclose(fp);
return 0;
}
And now the output is this:
Georgios
GEORGIOS
done with this word
Samaras
SAMARAS
done with this word
Γιώργος
ΓΙΏΡΓΟΣ
done with this word
Σαμαράς
ΣΑΜΑΡΆΣ
done with this word
I see that you may want to create a function which reads the words. If you need a simple example of functions in C, you can visit my pseudo-site here.
As for the 2D array I mentioned above, this picture might help:
where N is the number of rows (equal to 4) and M is the number of columns (equal to 5). In the code above, N is N and M is bufSize. I explain more here, were you can also found code for dynamic allocation of a 2D array.
I know see that you are on Windows. I tested the code in Ubuntu.
For Windows you might want to take a good look at this question.
So, after you read all the above and understand them, you can see what you asked for with dynamic memory management.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <wctype.h>
#include <locale.h>
#define bufSize 1024
wchar_t **get(int N, int M);
void free2Darray(wchar_t** p, int N);
int main(int argc, char *argv[])
{
setlocale(LC_CTYPE, "en_GB.UTF-8");
FILE *fp;
const size_t N = 15;
wchar_t** buf = get(N, bufSize);
if (argc != 2)
{
fprintf(stderr,
"Usage: %s <soure-file>\n", argv[0]);
return 1;
}
if ((fp = fopen(argv[1], "r")) == NULL)
{
perror("fopen source-file");
return 1;
}
wchar_t c;
int i = 0, j;
while (fwscanf(fp, L"%ls", buf[i]) == 1)
{
wprintf( L"%ls\n", buf[i]);
j = 0;
while (buf[i][j])
{
c = buf[i][j];
putwchar (towupper(c));
j++;
}
i++;
wprintf(L"\ndone with this word\n");
}
fclose(fp);
// NEVER FORGET, FREE THE DYNAMIC MEMORY
free2Darray(buf, N);
return 0;
}
// We return the pointer
wchar_t **get(int N, int M) /* Allocate the array */
{
/* Check if allocation succeeded. (check for NULL pointer) */
int i;
wchar_t **table;
table = malloc(N*sizeof(wchar_t *));
for(i = 0 ; i < N ; i++)
table[i] = malloc( M*sizeof(wchar_t) );
return table;
}
void free2Darray(wchar_t** p, int N)
{
int i;
for(i = 0 ; i < N ; i++)
free(p[i]);
free(p);
}
Note that this code is expected to work on Linux (tested on Ubuntu 12.04), not on Windows (tested on Win 7).

Resources