James
James

Reputation: 41

get characters from file rather than getchar

I cannot work out how to read text from a file rather than from getchar()

calc entropy of a string

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include <string>
#include <iostream>
#include <cmath>
#include <fstream>
#include <cstring>
using namespace std;

double log2(double number) 
{
return log(number)/std::log(2.);
}

int main() {

unsigned long table[256], total = 0;
double entropy = 0;
char mychar;

string line;
ifstream myfile ("sometext.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
cout << line << '\n';
}

}
short i;

for(i=0; i<256; i++) 
table[i] = 0;

while(1)  
{  
mychar = getchar();

how to read from myfile.txt ?

if (mychar==EOF) // ctrl Z 
{break;}
table[mychar]++;
}

for(i=33;i<127;i++)
if(table[i]) {
total += table[i]; 
entropy -= log2(table[i])*table[i];
}

entropy /= total;
entropy += log2(total);

printf("Total Characters: %6d\n",total);
printf("Entropy: %5.6f\n",entropy); 
}

Upvotes: 0

Views: 461

Answers (2)

Dietmar K&#252;hl
Dietmar K&#252;hl

Reputation: 154045

The loop reading lines with std::getline() reads the content of the file! You could actually process the data from the std::strings already read:

while (std::getline(myfile, line)) {
    std::cout << line << '\n';

    for (std::string::const_iterator it(line.begin()), end(line.end()); it != end; ++it) {
        unsigned char mychar = *it;
        ++table[mychar];
    }
}

The inner loop iterates over all characters in the string line. It obtains an unsigned char from the character currently processed (i.e., from *it) because char may be signed type and yield negative values which probably doesn't work too well. The ASCII characters are all positive but, e.g., the u-umlaut ü from my name may become a negative values; I'd guess that isn't really an issue for your input but I prefer code which works even when unexpected things happen.

In any case, this loops terminates when the std::getline() failed because there is no further data. If you want to read the data again, you'll either need to open a new std::ifstream or reset the std::ifstream you got:

myfile.clear();                        // clear error flags
myfile.seekg(0, std::ios_base::beg); // move to the start of the file

To actually read individual chars as int you could use

mychar = myfile.get();

Personally, I'd be inclined to read the characters using iterators, though:

for (std::istreambuf_iterator<char> it(myfile), end; it != end; ++it) {
    char mychar = *it; // well, you could keep using *it, of course
    // ...
}

Upvotes: 2

Robert Jacobs
Robert Jacobs

Reputation: 3360

Use fgetc(). You can pass it a FILE pointer.

Upvotes: 0

Related Questions