How to indicate the last line of the file - c

I want to read the txt line by line and store it to the array;
I am like success to store line by line in array;
I use printf("%s", loadtext[i]) with i= 0,1,2,3-20 respectively to check that things in stored in array;
but I realize that the for loop had done 1912 times when I
type printf("%d", i); right behind the for loops,
Suppose my txt is store like this:
I am a jerk
I am a noob
I am an idiot
I am done
I have another program to add new lines to the text file while this program is running.
How can I detect I am done or the new line added later is the last line to not allow the for loop do so many times?
Here is my code
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <string.h>
int main(){
FILE *fp = fopen("abc.txt","r");
int i = 0,j=0,k=0;
char ch[10000];
char loadtext[100][100];
for (i=0; ch[i] != EOF; i++){
ch[i] = fgetc(fp);
if (ch[i] != '\n'){
loadtext[j][k] = ch[i];
k++;
}
if(ch[i] == '\n'){
loadtext[j][k] = ch[i];
k=0;
j++;
}
}
printf("%s", loadtext[0]);
printf("%s", loadtext[1]);
printf("%s", loadtext[2]);
fclose(fp);
return 0;
}

To read a whole file into an "array" of pointers to char which represent the lines, you can do:
#include <stddef.h> // size_t
#include <stdlib.h> // EXIT_SUCCESS, EXIT_FAILURE
#include <stdio.h> // malloc(), realloc(), free(), fgets()
#include <string.h> // strlen(), strcpy()
enum { BUFFER_SIZE = 30 }; // whatever line length you suspect the input file to be + 1
int main(void)
{
char const *filename = "test.txt";
FILE *is = fopen(filename, "r");
if (!is) {
fprintf(stderr, "Couldn't open \"%s\" for reading :(\n\n", filename);
return EXIT_FAILURE;
}
int result = EXIT_SUCCESS; // assume a happy ending
char buffer[BUFFER_SIZE];
size_t num_lines = 0;
char **lines = NULL;
while (fgets(buffer, sizeof(buffer), is)) {
++num_lines;
char **temp = realloc(lines, num_lines * sizeof(*lines));
if (!temp) {
fputs("Not enough memory :(\n\n", stderr);
fclose(is);
result = EXIT_FAILURE;
goto cleanup;
}
lines = temp;
size_t length = strlen(buffer);
length = strlen(buffer);
// remove a trailing newline if any:
if (length && buffer[length - 1] == '\n')
buffer[--length] = '\0';
size_t line_length = length;
lines[num_lines - 1] = malloc((length + 1) * sizeof(*lines));
if (!lines[num_lines - 1]) {
fputs("Not enough memory :(\n\n", stderr);
fclose(is);
result = EXIT_FAILURE;
goto cleanup;
}
strcpy(lines[num_lines - 1], buffer);
// as long as the buffer has been filled completely by the previous
// call to fgets() and a next call to fgets() also succeeds:
while (length == BUFFER_SIZE - 1 && fgets(buffer, sizeof(buffer), is)) {
length = strlen(buffer);
// remove a trailing newline if any:
if (length && buffer[length - 1] == '\n')
buffer[--length] = '\0';
char *temp = realloc(lines[num_lines - 1], line_length + length + 1);
if (!temp) {
fputs("Not enough memory :(\n\n", stderr);
fclose(is);
result = EXIT_FAILURE;
goto cleanup;
}
lines[num_lines - 1] = temp;
strcpy(lines[num_lines - 1] + line_length, buffer);
line_length += length;
}
}
fclose(is);
// use lines:
for (size_t i = 0; i < num_lines; ++i)
puts(lines[i]);
cleanup:
for (size_t i = 0; i < num_lines; ++i)
free(lines[i]);
free(lines);
return result;
}
Using only a fixed-size two-dimensional array and fgetc()*):
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
enum { MAX_LINES = 100, MAX_LINE_LENGTH = 100 };
int main(void)
{
char const *filename = "test.txt";
FILE *is = fopen(filename, "r");
if (!is) {
fprintf(stderr, "Couldn't open \"%s\" for reading :(\n\n", filename);
return EXIT_FAILURE;
}
char text[MAX_LINES][MAX_LINE_LENGTH + 1] = { 0 }; // zero-initialize the array
// so we don't have to care
size_t num_lines = 0; // about zero terminating
size_t current_column = 0; // every line
int ch;
// as long as we are still inside the bounds of the fixed size array
// and fgetc() doesn't return EOF
while (num_lines < MAX_LINES && current_column < MAX_LINE_LENGTH &&
(ch = fgetc(is)) != EOF)
{
if (ch == '\n') { // "move" num_lines and current_column to the next
++num_lines; // line.
current_column = 0;
continue;
}
text[num_lines][current_column++] = ch;
}
if (ch != EOF) {
fputs("The file is too big :(\n\n", stderr);
return EXIT_FAILURE;
}
for (size_t i = 0; i <= num_lines; ++i)
puts(text[i]);
}
*) Could be done with fgets() too.

to read the txt line by line and store it to the array
Code has various problems:
ch[i] != EOF accesses ch[i] before it is assigned! Undefined Behavior (UB).
char can be signed or unsigned. EOF is some negative. When char is unsigned the below is an infinite loop. When char is signed, ch[i] != EOF could exit the loop early.
printf("%s", loadtext[0]); attempts to print loadtext[0] as if it was a string. But lacking a certain null character, and thus not a string, this leading to more UB.
Lack of buffer index checks: loadtext[j][k] = ch[i]; k++; may increment k to beyond 100. Similar weak code with i.
Code may fail to open the file and no check provided.
Instead save the result from fgetc() as an int, test for for EOF, test for '\n' and append a null character to form strings.
Some ideas for alternate code:
#define LINES_N 100
#define LINE_SIZE 100
int main(void) {
FILE *fp = fopen("abc.txt", "r");
if (fp) {
// char ch[10000];
char loadtext[LINES_N][LINE_SIZE];
int ch_index = 0;
int line_count = 0;
int character;
int previous_character = '\n';
while ((character = fgetc(fp)) != EOF) {
// Starting a new line?
if (previous_character == '\n') {
if (++line_count > LINES_N) {
printf("Too many lines\n");
return EXIT_FAILURE;
}
}
loadtext[line_count - 1][ch_index++] = (char) character;
loadtext[line_count - 1][ch_index] = '\0';
if (ch_index + 1 >= LINE_SIZE) {
printf("Too long a line\n");
return EXIT_FAILURE;
}
previous_character = character;
}
if (line_count >= 1) printf("%s", loadtext[0]);
if (line_count >= 2) printf("%s", loadtext[1]);
if (line_count >= 3) printf("%s", loadtext[2]);
fclose(fp);
}
return 0;
}

