iv'e written a part of a code which basically transfers text from a txt file into a variable and prints it(as a part of a program),yet it does not print the contents at all.
#include <stdio.h>
#include <stdlib.h>
#define WRONG_ARGUMENTS (-1)
int Lines(FILE * file);
int Length(FILE * file);
int Read(FILE * file);
int Lines(FILE * file)
{
int c=0,count=0;
++count;
while(c!=EOF)
{
c=fgetc(file);
if(c=='\n')
++count;
}
return count;
}
int Length(FILE * file)
{
int c,count=0;
while((c=fgetc(file))!=EOF)
{
++count;
}
return count;
}
int Reader(FILE * Text,char * File)
{
int counter=0;
while(fscanf(Text,"%s",File)!=EOF)
{
++counter;
strcat(File," ");
}
return counter;
}
int main(int argc,char * argv[]) {
FILE * Text=NULL;
if(argc!=2)
{
printf("usage:library text dictionary\n");
return -1;
}
Text = fopen(argv[1],"r");
if(Text==NULL)
{
printf("file %s could not be opened\n",argv[1]);
return -1;
}
char * File = "";
File=malloc(Length(Text)*(sizeof(char)));
int r = Reader(Text,File);
printf(File);
return 0;
}
i will be more than glad to understand the problem in the partial code
the output is x>
thanks,
Consider the following cut-down example. You'll notice that the getFileLength function (a) doesn't actually read anything from the file and (b) makes use of the fseek and ftell functions - fseek is the function that you use to reposition the file-pointer when it reaches EOF.
Imagine that you weren't printing the data, but doing something else with it. What if the file is a billion bytes long? We sure don't want to read 1,000,000,000 times from it just to determine its length!
As for the use of calloc - it zero initializes the data it allocates. Since you're reading text, you want to ensure that the text is NULL-terminated. (NULL generally = 0, though I've seen evil macros that change this) This NULL terminator is also why I allocate 1 byte more than the file contains.
#include <stdio.h>
#include <stdlib.h>
long getFileLength(FILE *input)
{
long result;
long origPos = ftell(input);
fseek(input, 0, SEEK_END);
result = ftell(input);
fseek(input, origPos, SEEK_SET);
return result;
}
int main (void)
{
FILE *fp;
long fileLen, numBytesRead;
char *data;
fp = fopen("main.cpp", "rb");
fileLen = getFileLength(fp);
data = (char*)calloc(sizeof(char), fileLen+1);
numBytesRead = fread(data, sizeof(char), fileLen, fp);
if (numBytesRead != fileLen)
printf("Error reading all bytes from file. Expected: %d, Read %d\n", fileLen, numBytesRead);
else
printf("%s", data);
free(data);
fclose(fp);
}
Related
I'm following a course about programming and went smooth so far. Now I'm stuck into this exercise which asks us to reverse a WAV file in C.
I have two questions about it:
It seems to work and correctly reverse few seconds audios but on longer ones it doesn't anymore. Why?
I previously added a get_data_size function to know a value to use later in the program, but after discovering the fseek() function it wasn't needed anymore. So I wanted to delete it, but if I do I get the "segmentation fault" error, while if I keep it it just runs ok. Why?
EDIT: Ok, now MAGICALLY, I tried to delete the get_data size function again and compiled it... and it doesn't go to segfault anymore. without changing anything. It still doesn't reverse the longer files though.
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "wav.h"
int check_format(WAVHEADER header);
int get_block_size(WAVHEADER header);
long get_data_size(FILE *input, int size);
int main(int argc, char *argv[])
{
// Ensure proper usage
if (argc != 3)
{
printf("insert input and output names");
return 2;
}
// Open input file for reading
char *infile = argv[1];
char *outfile = argv[2];
FILE *input = fopen(infile, "r");
if (input == NULL)
{
printf("could not open the file\n");
return 1;
}
// Read header into an array
WAVHEADER inwav;
fread(&inwav, sizeof(WAVHEADER), 1, input);
// Use check_format to ensure WAV format
if (check_format(inwav) != 0)
{
fclose(input);
printf("not a valid format");
return 3;
}
// Open output file for writing
FILE *output = fopen(outfile, "w");
if (output == NULL)
{
printf("could not open the file\n");
return 1;
}
// Write header to file
fwrite(&inwav, sizeof(WAVHEADER), 1, output);
// Use get_block_size to calculate size of block
int n = get_block_size(inwav);
//not needed anymore
long s = get_data_size(input, n);
//Sets it to the end of the file
fseek(input, n, SEEK_END);
// Write audio to file from the last block to the first
while (ftell(input) != sizeof(WAVHEADER))
{
WORD temp;
fread(&temp, n, 1, input);
fwrite(&temp, n , 1, output);
fseek(input, -2 * n, SEEK_CUR);
}
fclose(input);
fclose(output);
return 0;
}
int check_format(WAVHEADER header)
{
// Checks for the WAVE spelt in the header
if (header.format[0] != 'W' && header.format[1] != 'A' && header.format[2] != 'V' && header.format[3] != 'E')
{
return 1;
}
return 0;
}
int get_block_size(WAVHEADER header)
{
//Double checks the channels are either 1 or 2 and calculates the BYTES per audio block
if (header.numChannels == 1 || header.numChannels ==2)
{
int size = (header.bitsPerSample / 8) * header.numChannels;
return size;
}
else
{
printf("not supported\n");
return 0;
}
return 0;
}
//not needed anymore
long get_data_size(FILE *input, int size)
{
long data = 0;
int temp;
while (!feof(input))
{
fread (&temp, 1, 1, input);
data++;
}
return data;
}
```
#include <stdint.h>
typedef uint8_t BYTE;
typedef uint16_t WORD;
typedef uint32_t DWORD;
typedef struct
{
BYTE chunkID[4];
DWORD chunkSize;
BYTE format[4];
BYTE subchunk1ID[4];
DWORD subchunk1Size;
WORD audioFormat;
WORD numChannels;
DWORD sampleRate;
DWORD byteRate;
WORD blockAlign;
WORD bitsPerSample;
BYTE subchunk2ID[4];
DWORD subchunk2Size;
} __attribute__((__packed__))
WAVHEADER;
I have a large file containing floating point numbers and I want to read them.
52.881 49.779 21.641 37.230 23.417 7.506 120.190 1.240 79.167 82.397 126.502 47.377 112.583 124.590 103.339 5.821 24.566 38.916 42.576
This is just the beggining of the file. It has 10000000 numbers.
I got this code but I don't know how to print the numbers.
#include <stdio.h>
#include <stdlib.h>
#include <err.h>
#include <fcntl.h>
#include <sysexits.h>
#include <unistd.h>
int main()
{
int fd;
size_t bytes_read, bytes_expected = 1000000*sizeof(double);
double *data;
char *infile = "file.dat";
if ((fd = open(infile,O_RDONLY)) < 0)
err(EX_NOINPUT, "%s", infile);
if ((data = malloc(bytes_expected)) == NULL)
err(EX_OSERR, "data malloc");
bytes_read = read(fd, data, bytes_expected);
if (bytes_read != bytes_expected)
err(EX_DATAERR, "Read only %d of %d bytes",
bytes_read, bytes_expected);
/* print all */
free(data);
exit(EX_OK);
}
You are attempting to read a text file as if the data was binary, so you will read some bytes but the double values stored in the array will not be the values that you wanted to read from the file, you can probably do this
FILE *file;
double *array;
size_t count;
const char *infile = "file.dat";
file = fopen(infile, "r");
if (file == NULL)
return -1;
count = 0;
while (fscanf(file, "%*lf") == 1)
count += 1;
rewind(file);
array = malloc(count * sizeof(*array));
if (array == NULL) {
fprintf(stderr, "cannot allocate %zu bytes!\n", count * sizeof(*array));
fclose(file);
return -1;
}
// Read the values into the array
for (size_t i = 0; i < count; ++i) {
fscanf(file, "%lf", &array[i]);
}
// Print the array
for (size_t i = 0; i < count; ++i) {
fprintf(stdout, "%f\n", array[i]);
}
// Release memory
free(array);
Since you want a fast solution, maybe you have to sacrifice memory.
The faster manner of reading a file is in binary form.
Thus, I would obtain the file size with an efficient method,
then I would allocate memory accordingly,
with the idea of uploading the entire file to memory.
There, since memory reading is faster than file reading,
the data can be quickly read by using sscanf(...).
We can also observe that each floating point number
needs at least 3 characters to be stored in a text file:
1 char for the dot ('.'),
1 char for some digit,
and 1 char for
a space (' ') used to separating a value from its succesor in the
file.
Thus, the file size divided by 3 will be the upper bound for the size of the array of doubles.
#include <stdio.h>
int main(void) {
char *filename = "file.dat";
FILE *F = fopen(filename, "rb");
fseek(F, 0L, SEEK_END);
long int filesize = ftell(F);
rewind(F);
char *data = malloc(filesize+1);
fread(data, filesize, 1, F);
data[filesize] = '\0'; // End of string, just in case
fclose(F);
// The desired data will be stored in array:
double *array = malloc(sizeof(double) * filesize/3);
int ret;
int n; // represents the no chars in a sscanf(...) reading
double *a = array;
while (1) { // Infinite loop...
ret = sscanf(data, " %lg%n", a, &n);
if (ret == EOF) break; // <<---- EXIT POINT of the loop
a++;
data += n;
}
long int array_size = a - array + 1;
}
I need to build a program that reads each record, and according to that record information would update some other records on the same file. For that, I was thinking in this approach:
int main(int argc, char *argv[]) {
FILE *my_file;
int files_read;
struct my_struct an_struct;
my_file = fopen("myfile.dat", "rb");
files_read = fread(&an_struct, sizeof(struct my_struct), 1, my_file);
printf("main->files_read: %d \n", files_read); //This prints one
while (files_read == 1) {
do_update();
files_read = fread(&an_struct, sizeof(struct my_struct), 1, my_file);
printf("main->files_read: %d \n", files_read); //This prints one
}
fclose(archivo_paises);
return 0;
}
In the main function I'm reading the contents of the file, and every time I call read I get one as a response until I reach the end of the file. The problem is in the do_update function:
void do_update() {
FILE *my_file;
int files_read;
struct my_struct an_struct;
struct my_struct another_struct;
my_files = fopen("myfile.dat", "wb+"); //Using rb+ solves it
files_read = fread(&an_struct, sizeof(struct my_struct), 1, my_file);
printf("do_update->files_read: %d \n", files_read);
//This printed zero!. Prints one using rb+
while (files_read == 1) { //This never gets executed. Unless you use rb+
if(something){
fwrite(&another_struct, sizeof(struct my_struct), 1, my_file);
// Using rb+, this returns zero and didn't update
}
files_read = fread(&an_struct, sizeof(struct my_struct), 1, my_file);
printf("do_update->files_read: %d \n", files_read);
}
fclose(my_file);
}
What's happening is that the files_read variable gets the value of zero after the read call, so the logic to update the file is never executed.
Why is read returning zero when opening a file for wb+?
Update:
Using rb+ as file mode on do_update() works, but now the call to fwrite() always returns zero, and it didn't update the file. Is is related to the mode?
fwrite is moving the position in the file to the end of the file. The fread then has nothing to read.
Use fgetpos to save the file position before the fwrite, and fsetpos to set the position back after the fwrite.
The meaning of the flag "w+" (from http://www.cplusplus.com/reference/cstdio/fopen/):
write/update: Create an empty file and open it for update (both for input and output). If a file with the same name already exists its contents are discarded and the file is treated as a new empty file.
When you open a file with "w+", you will need to write to it first before you can read from it.
Update
Example program to demonstrate use of "rb+".
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void createFile(char const* filename, int num)
{
int i = 0;
int data = 0;
FILE* out = fopen(filename, "wb");
if ( out == NULL )
{
return;
}
for (i = 0; i < num; ++i )
{
data = rand()/10000;
fwrite(&data, sizeof(data), 1, out);
}
fclose(out);
}
void displayFileContents(char const* filename, int num)
{
int i = 0;
int data = 0;
FILE* in = fopen(filename, "rb");
if ( in == NULL )
{
return;
}
for (i = 0; i < num; ++i )
{
fread(&data, sizeof(data), 1, in);
printf("%d\n", data);
}
fclose(in);
}
void testReadAndWrite(char const* filename, int num)
{
int i = 0;
int data = 0;
long int pos = 0;
FILE* in = fopen(filename, "rb+");
if ( in == NULL )
{
return;
}
for ( i = 0; i < num; ++i )
{
pos = ftell(in);
fread(&data, sizeof(data), 1, in);
printf("%d\n", data);
// Rewind to previos position.
fseek(in, pos, SEEK_SET);
// Write at the previus position.
data = rand();
printf("%d\n", data);
if ( fwrite(&data, sizeof(data), 1, in) != 1 )
{
printf("Unable to write using fwrite.\n");
}
// Rewind to previos position.
fseek(in, pos, SEEK_SET);
// Read from the previus position.
if ( fread(&data, sizeof(data), 1, in) != 1 )
{
printf("Unable to read using fread.\n");
}
printf("%d\n\n", data);
}
fclose(in);
}
int main()
{
char const* filename = "test.txt";
int num = 10;
// See the random number generator.
srand(time(NULL));
// Create a file with some random data.
createFile(filename, num);
// Display the contents of the file.
displayFileContents(filename, num);
printf("\n");
// Test read and write using a single FILE*
testReadAndWrite(filename, num);
}
Sample output:
51830
169074
141071
61921
145333
101195
139074
9535
164668
49552
51830
1030292590
1030292590
169074
1003635396
1003635396
141071
1060541073
1060541073
61921
474399692
474399692
145333
1467401071
1467401071
101195
830521014
830521014
139074
1186142943
1186142943
9535
1759682963
1759682963
164668
848798825
848798825
49552
60932215
60932215
I tried cyclically read file in buffer of 100 byte.
When i read file first time - buffer was full. Returned value is 0. No error and no eof (functions "ferror" and "feof" shows no error). Then i tried read file second time and again returned value is 0, no error and no eof. But then i have empty buffer. I don't know what is the problem?
if(fopen_s(&file_in, argv[1], "rb") == 0){
printf("File was opened.\n");
while(!feof(file_in)){
read_code = fread_s(file_data, 100, sizeof(unsigned char), 100, file_in);
if(ferror(file_in)) {
printf("Error!\n");
}
if(feof(file_in)) {
printf("Eof!\n");
}
printf("Read result: %d\n", read_code);
/*Using the buffer*/
memset(file_data, 0, 100);
}
fclose(file_in);
}
For the reasons given in comments regarding fopen_s, et. al., Here is an alternative implementation of reading a binary file using getc(), along with fopen(), fclose(), etc. (I am not using a Microsoft implementation, but am using ANSI C99)
It has a commented section I used to create a test binary file. Other than that it sizes the file you are reading so you can allocate the right amount of memory, then reads the binary data into a buffer.
For navigating your file, take a look at fseek() with its stdio.h defined arguments:
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
In this example, everything is closed or freed before exiting:
#include <windows.h>
#include <ansi_c.h>
long int getFileSizeFromPath(char * path)
{
FILE * file;
long int fileSizeBytes = 0;
file = fopen(path,"r");
if(file){
fseek(file, 0, SEEK_END);
fileSizeBytes = ftell(file);
fseek(file, 0, SEEK_SET);
fclose(file);
}
return fileSizeBytes;
}
int main(int argc, char *argv[])
{
FILE *fp=0;
char *binBuf;
long int size=0;
int i=0;
int byte=0;
//create 100 byte test file (c:\\dev\\tessst.bin)
// fp = fopen(argv[1], "wb");
//
// srand(clock());
// for(i=0;i<100;i++)
// {
// byte = rand();
// putc(byte, fp);
// }
// putc(EOF, fp);
//
// fclose(fp);
size = getFileSizeFromPath(argv[1]);
binBuf = calloc(size + 1, sizeof(char));
fp = fopen(argv[1], "rb");
byte = getc(fp);
while(byte != EOF)
{
binBuf[i++] = (char)byte;
byte = getc(fp);
}
fclose(fp);
free(binBuf);
return 0;
}
I was wondering how I can get this code to overwrite a textfile from it's text value to it's ASCII value.
I want it to do something like this:
CMD > c:\users\username\desktop>cA5.exe content.txt
content.txt has "abc" in it and I want the command line to change the "abc" to it's ASCII values. 97... etc. I don't want anything written in the command window, I want it to change in the text file. Is this possible, if so, how could I do it with this existing code?
#include <stdio.h>
#include <stdlib.h>
int main(int argc[1], char *argv[1])
{
FILE *fp; // declaring variable
fp = fopen(argv[1], "rb");
if (fp != NULL) // checks the return value from fopen
{
int i;
do
{
i = fgetc(fp); // scans the file
printf("%c",i);
printf(" ");
}
while(i!=-1);
fclose(fp);
}
else
{
printf("Error.\n");
}
}
Not the best code but very simple.
#include <stdio.h>
#include <stdlib.h>
void convertToAHex(char *data, long int size, FILE *file){
rewind(file);
int i;
for(i = 0; i < size; ++i){
fprintf(file, "%d ", data[i]);
}
}
int main(int argc, char *argv[]){
if(argc != 2){
return EXIT_FAILURE;
}
FILE *file = fopen(argv[1], "r+");
if(file){
char *data;
long int size;
fseek(file, 0, SEEK_END);
size = ftell(file);
rewind(file);
data = (char *) calloc(size, sizeof(char));
if(data){
fread(data, 1, size, file);
convertToAHex(data, size, file);
free(data);
}
fclose(file);
}
return EXIT_SUCCESS;
}