using fgets() to extract lines from a file not working - c

I'm trying to develop a function that reads each line of a text file and the it stores them in an array of strings (char**) but fgets() doesnt seem to work, it always return a null character.
Here is the function
char** getLines(FILE* fp){
char** lines;
int numberOfLines; //number of lines int the file
char ch; //aux var
int i; //counter
while(!feof(fp)){
ch = fgetc(fp);
if( ch == '\n'){
numberOfLines++;
}
}
lines = malloc(numberOfLines*sizeof(char*));
if (lines==NULL){
fprintf(stderr,"Error, malloc failed");
exit(1);
}
for(i = 0; i<numberOfLines; i++){
lines[i] = malloc(MAX_LENGTH*sizeof(char)); //MAX_LENGTH = 128
}
i=0;
while(fgets(lines[i], MAX_LENGTH,fp)){
printf("Line %d: %s \n",i,lines[i]);
i++;
}
return lines;
}
The function never gets inside the while loop so it doesn't print anything
I'm also using a very simple input file:
test line 1
test line 2
test line 3
test line 4
Hope you can help me,
Thank you in advance.

You are already on the end of the file before entering the while loop.
Take a look here http://en.cppreference.com/w/cpp/io/c/rewind
Moves the file position indicator to the beginning of the given file stream. The function is equivalent to std::fseek(stream, 0, SEEK_SET); except that end-of-file and error indicators are cleared. The function drops any effects from previous calls to ungetc.
Check if this works:
char** getLines(FILE* fp){
/* ...... */
i=0;
rewind(fp); // Rewind here
while(fgets(lines[i], MAX_LENGTH,fp)){
printf("Line %d: %s \n", i, lines[i]); // Also use the index as first parameter
i++;
}
return lines;
}

Related

function which returns the specified line of a file given as input

I want to create a function which has a text file as input with a line number and returns the string which represents the line in the number given as argument, in C langage. I've written this function (getLineFromFile) but I think it changes the content of my file, because I tried to use it in one other function but it seems to act weird(in the function (compiled)). these are the codes of my fuction getLineFromFile and the function "compiled", in compiled, when I run it gives me weird caracteres which doesnt represent my line. Can you help me I dont see where is the problem with the function getLineFromFile, I think the function getNumberOfLines has also problems, I want her to return 0 when the file is empty.
thank you
#include <stdlib.h>
#include <string.h>
char* getLineFromFile(FILE *fp, int lineNumber)// si on depasse le nb de lignes, elle renvoie la derniere
{
char *str;
int i;
str = malloc(sizeof(char) * 80);// disons que ca ne depasse pas 80
for (i = 1 ; i <= lineNumber; i++)
fgets(str, 80, fp);
str[strlen(str) - 1] = '\0';
return str;
}
/// count the number of non empty lines in a file
int count_number_of_lines(FILE *fp) {
int count = 0;
char line[256];
while (fgets(line, sizeof(line), fp) != NULL) {
if (strlen(line) > 0) {
count++;
}
}
return count;
}
int compiled(FILE* fp){
char *line =malloc(sizeof(char)*80);
int nb_lines=count_number_of_lines(fp);
printf("number of lines : %d \n", nb_lines);
for (int j=1;j<=nb_lines;j++){
line=getLineFromFile(fp,j);
printf("%s \n",line);
}
return 0;
}
int main()
{
FILE *fichier=fopen("CodeSource.txt","r");
char *str=malloc(sizeof(char)*80);
int nb_lines=count_number_of_lines(fichier);
for (int j=1;j<=nb_lines;j++){
str=getLineFromFile(fichier,j);
printf("%s \n",str);
}
free(str);
return 0;
}
After you call count_number_of_lines, you've read the entire file. So, when you call getLineFromFile, there's nothing left to read because you're at the end of the file. What you need to do is seek to the beginning of the file on every call of getLineFromFile:
char* getLineFromFile(FILE *fp, int lineNumber)
{
fseek(fp, 0, SEEK_SET);
...
}
On a side note, you're counting lines inconsistently between the two functions. In count_number_of_lines, you don't count empty lines. However, in getLineFromFile, you do count them. Even then, strlen will actually be positive even for empty lines because of the newline character(s). So, you're accidentally getting the same line count.
In the function main, you are first calling count_number_of_lines and then getLineFromFile.
The function count_number_of_lines will read the file until it reaches the end of the file. Therefore, when you call getLineFromFile, you will already be at the end of the file. For this reason, getLineFromFile will be unable to find any further data in the file.
In order to get the function getLineFromFile to work, you will have to rewind to the beginning of the file, for example by adding the line
rewind( fp );
to the beginning of the function.

Reading text file into an array in C

