Memory problems with a course exercise in C - c

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;

Related

Reading the files contents to the allocated string

I am trying to read the contents of a file and copy those contents into a string which has dynamic memory. However my program keeps allocating only 8 bytes to x. Ultimately I'm trying to create a general function that can read contents from a file and then return the contents as a char. Any help is appreciated.
char* readFile(unsigned long size, char *fileName) {
FILE *file = fopen(fileName, "r");
int c;
if(file != NULL)
{
while(c != EOF){ //calculate size of file
c = fgetc(file); //store character
size++;
}
char *x = (char *)malloc((size) * (sizeof(char))); // Size of x = 8 and I'm not sure why
rewind(file);
printf("\n");
int i = 0;
while(size - 1 > i){ //Reading the files contents to the allocated string
c = fgetc(file); //store character
if(c == EOF){
break;
}
x[i] = c;
i++;
}
fclose(file);
printf("Done Reading");
}
else
{
printf("\nError: Unable to open the file for Reading.\n");
}
rewind(file);
return 0;
}
I get a segmentation fault when I run
char* str = readFile(size, originalFile);
I would use stat to first get the size of your file
stat() retrieves information about the file pointed
to by pathname;
And then I made some tiny modifications to your function to make it work:
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
char* readFile(char *fileName) {
FILE *file;
struct stat st;
if (!(file = fopen(fileName, "r")))
return NULL;
stat(fileName, &st);
unsigned long size = st.st_size;
char *x;
if (!(x = (char *)malloc((size + 1) * (sizeof(char))))) // Size of x = 8 and I'm not sure why
return NULL;
unsigned long i = 0;
while (i < size) //Reading the files contents to the allocated string
x[i++] = getc(file);
x[i] = '\0';
fclose(file);
printf("Done Reading\n");
return x;
}
int main(void) {
char *fileName = "a.txt";
char *res = readFile(fileName);
printf("%s\n", res);
return 0;
}
Don't forget that in C strings are NULL terminated, you need to malloc size+1 to add the final '\0'.
This is (IMHO) an easier way to find the size of the file:
char *readFile(const char *fileName)
{
unsigned long size = 0;
char *x;
FILE *file = fopen(fileName, "r");
int c;
if (file != NULL)
{
fseek(file, 0, SEEK_END); /* SET the position at EOF */
size = ftell(file); /* Record the position at EOF to return size of file */
rewind(file); /* SET position back to Origin */
printf("size detected %ld\n", size); // reads correct size
x = (char *)malloc((size) * (sizeof(char)));
rewind(file);
printf("\n");
int i = 0;
while (size - 1 > i)
{ //Reading the files contents to the allocated string
c = fgetc(file); //store character
if (c == EOF)
{
break;
}
x[i] = c;
i++;
}
fclose(file);
printf("Done Reading\n");
}
else
{
printf("\nError: Unable to open the file for Reading.\n");
return NULL;
}
rewind(file);
return x; // * you need to return x not zero
}
Successfully reads the content of the file:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *data;
data = readFile("records.txt");
printf("%s\n", data);
return 0;
}

Compare two binary files in C

