I'm trying to read file using file descriptor. The file descriptor is correct, so, the file is open correctly. The error is given when the program reads the last line
This is the code:
void readFile(char* filePath){
int fd,i=0;
char *c= NULL;
int read=1;
fd = open(filePath, O_RDONLY );
char **config;
config=(char**)malloc(4 * sizeof(char*));
if(fd<0){
printf("Error");
} else {
while (read==1){
c=readLine(fd);
if(*c=='\0'){
read=0;
}else{
config[i]=(char*) malloc(sizeof(char));
strcpy(config[i], c);
i++;
}
}
close(fd);
}
}
char *readLine(int fd){
char character;
char *array= malloc(1);
unsigned int siz=1;
while (read(fd, &character, 1) > 0 && character!='\n'){
array=realloc(array, siz + 1);
array[siz - 1]=character;
siz ++;
}
array[siz - 1]='\0';
return array;
The program has several flaws, including not freeing dynamically allocated memory (that returned by readline for example).
However, what is preventing the program to run at least is the lack of space of each of the config[i] locations. You just reserve space for one character malloc(sizeof(char)), but you have to reserve space for the whole string that afterwards is copied, plus the ending '\0': malloc(strlen(c) + 1). Also, take into account that using strlen, strcpy, etc. expects the string to contain non-binary data, and may fail with different encodings, etc.
Another solution would be to just assign config[i] to the returned c string, and later freeing it when freeing config. You would avoid the copy of the string.
Related
i'm trying to read a file and split this file into multiple buffers.
This is what i came up with:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define PKT_SIZE 2048;
#define PATH "directory of some kind"
int main() {
char filepath[200] = PATH;
FILE *packet;
int size = PKT_SIZE;
char *buffer[size];
int i=0;
//OPEN FILE
if((packet = fopen(filepath, "r")) == NULL){ //I'm trying with a txt file, then i'll change it to 'rb'
printf("Error Opening File\n");
return -1;
}
//READ FILE
while(*fgets((char *) *buffer[i], (int) strlen(buffer[i]), packet) != NULL) { //read the file and cycling insert the fgets into the buffer i
printf("Create %d buffer\n", i);
i++;
}
fclose(packet);
return 0;
}
Now, when i run this program, i get a SIGSEGV error, i managed to understand that this error is definetly:
*fgets((char *) *buffer[i], (int) strlen(buffer[i]), packet) != NULL
Do you have any suggestions?
*fgets((char *) *buffer[i], (int) strlen(buffer[i]), packet)
This line as several problems.
buffer[i] is just an un-initialized pointer pointing nowhere.
*buffer[i] is of type char you need to pass the char*.
strlen is not returning the size of the buffer. It is undefined behavior here because you called it over uninitialized pointer value.
Also dererencing whatever fgets is return is bad when the fgets returns NULL. It invokes undefined behavior.
There many solutions to this ranging from dynamic memory allocation to using
char buffer[size][MAXSIZE];. If you go about this you can get input this way:
#define MAXSIZE 100
...
char buffer[size][MAXSIZE];
while(fgets(buffer[i], sizeof(buffer[i]), packet)!=NULL){...
char* buffer[size] is an array of N char* pointers which are uninitialized. You must allocate memory to these before using them or your program will explode in a ball of fire.
The fix is to allocate:
for (size_t i = 0; i < size; ++i) {
buffer[i] = malloc(PKT_SIZE);
}
You're going to be responsible for that memory going forward, too, so don't forget to free later.
Allocating an arbitrary number of buffers is pretty wasteful. It's usually better to use some kind of simple linked-list type structure and append chunks as necessary. This avoids pointless over-allocation of memory.
I'm writting a passing program and I have a little problem.
I want to dynamically allocate memory location with the size of the sentence which is readed from a file. Also this pointer should have this text in contents
When file will have sentence:
"One two three four five"
Then I want char* example with allocated memory location for 25 chars.
And when I would like to print this text on console I want do it by
printf("%c", example);
Console should look like that:
One two three four five
I'm doing it like that:
char* czyt = (char*)malloc(sizeof(fgets( line/*static variable*/,
500 /*MAX LINE LENGHT*/,
wejscie /*FILE*/ )));
But in this case czyt doesn't have this sentence and I need to use static variable.
If your concern is to solve this without a buffer: It's somewhat unusual. But on a POSIX-like system you could use stat() (cf. http://pubs.opengroup.org/onlinepubs/009695399/functions/stat.html).
Less efficient is to use Posix' lseek(): open the file, seek to the end with int fileLength = lseek(fd, 0, SEEK_END); and allocate fileLength bytes.
Whatever function you use, it will tell you the size of the file without reading anything so that you can then allocate a buffer of exactly the required size. Don't forget to rewind the file with lseek(fd, 0, SEEK_SET) before you read from it, or close it and open again with fopen().
The most ideal way to sort the lines of file would be to
use a dictionary tree. Create a dictionary tree with individual lines
and then perform a depth-first traversal.
Here is a simple program that would do a dynamic buffer allocation based on line length( assuming the length of line is not more than 500)
int main(int argc, char const *argv[])
{
char string[500];
char *str;
FILE *in_file = fopen("abc.txt", "r");
if (in_file == NULL)
{
printf("Error file missing\n");
exit(-1);
}
while ( fgets(string, 500, in_file) != NULL)
{
str = (char *) malloc ( sizeof(char) * strlen(string));
strcpy(str, string);
printf("%s", str);
}
fclose(in_file);
return 0;
}
In case if you want to sort them, you can either use a linked list to store these data or can use an array of pointers (which would hold the pointer address of all the malloc-ed lines) and then sort by manipulating the pointers
Switching to C from Java, and I'm having some troubles grasping memory management
Say I have a function *check_malloc that behaves as such:
// Checks if malloc() succeeds.
void *check_malloc(size_t amount){
void *tpt;
/* Allocates a memory block in amount bytes. */
tpt = malloc( amount );
/* Checks if it was successful. */
if ( tpt == NULL ){
fprintf(stderr, "No memory of %lu bytes\n", amount);
exit(1);
}
return tpt;
}
I also have the following variables to work with:
FILE *f = fopen("abc.txt", "r"); // Pointer to a file with "mynameisbob" on the first line and
// "123456789" on the second line
char *pname; // Pointer to a string for storing the name
}
My goal is to use *check_malloc to dynamically allocate memory so that the String pointed to by *pname is just the correct size for storing "mynamisbob", which is the only thing on the first line of the text file.
Here is my (failed) attempt:
int main(int argc, char *argv[]){
FILE *f = fopen("abc.txt", "r"); // A file with "mynameisbob" on the first line and
// "123456789" on the second line
char *pname; // Pointer to a string for storing the name
char currentline[150]; // Char array for storing current line of file
while(!feof(f)){
fgets(currentline,100,f);
pname = ¤tline;
}
But I know this probably isn't the way to go about this, because I need to use my nice check_malloc* function.
Additionally, in my actual text file there is a "<" symbol before the name on the first line.But I just want the *pname to point to a String saying "mynameisbob" without the "<" symbol. This isn't that important now, it just is reinforcement to me that I know I can't just set the pointer to point straight to currentline.
Can anyone help me fix my thinking on this one? Thanks a lot.
In C you need to copy chars, not the "strings" (which are just pointers). Check out strcpy() and strlen(). Use strlen() to determine how long the line actually is which fgets has read, then use your malloc() to allocate exactly that (plus 1 for the 0). Then copy the chars over with strcpy().
There are several problems in your code, see my comments in this example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Checks if malloc() succeeds.
void *check_malloc (size_t amount) {
void *tpt;
/* Allocates a memory block in amount bytes. */
tpt = malloc( amount );
/* Checks if it was successful. */
if (tpt == NULL) {
fprintf (stderr, "No memory of %lu bytes\n", amount);
exit (EXIT_FAILURE);
}
return tpt;
}
// To avoid subtle errors I have defined buffer size here
#define BUFFER_SIZE 150
// I have used the (void) version of main () here, while not strictly neccessary, you where not using argc and argv anyway, so the can be left out in this case
int main (void) {
// It might be a good idea to make the filename a char[] as well, but I leave that as an exercise to the reader.
FILE *f = fopen("abc.txt", "r"); // A file with "mynameisbob" on the first line and
// "123456789" on the second line
// You have to check whether the file was *actually openend*
if (f == NULL) {
fprintf (stderr, "Could not open file abc.txt\n"); // '"...%s\n", filename);' might better.
exit (EXIT_FAILURE);
}
char *pname; // Pointer to a string for storing the name
char currentline[BUFFER_SIZE]; // Char array for storing current line of file
while(!feof (f)) {
char *res = fgets (currentline, BUFFER_SIZE, f);
// fgets returns NULL when EOF was encountered before the next '\n'
if (res) {
size_t read = strlen (res);
// The line might have been empty
if (read) {
// Better use "sizeof *varname", while char is always 1 byte it is a good practice
pname = check_malloc ((read + 1) * sizeof *pname); // + 1 because we have to provide an extra char für '\0'
strncpy (pname, currentline, read); // You have to use strcpy or strncpy to copy the contents of the string rather than just assigning the pointer
// What was allocated must be freed again
free (pname);
}
}
}
fclose(f); // Always close everything you open!
return EXIT_SUCCESS;
}
Actually you really don't have to use pname in this simple case, because currentline already contains the line, but since you're trying to learn about memory management this should give you a general idea of how things work.
In your code you had this line:
pname = ¤tline;
There are two problems here:
As already mentioned in my code assigning currentline to pname only copies the pointer not the contents.
The correct assignment would be pname = currentline (without the address operator &), because currentline is also a pointer under the hood (it behaves like char *currentline even though it's statically allocated).
I was trying to open a binary file in the directory and perform the operations accordingly.I doubt this line..is not the correct way of representation to work the below logic.
int main(int argc, char* argv[])
{
int k=0;
FILE *fp;
unsigned char cd[255];
unsigned long cd1[500];
char *buffer;
unsigned long sa=80044;
int j=0,i=0,n=0;
DIR *dir;
struct dirent *direntry; //could be a file, or a directory
dir = opendir("C:/Documents and Settings/Administrator/Desktop/vicky");
if(!dir) {
printf("Error: directory did not open!\n");
return 1;
}
while((direntry=readdir(dir))!=NULL) {
if(++k < 100)
{
printf("%s\n",direntry->d_name);
sprintf(buffer,"%s",direntry->d_name);//here i got the unhanded exception.
fp=fopen("buffer","rb");
sa=sa-44;
sa=sa/8;
if(fp==NULL)
{
printf("file not found!");
}
else
{
for(j=0;j<(sa);j++)
{
for(i=0;i<8;i++)
{
cd[i]=fgetc(fp);//get each character from file
// printf("%c",cd[i]);
}
if(i==8)//if the i is 8 the character then do the following,just read 8 bytes and then calculate the cd1.
{
sa=sa-8;
cd1[j]=(cd[6] * 65536 + cd[5] * 256 + cd[4]);//multiply the positional weightage and calculate the cd1,which contains the 7 digits decimal value.
//if((cd1[j]> 0x7FFFFF)&&(cd1[j]<=0xFFFFFF))
//cd1[j]=cd1[j]- 0xFFFFFF;
//cd1[j]=cd1[i] * -1;
}
printf("completes first 8 bytes read:%d - %d",j,cd1[j]);//print j and cd1[j] value in console window
}
fclose(fp);//close the file
}
}
if((strcmp(direntry->d_name, "text.txt"))==0) {
printf("\nThe %s file has been found\n",direntry->d_name);
k=-99; //just a flag value to show the file was found
break;
}
}
if(k!=-99)
printf("\nThe test.txt file was not found\n");
closedir(dir);
printf("\n");
getchar();
return 0;
}
This is error i got:Unhandled exception at 0x1029a189 (msvcr90d.dll) in READ_TEXT.exe: 0xC0000005: Access violation writing location 0xcccccccc.Kindly let me any suggestion to read the "direntry->d_name" file name to process the above logic.
Make the character buffer an ordinary array, for simplicity's sake:
char buffer[1024];
That way you're sure to have the memory put aside and ready to use. You should use snprintf() if your platform provides it.
buffer is not allocated. sprintf() is basically attempting to write "nowhere".
The destination variable needs to be either allocated on the heap using malloc or on the stack restricting its use to the current scope.
You have only declared char* buffer, not allocate memory for it using malloc().
Your problem is an uninitialized pointer.
Initialize the pointer with malloc or try an array
char buffer[1024];
change
char * buffer;
to
char buffer[MAX_PATH];
or something similar.
U must allocate the memory for the buffer variable.
char *buffer; statement is not allocating any memory so that i could have
any data.
so better u try
chat buffer[//buffer length];
or char *buffer = new char(//buffer length);
or char buffer = (char)malloc(//buffer length);
these above statement will allocate memory and fix your issue.
I have an assignment that is supposed to be written in C (not C++), in which I need to create some structs from reading multiple text files. I have learnt c before (2 years ago) - I'm far more comfortable with Java, just can't use that for this project. I guess my issue comes from not understanding the pointer syntax very well :/.
However, my real issue:
The code I have written crashes when I try to use the strcpy function:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char* filename;
int time;
} JOB;
JOB **jobQueue;
int nJobs;
void trimLine(char* line) {
for (int i = strlen(line); i >=0; i--) {
if (line[i] == '\n' || line[i] == '\r') line[i] = '\0';
}
}
int main(int argc, char* argv[]) {
if (argc !=2) {
printf("Error - Usage is: my_project file\n");
exit(-1);
}
FILE *fp;
fp = fopen(argv[1],"r");
if (fp==NULL) {
printf("Error - file %s could not be read.\n",argv[1]);
exit(-1);
}
jobQueue = malloc(3*sizeof(JOB*));
char filename[BUFSIZ];
nJobs = 0;
while (fgets(filename,sizeof(jobfilename),fp)!=NULL) {
trimLine(filename);
JOB* newjob;
newjob = malloc(sizeof(JOB));
//** THIS IS WHERE IT SCREWS UP
strcpy(newjob->filename,filename);
jobQueue[nJobs++] = newjob;
}
}
If I delete the line containing strcpy, the program runs fine (well, I realise this part doesn't really do anything, but still). However, when the program contains the strcpy line, it breaks when attempting to do Job #2. Any idea why?
Also: If I need to maintain an array of JOBs for use in other functions, is the way I have done it correct? JOB **jobQueue is an array of pointers to JOBs, JOB *newjob is a pointer to a JOB, would this work correctly?
newjob->filename is a wild pointer(not set to anything), you have to allocate memory before you can store things at it.
Change:
typedef struct{
char* filename;
int time;
} JOB;
to:
#include <limits.h>
typedef struct{
char filename[PATH_MAX];
int time;
} JOB;
I'd like to add a few suggestions
nJobs = 0;
Globals are initialised with 0, you don't need to do it manually.
while (fgets(filename,sizeof(jobfilename),fp)!=NULL) {
jobfilename is not declared in your code. I guess you mean filename.
for (int i = strlen(line); i >=0; i--) {
if (line[i] == '\n' || line[i] == '\r') line[i] = '\0';
}
You start with the ending \0 which you could skip.
You declare new variables everywhere you like, it's good practice (and C89 standard) that increases readability to declare variables at the start of a code block.
Additional suggestions for improvement of your code:
You do never free() the malloced pointers.
What is there are more than 3 Jobs?
Your code doesn't handle this. You
could use a linked list instead of an
array.
You do not call fclose() on your file handle.
Trasvi, don't forget that your jobQueue is malloc'ed to hold only 3 instances of the JOB struct. However, your "while loop" goes around as many times as the user inputs.
But to answer your original question, simply add this to your code before the strcpy.
newjob->filename = malloc ( strlen( filename) +1 );
//You only need to malloc the amount of characters in the filename + 1,
//which is for the null-terminated char, and you don't need to worry about
//multiplying by 'sizeof' because a char is one byte on any compiler.
You have a null pointer in newjob->filename:
int nJobsMax=3;
char* filename;
JOB* newjob;
...
jobQueue = malloc(nJobsMax*sizeof(JOB*));
filename=(char*)malloc(BUFSIZ);
while (fgets(filename,BUFSIZ,fp)!=NULL) {
trimLine(filename);
newjob = (JOB*)malloc(sizeof(JOB));
newjob->filename = filename;
filename=(char*)malloc(BUFSIZ);
jobQueue[nJobs++] = newjob;
if (nJobs > nJobsMax)
//possible buffer overflow need escape
}
free(filename);
fclose(fp);
more things:
void trimLine(char* line) {
int i = strlen(line)-1;
do{
if (line[i] == '\n' || line[i] == '\r')
line[i] = '\0';
}while(!(line[i]>=' ')||i-->=0);
}
really you don't need iterate all the string
example: fgetd output => text_text_text\r\n\0aq
' ' is character space values over this element are printer characters see ascii.
fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A terminating null byte (aq\0aq) is stored after the last character in the buffer.
source: fgets
strncpy is more recommended that strcpy because protect your code against buffer overflow.
The strncpy() function is similar, except that at most n bytes of src are copied. Warning: If there is no null byte among the first n bytes of src, the string placed in dest will not be null-terminated.
If the length of src is less than n, strncpy() writes additional null bytes to dest to ensure that a total of n bytes are written.
source:strncpy
other solution to strcmp:
The strdup() function returns a pointer to a new string which is a duplicate of the string s. Memory for the new string is obtained with malloc(3), and can be freed with free(3).
The strndup() function is similar, but only copies at most n bytes. If s is longer than n, only n bytes are copied, and a terminating null byte ('\0') is added.
source:strndup