Passing file content into memory is faulty - c

I am wondering why while I think I make the function call to load appropriately,
it seems that fread cannot read into my chunk of memory correctly and so it creates a segmentation fault[in load function]!Please point me to the right approach
The link to the code is
#include <math.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
bool load(FILE* file, char** content, size_t* length);
int main()
{
// opens file
FILE * file = fopen("test.txt", "r");
// initialises variables
char* content;
size_t length;
// sending arguments to load function
bool receive = load(file, &content, &length);
// debugging content
printf("values of content: %s\n", content);
// debugs length
printf("values of content: %zu\n", length);
// closes file
fclose(file);
// for success
return 0;
}
bool load(FILE* file, char** content, size_t* length)
{
{
// proof checking for the existence of file
if (file == NULL)
{
return false;
}
// perusing to end of file
fseek(file, 0, SEEK_END);
// for approximation of size of file
size_t len = ftell(file);
// returns cursor to beginning of file
fseek(file, 0, SEEK_SET);
// apportions memory on heap for content of file
* content = (char *) malloc (len + 1);
// memory error checking
if(*content == NULL)
{
printf("It's unfortunate\n");
}
// to read into content
fread(* content, sizeof(char), len, file);
// null terminates content
(* content)[len] = 0;
// debugs content
printf(" content contains %s\n", * content);
// debugs length
* length = len;
printf(" length is %d\n", * length);
// if success
return true;
}
// if fail
return false;
}
Thank you

you need to check that the file opened OK
FILE * file = fopen("test.txt", "r");
if(file == NULL)
{
perror("failed to open file: ");
exit(1);
}
Secondly your load function returns false of it fails, but you dont check it. Do
bool receive = load(file, &content, &length);
if(!receive)
{
fprintf(stderr, "failed to read file");
exit(1);
}
in load you do
if(*content == NULL)
{
printf("It's unfortunate\n");
}
but carry on any way. You should do
if(*content == NULL)
{
printf("It's unfortunate\n");
return false;
}
In general you are not checking the return of any function you call, fseek,ftell,fread,.... You should not be surprised when your program fails. Yes its a boring slog, but thats just the way it is in C land

Related

Why can't I close the file

I have a problem when I close the file fc.
Here is my code
#include <stdio.h>
#include <wchar.h>
int main()
{
FILE* fc = fopen("template.txt","rt,ccs=UTF-8");
wchar_t subStr[2300];
fread(subStr,sizeof(wchar_t),2300,fc);
wchar_t* scrStr=new wchar_t[2300];
wcscpy(scrStr,subStr);
fclose(fc);
return 0;
}
The file was probably not opened correctly in the first place. You must check that the 'handle' to the stream returned by fopen is not NULL. The following code checks the file 'handle', with a few bits changed to make it 'reasonable' C.
#include <stdio.h>
#include <wchar.h>
int main()
{
wchar_t* scrStr = NULL;
FILE* fc = fopen("template.txt","rt,ccs=UNICODE");
// Check that the file was opened.
if(NULL != fc)
{
wchar_t subStr[2301];
size_t wcharsRead = fread(subStr, sizeof wchar_t , 2300, fc);
fclose(fc);
// Check if anything was read.
if(0 != wcharsRead)
{
// Terminate the string in the temporary buffer.
subStr[wcharsRead] = `\0`;
// Allocate a smaller string (use new, if you're in C++).
if(scrStr = malloc(1 + sizeof wchar_t * wcharsRead), NULL != scrStr)
{
// Copy the useful bit into the new string.
wcscpy(scrStr, subStr);
}
}
}
else
{
// Do some error handling
printf("Unable to open file. Error code: %d\r\n",errno);
}
// Check if a string was read.
if(NULL != scrStr)
{
// Do something with scrStr
// Free the string once it's finished with (use delete if you're in C++).
free(scrStr);
}
return 0;
}

How to assign text file data to variable

I am trying to read from a text file and assign that to a variable. At the moment I have it at the stage where it reads from the file and prints it out, however I haven't figured out how to assign the result to a variable.
This is my code:
int c;
FILE *file;
file = fopen(inputFilename, "r");
if (file) {
while ((c = getc(file)) != EOF) {
putchar(c);
}
fclose(file);
}
I'm not entirely sure what putchar(c) means but I assume it is just printing out the characters one at a time?
How would I go about trying to achieve what I am looking to do?
What you mean is to get the whole file content, that is easily done this way
#include <stdio.h>
#include <stdlib.h>
char *readFileContent(const char *const filename)
{
size_t size;
FILE *file;
char *data;
file = fopen(filename, "r");
if (file == NULL)
{
perror("fopen()\n");
return NULL;
}
/* get the file size by seeking to the end and getting the position */
fseek(file, 0L, SEEK_END);
size = ftell(file);
/* reset the file position to the begining. */
rewind(file);
/* allocate space to hold the file content */
data = malloc(1 + size);
if (data == NULL)
{
perror("malloc()\n");
fclose(file);
return NULL;
}
/* nul terminate the content to make it a valid string */
data[size] = '\0';
/* attempt to read all the data */
if (fread(data, 1, size, file) != size)
{
perror("fread()\n");
free(data);
fclose(file);
return NULL;
}
fclose(file);
return data;
}
int main()
{
char *content;
content = readFileContent(inputFilename);
if (content != NULL)
{
printf("%s\n", content);
free(content);
}
reutrn 0;
}
and this will of course fail in the rare case where the file size exceeds the available RAM, but it will not cause undedined behavior, because that case is handeled as a malloc() failure.

