fgets error and strings declaration style on c - c

I'm curious about one thing, the following code works perfectly.
#include <stdio.h>
int main()
{
FILE * fp = fopen("test.txt", "r");
char line[100];
while( fgets(line, sizeof(line), fp) != NULL )
fputs(line, stdout);
fclose(fp);
return 0;
}
But why it is not possible to use instead:
char *line;
Without causing fgets to crash?

fgets crashes because it is writing the result into unallocated memory.
Without any further memory allocation, char *line points to "nothing". It points to something, but not to any valid memory location -- null if your compiler sets uninitialized values to 0, or any random memory location anywhere on or not on your system.
Even if fgets does not crash, you cannot predict what it does as writing into unallocated memory results in undefined behavior (What is undefined behavior?).

It is possible. Just point it to some valid memory.
char line[100];
char* linep = line ;
while( fgets(linep, sizeof(line), fp) != NULL )...
If you don't assing line to linep, then linep points to random memory, and you cannot use that.

char *line and char line[100] don't mean the same.
The first is a pointer to a char, we don't know if it will be a single char or an array of chars it is pointing to. The second on the other hand is an array.
fgets needs a valid location to write to. In this case, char *line doesn't have any valid location to point at, whereas char line[100] is a valid char array location

Related

Unable to print a char* string

It's not clear to me what's wrong with my program, it's a simple code to open a file, read the first line from it, and then print it. But the program keeps crashing. The actual content of my text file is a sentence: Test my code.
int main(void)
{
FILE *stream;
char *s;
stream = fopen("input.txt", "r");
fscanf(stream, " %s", &s);
printf("%s", s);
fclose(stream);
return 0;
}
I'm instructed not to use the library functions found in <string.h>
s is an uninitialized pointer. You need to allocate some memory for fscanf to write into.
char *s;
Allocates the number of bytes needed for holding a memory address (on most systems 32/64 bits).
But since you are not initializing the pointer, its value (the address it points to) is undefined.
Ergo: fscanf tries to write to an undefined memory address.
I initialized it as char *s = NULL;
Yes, the pointer is now initialized (yay!) but now points to nowhere.
Ergo: fscanf will try to write to nothing.
The solution is to allocate some memory fscanf can use.
fscanf does not magically allocate memory for you!
You can use either stack memory or dynamic allocated memory (heap).
Stack memory is easier to manage but is much smaller than the heap.
Here a solution which uses memory on the stack:
// Allocates 10 bytes on the stack
// Given 1 Character = 1 Byte the
// buffer can hold up to 9 characters.
char myBuffer[10];
// Initialize s with the address of myBuffer
char *s = myBuffer;
// Call fscanf
fscanf(stream, "%9s", s);
You may be wondering why I used %9s instead of %s.
The reason is to prevent a buffer overflow:
fscanf does not know how big the buffer is, so you need to tell it.
Otherwise fscanf will write data beyond your allocated memory.
I suggest you read up on C strings and memory management in general.
There are few things you are missing in your code.
// Uninitialise pointer, you need to allocate memory dynamically with malloc before you use it. That is
char *s;
int size = 20; // size of the string you want
s = malloc(size * sizeof(char));
// Or you can use a VLA and with this you don't have to use free(s)
char s[20];
// fopen could fail, always check the return value before using it.
stream = fopen("input.txt", "r");
if(stream == NULL){
perror("File opening failed");
return EXIT_FAILURE;
}
fscanf(stream, "%s", s);
//Don't forget to do free(s) to free memory allocated with malloc . when you are done with it

How to use fscanf for reading files in c(Segmentation Fault)?

I'm new user in stackoverflow. I wrote this code in c and I have no problem and the output is correct.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *str[10];
FILE * fp;
fp = fopen ("file.txt", "w+");
fputs("We\nare\nin\n2016", fp);
rewind(fp);
fscanf(fp, "%s", str[0]);
fscanf(fp, "%s", str[1]);
printf("Read String1 |%s|\n", str[0] );
printf("Read String2 |%s|\n", str[1] );
fclose(fp);
return(0);
}
but when I use char *str[15] instead of char *str[10], the result is segmentation fault. What is wrong?
The pointers str[0] and str[1] are uninitialized. So, your program has undefined behaviour.
Either you need to allocate using malloc() or make them an array of arrays (e.g. str[2][256];) with fixed length that's sufficient enough for the strings you read from the file.
In any case, I'd personally use fgets() instead of fscanf() and then parse the line as necessary.
It would also help to do error checking for all functions (fopen(), fscanf(), etc).
Keep in mind you are declaring char * str[10], you are reserving memory for ten pointers but you didn't call malloc to reserve memory for the contents of these pointers.
Your example seems similar to this tutorial of the function fscanf, http://www.tutorialspoint.com/c_standard_library/c_function_fscanf.htm.
But there, string parts are declared as char[10] instead of char *[10] which means they already have memory reserved for 10 characters. In this same example reading a string with length greater than 10 will also generate problems.