Related

pallindrome is not copied to next file but printed on output screen

I have a file named fp1 containing different names, some being palindromes, and have to read all names from fp1 and check if each name is a palindrome or not. If it's a palindrome the I need to print the name to screen and copy it to another file named fp.
Here's my program:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
void main() {
FILE *fp, *fp1;
char m, y[100];
int k = 0, i = 0, t = 1, p = 0;
fp = fopen("C:\\Users\\HP\\Desktop\\New folder\\file 2.txt", "w");
fp1 = fopen("C:\\Users\\HP\\Desktop\\New folder\\file4.txt", "r");
if (fp == NULL) {
printf("error ");
exit(1);
}
if (fp1 == NULL) {
printf("error");
exit(1);
}
k = 0;
m = fgetc(fp1);
while (m != EOF) {
k = 0;
i = 0;
t = 1;
p = 0;
while (m != ' ') {
y[k] = m;
k = k + 1;
m = fgetc(fp1);
}
p = k - 1;
for (i = 0; i <= k - 1; i++) {
if (y[i] != y[p]) t = 0;
p = p - 1;
}
if (t == 1) {
fputs(y, fp);
printf("%s is a pallindrome\n", y);
}
m = fgetc(fp1);
}
fclose(fp);
fclose(fp1);
}
coping pallindrome from one file to next file
You are not null terminating your buffer before attempting to use the contents as a string. After placing the last valid character read by fgetc into the buffer, you must place a null terminating character (\0).
A character buffer without a null terminating byte is not a string. Passing such a buffer to fputs, or the printf specifier %s without a length bound, will invoke Undefined Behaviour.
fgetc returns an int, not a char. On systems where char is unsigned, you will not be able to reliably test against the negative value of EOF.
The inner while loop is not checking for EOF. When the file is exhausted, it will repeatedly assign EOF to the buffer, until the buffer overflows.
To that end, in general, the inner while loop does nothing to prevent a buffer overflow for longer inputs.
In a hosted environment, void main() is never the correct signature for main. Use int main(void) or int main(int argc, char **argv).
Note that fputs does not print a trailing newline. As is, you would fill the output file full of strings with no delineation.
The nested while loops are fairly clumsy, and I would suggest moving your palindrome logic to its own function.
Here is a refactored version of your program. This program discards the tails of overly long words ... but the buffer is reasonably large.
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#define BUFFER_SIZE 1024
FILE *open_file_or_die(const char *path, const char *mode)
{
FILE *file = fopen(path, mode);
if (!path) {
perror(path);
exit(EXIT_FAILURE);
}
return file;
}
int is_palindrome(const char *word, size_t len)
{
for (size_t i = 0; i < len / 2; i++)
if (word[i] != word[len - i - 1])
return 0;
return 1;
}
int main(void)
{
/*
FILE *input = open_file_or_die("C:\\Users\\HP\\Desktop\\New folder\\file4.txt", "r");
FILE *output = open_file_or_die("C:\\Users\\HP\\Desktop\\New folder\\file 2.txt", "w");
*/
FILE *input = stdin;
FILE *output = stdout;
char buffer[BUFFER_SIZE];
size_t length = 0;
int ch = 0;
while (EOF != ch) {
ch = fgetc(input);
if (isspace(ch) || EOF == ch) {
buffer[length] = '\0';
if (length && is_palindrome(buffer, length)) {
fputs(buffer, output);
fputc('\n', output);
printf("<%s> is a palindrome.\n", buffer);
}
length = 0;
} else if (length < BUFFER_SIZE - 1)
buffer[length++] = ch;
}
/*
fclose(input);
fclose(output);
*/
}

zsh: segmentation fault when reading a file in c [duplicate]