Function mallocs a pointer and reads data into it, but caller can not access it

I have a specific problem: I have an issue when I try to use my own function to load file on memory.
load_file_on_memory() receives a filename and a pointer. It just opens the file, allocates memory dynamically for file content and fills it, and passes the pointer to the caller using destiny as an argument.
But I have a problem: Inside load_file_on_memory() function, I have success on malloc space for content. I can put data on pointer and get it, too.
When I try to use the pointer outside function, the caller just gets trash. I will post my code (shortly) here.
I can't understand why this happen. I am using Windows 7 with Tiny C Compiler. I don't know if that environment can cause errors.
Here's my source
#include <stdio.h>
#include <stdlib.h>
int load_file_on_buffer(char filename[], void *buffer_destiny){
FILE *file_loaded;
unsigned int file_size;
file_loaded = fopen(filename, "rb");
if(file_loaded == NULL)
return -1;
fseek(file_loaded, 0, SEEK_END);
file_size = ftell(file_loaded);
fseek(file_loaded, 0, SEEK_SET);
buffer_destiny = (void *) malloc(file_size);
fread((char *) buffer_destiny, file_size, 1, file_loaded);
printf("BEGIN DEBUG FILE\n");
printf("%s", buffer_destiny);
printf("\n\nEND DEBUG FILE\n");
fclose(file_loaded);
return 0;
}
int main(int argc, char *argv[]){
char *buffered_input_file;
///First, load input file
if(load_file_on_buffer("test.txt", (void *)buffered_input_file) != 0)
return -1;
printf("Input file loaded successfully\n");
printf("This function must print file content: \n\n");
printf("%s", buffered_input_file);
}
You are passing a parameter void* buffer_destiny. Once the function is entered, this is just a normal variable. Which you overwrite using a malloc () call. This has no effect on the calling function. Instead declare the function as
int load_file_on_buffer(char filename[], void **pbuffer_destiny)
call it as
void* buffered_input_file;
load_file_on_buffer("test.txt", &buffered_input_file)
and in the function write
void* buffer_destiny = malloc (...);
*pbuffer_destiny = buffer_destiny;
The pointer buffer_destiny is a local variable in the function load_file_on_buffer. Changing buffer_destiny has no effect on the pointer buffer_input_file in main. One way to fix the problem is to return the pointer to main.
Another problem is that you're using "%s" to print the files content. In order for that to work, you need to properly NUL terminate the buffer. In other words, the buffer needs to be one byte bigger than the file size and a NUL terminator '\0' needs to be placed in that extra byte.
#include <stdio.h>
#include <stdlib.h>
char *load_file_on_buffer( const char *filename )
{
FILE *file_loaded;
unsigned int file_size;
file_loaded = fopen(filename, "rb");
if(file_loaded == NULL)
return NULL;
fseek(file_loaded, 0, SEEK_END);
file_size = ftell(file_loaded);
fseek(file_loaded, 0, SEEK_SET);
char *buffer_destiny = malloc(file_size + 1);
fread( buffer_destiny, file_size, 1, file_loaded );
buffer_destiny[file_size] = '\0';
printf("BEGIN DEBUG FILE\n");
printf("%s", buffer_destiny);
printf("\n\nEND DEBUG FILE\n");
fclose(file_loaded);
return buffer_destiny;
}
int main(int argc, char *argv[])
{
char *buffered_input_file;
///First, load input file
if( (buffered_input_file = load_file_on_buffer("test.txt")) == NULL )
return -1;
printf("Input file loaded successfully\n");
printf("This function must print file content: \n\n");
printf("%s", buffered_input_file);
}
If you still want to pass the buffered_input_file as a parameter then this will work for you, I commented the code at some parts I believe clarification is required.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int load_file_on_buffer(char filename[], void **buffer_destiny)
{
FILE *file_loaded;
unsigned int file_size;
if (buffer_destiny == NULL)
return -1;
*buffer_destiny = NULL; /* to check in the calling function */
file_loaded = fopen(filename, "r"); /* rb is no longer needed in new code */
if(file_loaded == NULL)
return -1;
fseek(file_loaded, 0, SEEK_END);
file_size = ftell(file_loaded);
fseek(file_loaded, 0, SEEK_SET);
*buffer_destiny = malloc(1 + file_size); /* +1 for the null terminator */
if (*buffer_destiny == NULL)
{
fclose(file_loaded);
return -1;
}
/* add a null terminator so the string is acceptable by printf */
memset(*buffer_destiny + file_size, '\0', 1);
/* you got this wrong
*
* fread((char *) buffer_destiny, file_size, 1, file_loaded);
*
* the correct way is
*
* fread(void *ptr, size_t size, size_t count, FILE *fp);
*
* where size is the size of each element and count is the number of elements.
*/
if (fread(*buffer_destiny, 1, file_size, file_loaded) != file_size)
{
free(*buffer_destiny);
*buffer_destiny = NULL;
fclose(file_loaded);
return -1;
}
printf("BEGIN DEBUG FILE\n");
printf("%s", (char *)*buffer_destiny);
printf("END DEBUG FILE\n");
fclose(file_loaded);
return 0;
}
int main(int argc, char *argv[])
{
char *buffered_input_file;
if (load_file_on_buffer("data.dat", (void **)&buffered_input_file) != 0)
return -1;
printf("Input file loaded successfully\n");
printf("This function must print file content: \n\n");
printf("%s", buffered_input_file);
free(buffered_input_file);
return 0;
}
buffered_input_file is NULL initially in main() and passed to load_file_on_buffer() by value. buffer_destiny initially got NULL from main() but inside function after memory allocation it should behave normally as you mentioned. However buffer_destiny is a local variable not a pointer for passed variable, hence at the end of function it loses its information and buffered_input_file in main() is still NULL.