The variable 'buff' is being used without being defined

I need to read some data from text file and store it in 2D-array.
This code works good:
#include <string.h>
#include <stdio.h>
int main() {
FILE *f = fopen("Read.txt", "r");
char buff[100][100];
char str[100];
int i = 0;
while(fgets(str, 100, f)) {
strcpy(buff[i], str);
i++;
}
return 0;
}
But why doesn't it work when I try to change buff definition in line 5 to:
char (*buff)[100];
I expected this definition to work too.
The error I get:
Run-Time Check Failure #3 - The variable 'buff' is being used without being defined
char (*buff)[100];
Here buff is a pointer to an array of 100 characters. So first you should make the pointer point to valid memory location before storing some value in it.
Presuming you want to go for dynamic memory allocation then you can have
char *buff[100];
Now in the fgets() loop allocate memory to each pointer individually like
buff[i] = malloc(100);
Note here buff is an array of 100 char pointers.

Dynamic array with malloc doesn't work but fixed size does - C

Why does a fixed array work but when I try to make it dynamic with malloc it gives a segmentation fault? I've tried all sorts of values besides *10. This is just using a small file. I need this to work with a dictionary of 90,000 words.
FILE *fp;
long lSize;
//char buffer[100];
char *buffer=malloc(sizeof(char)*10);
int i = 0;
fp = fopen ( "cats.txt" , "rb" );
if( !fp ) perror("cats.txt"),exit(1);
wordTree = makeEmptyTree();
while( fscanf(fp, "%s", &buffer) != EOF )
{
addStringToTree(wordTree, buffer);
//printf("%s\n", words[i]);
}
fclose(fp);
//free(buffer);
I can include addStringToTree as well if needed.
Edit 1
Thanks guys that fixed it. Unfortunately I couldn't get the 90,000 words text file to work, still getting the seg fault error.
It should be
fscanf(fp, "%s", buffer) //remove the ampersand
Change
char *buffer=malloc(sizeof(char)*10);
to
char *buffer=malloc(100);
and
while( fscanf(fp, "%s", &buffer) != EOF )
to
while( fscanf(fp, "%s", buffer) != EOF )
then try again.
sizeof(char) always returns 1, and the size of buffer should be 100 (because in static case its 100);
buffer already a pointer to char, & before it is not necessary and will give the address of pointer instead of address pointed to by buffer. (And this is probably the cause of segment fault.)
You are passing pointer-to-a-pointer in fscanf. Just have buffer in fscanf. In 'char buffer[]' case, &buffer and buffer are equivalent. Hence no seg-fault in that case.
Notice that the types of your fixed array and dynamically allocated array are different:
char buffer[100];
vs.
char* buffer
Malloc returns the address location of your dynamically allocated memory, so you don't need to prefix it with '&'. So simply use this:
while( fscanf(fp, "%s", buffer) != EOF )
{
.....

Using fgets() with char* type

I have a simple question about using fgets() with char* string.
....
char *temp;
FILE fp=fopen("test.txt", "r");
fgets(temp, 500, fp);
printf("%s", temp);
....
This code didn't work well.
But after I modified char *temp to char temp[100];, the code worked well as I intended.
What is the difference between those two?
When I googled it, some said that memory must be allocated to char * using malloc()...
But I couldn't understand it.
char *temp is only a pointer. At begin it doesn't points to anything, possibly it has a random value.
fgets() reads 500 bytes from fp to the memory addresse, where this temp pointer points! So, it can overwrite things, it can make segmentation faults, and only with a very low chance will be work relativale normally.
But char temp[500] is a 500 bytes long array. That means, that the compiler does the allocation on the beginning of your process (or at the calling of your function). Thus this 500 bytes will be a useable 500 bytes, but it has a price: you can't reallocate, resize, free, etc. this.
What the google wants from you, is this:
char *temp = (char*)malloc(500);
And a
free(temp);
after you don't need this any more.
When we write
char *temp ;
it means temp is an uninitialized pointer to char i.e. currently it does not contain any address in it .
While using fgets you have to pass a string in which the bytes read from file pointer is to be copied . link
since the temp is uninitialized , the fgets looks like this
fgets(<no string> , 500 , fp ) ;
which is invalid .
Hence , we should give initialized string which can be formed as :
1) char *temp = malloc(sizeof(500)) ;
or
2) char temp[500] ;
Hence if we pass initialized string to fgets , it would look like
fgets( < some string > , 500 , fp) ;
char *temp is uninitialized, that is, it isn't pointing to valid memory. Either make it an array (char temp[]) or use malloc to assign memory for it.

Resources