I wrote this function to read a line from a file:
const char *readLine(FILE *file) {
if (file == NULL) {
printf("Error: file pointer is null.");
exit(1);
}
int maximumLineLength = 128;
char *lineBuffer = (char *)malloc(sizeof(char) * maximumLineLength);
if (lineBuffer == NULL) {
printf("Error allocating memory for line buffer.");
exit(1);
}
char ch = getc(file);
int count = 0;
while ((ch != '\n') && (ch != EOF)) {
if (count == maximumLineLength) {
maximumLineLength += 128;
lineBuffer = realloc(lineBuffer, maximumLineLength);
if (lineBuffer == NULL) {
printf("Error reallocating space for line buffer.");
exit(1);
}
}
lineBuffer[count] = ch;
count++;
ch = getc(file);
}
lineBuffer[count] = '\0';
char line[count + 1];
strncpy(line, lineBuffer, (count + 1));
free(lineBuffer);
const char *constLine = line;
return constLine;
}
The function reads the file correctly, and using printf I see that the constLine string did get read correctly as well.
However, if I use the function e.g. like this:
while (!feof(myFile)) {
const char *line = readLine(myFile);
printf("%s\n", line);
}
printf outputs gibberish. Why?
If your task is not to invent the line-by-line reading function, but just to read the file line-by-line, you may use a typical code snippet involving the getline() function (see the manual page here):
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE * fp;
char * line = NULL;
size_t len = 0;
ssize_t read;
fp = fopen("/etc/motd", "r");
if (fp == NULL)
exit(EXIT_FAILURE);
while ((read = getline(&line, &len, fp)) != -1) {
printf("Retrieved line of length %zu:\n", read);
printf("%s", line);
}
fclose(fp);
if (line)
free(line);
exit(EXIT_SUCCESS);
}
FILE* filePointer;
int bufferLength = 255;
char buffer[bufferLength]; /* not ISO 90 compatible */
filePointer = fopen("file.txt", "r");
while(fgets(buffer, bufferLength, filePointer)) {
printf("%s\n", buffer);
}
fclose(filePointer);
In your readLine function, you return a pointer to the line array (Strictly speaking, a pointer to its first character, but the difference is irrelevant here). Since it's an automatic variable (i.e., it's “on the stack”), the memory is reclaimed when the function returns. You see gibberish because printf has put its own stuff on the stack.
You need to return a dynamically allocated buffer from the function. You already have one, it's lineBuffer; all you have to do is truncate it to the desired length.
lineBuffer[count] = '\0';
realloc(lineBuffer, count + 1);
return lineBuffer;
}
ADDED (response to follow-up question in comment): readLine returns a pointer to the characters that make up the line. This pointer is what you need to work with the contents of the line. It's also what you must pass to free when you've finished using the memory taken by these characters. Here's how you might use the readLine function:
char *line = readLine(file);
printf("LOG: read a line: %s\n", line);
if (strchr(line, 'a')) { puts("The line contains an a"); }
/* etc. */
free(line);
/* After this point, the memory allocated for the line has been reclaimed.
You can't use the value of `line` again (though you can assign a new value
to the `line` variable if you want). */
//open and get the file handle
FILE* fh;
fopen_s(&fh, filename, "r");
//check if file exists
if (fh == NULL){
printf("file does not exists %s", filename);
return 0;
}
//read line by line
const size_t line_size = 300;
char* line = malloc(line_size);
while (fgets(line, line_size, fh) != NULL) {
printf(line);
}
free(line); // dont forget to free heap memory
A complete, fgets() solution:
#include <stdio.h>
#include <string.h>
#define MAX_LEN 256
int main(void)
{
FILE* fp;
fp = fopen("file.txt", "r");
if (fp == NULL) {
perror("Failed: ");
return 1;
}
char buffer[MAX_LEN];
while (fgets(buffer, MAX_LEN, fp))
{
// Remove trailing newline
buffer[strcspn(buffer, "\n")] = 0;
printf("%s\n", buffer);
}
fclose(fp);
return 0;
}
Output:
First line of file
Second line of file
Third (and also last) line of file
Remember, if you want to read from Standard Input (rather than a file as in this case), then all you have to do is pass stdin as the third parameter of fgets() method, like this:
while(fgets(buffer, MAX_LEN, stdin))
Appendix
Removing trailing newline character from fgets() input
how to detect a file is opened or not in c
readLine() returns pointer to local variable, which causes undefined behaviour.
To get around you can:
Create variable in caller function and pass its address to readLine()
Allocate memory for line using malloc() - in this case line will be persistent
Use global variable, although it is generally a bad practice
Use fgets() to read a line from a file handle.
Some things wrong with the example:
you forgot to add \n to your printfs. Also error messages should go to stderr i.e. fprintf(stderr, ....
(not a biggy but) consider using fgetc() rather than getc(). getc() is a macro, fgetc() is a proper function
getc() returns an int so ch should be declared as an int. This is important since the comparison with EOF will be handled correctly. Some 8 bit character sets use 0xFF as a valid character (ISO-LATIN-1 would be an example) and EOF which is -1, will be 0xFF if assigned to a char.
There is a potential buffer overflow at the line
lineBuffer[count] = '\0';
If the line is exactly 128 characters long, count is 128 at the point that gets executed.
As others have pointed out, line is a locally declared array. You can't return a pointer to it.
strncpy(count + 1) will copy at most count + 1 characters but will terminate if it hits '\0' Because you set lineBuffer[count] to '\0' you know it will never get to count + 1. However, if it did, it would not put a terminating '\0' on, so you need to do it. You often see something like the following:
char buffer [BUFFER_SIZE];
strncpy(buffer, sourceString, BUFFER_SIZE - 1);
buffer[BUFFER_SIZE - 1] = '\0';
if you malloc() a line to return (in place of your local char array), your return type should be char* - drop the const.
Here is my several hours... Reading whole file line by line.
char * readline(FILE *fp, char *buffer)
{
int ch;
int i = 0;
size_t buff_len = 0;
buffer = malloc(buff_len + 1);
if (!buffer) return NULL; // Out of memory
while ((ch = fgetc(fp)) != '\n' && ch != EOF)
{
buff_len++;
void *tmp = realloc(buffer, buff_len + 1);
if (tmp == NULL)
{
free(buffer);
return NULL; // Out of memory
}
buffer = tmp;
buffer[i] = (char) ch;
i++;
}
buffer[i] = '\0';
// Detect end
if (ch == EOF && (i == 0 || ferror(fp)))
{
free(buffer);
return NULL;
}
return buffer;
}
void lineByline(FILE * file){
char *s;
while ((s = readline(file, 0)) != NULL)
{
puts(s);
free(s);
printf("\n");
}
}
int main()
{
char *fileName = "input-1.txt";
FILE* file = fopen(fileName, "r");
lineByline(file);
return 0;
}
const char *readLine(FILE *file, char* line) {
if (file == NULL) {
printf("Error: file pointer is null.");
exit(1);
}
int maximumLineLength = 128;
char *lineBuffer = (char *)malloc(sizeof(char) * maximumLineLength);
if (lineBuffer == NULL) {
printf("Error allocating memory for line buffer.");
exit(1);
}
char ch = getc(file);
int count = 0;
while ((ch != '\n') && (ch != EOF)) {
if (count == maximumLineLength) {
maximumLineLength += 128;
lineBuffer = realloc(lineBuffer, maximumLineLength);
if (lineBuffer == NULL) {
printf("Error reallocating space for line buffer.");
exit(1);
}
}
lineBuffer[count] = ch;
count++;
ch = getc(file);
}
lineBuffer[count] = '\0';
char line[count + 1];
strncpy(line, lineBuffer, (count + 1));
free(lineBuffer);
return line;
}
char linebuffer[256];
while (!feof(myFile)) {
const char *line = readLine(myFile, linebuffer);
printf("%s\n", line);
}
note that the 'line' variable is declared in calling function and then passed, so your readLine function fills predefined buffer and just returns it. This is the way most of C libraries work.
There are other ways, which I'm aware of:
defining the char line[] as static
(static char line[MAX_LINE_LENGTH]
-> it will hold it's value AFTER returning from the function). -> bad,
the function is not reentrant, and
race condition can occur -> if you
call it twice from two threads, it
will overwrite it's results
malloc()ing the char line[], and
freeing it in calling functions ->
too many expensive mallocs, and,
delegating the responsibility to free the buffer to another function (the most elegant solution is to call malloc and free on any buffers in same function)
btw, 'explicit' casting from char* to const char* is redundant.
btw2, there is no need to malloc() the lineBuffer, just define it char lineBuffer[128], so you don't need to free it
btw3 do not use 'dynamic sized stack arrays' (defining the array as char arrayName[some_nonconstant_variable]), if you don't exactly know what are you doing, it works only in C99.
void readLine(FILE* file, char* line, int limit)
{
int i;
int read;
read = fread(line, sizeof(char), limit, file);
line[read] = '\0';
for(i = 0; i <= read;i++)
{
if('\0' == line[i] || '\n' == line[i] || '\r' == line[i])
{
line[i] = '\0';
break;
}
}
if(i != read)
{
fseek(file, i - read + 1, SEEK_CUR);
}
}
what about this one?
Implement method to read, and get content from a file (input1.txt)
#include <stdio.h>
#include <stdlib.h>
void testGetFile() {
// open file
FILE *fp = fopen("input1.txt", "r");
size_t len = 255;
// need malloc memory for line, if not, segmentation fault error will occurred.
char *line = malloc(sizeof(char) * len);
// check if file exist (and you can open it) or not
if (fp == NULL) {
printf("can open file input1.txt!");
return;
}
while(fgets(line, len, fp) != NULL) {
printf("%s\n", line);
}
free(line);
}
Hope this help. Happy coding!
You should use the ANSI functions for reading a line, eg. fgets. After calling you need free() in calling context, eg:
...
const char *entirecontent=readLine(myFile);
puts(entirecontent);
free(entirecontent);
...
const char *readLine(FILE *file)
{
char *lineBuffer=calloc(1,1), line[128];
if ( !file || !lineBuffer )
{
fprintf(stderr,"an ErrorNo 1: ...");
exit(1);
}
for(; fgets(line,sizeof line,file) ; strcat(lineBuffer,line) )
{
if( strchr(line,'\n') ) *strchr(line,'\n')=0;
lineBuffer=realloc(lineBuffer,strlen(lineBuffer)+strlen(line)+1);
if( !lineBuffer )
{
fprintf(stderr,"an ErrorNo 2: ...");
exit(2);
}
}
return lineBuffer;
}
My implement from scratch:
FILE *pFile = fopen(your_file_path, "r");
int nbytes = 1024;
char *line = (char *) malloc(nbytes);
char *buf = (char *) malloc(nbytes);
size_t bytes_read;
int linesize = 0;
while (fgets(buf, nbytes, pFile) != NULL) {
bytes_read = strlen(buf);
// if line length larger than size of line buffer
if (linesize + bytes_read > nbytes) {
char *tmp = line;
nbytes += nbytes / 2;
line = (char *) malloc(nbytes);
memcpy(line, tmp, linesize);
free(tmp);
}
memcpy(line + linesize, buf, bytes_read);
linesize += bytes_read;
if (feof(pFile) || buf[bytes_read-1] == '\n') {
handle_line(line);
linesize = 0;
memset(line, '\0', nbytes);
}
}
free(buf);
free(line);
Provide a portable and generic getdelim function, test passed via msvc, clang, gcc.
/*
* An implementation conform IEEE Std 1003.1-2017:
* https://pubs.opengroup.org/onlinepubs/9699919799/functions/getdelim.html
*
* <nio.h>:
* https://github.com/junjiemars/c/blob/c425bd0e49df35a2649327664d3f6cd610791996/src/posix/nio.h
* <nio.c>:
* https://github.com/junjiemars/c/blob/c425bd0e49df35a2649327664d3f6cd610791996/src/posix/nio.c
*
*/
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
/*
* LINE_MAX dependents on OS' implementations so check it first.
* https://github.com/junjiemars/c/blob/c425bd0e49df35a2649327664d3f6cd610791996/src/posix/nlim_auto_check
*/
#define NM_LINE_MAX 4096 /* Linux */
#if (MSVC)
typedef SSIZE_T ssize_t;
# if !defined(SSIZE_MAX)
# define SSIZE_MAX ((ssize_t)((size_t)((ssize_t)-1) >> 1))
# endif
#endif
ssize_t getdelim(char **restrict lineptr, size_t *restrict n, int delimiter,
FILE *restrict stream);
#if defined(getline)
# undef getline
#endif
#define getline(lp, n, f) getdelim((lp), (n), 0x0a, (f))
ssize_t
getdelim(char **restrict lineptr, size_t *restrict n, int delimiter,
FILE *restrict stream)
{
int c;
char *p, *p1;
ssize_t len;
if (NULL == lineptr || NULL == n || NULL == stream
|| (UCHAR_MAX < delimiter || delimiter < 0))
{
errno = EINVAL;
return EOF;
}
if (feof(stream) || ferror(stream))
{
return EOF;
}
if (0 == *lineptr)
{
if (0 == *n)
{
*n = NM_LINE_MAX;
}
*lineptr = malloc(*n);
if (0 == *lineptr)
{
return EOF;
}
}
p = *lineptr;
len = 0;
while (EOF != (c = fgetc(stream)))
{
if (SSIZE_MAX == (ssize_t) len)
{
errno = EOVERFLOW;
return EOF;
}
if ((size_t) len == (*n - 1))
{
*n <<= 1;
p1 = realloc(*lineptr, *n);
if (0 == p1)
{
return EOF;
}
*lineptr = p1;
p = p1 + len;
}
*p++ = (char) c;
len++;
if (c == delimiter)
{
break;
}
}
if (ferror(stream))
{
return EOF;
}
*p = 0;
return len;
}
int
main(void)
{
FILE *fp;
char *line = NULL;
size_t len = 0;
ssize_t read;
fp = fopen("/some-file", "r");
if (fp == NULL)
exit(1);
while ((read = getline(&line, &len, fp)) != -1) {
printf("Retrieved line of length %zu :\n", read);
printf("%s", line);
}
if (ferror(fp)) {
/* handle error */
}
free(line);
fclose(fp);
return 0;
}
You make the mistake of returning a pointer to an automatic variable.
The variable line is allocated in the stack and only lives as long as the function lives.
You are not allowed to return a pointer to it, because as soon as it returns the memory will be given elsewhere.
const char* func x(){
char line[100];
return (const char*) line; //illegal
}
To avoid this, you either return a pointer to memory which resides on the heap eg. lineBuffer
and it should be the user's responsibility to call free() when he is done with it.
Alternatively you can ask the user to pass you as an argument a memory address on which to write the line contents at.
I want a code from ground 0 so i did this to read the content of dictionary's word line by line.
char temp_str[20]; // you can change the buffer size according to your requirements And A single line's length in a File.
Note I've initialized the buffer With Null character each time I read line.This function can be Automated But Since I need A proof of Concept and want to design a programme Byte By Byte
#include<stdio.h>
int main()
{
int i;
char temp_ch;
FILE *fp=fopen("data.txt","r");
while(temp_ch!=EOF)
{
i=0;
char temp_str[20]={'\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0'};
while(temp_ch!='\n')
{
temp_ch=fgetc(fp);
temp_str[i]=temp_ch;
i++;
}
if(temp_ch=='\n')
{
temp_ch=fgetc(fp);
temp_str[i]=temp_ch;
}
printf("%s",temp_str);
}
return 0;
}

Reading, a set line range from a file in C

I' am writing a C program which allows the user to dynamically specify the File name from which the data is to be read. Next the user enters a lower bound and an upper bound. The data in the lines from between the bounds is to be printed.
For this the main function makes a call: readValues(cTargetName, iLower, iHiger);
The function readValues is supposed to work as follows:
Check if file exist, if yes. Open it with fopen
Read with feof and fgets line by line the whole file, and store each line in char string
With a for loop, print the correct range of lines from the string
I'm not sure why but the while loop doesn't seem to exit although I use the feof statement, which should terminate after the end of the File is reached.
The code looks as follows:
#include <stdio.h>
#include <stdlib.h>
void readValues(char cFileName[75], int n, int m)
{
//Variable declaration;
char strArray[50][50];
char *parser;
int i = 0;
FILE *Data;
if(Data = fopen(cFileName, "rt") == NULL){
printf("File could not be opened");
return 1; //Can you return 1 in a void function?
}
//Read the file line by line
while(feof(Data)==0){
fgets(strArray[i], 200, Data);
i++;
}
//Reading the specified lines
for(n; n<=m; n++){
printf("%s", strArray[n]);
}
}
int main()
{
char cTargetName[75] = {"C:/Users/User1/Desktop/C_Projects_1/TestData.txt"};
int iLower = 2;
int iHiger = 4;
readValues(cTargetName, iLower, iHiger);
return 0;
}
All help is appreciated. Thanks in advance!
Here is my solution to your question:
#include <stdio.h>
#include <stdlib.h>
#define MIN_LINE_LENGTH 64
typedef enum {
false, true
} bool;
int main() {
char filename[PATH_MAX] = {0};
printf("Enter filename:\n");
fgets(filename, PATH_MAX, stdin); // get filename from stdin
char *ptr = filename;
while (*ptr) { // remove trailing newline at the end of filename (fgets() includes newline)
if (*ptr == '\n') {
*ptr = 0;
}
++ptr;
}
printf("Enter starting line and end line, separated by a space:\n");
size_t startLine = 0;
size_t endLine = 0;
bool hasFirstNum = false;
bool hasSecondNum = false;
bool hasMiddleSpace = false;
bool hasLastSpace = false;
size_t numCount = 0;
int ch;
while ((ch = fgetc(stdin)) != EOF && ch != '\n') { // continually receive chars from stdin
if (ch != 32 && !(ch >= 48 && ch <= 57)) { // if not a space or number, raise error
fprintf(stderr, "Only numerical values (and spaces) can be entered.\n");
return 1;
}
if (ch == 32) {
if (hasFirstNum) {
hasMiddleSpace = true;
}
if (hasSecondNum) {
hasLastSpace = true;
}
continue;
}
else if (!hasFirstNum) {
++numCount;
hasFirstNum = true;
}
else if (!hasSecondNum && hasMiddleSpace) {
++numCount;
hasSecondNum = true;
}
else if (hasLastSpace) {
++numCount;
}
if (numCount == 1) {
startLine *= 10;
startLine += ch - 48; // '0' character in ASCII is 48
}
else if (numCount == 2){
endLine *= 10;
endLine += ch - 48;
}
else {
break;
}
}
FILE *fp = fopen(filename, "r");
if (fp == NULL) {
fprintf(stderr, "Error opening file.\n");
return 1;
}
char **lines = malloc(sizeof(char *));
char *line = malloc(MIN_LINE_LENGTH);
*lines = line;
int c;
size_t char_count = 0;
size_t line_count = 1;
while ((c = fgetc(fp)) != EOF) { // continually get chars from file stream
if (c == '\n') { // expand lines pointer if a newline is encountered
*(line + char_count) = 0;
++line_count;
lines = realloc(lines, line_count*sizeof(char *));
line = (*(lines + line_count - 1) = malloc(MIN_LINE_LENGTH));
char_count = 0;
continue;
}
if ((char_count + 1) % MIN_LINE_LENGTH == 0 && char_count != 0) { // expand line pointer if needed
line = realloc(line, char_count + MIN_LINE_LENGTH);
}
*(line + char_count) = c;
++char_count;
}
*(line + char_count) = 0; // to ensure the last line always ends with the null byte
if (startLine >= line_count) { // raise error if starting line specified is greater than num. of lines in doc.
fprintf(stderr, "Specified starting line is less than total lines in document.\n");
return 1;
}
if (endLine > line_count) { // adjust ending line if it is greater than number of lines in doc.
endLine = line_count;
}
if (startLine == 0) { // we will be using the starting index of 1 as the first line
startLine = 1;
}
char **linesPtr = lines + startLine - 1;
while (startLine++ <= endLine) { // print lines
printf("%s\n", *linesPtr++);
}
for (size_t i = 0; i < line_count; ++i) { // free all memory
free(*(lines + i));
}
free(lines);
return 0;
}
It is a little more convoluted, but because it uses dynamic memory allocation, it can handle lines of any length within a text file.
If there is anything unclear, please let me know and I would be happy to explain.
Hope this helps!!
several issues here,
first, you limited the length of lines to 200, not exactly what you might expect to get.
the fgets function returns lines up to specified length unless hit by newline character - this should be taken into account.
additionally, fgets returns NULL if you hit EOF - no real need to use feof.
second, you could save yourself a lot of pain and simply count the number of times you get a string, and for the times you are within the range just print it immediately. will save you a nice amount of overhead
like this:
#include <stdio.h>
#include <stdlib.h>
#define MAXLINE 200//or anything else you want
void readValues(char cFileName[75], int n, int m)
{
//Variable declaration;
char line[MAXLINE];
int i = 0;
FILE *Data;
if((Data = fopen(cFileName, "rt")) == NULL){
printf("File could not be opened");
return 1; //Can you return 1 in a void function?
}
//Read the file line by line and print within range of lines
while((line=fgets(line, MAXLINE,Data))!=NULL){//terminates upon EOF
if (++i>=n&&i<=m)
printf(""%s\n",line);
}
}

Why does this code keep giving me a Segfault Error when i run it in Linux?

So I'm trying to create a function that takes in a text file, which contains a bunch of words separated by the newline character, and reads the text file into a char** array.
When I run this code in netbeans on windows, it works fine but if I run it in Linux, I get a segmentation fault error.
// globals
FILE *words_file;
char **dic;
int num_words = 0;
void read_to_array() {
words_file = fopen("words.txt", "r");
char *line = NULL;
int i = 0;
size_t len = 0;
dic = (char **)malloc(99999 * sizeof(char *));
// read dic to array
while (getline(&line, &len, words_file) != -1) {
dic[i] = (char*)malloc(len);
strcpy(dic[i], line);
// get rid of \n after word
if (dic[i][strlen(dic[i]) - 1] == '\n') {
dic[i][strlen(dic[i]) - 1] = '\0';
}
++i;
num_words++;
}
//printf("%s", dic[i][strlen(dic[i]) - 1]); //testing
fclose(words_file);
dic[i] = NULL;
}
What am I missing here?
There are some problems in your program that may cause the undefined behavior that you observe:
You do not test if the file was open successfully, causing undefined behavior if the file is not where you expect it or has a different name.
You do not limit the number of lines read into the array, causing undefined behavior if the file contains more than 99998 lines, which may be be the case in linux as /usr/share/dict/words has 139716 lines on my system, for example.
Your memory allocation scheme is suboptimal but correct: you should compute the length of the word and strip the newline before allocating the copy. As coded, you allocate too much memory. Yet you should free line before returning from read_to_array and you should avoid using global variables.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char **read_to_array(const char *filename, int *countp) {
FILE *words_file;
char *line = NULL;
size_t line_size = 0;
char **dic = NULL;
int dic_size = 0;
int i = 0;
words_file = fopen(filename, "r");
if (words_file == NULL) {
fprintf(stderr, "cannot open dictionary file %s\n", filename);
return NULL;
}
dic_size = 99999;
dic = malloc(dic_size * sizeof(char *));
if (dic == NULL) {
fprintf(stderr, "cannot allocate dictionary array\n");
fclose(words_file);
return NULL;
}
// read dic to array
while (getline(&line, &line_size, words_file) != -1) {
size_t len = strlen(line);
/* strip the newline if any */
if (len > 0 && line[len - 1] == '\n') {
line[--len] = '\0';
}
if (i >= dic_size - 1) {
/* too many lines: should reallocate the dictionary */
fprintf(stderr, "too many lines\n");
break;
}
dic[i] = malloc(len + 1);
if (dic[i] == NULL) {
/* out of memory: report the error */
fprintf(stderr, "cannot allocate memory for line %d\n", i);
break;
}
strcpy(dic[i], line);
i++;
}
dic[i] = NULL;
*countp = i;
fclose(words_file);
free(line);
return dic;
}
int main(int argc, char **argv) {
const char *filename = (argc > 1) ? argv[1] : "words.txt";
int num_words;
char **dic = read_to_array(filename, &num_words);
if (dic != NULL) {
printf("dictionary loaded: %d lines\n", num_words);
while (num_words > 0)
free(dic[--num_words]);
free(dic);
}
return 0;
}
Output:
chqrlie> readdic /usr/share/dict/words
too many lines
dictionary loaded: 99998 lines

C read file line by line

I wrote this function to read a line from a file:
const char *readLine(FILE *file) {
if (file == NULL) {
printf("Error: file pointer is null.");
exit(1);
}
int maximumLineLength = 128;
char *lineBuffer = (char *)malloc(sizeof(char) * maximumLineLength);
if (lineBuffer == NULL) {
printf("Error allocating memory for line buffer.");
exit(1);
}
char ch = getc(file);
int count = 0;
while ((ch != '\n') && (ch != EOF)) {
if (count == maximumLineLength) {
maximumLineLength += 128;
lineBuffer = realloc(lineBuffer, maximumLineLength);
if (lineBuffer == NULL) {
printf("Error reallocating space for line buffer.");
exit(1);
}
}
lineBuffer[count] = ch;
count++;
ch = getc(file);
}
lineBuffer[count] = '\0';
char line[count + 1];
strncpy(line, lineBuffer, (count + 1));
free(lineBuffer);
const char *constLine = line;
return constLine;
}
The function reads the file correctly, and using printf I see that the constLine string did get read correctly as well.
However, if I use the function e.g. like this:
while (!feof(myFile)) {
const char *line = readLine(myFile);
printf("%s\n", line);
}
printf outputs gibberish. Why?
If your task is not to invent the line-by-line reading function, but just to read the file line-by-line, you may use a typical code snippet involving the getline() function (see the manual page here):
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE * fp;
char * line = NULL;
size_t len = 0;
ssize_t read;
fp = fopen("/etc/motd", "r");
if (fp == NULL)
exit(EXIT_FAILURE);
while ((read = getline(&line, &len, fp)) != -1) {
printf("Retrieved line of length %zu:\n", read);
printf("%s", line);
}
fclose(fp);
if (line)
free(line);
exit(EXIT_SUCCESS);
}
FILE* filePointer;
int bufferLength = 255;
char buffer[bufferLength]; /* not ISO 90 compatible */
filePointer = fopen("file.txt", "r");
while(fgets(buffer, bufferLength, filePointer)) {
printf("%s\n", buffer);
}
fclose(filePointer);
In your readLine function, you return a pointer to the line array (Strictly speaking, a pointer to its first character, but the difference is irrelevant here). Since it's an automatic variable (i.e., it's “on the stack”), the memory is reclaimed when the function returns. You see gibberish because printf has put its own stuff on the stack.
You need to return a dynamically allocated buffer from the function. You already have one, it's lineBuffer; all you have to do is truncate it to the desired length.
lineBuffer[count] = '\0';
realloc(lineBuffer, count + 1);
return lineBuffer;
}
ADDED (response to follow-up question in comment): readLine returns a pointer to the characters that make up the line. This pointer is what you need to work with the contents of the line. It's also what you must pass to free when you've finished using the memory taken by these characters. Here's how you might use the readLine function:
char *line = readLine(file);
printf("LOG: read a line: %s\n", line);
if (strchr(line, 'a')) { puts("The line contains an a"); }
/* etc. */
free(line);
/* After this point, the memory allocated for the line has been reclaimed.
You can't use the value of `line` again (though you can assign a new value
to the `line` variable if you want). */
//open and get the file handle
FILE* fh;
fopen_s(&fh, filename, "r");
//check if file exists
if (fh == NULL){
printf("file does not exists %s", filename);
return 0;
}
//read line by line
const size_t line_size = 300;
char* line = malloc(line_size);
while (fgets(line, line_size, fh) != NULL) {
printf(line);
}
free(line); // dont forget to free heap memory
A complete, fgets() solution:
#include <stdio.h>
#include <string.h>
#define MAX_LEN 256
int main(void)
{
FILE* fp;
fp = fopen("file.txt", "r");
if (fp == NULL) {
perror("Failed: ");
return 1;
}
char buffer[MAX_LEN];
while (fgets(buffer, MAX_LEN, fp))
{
// Remove trailing newline
buffer[strcspn(buffer, "\n")] = 0;
printf("%s\n", buffer);
}
fclose(fp);
return 0;
}
Output:
First line of file
Second line of file
Third (and also last) line of file
Remember, if you want to read from Standard Input (rather than a file as in this case), then all you have to do is pass stdin as the third parameter of fgets() method, like this:
while(fgets(buffer, MAX_LEN, stdin))
Appendix
Removing trailing newline character from fgets() input
how to detect a file is opened or not in c
readLine() returns pointer to local variable, which causes undefined behaviour.
To get around you can:
Create variable in caller function and pass its address to readLine()
Allocate memory for line using malloc() - in this case line will be persistent
Use global variable, although it is generally a bad practice
Use fgets() to read a line from a file handle.
Some things wrong with the example:
you forgot to add \n to your printfs. Also error messages should go to stderr i.e. fprintf(stderr, ....
(not a biggy but) consider using fgetc() rather than getc(). getc() is a macro, fgetc() is a proper function
getc() returns an int so ch should be declared as an int. This is important since the comparison with EOF will be handled correctly. Some 8 bit character sets use 0xFF as a valid character (ISO-LATIN-1 would be an example) and EOF which is -1, will be 0xFF if assigned to a char.
There is a potential buffer overflow at the line
lineBuffer[count] = '\0';
If the line is exactly 128 characters long, count is 128 at the point that gets executed.
As others have pointed out, line is a locally declared array. You can't return a pointer to it.
strncpy(count + 1) will copy at most count + 1 characters but will terminate if it hits '\0' Because you set lineBuffer[count] to '\0' you know it will never get to count + 1. However, if it did, it would not put a terminating '\0' on, so you need to do it. You often see something like the following:
char buffer [BUFFER_SIZE];
strncpy(buffer, sourceString, BUFFER_SIZE - 1);
buffer[BUFFER_SIZE - 1] = '\0';
if you malloc() a line to return (in place of your local char array), your return type should be char* - drop the const.
Here is my several hours... Reading whole file line by line.
char * readline(FILE *fp, char *buffer)
{
int ch;
int i = 0;
size_t buff_len = 0;
buffer = malloc(buff_len + 1);
if (!buffer) return NULL; // Out of memory
while ((ch = fgetc(fp)) != '\n' && ch != EOF)
{
buff_len++;
void *tmp = realloc(buffer, buff_len + 1);
if (tmp == NULL)
{
free(buffer);
return NULL; // Out of memory
}
buffer = tmp;
buffer[i] = (char) ch;
i++;
}
buffer[i] = '\0';
// Detect end
if (ch == EOF && (i == 0 || ferror(fp)))
{
free(buffer);
return NULL;
}
return buffer;
}
void lineByline(FILE * file){
char *s;
while ((s = readline(file, 0)) != NULL)
{
puts(s);
free(s);
printf("\n");
}
}
int main()
{
char *fileName = "input-1.txt";
FILE* file = fopen(fileName, "r");
lineByline(file);
return 0;
}
const char *readLine(FILE *file, char* line) {
if (file == NULL) {
printf("Error: file pointer is null.");
exit(1);
}
int maximumLineLength = 128;
char *lineBuffer = (char *)malloc(sizeof(char) * maximumLineLength);
if (lineBuffer == NULL) {
printf("Error allocating memory for line buffer.");
exit(1);
}
char ch = getc(file);
int count = 0;
while ((ch != '\n') && (ch != EOF)) {
if (count == maximumLineLength) {
maximumLineLength += 128;
lineBuffer = realloc(lineBuffer, maximumLineLength);
if (lineBuffer == NULL) {
printf("Error reallocating space for line buffer.");
exit(1);
}
}
lineBuffer[count] = ch;
count++;
ch = getc(file);
}
lineBuffer[count] = '\0';
char line[count + 1];
strncpy(line, lineBuffer, (count + 1));
free(lineBuffer);
return line;
}
char linebuffer[256];
while (!feof(myFile)) {
const char *line = readLine(myFile, linebuffer);
printf("%s\n", line);
}
note that the 'line' variable is declared in calling function and then passed, so your readLine function fills predefined buffer and just returns it. This is the way most of C libraries work.
There are other ways, which I'm aware of:
defining the char line[] as static
(static char line[MAX_LINE_LENGTH]
-> it will hold it's value AFTER returning from the function). -> bad,
the function is not reentrant, and
race condition can occur -> if you
call it twice from two threads, it
will overwrite it's results
malloc()ing the char line[], and
freeing it in calling functions ->
too many expensive mallocs, and,
delegating the responsibility to free the buffer to another function (the most elegant solution is to call malloc and free on any buffers in same function)
btw, 'explicit' casting from char* to const char* is redundant.
btw2, there is no need to malloc() the lineBuffer, just define it char lineBuffer[128], so you don't need to free it
btw3 do not use 'dynamic sized stack arrays' (defining the array as char arrayName[some_nonconstant_variable]), if you don't exactly know what are you doing, it works only in C99.
void readLine(FILE* file, char* line, int limit)
{
int i;
int read;
read = fread(line, sizeof(char), limit, file);
line[read] = '\0';
for(i = 0; i <= read;i++)
{
if('\0' == line[i] || '\n' == line[i] || '\r' == line[i])
{
line[i] = '\0';
break;
}
}
if(i != read)
{
fseek(file, i - read + 1, SEEK_CUR);
}
}
what about this one?
Implement method to read, and get content from a file (input1.txt)
#include <stdio.h>
#include <stdlib.h>
void testGetFile() {
// open file
FILE *fp = fopen("input1.txt", "r");
size_t len = 255;
// need malloc memory for line, if not, segmentation fault error will occurred.
char *line = malloc(sizeof(char) * len);
// check if file exist (and you can open it) or not
if (fp == NULL) {
printf("can open file input1.txt!");
return;
}
while(fgets(line, len, fp) != NULL) {
printf("%s\n", line);
}
free(line);
}
Hope this help. Happy coding!
You should use the ANSI functions for reading a line, eg. fgets. After calling you need free() in calling context, eg:
...
const char *entirecontent=readLine(myFile);
puts(entirecontent);
free(entirecontent);
...
const char *readLine(FILE *file)
{
char *lineBuffer=calloc(1,1), line[128];
if ( !file || !lineBuffer )
{
fprintf(stderr,"an ErrorNo 1: ...");
exit(1);
}
for(; fgets(line,sizeof line,file) ; strcat(lineBuffer,line) )
{
if( strchr(line,'\n') ) *strchr(line,'\n')=0;
lineBuffer=realloc(lineBuffer,strlen(lineBuffer)+strlen(line)+1);
if( !lineBuffer )
{
fprintf(stderr,"an ErrorNo 2: ...");
exit(2);
}
}
return lineBuffer;
}
My implement from scratch:
FILE *pFile = fopen(your_file_path, "r");
int nbytes = 1024;
char *line = (char *) malloc(nbytes);
char *buf = (char *) malloc(nbytes);
size_t bytes_read;
int linesize = 0;
while (fgets(buf, nbytes, pFile) != NULL) {
bytes_read = strlen(buf);
// if line length larger than size of line buffer
if (linesize + bytes_read > nbytes) {
char *tmp = line;
nbytes += nbytes / 2;
line = (char *) malloc(nbytes);
memcpy(line, tmp, linesize);
free(tmp);
}
memcpy(line + linesize, buf, bytes_read);
linesize += bytes_read;
if (feof(pFile) || buf[bytes_read-1] == '\n') {
handle_line(line);
linesize = 0;
memset(line, '\0', nbytes);
}
}
free(buf);
free(line);
Provide a portable and generic getdelim function, test passed via msvc, clang, gcc.
/*
* An implementation conform IEEE Std 1003.1-2017:
* https://pubs.opengroup.org/onlinepubs/9699919799/functions/getdelim.html
*
* <nio.h>:
* https://github.com/junjiemars/c/blob/c425bd0e49df35a2649327664d3f6cd610791996/src/posix/nio.h
* <nio.c>:
* https://github.com/junjiemars/c/blob/c425bd0e49df35a2649327664d3f6cd610791996/src/posix/nio.c
*
*/
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
/*
* LINE_MAX dependents on OS' implementations so check it first.
* https://github.com/junjiemars/c/blob/c425bd0e49df35a2649327664d3f6cd610791996/src/posix/nlim_auto_check
*/
#define NM_LINE_MAX 4096 /* Linux */
#if (MSVC)
typedef SSIZE_T ssize_t;
# if !defined(SSIZE_MAX)
# define SSIZE_MAX ((ssize_t)((size_t)((ssize_t)-1) >> 1))
# endif
#endif
ssize_t getdelim(char **restrict lineptr, size_t *restrict n, int delimiter,
FILE *restrict stream);
#if defined(getline)
# undef getline
#endif
#define getline(lp, n, f) getdelim((lp), (n), 0x0a, (f))
ssize_t
getdelim(char **restrict lineptr, size_t *restrict n, int delimiter,
FILE *restrict stream)
{
int c;
char *p, *p1;
ssize_t len;
if (NULL == lineptr || NULL == n || NULL == stream
|| (UCHAR_MAX < delimiter || delimiter < 0))
{
errno = EINVAL;
return EOF;
}
if (feof(stream) || ferror(stream))
{
return EOF;
}
if (0 == *lineptr)
{
if (0 == *n)
{
*n = NM_LINE_MAX;
}
*lineptr = malloc(*n);
if (0 == *lineptr)
{
return EOF;
}
}
p = *lineptr;
len = 0;
while (EOF != (c = fgetc(stream)))
{
if (SSIZE_MAX == (ssize_t) len)
{
errno = EOVERFLOW;
return EOF;
}
if ((size_t) len == (*n - 1))
{
*n <<= 1;
p1 = realloc(*lineptr, *n);
if (0 == p1)
{
return EOF;
}
*lineptr = p1;
p = p1 + len;
}
*p++ = (char) c;
len++;
if (c == delimiter)
{
break;
}
}
if (ferror(stream))
{
return EOF;
}
*p = 0;
return len;
}
int
main(void)
{
FILE *fp;
char *line = NULL;
size_t len = 0;
ssize_t read;
fp = fopen("/some-file", "r");
if (fp == NULL)
exit(1);
while ((read = getline(&line, &len, fp)) != -1) {
printf("Retrieved line of length %zu :\n", read);
printf("%s", line);
}
if (ferror(fp)) {
/* handle error */
}
free(line);
fclose(fp);
return 0;
}
You make the mistake of returning a pointer to an automatic variable.
The variable line is allocated in the stack and only lives as long as the function lives.
You are not allowed to return a pointer to it, because as soon as it returns the memory will be given elsewhere.
const char* func x(){
char line[100];
return (const char*) line; //illegal
}
To avoid this, you either return a pointer to memory which resides on the heap eg. lineBuffer
and it should be the user's responsibility to call free() when he is done with it.
Alternatively you can ask the user to pass you as an argument a memory address on which to write the line contents at.
I want a code from ground 0 so i did this to read the content of dictionary's word line by line.
char temp_str[20]; // you can change the buffer size according to your requirements And A single line's length in a File.
Note I've initialized the buffer With Null character each time I read line.This function can be Automated But Since I need A proof of Concept and want to design a programme Byte By Byte
#include<stdio.h>
int main()
{
int i;
char temp_ch;
FILE *fp=fopen("data.txt","r");
while(temp_ch!=EOF)
{
i=0;
char temp_str[20]={'\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0'};
while(temp_ch!='\n')
{
temp_ch=fgetc(fp);
temp_str[i]=temp_ch;
i++;
}
if(temp_ch=='\n')
{
temp_ch=fgetc(fp);
temp_str[i]=temp_ch;
}
printf("%s",temp_str);
}
return 0;
}

Resources