I want to parse a .txt file into a 1D array in C. I'm using the fgets function to read the contents of the file into the array("waveform" as the array into which the file contents are to be stored - defined as a "char"). The saved values need to be saved into a new array as integer values. I am not sure where I am going wrong.
P.S: I am new to programming in C, please bear with me :)
Please ignore the indexing issues, done due to pasting
int main(){
int a, win[10];
FILE *filename = fopen("testFile.txt","r");
char waveform[10];
if (filename == NULL)
{
printf("Error opening file.\n");
exit(8);
}
for(int i =0;1;i++){
if(fgets(waveform[i], 10, filename) == NULL);
break;
if(i < 10)
{
a = atoi(waveform[i]);
win[i] = a;
}
}
fclose(filename);
return 0;
}
Compiler errors - image embedded
Data in testFile.txt:
1 to 10 in a row vector.
You are on the right track. Here is my contribution on the topic:
Open the file (fopen)
Count number of lines (getc and rewind)
Read all lines into array (getline)
Free memory and close file (free and fclose)
Code example:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
// Open File
const char fname[] = "testFile.txt";
FILE *fp = fopen(fname, "r");
if( !fp )
goto error_open_file;
printf("Opened file: %s\n", fname);
// Count Lines
char cr;
size_t lines = 0;
while( cr != EOF ) {
if ( cr == '\n' ) {
lines++;
}
cr = getc(fp);
}
printf("Number of lines: %ld\n", lines);
rewind(fp);
// Read data
{// 'goto' + data[lines] causes error, introduce block as a workaround
char *data[lines];
size_t n;
for (size_t i = 0; i < lines; i++) {
data[i] = NULL;
size_t n = 0;
getline(&data[i], &n, fp);
if ( ferror( fp ) )
goto error_read_file;
}
for (size_t i = 0; i < lines; i++) {
printf("%s", data[i]);
free(data[i]);
}
}
// Close File
fclose(fp);
return 0;
error_read_file:
perror("fopen ");
return 1;
error_open_file:
perror("getline ");
return 2;
}
There are several errors in this loop
for(int i =0;1;i++){
if(fgets(waveform[i], 10, filename) == NULL);
break;
if(i < 10)
{
a = atoi(waveform[i]);
win[i] = a;
}
}
For starters there is a semicolon after the if statement
if(fgets(waveform[i], 10, filename) == NULL);
^^^
Secondly the fgets call
fgets(waveform[i], 10, filename)
^^^
is invalid because the type of the expression waveform[i] is char.
And correspondingly this statement
a = atoi(waveform[i]);
is also invalid.
There must be at least
fgets( waveform, 10, filename)
and
a = atoi( waveform );
I suppose that each line of the file contains exactly one number. (Otherwise you should use for example sscanf to extract numbers from a line using an internal additional loop.)
The loop can look like
int i = 0;
for ( ; i < 10 && fgets( waveform, 10, filename) != NULL; i++ )
{
a = atoi( waveform );
win[i] = a;
}
After the loop the variable i will contain the actual number of elements of the array win.
Pay attention to that the name filename is not good for a pointer of the type FILE *. File name is the string "testFile.txt" in your code.
If you want to use the fgets() function you don't have to put it into a loop. Indeed, the second argument of fgets() is the number of elements you want to read.
I would have put the fgets() into a singl-line instruction, and then loop from 0 to 10 to make the conversion from char to int with the atoi() function.
Moreover, you have a ; at the end of your if() statement, so you'll execute it not in the way you want.

EXC_BAD_ACCESS when reading from csv file using fgets and sscanf

I am trying to read from a huge .csv file (about 100,000 lines). Using fgets, I extract the entire line then using sscanf, I read 21 int values inside the line. However, sscanf returns error EXC_BAD_ACCESS at line 758. I tried to increase the size for the buffer and can read more lines but not all. Is there more elegant and clean way to read huge data with C? Thank you.
char buffer[316]; // buffer to contain one line
int x[20][100000]; // int values saved in a matrix
int line = 0; // counter for lines
int j = 0; // counter for lines (excluding headers)
FILE *fp;
char fname[] = "/Users/basho/data_TS-20.csv";
fp = fopen(fname, "r");
if(fp == NULL) {
printf("%s file not open!\n", fname);
return -1;
}
// read one line at a time using fgets
while (fgets(buffer, sizeof buffer, fp) != NULL) {
if (line > 1) // we first skip the two first lines of the file, some empty line and the header.
{
printf("line %d\n",line);
sscanf(buffer, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d, ",
&x[0][j], &x[1][j], &x[2][j], &x[3][j], &x[4][j], &x[5][j], &x[6][j], &x[7][j], &x[8][j], &x[9][j],
&x[10][j], &x[11][j], &x[12][j], &x[13][j],&x[14][j], &x[15][j], &x[16][j], &x[17][j], &x[18][j],
&x[19][j], &x[20][j]);
for(int i = 0; i<20; i++){
printf("%d ",x[i][j]);
}
printf("%d\n",x[20][j]);
j = j+ 1;
//}
}
line =line + 1;
}
fclose(fp);
return 0;
}
Review int x[20][100000]; and &x[20][j] --> off by 1.
// int x[20][100000];
int x[21][100000];
Also
j = j+ 1;
if (j >= 100000) break;

Reading text from a file using fscanf()