I am writing a program to compare two binary files and plot the first difference. I want to read 16 bytes of data from each file continuously and compare them. For that I am storing 16 bytes from both file into char *buffer1, buffer2. When I print the output I am getting that buffer1 has both the data of file1 and file2.
The code is as follows:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void printConversion(char *buf1, char *buf2) {
size_t len = strlen(buf1);
char *binary = malloc(len * 8 + 1);
binary[0] = '\0';
for (size_t i = 0; i < len; ++i) {
char ch = buf1[i];
for (int j = 7; j >= 0; --j) {
if (ch & (1 << j)) {
strcat(binary,"1");
} else {
strcat(binary,"0");
}
}
}
printf("File1: %s\t", binary);
free(binary);
printf("File2:");
for (int i = 0; i < sizeof(buf2); i++) {
printf("%x", buf2[i] - '0');
}
}
void fileRead(FILE *fp, char *buf, int count) {
fseek(fp, count, SEEK_SET);
fread(buf, 1, 16, fp);
}
int fileSize(FILE *fp) {
fseek(fp, 0, SEEK_END);
int size = ftell(fp) + 1;
return size;
}
int main(int argc, char *argv[]) {
printf("***Binary File Comparator***\n ");
int count = 0;
int index = 0;
char buffer1[16];
char buffer2[16];
char buffer3[16];
char buffer4[16];
// Invalid Number of Arguments
if (argc < 3 || argc > 3) {
printf("Invalid Number of Arguments\n");
}
FILE *fp1, *fp2;
fp1 = fopen(argv[1], "rb");
int size = fileSize(fp1);
int size1 = size;
fclose(fp1);
while (size > 1) {
fp1 = fopen(argv[1], "rb");
fileRead(fp1, buffer1, count);
fclose(fp1);
fp2 = fopen(argv[2], "rb");
fileRead(fp2, buffer2, count);
if (size1 < count) {
int lastSize = count - size1;
count = count + lastSize;
fclose(fp2);
} else {
count = count+16;
fclose(fp2);
}
**printf("buffer1:%s\tbuffer2:%s\n", buffer1, buffer2)**;
size = size - 16;
int result = strcmp(buffer1, buffer2);
if (result != 0) {
for (int i = 0; i < sizeof(buffer1); i++) {
if (buffer1[i] != buffer2[i]) {
int count1 = (count - 16) + i;
index++;
if (index == 1) {
printf("Byte_Offset:%x\n", count1);
fp1 = fopen(argv[1], "rb");
fileRead(fp1, buffer3, count1);
fclose(fp1);
fp2 = fopen(argv[2], "rb");
fileRead(fp2, buffer4, count1);
fclose(fp2);
printConversion(buffer3, buffer4);
break;
}
} else {
continue;
}
}
}
}
}
I have tried to highlight the printf part that is printing my buffer1 and buffer2
The output is as follows:
buffer1:83867715933586928386771593358692 buffer2:8386771593358692
buffer1:49216227905963264921622790596326 buffer2:4921622790596326
buffer1:40267236116867294026723611686729 buffer2:4026723611686729
buffer1:82306223673529228230622367352922 buffer2:8230622367352922
buffer1:25869679356114222586967935611422 buffer2:2586967935611422
Can anybody help what I am doing wrong. Please point me the error and what optimization changes could be done in code. I am at learning stage your feedback will be very helpful.
You are complicating the task by reading 16 bytes at a time. If the goal is to indicate the first difference, just read one byte at a time from both files with getc() this way:
int compare_files(FILE *fp1, FILE *fp2) {
unsigned long pos;
int c1, c2;
for (pos = 0;; pos++) {
c1 = getc(fp1);
c2 = getc(fp2);
if (c1 != c2 || c1 == EOF)
break;
}
if (c1 == c2) {
printf("files are identical and have %lu bytes\n", pos);
return 0; // files are identical
} else
if (c1 == EOF) {
printf("file1 is included in file2, the first %lu bytes are identical\n", pos);
return 1;
} else
if (c2 == EOF) {
printf("file2 is included in file1, the first %lu bytes are identical\n", pos);
return 2;
} else {
printf("file1 and file2 differ at position %lu: 0x%02X <> 0x%02X\n", pos, c1, c2);
return 3;
}
}
In terms of efficiency, reading one byte at a time does not pose a problem if the streams are buffered. For large files, you can get better performance by memory mapping the file contents if available on the target system and for the given input streams.
Not an actual answer, but a word on optimisation. You can increase the speed of the program if you have a bigger buffer. Basically the larger the buffer the faster the program runs HOWEVER the speed you gain from just making it larger will increase logarithmically.
Here is a picture of a graph that will help you understand. Also, what i mentioned applies to any simmilar situation. This includes: Copying files, filling the sound buffer etc. Loading the entire file in your RAM first and operationg on it will usually be faster than loading parts of it. Ofc this is not possible with larger files but still this is what you should aim for if you want speed.
PS: I'm writting here because i don't have rep to comment.
EDIT: I came up with solution but since you did not state what you need to do with your buffer3 and buffer4 i packed it up inside a function.
If you are sure that you are only going to use 16 bytes as a buffer size, remove the nBufferSize parameter and replace the buffer dynamic allocation with a static one.
If after the execution you need the buffers, add them as parameters and keep the nBufferSize param. Keep in mind that if you intend to use them outside the function, you should also allocate them outside the function, so things don't get messy.
/** Returns 0 if files are identical, 1 if they are different and -1 if there
is an error. */
int FileCmp(char* szFile1, char* szFile2, int nBufferSize)
{
FILE *f1, *f2;
f1 = fopen(szFile1, "rb");
f2 = fopen(szFile2, "rb");
// Some error checking?
if (f1 == NULL || f2 == NULL)
return -1;
// You can check here for file sizes before you start comparing them.
// ...
// Start the comparrison.
/// Replace this part with static allocation. --------
char* lpBuffer1 = malloc(sizeof(char)*nBufferSize);
if (lpBuffer1 == NULL) // close the files and return error.
{
fclose(f1);
fclose(f2);
return -1;
}
char* lpBuffer2 = malloc(sizeof(char)*nBufferSize);
if (lpBuffer2 == NULL) // close the files, free buffer1 and return error.
{
free(lpBuffer1);
fclose(f1);
fclose(f2);
return -1;
}
/// --------------------------------------------------
while(1)
{
unsigned int uRead1 = fread(lpBuffer1, sizeof(char), nBufferSize, f1);
unsigned int uRead2 = fread(lpBuffer2, sizeof(char), nBufferSize, f2);
if (uRead1 != uRead2)
goto lFilesAreDifferent;
for(unsigned int i = 0; i < uRead1; i++)
if (lpBuffer1[i] != lpBuffer2[i])
goto lFilesAreDifferent;
if ((feof(f1) != 0) && (feof(f2) != 0))
break; // both files have nothing more to read and are identical.
goto lSkip;
lFilesAreDifferent:
free(lpBuffer1);
free(lpBuffer2);
fclose(f1);
fclose(f2);
return 1;
lSkip:;
}
// The files are the same. Close them, free the buffers and return 0.
free(lpBuffer1);
free(lpBuffer2);
fclose(f1);
fclose(f2);
return 0;
}
A simple Demo:
#define BUFFER_SIZE 16
int main(int nArgs, char** szArgs)
{
if (nArgs != 3)
{
printf("Invalid number of arguments.");
return 0;
}
int nResult = FileCmp(szArgs[1], szArgs[2], BUFFER_SIZE);
switch (nResult)
{
case 0: printf("Files [%s] and [%s] are identical.", szArgs[1], szArgs[2]); break;
case 1: printf("Files [%s] and [%s] are different.", szArgs[1], szArgs[2]); break;
case -1: printf("Error."); break;
}
return 0;
}
EDIT II: Personally, i have never used the C standard FILE library (it was either C++ fstream or pure win32 fileapi) so don't take my word here for granted but fread is the fastest function i could find (faster than fgets or fgetc). If you want even faster than this you should get into OS dependant functions (like ReadFile() for Windows).
chqrlie's solution using getc is absolutely the right way to do this. I wanted to address some points brought up in comments, and find it's best to do that with code. In one comment, I recommend pseudo code which could be confusing (namely, you can't write fwrite(file1...) || fwrite(file2 ...) because of the short circuit. But you can implement the idea of that with:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*
* Compare two files, 16 bytes at a time. (Purely to demonstrate memcmp.
* Clearly, this should be implemented with getc.)
*/
FILE * xfopen(const char *, const char *);
size_t xfread(void *, FILE *, const char *);
int
main(int argc, char **argv)
{
FILE *fp[2];
size_t n[2];
char buf[2][16];
unsigned count = 0;
if(argc != 3) { return EXIT_FAILURE; }
fp[0] = xfopen(argv[1], "r");
fp[1] = xfopen(argv[2], "r");
do {
n[0] = xfread(buf[0], fp[0], argv[1]);
n[1] = xfread(buf[1], fp[1], argv[2]);
if( n[0] != n[1] || (n[0] && memcmp(buf[0], buf[1], n[0]))) {
fprintf(stderr, "files differ in block %u\n", count);
return 1;
}
count += 1;
} while(n[0]);
puts("files are identical");
return 0;
}
size_t
xfread(void *b, FILE *fp, const char *name)
{
size_t n = fread(b, 1, 16, fp);
if(n == 0 && ferror(fp)) {
fprintf(stderr, "Error reading %s\n", name);
exit(EXIT_FAILURE);
}
return n;
}
FILE *
xfopen(const char *path, const char *mode)
{
FILE *fp = strcmp(path, "-") ? fopen(path, mode) : stdin;
if( fp == NULL ) {
perror(path);
exit(EXIT_FAILURE);
}
return fp;
}

Is there any way to shift content of a file without storing it in array in c?

I am trying to replace words from a file, This works fine with words of the same length.
I know it can be done by storing content in a temporary array and then shifting but I was wondering if it can be done without using array.
#include<stdio.h>
#include<string.h>
int main(int argc, char **argv)
{
char s1[20], s2[20];
FILE *fp = fopen(argv[1], "r+");
strcpy(s1, argv[2]);
strcpy(s2, argv[3]);
int l, i;
while(fscanf(fp, "%s", s1)!=EOF){
if(strcmp(s1, argv[2]) == 0){
l = strlen(s2);
fseek(fp, -l, SEEK_CUR);
i=0;
while(l>0){
fputc(argv[3][i], fp);
i++;
l--;
}
}
}
}
Here is my code for replacing same length words, what can I modify here for different lengths?
Assuming that the OP's goal is to avoid storing the whole content of the file into a byte array (maybe not enough memory) and he also said that it needs to "shift" the file's content, so it cannot use a temp file to make the text replacement (perhaps not enough room in the storage device).
Note that copying into a temp file would be the easiest method.
So as I can see the solution has two algorithms:
Shift to left: Replace a text with another of equal or smaller length.
Shift to right: Replace a text with a longer one.
Shift to left:
Maintain 2 file position pointers: one for the read position (rdPos) and another for the write position (wrPos).
Both start in zero.
read char from rdPos until find the oldText and write it into the wrPos (but only if rdPos != wrPos to avoid unnecessary write operations).
write the newText into wrPos.
repeat from step 3 until EOF.
if len(oldText) > len(newText) then truncate the file
Shift to right:
Maintain 2 file position pointers: (rdPos and wrPos).
scan the whole file to find the number of the oldText occurrences.
store their file positions into a small array (not strictly needed, but useful to avoid a second reverse scan of the oldText)
set rdPos = EOF-1 (the last char in the file)
set wrPos = EOF+foundCount*(len(newText)-len(oldText)): reserving enough extra space for the shifting.
read char from rdPos until find the position in the "found" array and write the char into the wrPos.
write the newText into wrPos.
repeat from step 6 until BOF.
I wrote the following implementation as an example of the mentioned algorithms, but without caring too much about validations and edge cases.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define MAX_ITEMS 100
#define DO_WRITE 0x01
#define DO_FIND 0x02
FILE *fp;
long rdPos = 0L, wrPos = 0L, rdCount=0L, wrCount=0L;
int newLen, oldLen;
char *newText, *oldText;
struct found_t { int len; long pos[MAX_ITEMS];} found;
/* helper functions */
void writeChars(char *buffer, int len){
if(wrPos < rdPos){
long p = ftell(fp);
fseek(fp, wrPos, SEEK_SET);
fwrite(buffer, len, 1, fp);
fseek(fp, p, SEEK_SET);
wrCount += len;
}
wrPos += len;
}
int nextReadChar = -1;
int readChar(){
int c;
if(nextReadChar == EOF) {
if((c = fgetc(fp)) != EOF)
rdCount++;
} else {
c = nextReadChar;
nextReadChar = EOF;
}
return c;
}
int findFirstChar(int action){
int c; char ch;
for(; (c = readChar()) != EOF && c != (int)oldText[0]; rdPos++)
if(action == DO_WRITE) {
ch = (char)c;
writeChars(&ch, 1);
}
return c;
}
int testOldText(int c, int action){
char *cmp;
for(cmp = oldText; *cmp != '\0' && c == (int)*cmp; cmp++)
c = readChar();
nextReadChar = c;
if(*cmp == '\0') { /* found oldText */
if(action == DO_FIND)
found.pos[found.len++] = rdPos;
rdPos += oldLen;
if(action == DO_WRITE){
writeChars(newText, newLen);
found.len++;
}
}
else { /* some chars were equal */
if(action == DO_WRITE)
writeChars(oldText, cmp-oldText);
rdPos += cmp-oldText;
}
return c;
}
void writeReverseBlock(long firstCharPos){
for(;rdPos >= firstCharPos+oldLen; rdPos--, wrPos--, rdCount++, wrCount++){
int c;
fseek(fp, rdPos, SEEK_SET); c = fgetc(fp);
fseek(fp, wrPos, SEEK_SET); fputc(c, fp);
}
rdPos = firstCharPos-1;
wrPos -= newLen-1;
fseek(fp, wrPos--, SEEK_SET);
fwrite(newText, newLen, 1, fp);
wrCount += newLen;
}
void scanFile(int action){
int c;
do {
if( (c = findFirstChar(DO_WRITE)) == EOF ) break;
}while(testOldText(c, DO_WRITE) != EOF);
}
/** Main Algorithms */
void shiftToLeft(){
scanFile(DO_WRITE);
fflush(fp);
ftruncate(fileno(fp), wrPos);
}
void shiftToRight(){
int i;
scanFile(DO_FIND);
wrPos = --rdPos + found.len * (newLen-oldLen); /* reserve space after EOF */
for(i=found.len-1; i>=0; i--)
writeReverseBlock(found.pos[i]);
}
/* MAIN program */
int main(int argc, char **argv){
if(argc != 4){
fprintf(stderr, "Usage: %s file.ext oldText newText\n", argv[0]);
return 1;
}
if(!(fp = fopen(argv[1], "r+b"))) {
fprintf(stderr, "Cannot open file '%s'\n", argv[1]);
return 2;
}
oldLen = strlen(oldText = strdup(argv[2]));
newLen = strlen(newText = strdup(argv[3]));
found.len = 0;
/* which algorithm? */
if(newLen <= oldLen) shiftToLeft();
else shiftToRight();
fclose(fp);
printf("%7d occurrences\n"
"%7ld bytes read\n"
"%7ld bytes written\n", found.len, rdCount, wrCount);
return 0;
}

Reading Binary PE Files in C

I'm attempting to read a PE file in C. After reading the relevant Microsoft documentation and other articles on OSDev and on SO, I'm still confused as to how to deal with offsets in the file.
The MS-DOS stub at the head of the file contains a flag at 0x3c which provides the offset to the start of the actual PE header (the PE signature, which is literally a 4-byte "PE\0\0").
What I've tried to do is to use pointer arithmetic to interpret the address given in the PE file as exactly that - an address, but I'm afraid I don't quite know how to do it.
Also, I am aware this is possible via the Win32 API; however, I want to learn from this and learn how to do it myself.
Thank you very much for any help in advance.
#include <stdio.h>
#include <stdlib.h>
#define PE_SIG_OFFSET_LOCATION 0x3c
int main(void)
{
const char* filepath = "sample.exe";
FILE* file = fopen(filepath, "rb");
int i, n = 0;
if(!file)
{
perror("Failed to open file");
return EXIT_FAILURE;
}
fpos_t start = fgetpos(file, &start);
int c;
while((c = fgetc(file)) != EOF)
{
n++;
// putchar(c);
}
if(ferror(file))
{
puts("I/O error when reading.");
}
else if(feof(file))
{
fsetpos(file, &start);
int c = 0;
char* contents = (char*)malloc(n * sizeof(char));
for(i=0;i<=n;i++)
{
if(c == EOF)
{
break;
}
c = fgetc(file);
contents[i] = c;
}
fclose(file);
i = 0;
char offset[4 * sizeof(char)] = {contents[PE_SIG_OFFSET_LOCATION * sizeof(char)], contents[(PE_SIG_OFFSET_LOCATION * sizeof(char))+ (1 * sizeof(char))], contents[(PE_SIG_OFFSET_LOCATION * sizeof(char))+ (2 * sizeof(char))], contents[(PE_SIG_OFFSET_LOCATION * sizeof(char))+ (3 * sizeof(char))]};
char* sig = &contents[PE_SIG_OFFSET_LOCATION * sizeof(char)];
printf("sig = %c \n", sig);
// somehow interpret the character the sig currently points to as a hex memory and get sig to point to that (i.e. the start of the PE header)
free(contents);
return EXIT_SUCCESS;
}
}
EDIT: After technosaurus advised I union a packed struct representing the DOS header with a char array of the actual contents, the code still doesn't appear to be functioning correctly (it reads and prints the file okay, but right at the end when it needs to print the signature it prints garbage instead of MZ).
#include <stdio.h>
#include <stdlib.h>
#define PE_SIG_OFFSET_LOCATION 0x3c
int main(void)
{
const char* filepath = "sample.exe";
FILE* file = fopen(filepath, "rb");
int i, n = 0;
if(!file)
{
perror("Failed to open file");
return EXIT_FAILURE;
}
fpos_t start = fgetpos(file, &start);
int c;
while((c = fgetc(file)) != EOF)
{
n++;
// putchar(c);
}
if(ferror(file))
{
puts("I/O error when reading.");
}
else if(feof(file))
{
fsetpos(file, &start);
int c = 0;
typedef struct DOS_Header
{
char signature[2];
short lastsize;
short nblocks;
short nreloc;
short hdrsize;
short minalloc;
short maxalloc;
void *ss;
void *sp;
short checksum;
void *ip;
void *cs;
short relocpos;
short noverlay;
short reserved1[4];
short oem_id;
short oem_info;
short reserved2[10];
long e_lfanew;
}DOS_Header;
union
{
DOS_Header header;
char* contents;
}u;
u.contents = (char*)malloc(n * sizeof(char));
for(i=0;i<=n;i++)
{
if(c == EOF)
{
break;
}
c = fgetc(file);
u.contents[i] = c;
}
fclose(file);
i = 0;
for(i=0;i<=n;i++)
{
printf("%c", u.contents[i]);
}
printf("\n DOS sig: %c%c \n", u.header.signature[0], u.header.signature[1]);
free(u.contents);
return EXIT_SUCCESS;
}
}

c code text not displayed

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);
}

Resources