Unable to read a file and pass into arguments

1) I'm trying to open a file, read the mix data (ints, chars and strings) and store them into args.
1.1) so in the sample.txt is a total of 13 (excluding args[0])
2) Need to read a file from terminal "./myprog.c < sample.txt"
Heres my code and have no idea where i went wrong:
sample.txt:
123 213 110 90 1
hello my friend
boo bleh
a b c
myprog.c:
#include <stdio.h>
int main()
{
int i = 1;
FILE *fstin=fopen(argv[0], "r"); //open the file
if (fstin == NULL) {
puts("Couldn't fopen...");
return -1;
}
//Getting all the inputs from file
while ((fscanf(fstin, "%d", argv[i])) != EOF){
i++;
}
fclose(fstin);
for (i=0; i<10; i++) {
printf("%d\n",argv[i]);
}
return 0;
}
Any help is greatly appreciated!
PS: Would like if anyone could post their complete solution? Will upload unto this post and let everyone have a review of this problem
PPS: Please excuse the poor level of coding as I am a beginner and completely new to C.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int ac, char *av[]){
int i, argc=0;
char **argv=NULL, data[16];
FILE *fstin = stdin;
if(ac == 2){
if(NULL==(fstin = fopen(av[1], "r"))){
puts("Couldn't fopen...");
return -1;
}
}
while (1==fscanf(fstin, "%15s", data)){
argv = realloc(argv, (argc+1)*sizeof(char*));
argv[argc] = malloc(strlen(data)+1);
strcpy(argv[argc++], data);
}
if(ac == 2)
fclose(fstin);
for (i=0; i<argc; ++i) {
printf("%s\n", argv[i]);
}
//deallocate
return 0;
}
You are making mistake at 2nd point where you divert your file to other file which is wrong. Actually you need to first compile and need to make executable.
gcc -o my_prog ./myprog.c -Wall
You need to execute this program as below to read file from c program:
./my_prog ./sample.txt
As you are new to C programming first go to man pages related to file operations.
Solution:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
//If command line argument is not inserted then stop operation
if (2 != argc) {
printf("Invalid number of arguments : %d\n", argc);
return -1;
}
int size = 0, ret = 0;
char *data = NULL;
FILE *fp = NULL;
//Open file in read mode given from command line argument
if (NULL != (fp = fopen(argv[1], "r")))
{
//Find size of file
fseek(fp, 0L, SEEK_END);
size = ftell(fp);
fseek(fp, 0L, SEEK_SET);
//if file is empty no need to read it.
if (size > 0)
{
//Data pointer which contains file information
data = (char *) calloc(sizeof(char), size);
if (NULL != data)
{
//Read whole file in one statement
fread(data, sizeof(char), size, fp);
printf("File %s is readed successfully\n", argv[1]);
printf("Data:\n");
printf("%s\n", data);
free(data); data = NULL;
}
else
{
perror("memory allocation failed\n");
ret = -1;
}
}
else
{
printf("File %s is empty\n", argv[1]);
}
fclose(fp); fp = NULL;
}
else
{
perror("File open failed\n");
ret = -1;
}
return ret;
}
Now Test it on your setup and if any query please post comments.

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