guys i want to read the text from my file and assign every character to a single element of the array
char A[1000];
FILE * fpointer;
fpointer=fopen("text.txt","r");
i=0;
while(!feof(fpointer))
{
fscanf(fpointer,"%c",&A[i]);
i=i+1;
}
fclose(fpointer);
for (i=0;i<100;i++)
{
printf("%c",A[i]);
}
return 0;
but the problem is that the output is some weird symbols instead of the file's text which is "This is just a test".Why is that happening ?
Possible reasons include:
fopen failed to open the specified file. Fix by checking the return value of fopen.
See Why is “while ( !feof (file) )” always wrong?
You always print 100 characters, but if the file contains less than 100 characters, you're in trouble because you print uninitialized locations of the array, leading to UB. Fix by printing everything starting from zero upto i.
Corrected code snippet:
int i = 0, j = 0;
char A[1000];
FILE* fpointer;
fpointer = fopen("text.txt", "r");
if(!fpointer)
{
fputs("fopen failed! Exiting...\n", stderr);
exit(-1); /* Requires `stdlib.h` */
}
while(fscanf(fpointer, "%c", &A[i]) != EOF)
{
i = i + 1;
}
fclose(fpointer);
for (j = 0; j < i; j++){
printf("A[%d] = '%c'\n", j, A[j]);
}
To expand on the points by #Cool Guy:
In case your files do not contain the null character, you can avoid using another variable to store the number of characters read. If you null terminate your read in characters, you can just print them directly as a string.
You have to make sure that A can hold enough characters. If you expect at most 1000 characters, make sure that A has a size of 1001 bytes to contain the terminating NUL character.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
char A[1001] = { 0 }; /* init to NUL, expect at most 1000 chars */
int i;
FILE *fpointer;
fpointer=fopen("text.txt","r");
if(!fpointer) {
perror("Error opening file"); /* print error message */
exit(-1); /* Requires `stdlib.h` */
}
/* read all characters from fpointer into A */
for (i=0; fscanf(fpointer, "%c", &A[i]) != EOF; i++);
fclose(fpointer);
printf("%s\n",A); /* print all characters as a string */
/* alternatively, loop until NUL found */
for (i=0; A[i]; i++)
printf("%c", A[i]);
printf("\n");
return 0;
}

reading text file, copying into array in C

The code is supposed to read a user-inputted text file name, copy every character into a multidimensional array, then display it with standard output. It compiles, but produces unintelligible text. Am I missing something?
for (i = 0; i < BIGGEST; i++) {
for (j = 0; j < BIGGESTL; j++) {
if (fgetc(array, fp) ) != EOF)
array[i][j] = c;
else array[i][j] = '\0'
}
fclose(fp);
return 0;
}
You stop filling the array when you encounter EOF, but you print the full array out no matter what.
If the data read from the file is smaller than the input array, you will read that data in and then print that data out, plus whatever random characters were in the memory locations that you do not overwrite with data from the file.
Since the requirement seems to be to print text data, you could insert a special marker in the array (e.g. '\0') to indicate the position where you encountered EOF, and stop displaying data when you reach that marker.
You had better read each line from file
For example:
int i = 0;
while(fgets(text[i],1000,fp))
{
i++;
}
Though the question is edited and only part of the code is left in question. I am posting more than what is required for the question at the moment.
Reason being, there can be numberous improvements to originally posted full code.
In main() function:
You need to check for the argc value to be equal to 2 for your purpose and only then read in value of argv[1] . Else if program executed without the command-line-argument which is file_name in this case, invalid memory read occurs, resulting in segmentation fault if you read in argv[1].
In read_file_and_show_the contents() function:
Stop reading file if end of file is reached or maximum characters is read and store in the character array.
Below Program will help you visualize:
#include <stdio.h>
/*Max number of characters to be read/write from file*/
#define MAX_CHAR_FOR_FILE_OPERATION 1000000
int read_and_show_the_file(char *filename)
{
FILE *fp;
char text[MAX_CHAR_FOR_FILE_OPERATION];
int i;
fp = fopen(filename, "r");
if(fp == NULL)
{
printf("File Pointer is invalid\n");
return -1;
}
//Ensure array write starts from beginning
i = 0;
//Read over file contents until either EOF is reached or maximum characters is read and store in character array
while( (fgets(&text[i++],sizeof(char)+1,fp) != NULL) && (i<MAX_CHAR_FOR_FILE_OPERATION) ) ;
//Ensure array read starts from beginning
i = 0;
while((text[i] != '\0') && (i<MAX_CHAR_FOR_FILE_OPERATION) )
{
printf("%c",text[i++]);
}
fclose(fp);
return 0;
}
int main(int argc, char *argv[])
{
if(argc != 2)
{
printf("Execute the program along with file name to be read and printed. \n\
\rFormat : \"%s <file-name>\"\n",argv[0]);
return -1;
}
char *filename = argv[1];
if( (read_and_show_the_file(filename)) == 0)
{
printf("File Read and Print to stdout is successful\n");
}
return 0;
}

Resources