I have this fragment
fseek(sp,f_line*fm,SEEK_SET);
fgets(buffer,LEN,(FILE*)sp);
I don't understand this part
(FILE)sp
I try to fill a char array with data from a file.
Apparently, someone thinks they are storing a file pointer in a variable sp that is not of type FILE *, so it is reputed to be necessary to cast the type to FILE *. See the POSIX definition of fgets(), which is meant to be equivalent to the standard C definition of the function.
However, given that the prior line calls fseek() with an uncast sp, and fseek() also expects a FILE *, someone is confused — the person writing the cast is confused.
The cast should be removed from the call to fgets().
Or, possibly but implausibly, the cast should be added to the call to fseek().
One outré possibility is that the user defined void *sp and used that to store the FILE * returned by fopen() or equivalent. Such a decision would be extremely unorthodox, and pointlessly opens up the code to type confusion, but could actually allow the code shown below to compile and run — but the cast is still unnecessary.
/* Abominable code - do not use! */
#include <stdio.h>
int main(void)
{
void *sp = fopen("abuse47.c", "r"); // The abomination!
if (sp != 0)
{
char buffer[256];
fseek(sp, 120, SEEK_SET);
if (fgets(buffer, sizeof(buffer), sp) != 0)
printf("[%s]\n", buffer);
fclose(sp);
}
return 0;
}
Related
I am currently studying c programming and I have an assignment called get_next_line.
This is my function prototype:
int get_next_line(const int fd, char **line);
This is what it's supposed to do according to the assignment:
"Write a function that returns a line read from a file descriptor."
"What we call a “line” is a succession of characters that end with ’\n’` (ascii code 0x0a) or with End Of File (EOF)."
"Calling your function get_next_line in a loop will then allow you to read the text available on a file descriptor one line at a time until the end of the text, no matter the size of either the text or one of its lines."
The way I understand it, if your function is called once, you return a single line. If your function is called within a loop, you return x lines. Note that the prototype has no argument that indicates how many times the function has been looped. So my problem is, how will my function know to read x lines or just a single line?
The test file contains 3 lines of 5 zeros.
I have tried using 2 while loops to read all the lines in the file, but testing my function with a loop will be pointless then no? Because instead of returning x lines it will return all the lines x times.
I have tried searching Google. I have spent countless hours trying to figure this out. But I'm stuck and in need of some help! I am not sure if I'm missing something obvious as is usually the case.
A few things though, we are only allowed to use while loops. We are only allowed to use read, malloc and free. Only 5 functions are allowed per c file and 25 lines per function. For this assignment only 1 c file is allowed. We aren't allowed to use printf, but I use it for testing. We may use a custom made library consisting of re-made functions such as:
memchr, putstr, strjoin, strsplit, memcmp, putstr_fd, strlcat, strstr, atoi, memcpy, strcat, strlen, bzero, memdel, strchr, strmap, isalnum, memmove, strclr, strmapi, isalpha, memset, strcmp, strncat, isascii, putchar, strcpy, strncmp, isdigit, strdel, strncpy, strnequ, isprint, putendl, strdup, strnew, itoa, strequ, strnstr, toupper, memalloc, putnbr, striter, tolower, memccpy, striteri, strrchr, strtrim, strsub.
So, below is my code. If anyone can give me guidance I'd appreciate it.
static void ft_doread(const int fd, char **line, char *buff, int x, int y)
{
if (buff[y] != '\n')
{
read(fd, (void *)buff, BUFF_SIZE);
line[x][y] = buff[y];
y++;
}
}
int get_next_line(const int fd, char **line)
{
int x;
int y;
char *buff;
buff = (char *)malloc(BUFF_SIZE);
x = 0;
y = 0;
ft_doread(fd, line, buff, x, y);
return (0);
}
int main(void)
{
char *str;
int fd;
int lines;
str = (char *)malloc(BUFF_SIZE);
fd = open("./test.txt", O_RDONLY);
get_next_line(fd, &str);
printf("%s", str);
return (0);
}
I think it meant that the call within each iteration of the loop will return a successive line, so that if called X times from within a loop, it will yield X lines one at a time. As such, the function only needs to keep track of where it is in the file (which you will unless you forcibly change the position or close and re-open the file).
so written a small function (part of a larger program) and when i run it and input "GET" it exits with a value of 1. to be honest i'm still grasping the concept of open read and write to stdout but not sure what i've done wrong here.
int input_arg()
{
MainStruct val; //variables are loaded from a config file to this structure
char *getInput;
char *fileInput;
FILE *loadfile;
char buffer[1024];
int n;
int defaultFile = val.def; //success.txt value read when fileparser.c is run
printf("http >> :");
fflush(NULL);
fscanf(stdin,"%s", getInput);
if (getInput == "GET")
{
loadfile = fopen(defaultFile, "r");
if (loadfile == NULL)
{
fprintf(stderr, "error loading default resource: PROGRAM WILL EXIT");
exit(0);
}
while ((n = read(loadfile, buffer, sizeof(buffer))) > 0) //reads file (not sure this should be a while loop)
{
if((write(STDOUT_FILENO, buffer, n)) < 0) //writes to stdout
{
perror("failed to display file to output");
close(loadfile);
exit(1);
}
}
}
}
for compiling purposes the val.def pointer is a string as below
char defaultFile = "success.txt";
unsure of what i am missing here. tried changing the structure pointer to a simple char string to see if it was anything there but didn't actually make any difference. i think the problem is with the while loop...i don't think it should be there, but i have yet to find an example where a while loop ISN'T used in a write to stdout scenario.
thanks
It crashes because you have not allocated any memory for getInput to point at. So the program will crash when it attempts to follow the pointer, which will not point to anything useful.
Either allocate memory dynamically with for example malloc, or replace it with a static buffer.
Also, you may want to look at strcmp for comparing strings. Comparing strings in C with == will not compare the strings lexically, instead it will only compare the pointers pointing at them.
fscanf(stdin,"%s", getInput);
getInput is never initialized or allocated memory.Fix it by allocating memory
getInput = malloc(200);
Your program has serious issues, the most important one is that you are using fopen() with read() and that is wrong.
The read() function takes and int as first parameter, which is a file descriptor tha you can create via the open() function, and not fopen() which returns a FILE * object, so change[1]
FILE *loadFile;
to
int loadFile;
and
loadFile = fopen(defaultFile, "r");
to
loadFile = open(defaultFile, O_RDONLY);
and then to check for failure
if (loadFile == -1) /* it failed to open check errno? perhaps... */
you must enable compiler warnings to prevent this kind of mistake, because the first parameter of read() in your program is of incompatible type.
The fscanf() function expects a valid pointer for each "%s" specifier, you are passing an unintialzed pointer to it, dereferencing it inside of scanf() is undefined behavior.
You need to allocate space for it, something like this should work
char inputBuffer[100];
if (fscanf(stdin, "%99s", inputBuffer) != 1)
thereWasAProblemGettingInput_DoNotUse_inputBuffer_InTheCodeThatFollows();
Note that:
I used inputBuffer as a name for the variable, though this doesn't affect the program execution or compilation at all, the readability matters.
Used "%99s" to prevent buffer overflow.
Checked the value returned by fscanf() to make sure that the inputBuffer has valid data and was properly initialized.
String comparison in c is not like in many other languages, in your code
if (getInput == "GET")
is comparing the addresses of getInput and the string literal "GET", which will not be the same unless you make getInput point to "GET", since you want to compare the contents you need
if (strcmp(inputBuffer, "GET") == 0)
instead, and do not forget to include the string.h header.
[1]Note that loadFile is also a bad choice for a variable name, it feels like a function name, inputFile would be more appropriate.
I'm getting a seg fault when I try and print fname. Can someone explain why this is happening to me? Is it that I'm not allowed to write to a file, close it, and then read from a file? argv[2] is defined. I've tried with multiple different allocations.
int main(int argc, char *argv[]){
//Other stuff
char *rfile=calloc(1, 2049);
strcpy(rfile, argv[2]);
FILE *wfile;
wfile = fopen(argv[2], "w");
SaveIndexToFile(index, wfile, alpha); // This does a whole bunch of writing to a the file.
fclose(wfile);
//alpha is declared here, and works just fine.
RemakeIndex(rfile, alpha);
return 1;
}
int RemakeIndex(char *fname, WordList * alpha){
printf("%s", fname);
return 1;
}
You are not checking the return value of fopen. If the fopen fails it can
return NULL. If you are doing something with NULL that can undefined behavior. Place this line after opening the file.
if ( wfile == NULL ){
perror("fopen");
return;
}
And check whether the argc count is three. If you are not giving arguments to the ./a.out then accessing the argv[2] can also lead to segmentation fault.
Is it that I'm not allowed to write to a file, close it, and then read from a file?
Yes, you are not allowed to read from a file [stream] after it had been closed.
Note on the (OP's) wording:
char * rfile is called a "pointer to char".
FILE * is called a "file-pointer" (or also just "pointer to FILE) or commonly (but formally wrong) just "file".
Also RemakeIndex() is called in main() without proper protoyping.
To fix this
either add a prototype before main():
int RemakeIndex(char *, WordList *);
or move the whole implementation of RemakeIndex() before main().
Also the printf() calls' output might not show up immediately on the console, as stdout is line buffered.
To fix this
either print out a trailing new-line:
printf("%s\n", fname);
or printf to stderr, which itself isn't line bufferd by default:
fprintf(strerr, "%s\n", fname);
or flush stdout after having printed to it:
printf("%s\n", fname);
fflush(stdout);
Prototyping the function is very important, the GCC compiler will assume an implicitly declared function (RemakeIndex in your code) has two arguments which are both int, which would make your code look like this:
int RemakeIndex(int fname, int alpha) {
printf("%s", (char *)fname);
return 1;
}
On a 64 bit machine and with GCC where pointers are 64 bits and ints are 32 bits then your arguments will be truncated to 32 bits which is likely to cause a segfault. The other answers have mentioned prototyping the function and if you are using a 64bit compiler I would suggest that this is your problem.
It ended up being that I was allocating way too much memory on the heap. I had a loop that was allocating strings of max_length of an unsigned int. Thank you for all of your comments and help!
I am trying to read a binary file containing integers in the binary form. I need to use the open() and read() functions rather than fopen() and the like.
I open my file and try to read it, but i get binary symbols in my output.
char buffer[sizeof(int)];
int file1;
int bytesRead;
file1 = open(argv[1], O_RDONLY);
if(file1 == -1)
{
printf("unable to open file\n");
exit(1);
}
while((bytesRead = read(file1, &buffer, sizeof(buffer))))
{
printf("%d\n", buffer);
}
Can anyone point me in the right direction?
Error 1: read(file1, &buffer, sizeof(buffer)
When you use an array, then you need not pass it address to the "read" call.
Correction :
read(file1, buffer, sizeof(buffer);
Error 2 :
while((bytesRead = read(file1, &buffer, sizeof(buffer))))
Correction :
while((bytesRead = read(file1, &buffer, sizeof(buffer))) >= 0)
The while loop will evaluate to true even if the read call fails, since it returns -1 on
failure which means true.
It returns 0 when there's nothing left to read, you can apply a check on that to
indicating that there's nothing more tobe read.
Variables should be declared with the type they are used as:
int buffer;
If you want an int, declare an int. This is an oversimplification, but this way you’re safe against strict-aliasing violations. If only this line is changed, the other code is fine.
The original
char buffer[sizeof(int)];
has the drawback, that it’s impossible to read it as an int without violating strict-aliasing*) (strict-aliasing means, you mustn’t access an object through an lvalue with a wrong type—in short, that is, different from the declared one).
The behaviour of
printf("%d\n", buffer);
is undefined, a value of type char * is passed to printf where an int is expected. (This line is OK if buffer is an int; and it should be declared as an int, since it is read as an int.)
If a char array was really what is intended, the line
while((bytesRead = read(file1, &buffer, sizeof(buffer))))
would be unusual: Arrays decay to pointers when passed to a function, there’s no need to use the address operator &. (But it’s needed if buffer is of type int.)
*) Not entirely impossible, you could type-pun with a union.
when it comes to C i am not a noob - i'm more like a total & complete stupid ignorant noob! i am trying to write a program to parse simple text files, and i would like to make it as general as possible(why i use getline). well here is my code:
//afile.c
#include <stdio.h>
#include <stdlib.h>
main( )
{FILE *fp1;
char *filename;
char **line;
size_t *sz;
int s;
filename = "n";
if ((fp1 = fopen(filename,"r")) == NULL ){printf("error...");return 1;}
do {
s = getline(&line,sz,fp1);
if (s != -1)
printf(" %s \n",line);//<-- %s seems to be wrong! %*s removes the gcc warning
} while (s != EOF);
fclose(fp1);}
I am pretty sure its some pointer allocation problem, but i really cant figure out where it is. i've found out that replacing %s with %s makes the compiler warning disappear, but it results in an infinity of \t(tabs) being written in the terminal.
By the way, the error message i get is:
stack smashing detected *: ./afile terminated
Segmentation fault
getline expects an argument of type char**, and you supplied &line, which is char***. Additionally, getline acts on the current value of the value its first arguments points to (so, the value of line), and you didn't initialize it. Change your program to:
char *line = NULL;
and it should be fine.
You failed to initialize the line variable, and it contains a random value. Readline probably tries to realloc() it.
UPDATE: the definition for line is also wrong, only one asterix needed, as pointed out by others.
int main(void )
{
FILE *fp1;
char *filename;
char *line = NULL; /* <- here */
size_t *sz;
int s;
...
}
Your pointer redirections are inconsistent. The variable line is declared:
char **line;
Which is a pointer to a pointer to a character, or a pointer to a string. getline() expects a pointer to a string, but you pass &line - a pointer to a pointer to a string.
Finally, your printf() format specified is %s, do it wants to format a string, but you give it a pointer to a string.
Long story short: remove an asterisk to create
char *line;