I need to read each line in the "test.txt" file using fscanf and print to new files using fprintf. If the read line is an integer, it is written to the integer file.
Float to the float file and string to string file respectively. However, when i try to compile it and run it, nothing happens and it goes to infinite loop.
Here is my code
#include <iostream>
#include <stdio.h>
using namespace std;
void writeFloat(){
FILE *file;
FILE *file2;
float value;
file = fopen("test.txt", "r");
file2 = fopen("float.out.txt", "w");
while(!feof(file)){
fscanf(file, "%f", &value);
fprintf(file2,"%f", value);
}
fclose(file);
fclose(file2);
}
void writeInteger(){
FILE *file;
FILE *file2;
int value;
file = fopen("test.txt", "r");
file2 = fopen("int.out.txt", "w");
while(!feof(file)){
fscanf(file, "%d", &value);
fprintf(file2, "%d", value);
}
fclose(file);
fclose(file);
}
void writeString(){
FILE *file;
FILE *file2;
char value;
file = fopen("test.txt", "r");
file2 = fopen("string.out.txt", "w");
while(!feof(file)){
fscanf(file, "%s", &value);
cout<<value<<endl;
fprintf(file2, "%s", value);
}
fclose(file);
fclose(file2);
}
int main(){
writeFloat();
writeInteger();
writeString();
return(0);
}
The test.txt file contains the values:
100
1.6E-10
hey nice to meet you.
43
56
4.5E-09
what is going on?
I don't know what wrong with my code. Please help me to achieve my requirement.
feof() is never true because fscanf in writefloat() refuses to read the first letter of "hey": It's not part of a legal number. scanf then returns with 0 ("no item could be read"). That is not EOF yet, though. But you should do something about it ;-).
Besides you must check for eof after you try to read something, before you try to use it. Not before the first failed read will the eof flag be turned on, but those variables will not be assigned.
I think, adopting a different strategy might be more appropriate for your needs.
Just have one function that reads the contents of the file line by line. It checks whether the line contains an integer or a floating point number. It line does not contain any numbers, the line is written out to "string.out.txt". If the number is an integer, it is written out to "int.out.txt". If the number is a floating point number, it is written out to "float.out.txt".
With this strategy, you have to read the contents of the input file only once and process the contents of the file only once.
It also simplifies the reading of the data and checking when you have reached EOF.
#include <stdio.h>
void writeData()
{
FILE *file1 = NULL;
FILE *file2 = NULL;
FILE *file3 = NULL;
FILE *file4 = NULL;
char value;
double realNum = 0.0;
int intNum = 0;
int n = 0;
char line[256];
file1 = fopen("test.txt", "r");
file2 = fopen("string.out.txt", "w");
file3 = fopen("int.out.txt", "w");
file4 = fopen("float.out.txt", "w");
while ( fgets(line, 255, file1) != NULL )
{
// Each line can be plain old text, a floating point number, or an
// integer.
// If the line does not contain a number, assume it is a float.
// Try to read a real number.
n = sscanf(line, "%lf", &realNum);
if ( n == 0 )
{
// The line does not have a number.
// Write the line to the text file.
fputs(line, file2);
}
else
{
// We have a real number.
// Could it be just an integer?
// Read the integer.
sscanf(line, "%d", &intNum);
// How do we decide whether the number is a real number or an
// integer?
// Is 1.0 a real number or an integer?
// Assume for now it is an integer.
if ( realNum == intNum )
{
// We have an integer.
fprintf(file3, "%d\n", intNum);
}
else
{
// We have a real number.
fprintf(file4, "%lG\n", realNum);
}
}
}
fclose(file4);
fclose(file3);
fclose(file2);
fclose(file1);
}
int main()
{
writeData();
return(0);
}
That is not the common way to open and close a file in C++. It looks like a c program. Try using functions from fstream and iostream libraries. See http://www.tutorialspoint.com/cplusplus/cpp_files_streams.htm.
Related
I am writing a XOR encryption program which works fine during encryption but during decryption
the
char ca2=fgetc(f);
gets stuck at one point and no decryption takes place after that my best guess about the problem is (the encrypted file contains all sorts of characters ) as soon as fgetc reaches EOF mark which can be present before the actual end of the file it gets stuck there and stop reading the next characters .
is this some kind of limitation of getc() ? here is my rubbish code
int get_file_size(char filename[])
{
FILE *p_file = NULL;
p_file = fopen(filename,"rb");
fseek(p_file,0,SEEK_END);
int size = ftell(p_file);
fclose(p_file);
return size;
}
int endec(char filename[],char psdw[])
{
FILE *f;
int hashed=0,ed=0;
int inphash=inhash(psdw);
inphash=inphash%50;
f=fopen(filename,"r");
if(f==NULL)
printf("failed");
char temps[999999];
long int crs=0,j=0;
int filesz=get_file_size(filename);
printf("file size = %d\n\n",filesz);
while(1){
inphash=inphash+2;
char ca=(char)inphash;
char ca2=fgetc(f);
printf("%c\n",ca2);
if(crs>=filesz)
break;
temps[crs]= ca2 ^ ca;
crs++;
}
fclose(f);
printf("%d",strlen(temps));
FILE *fp;
fp=fopen(filename,"wt");
for(j=0;j<crs;j++){
putc (temps[j] , fp);
printf("%c",temps[j]);
}
fclose(fp);
}
Your problem is right here:
f=fopen(filename,"r");
You open the file for text reading, not for binary. Your file size function gets it right, but your decoder function does not.
The idiomatic way to read a file character by character using the C-style IO routines is like this:
f = fopen(filename, "rb");
if (!f)
// handle error
int c; // NOTE: int, not char!
while ( (c = fgetc(f)) != EOF )
{
// do something with 'c'
}
This idiom does not require you to get the file size as a separate operation. You can rewrite your XOR "encryption" routine with a simple loop of the above form. It will be much clearer and more concise.
Your entire decoder function could be rewritten as follows: (minus the debug code)
int endec(char filename[], char psdw[])
{
int inphash = inhash(psdw) % 50;
char temp[999999]; // really, should be std::vector<char>
FILE *f;
if ( (f = fopen(filename, "rb")) == NULL )
{
printf("opening for read failed\n");
return -1;
}
size_t crs = 0;
int c;
while ( (c = fgetc(f)) != EOF )
{
inphash += 2;
temp[crs++] = (char)(inphash ^ c);
}
fclose(f);
if ( (f = fopen(filename, "wt")) == NULL )
{
printf("opening for write failed\n");
return -1;
}
if (fwrite(temp, crs, 1, f) != crs)
{
printf("short write\n");
fclose(f);
return -1;
}
fclose(f);
return 0;
}
Not stellar error handling, but it is error handling.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Could anyone tell me a simple way, how to read the last X bytes of a specific file?
If I'm right, I should use ifstream, but I'm not sure how to use it. Currently I'm learning C++ ( at least I'm trying to learn :) ).
Input file streams have the seekg() method that repositions the current position to an absolute position or a relative position. One overload takes a positon type that represents an absolute value. The other takes an offset type and direction mask that determines the relative position to move to. Negating the offset allows you to move backward. Specifying the end constant moves the indicator relative to the end.
file.seekg(-x, std::ios_base::end);
This is a C solution, but works and handles errors. The trick is to use a negative index in fseek to "seek from EOF" (ie: seek from the "right").
#include <stdio.h>
#define BUF_SIZE (4096)
int main(void) {
int i;
const char* fileName = "test.raw";
char buf[BUF_SIZE] = { 0 };
int bytesRead = 0;
FILE* fp; /* handle for the input file */
size_t fileSize; /* size of the input file */
int lastXBytes = 100; /* number of bytes at the end-of-file to read */
/* open file as a binary file in read-only mode */
if ((fp = fopen("./test.txt", "rb")) == NULL) {
printf("Could not open input file; Aborting\n");
return 1;
}
/* find out the size of the file; reset pointer to beginning of file */
fseek(fp, 0L, SEEK_END);
fileSize = ftell(fp);
fseek(fp, 0L, SEEK_SET);
/* make sure the file is big enough to read lastXBytes of data */
if (fileSize < lastXBytes) {
printf("File too small; Aborting\n");
fclose(fp);
return 1;
} else {
/* read lastXBytes of file */
fseek(fp, -lastXBytes, SEEK_END);
bytesRead = fread(buf, sizeof(char), lastXBytes, fp);
printf("Read %d bytes from %s, expected %d\n", bytesRead, fileName, lastXBytes);
if (bytesRead > 0) {
for (i=0; i<bytesRead; i++) {
printf("%c", buf[i]);
}
}
}
fclose(fp);
return 0;
}
You need to use he seekg function and pass a negative offset from the end of the stream.
std::ifstream is("file.txt");
if (is)
{
is.seekg(-x, is.end); // x is the number of bytes to read before the end
}
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char* argv)
{
ifstream ifs("F:\\test.data", ifstream::binary);
if(ifs.fail())
{
cout << "Error:fail to open file" << endl;
return -1;
}
//read the last 10 bits of file
const int X = 10;
char* buf = new char[X];
ifs.seekg(-X, SEEK_END);
ifs.read(buf, X);
ifs.close();
delete buf;
return 0;
}
Use seekg() for relative positionning from end of file, then use read():
ifstream ifs("test.txt");
int x=10;
char buffer[11]={};
ifs.seekg(-x, ios_base::end);
if (!ifs.read(buffer, x))
cerr << "There's a problem !\n";
else cout <<buffer<<endl;
Note that read() just takes the x bytes from the file and puts them in the buffer, without adding a '\0' at the end. So if you expect a C string, you have to make sure that your buffer ends with a 0.
I am writing a XOR encryption program which works fine during encryption but during decryption
the
char ca2=fgetc(f);
gets stuck at one point and no decryption takes place after that my best guess about the problem is (the encrypted file contains all sorts of characters ) as soon as fgetc reaches EOF mark which can be present before the actual end of the file it gets stuck there and stop reading the next characters .
is this some kind of limitation of getc() ? here is my rubbish code
int get_file_size(char filename[])
{
FILE *p_file = NULL;
p_file = fopen(filename,"rb");
fseek(p_file,0,SEEK_END);
int size = ftell(p_file);
fclose(p_file);
return size;
}
int endec(char filename[],char psdw[])
{
FILE *f;
int hashed=0,ed=0;
int inphash=inhash(psdw);
inphash=inphash%50;
f=fopen(filename,"r");
if(f==NULL)
printf("failed");
char temps[999999];
long int crs=0,j=0;
int filesz=get_file_size(filename);
printf("file size = %d\n\n",filesz);
while(1){
inphash=inphash+2;
char ca=(char)inphash;
char ca2=fgetc(f);
printf("%c\n",ca2);
if(crs>=filesz)
break;
temps[crs]= ca2 ^ ca;
crs++;
}
fclose(f);
printf("%d",strlen(temps));
FILE *fp;
fp=fopen(filename,"wt");
for(j=0;j<crs;j++){
putc (temps[j] , fp);
printf("%c",temps[j]);
}
fclose(fp);
}
Your problem is right here:
f=fopen(filename,"r");
You open the file for text reading, not for binary. Your file size function gets it right, but your decoder function does not.
The idiomatic way to read a file character by character using the C-style IO routines is like this:
f = fopen(filename, "rb");
if (!f)
// handle error
int c; // NOTE: int, not char!
while ( (c = fgetc(f)) != EOF )
{
// do something with 'c'
}
This idiom does not require you to get the file size as a separate operation. You can rewrite your XOR "encryption" routine with a simple loop of the above form. It will be much clearer and more concise.
Your entire decoder function could be rewritten as follows: (minus the debug code)
int endec(char filename[], char psdw[])
{
int inphash = inhash(psdw) % 50;
char temp[999999]; // really, should be std::vector<char>
FILE *f;
if ( (f = fopen(filename, "rb")) == NULL )
{
printf("opening for read failed\n");
return -1;
}
size_t crs = 0;
int c;
while ( (c = fgetc(f)) != EOF )
{
inphash += 2;
temp[crs++] = (char)(inphash ^ c);
}
fclose(f);
if ( (f = fopen(filename, "wt")) == NULL )
{
printf("opening for write failed\n");
return -1;
}
if (fwrite(temp, crs, 1, f) != crs)
{
printf("short write\n");
fclose(f);
return -1;
}
fclose(f);
return 0;
}
Not stellar error handling, but it is error handling.
Noobie Alert.
Ugh. I'm having some real trouble getting some basic file I/O stuff done using <stdio.h> or <fstream>. They both seem so clunky and non-intuitive to use. I mean, why couldn't C++ just provide a way to get a char* pointer to the first char in the file? That's all I'd ever want.
I'm doing Project Euler Question 13 and need to play with 50-digit numbers. I have the 150 numbers stored in the file 13.txt and I'm trying to create a 150x50 array so I can play with the digits of each number directly. But I'm having tons of trouble. I've tried using the C++ <fstream> library and recently straight <stdio.h> to get it done, but something must not be clicking for me. Here's what I have;
#include <iostream>
#include <stdio.h>
int main() {
const unsigned N = 100;
const unsigned D = 50;
unsigned short nums[N][D];
FILE* f = fopen("13.txt", "r");
//error-checking for NULL return
unsigned short *d_ptr = &nums[0][0];
int c = 0;
while ((c = fgetc(f)) != EOF) {
if (c == '\n' || c == '\t' || c == ' ') {
continue;
}
*d_ptr = (short)(c-0x30);
++d_ptr;
}
fclose(f);
//do stuff
return 0;
}
Can someone offer some advice? Perhaps a C++ guy on which I/O library they prefer?
Here's a nice efficient solution (but doesn't work with pipes):
std::vector<char> content;
FILE* f = fopen("13.txt", "r");
// error-checking goes here
fseek(f, 0, SEEK_END);
content.resize(ftell(f));
fseek(f, 0, SEEK_BEGIN);
fread(&content[0], 1, content.size(), f);
fclose(f);
Here's another:
std::vector<char> content;
struct stat fileinfo;
stat("13.txt", &fileinfo);
// error-checking goes here
content.resize(fileinfo.st_size);
FILE* f = fopen("13.txt", "r");
// error-checking goes here
fread(&content[0], 1, content.size(), f);
// error-checking goes here
fclose(f);
I would use an fstream. The one problem you have is that you obviously can't fit the numbers in the file into any of C++'s native numeric types (double, long long, etc.)
Reading them into strings is pretty easy though:
std::fstream in("13.txt");
std::vector<std::string> numbers((std::istream_iterator<std::string>(in)),
std::istream_iterator<std::string>());
That will read in each number into a string, so the number that was on the first line will be in numbers[0], the second line in numbers[1], and so on.
If you really want to do the job in C, it can still be quite a lot easier than what you have above:
char *dupe(char const *in) {
char *ret;
if (NULL != (ret=malloc(strlen(in)+1))
strcpy(ret, in);
return ret;
}
// read the data:
char buffer[256];
char *strings[256];
size_t pos = 0;
while (fgets(buffer, sizeof(buffer), stdin)
strings[pos++] = dupe(buffer);
Rather than reading the one hundred 50 digit numbers from a file, why not read them directly in from a character constant?
You could start your code out with:
static const char numbers[] =
"37107287533902102798797998220837590246510135740250"
"46376937677490009712648124896970078050417018260538"...
With a semicolon at the last line.
Is there a function for FILE (fopen?) that allows me to just read one int from a binary file?
So far I'm trying this, but I'm getting some kind of error I can't see cause the program just crashes without telling me.
void opentest()
{
FILE *fp = fopen("dqmapt.mp", "r");
int i = 0;
int j = 0;
int k = 0;
int * buffer;
if (fp)
{
buffer = (int *) (sizeof(int));
i = (int) fread(buffer,1, (sizeof(int)), fp);
fscanf(fp, "%d", &j);
fclose(fp);
}
printf("%d\n", i);
printf("%d\n", j);
}
Now that you have changed your question, let me ask one. What is the format of the file you are trying to read?
For a binary file there are some changes required how you open the file:
/* C way */
FILE *fp = fopen("text.bin", "rb"); /* note the b; this is a compound mode */
/* C++ way */
std::ifstream ifs("test.txt", ios::in | ios::binary);
Reading in the contents is easy. But remember, your file has 2 integers at the begining -- width, height which determine how many more to read i.e. another width * height number of integers. So, your best bet is to read the first two integers first. You will need to use two buffers -- one for the width and height and then depending on their value another one to read the rest of the file. So, lets read in the first two integers:
char buf[ 2 * sizeof(int) ]; /* will store width and height */
Read in the two integers:
/* C way */
fread(buf, sizeof(int), 2, fp); /* the syntax changes, FILE pointer is last */
/* C++ way*/
ifs.read(buf, sizeof buf);
Now, the tricky part. You have to convert the stuff to double. This again depends on your system endianness -- whether a simple assignment works or whether a byte swapping is necessary. As another poster has pointed out WriteInt() writes integers in big-endian format. Figure out what system you are on. And then you can proceed further.
FILE is a C datastructure. It is included in C++ for C compatibility. You can do this:
/* The C way */
#include <stdio.h>
#include <stdlib.h>
int main(void) {
FILE *fp = fopen("test.txt", "r");
int i = 0;
if (fp) {
fscanf(fp, "%d", &i);
fclose(fp);
}
printf("%d\n", i);
}
You can use the std::ifstream thing to open a file for reading. You have to read in the contents using some other incantation to read the file contents and extract the desired information out of it yourself.
/* The C++ way */
#include <fstream>
#include <iostream>
int main() {
std::ifstream ifs("test.txt");
int i = 0;
if (ifs.good()) {
ifs >> i;
}
std::cout << i << std::endl;
}
Note you can use the C style functions in C++ as well, though this is the least recommended way:
/* The C way in C++ */
#include <cstdio>
#include <cstdlib>
int main() {
using namespace std;
FILE *fp = fopen("test.txt", "r");
int i = 0;
if (fp) {
fscanf(fp, "%d", &i);
fclose(fp);
}
printf("%d\n", i);
}
[Note: Both examples assume you have a text file to read from]
Do you want to read a textual representation of an int? Then you can use fscanf, it's sort of the opposite of printf
int n;
if( fscanf(filePointer, "%d", &n) == 1 )
// do stuff with n
If you want to read some binary data and treat it as an int, well that's going to depend how it was written in the first place.
I am not a Java programmer, so this is just based on what I've read in the [docs](http://java.sun.com/j2se/1.4.2/docs/api/java/io/DataOutputStream.html#writeInt(int)).
That said, it says
Writes an int to the underlying output stream as four bytes, high byte first. If no exception is thrown, the counter written is incremented by 4.
So it's a big endian four byte integer. I don't know if it's two's complement or not, but that's probably a safe assumption (and can probably be found somewhere in the java docs/spec). Big endian is the same as network byte order, so you can use ntohl to convert it the endianness of your C++ platform. Beyond that, you just need to read the four bytes, which can be done with fread.
Int represented as text or binary?
For text, use fscanf; for binary, use fread.