Segmentation fault at the last line when reading file - c

I got a segmentation fault when reading a file. There is an empty line at the end of the file. I thought when I did fscanf( input, "[^\n]\n", c ), it would take the next line tab from the second last line and the token went to the empty line at the end, which will be '\0', but I got the a segmentation fault.
FILE *input = fopen( filename, "r" );
if ( input == NULL ) {
fprintf( stderr, "Can't open file: %s\n", filename );
exit( EXIT_FAILURE );
}
file = ( char ** )malloc( MAX_LINE * sizeof( char * ) );
int index = 0;
char *c = ( char * )malloc( MAX_CHAR * sizeof( char ) );
int length = 0;
while ( fscanf( input, "%[^\n]\n", c ) != EOF ) {
if ( c == NULL ) {
fprintf( stderr, "Cannot read line: %d ", index );
exit( EXIT_FAILURE );
}
length = ( int ) strlen( c );
// checking if a line has too many characters
if ( length > MAX_CHAR ) {
fprintf( stderr, "Line too long: %s:%d\n", filename, ( index + 1 ) );
exit( EXIT_FAILURE );
}
//checking if the file has too many lines
if ( index > MAX_LINE ) {
fprintf( stderr, "Too many lines: %s\n", filename );
exit( EXIT_FAILURE );
}
//printf( "%s\n%d %d\n", c, index, length );
file[ index ] = ( char * )malloc( MAX_CHAR * sizeof( char ) );
file[ index ] = c;
index++;
}

Related

C language reading from file and placing in variables

In a text file I have the form Type:Username Password, how do I place it in three different variables, so that the variable Type is in the variable type, username is in username, and password is in password in C ?
Example:
Admin:Username Password
How to make?
Type:Admin
User:Username
Pw:Password
Here's my code:
int ch;
int i = 0;
while ((ch = fgetc(fp)) != EOF) {
// Check for the colon character
if (ch == ':') {
// We have reached the end of the type string
// Move to the next variable
i = 0;
continue;
}
// Check for the space character
if (ch == ' ')
{
// We have reached the end of the username string
// Move to the next variable
i = 0;
continue;
}
// Store the character in the appropriate variable
if (i < 50) {
if (type[0] == 0) {
type[i] = ch;
} else if (username[0] == 0) {
username[i] = ch;
} else {
password[i] = ch;
}
i++;
}
}
Considering your initial requirement that you posted in your Question, that a text file consists of following line:
Admin:Username Password
To store Admin in variable type, Username in variable username and similarly Password in variable Password.
You can declare a structure something similar to:
typedef struct user {
char type[512];
char username[512];
char password[512];
} user;
And as #IngoLeonhardt commented, that strtok() or strchr() can be used to parse the line read from the text file, you can refer the below simple example code snippet to understand and further improve the logic.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct user {
char type[512];
char username[512];
char password[512];
} user;
int main(void)
{
FILE *file = fopen("test.txt","r");
char *line = NULL;
size_t linesize = 0;
char *token;
const char colon[2] = ":";
const char space[2] = " ";
user user_1;
if (file)
{
while (getline(&line, &linesize, file) != -1)
{
printf("%s\n", line);
token = strtok(line, colon);
strcpy(user_1.type, token);
token = strtok(NULL, space);
strcpy(user_1.username, token);
token = strtok(NULL, space);
strcpy(user_1.password, token);
printf("%s\n", user_1.type);
printf("%s\n", user_1.username);
printf("%s", user_1.password);
free(line);
}
fclose(file);
}
return 0;
}
PS: There may be some flaws/bugs in above implementation, please consider the above code just as an example.
Here is a solution which reads one character at a time from the file:
#include <stdio.h>
#include <stdlib.h>
#define MAX_STRING_SIZE 200
int main( void )
{
char type[MAX_STRING_SIZE];
char user[MAX_STRING_SIZE];
char pw[MAX_STRING_SIZE];
FILE *fp;
int ch;
int i;
//open the input file
fp = fopen( "input.txt", "r" );
if ( fp == NULL )
{
fprintf( stderr, "Error opening file!\n" );
exit( EXIT_FAILURE );
}
//read first token
i = 0;
while ( ( ch = fgetc( fp ) ) != ':' )
{
if ( ch == EOF )
{
fprintf( stderr, "Input error!\n" );
exit( EXIT_FAILURE );
}
if ( i == MAX_STRING_SIZE )
{
fprintf( stderr, "Sub-string is too long!\n" );
exit( EXIT_FAILURE );
}
type[i++] = ch;
}
type[i] = '\0';
//read second token
i = 0;
while ( ( ch = fgetc( fp ) ) != ' ' )
{
if ( ch == EOF )
{
fprintf( stderr, "Input error!\n" );
exit( EXIT_FAILURE );
}
if ( i == MAX_STRING_SIZE )
{
fprintf( stderr, "Sub-string is too long!\n" );
exit( EXIT_FAILURE );
}
user[i++] = ch;
}
user[i] = '\0';
//read third token
i = 0;
while ( ( ch = fgetc( fp ) ) != EOF )
{
if ( i == MAX_STRING_SIZE )
{
fprintf( stderr, "Sub-string is too long!\n" );
exit( EXIT_FAILURE );
}
pw[i++] = ch;
}
pw[i] = '\0';
//close the file
fclose( fp );
//print the three strings
printf( "Type:%s\n", type );
printf( "User:%s\n", user );
printf( "Pw:%s\n", pw );
}
For the input stated in the question, this program has the desired output:
Type:Admin
User:Username
Pw:Password
Here is an alternative solution, which reads a whole line at once:
This solution reads a line from the file as a string, by using the function fgets. After doing that, it uses the function strchr to find the ':' and ' ' delimiter characters in the string. Once they are found, the characters between the tokens can be copied so that they form a string.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define MAX_STRING_SIZE 200
bool read_exactly_one_line( char buffer[], int buffer_size, FILE *fp );
int main( void )
{
char type[MAX_STRING_SIZE];
char user[MAX_STRING_SIZE];
char pw[MAX_STRING_SIZE];
FILE *fp;
char line[500];
char *p, *q;
int token_length;
//open the input file
fp = fopen( "input.txt", "r" );
if ( fp == NULL )
{
fprintf( stderr, "Error opening file!\n" );
exit( EXIT_FAILURE );
}
//read one line of input
if ( ! read_exactly_one_line( line, sizeof line, fp ) )
{
fprintf( stderr, "File is empty!\n" );
exit( EXIT_FAILURE );
}
//find the delimiter between the first and second token
p = strchr( line, ':' );
if ( p == NULL )
{
fprintf( stderr, "Unable to find first delimiter!\n" );
exit( EXIT_FAILURE );
}
//verify that first token is not too large
token_length = p - line;
if ( token_length >= MAX_STRING_SIZE )
{
fprintf( stderr, "Token too large!\n" );
exit( EXIT_FAILURE );
}
//copy the first token
memcpy( type, line, token_length );
type[token_length] = '\0';
//move pointer to start of second token
p++;
//find the delimiter between the second and third token
q = strchr( p, ' ' );
if ( q == NULL )
{
fprintf( stderr, "Unable to find second delimiter!\n" );
exit( EXIT_FAILURE );
}
//verify that second token is not too large
token_length = q - p;
if ( token_length >= MAX_STRING_SIZE )
{
fprintf( stderr, "Token too large!\n" );
exit( EXIT_FAILURE );
}
//copy the second token
memcpy( user, p, token_length );
user[token_length] = '\0';
//move pointer to start of third token
q++;
//verify that third token is not too large
token_length = strlen( q );
if ( token_length >= MAX_STRING_SIZE )
{
fprintf( stderr, "Token too large!\n" );
exit( EXIT_FAILURE );
}
//copy the third token
memcpy( pw, q, token_length );
pw[token_length] = '\0';
//close the file
fclose( fp );
//print the three strings
printf( "Type:%s\n", type );
printf( "User:%s\n", user );
printf( "Pw:%s\n", pw );
}
//This function will read exactly one line and remove the newline
//character, if it exists. On success, it will return true. If this
//function is unable to read any further lines due to end-of-file,
//it returns false. If it fails for any other reason, it will not
//return, but will print an error message and call "exit" instead.
bool read_exactly_one_line( char buffer[], int buffer_size, FILE *fp )
{
char *p;
//attempt to read one line from the stream
if ( fgets( buffer, buffer_size, fp ) == NULL )
{
if ( ferror( fp ) )
{
fprintf( stderr, "Input error!\n" );
exit( EXIT_FAILURE );
}
return false;
}
//make sure that line was not too long for input buffer
p = strchr( buffer, '\n' );
if ( p == NULL )
{
//a missing newline character is ok if the next
//character is a newline character or if we have
//reached end-of-file (for example if the input is
//being piped from a file or if the user enters
//end-of-file in the terminal itself)
if ( getc(fp) != '\n' && !feof(stdin) )
{
printf( "Line input was too long!\n" );
exit( EXIT_FAILURE );
}
}
else
{
//remove newline character by overwriting it with a null
//character
*p = '\0';
}
return true;
}
This program has the same output as the first one.

How to detect a repeated " user input String " in a file?

The idea is like compare line by line of strings and detecting the duplicated ones to evade putting theme in another file
after I fill my file with names and created a new file to put all strings without the duplicated ones, I used this loop, but I don't know if it's right or nah. It didn't work
FILE *Tr , *temp;
char test[50] , test1[50];
Tr = fopen("test.txt","w");
temp = fopen("temp1.txt" , "r");
while( !feof(temp) )
{
fgets(test , 50 , temp);
while( !feof(temp) ){
if ( fgets(test , 50 , temp) == fgets(test1 , 50 , temp) ){
printf("a string exist in the file");
}
else{ fprintf(Tr, "%s" , test1);
}
}
}
The following line is wrong:
if ( fgets(test , 50 , temp) == fgets(test1 , 50 , temp) ){
Using == on pointers will compare the actual pointer values, i.e. the memory addresses. If you want to compare the actual string contents (i.e. what the pointers are pointing to), then you must use strcmp instead.
Also, you should only read from the input file, not the output file.
You should also remember all strings that you have read. Otherwise, you will have no way of determining whether the current line is a duplicate or not.
Additionally, it does not make sense having both an outer loop and an inner loop with the same loop condition:
while( !feof(temp) )
Also, using !feof(temp) as a loop condition is generally wrong. See this question for further information:
Why is “while ( !feof (file) )” always wrong?
The following program will remember up to 100 strings, each up to 100 chars in length (including the terminating null character).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define MAX_STRINGS 100
#define MAX_STRING_LEN 100
int main( void )
{
FILE *input, *output;
char strings[MAX_STRINGS][MAX_STRING_LEN];
int num_strings = 0;
char line[MAX_STRING_LEN];
//open input file
input = fopen( "input.txt", "r" );
if ( input == NULL )
{
fprintf( stderr, "Error opening input file!\n" );
exit( EXIT_FAILURE );
}
//open output file
output = fopen( "output.txt", "w" );
if ( output == NULL )
{
fprintf( stderr, "Error opening output file!\n" );
exit( EXIT_FAILURE );
}
//read one line of input per loop iteration
while ( fgets( line, sizeof line, input ) != NULL )
{
bool is_duplicate = false;
char *p;
//find newline character
p = strchr( line, '\n' );
//make sure that input buffer was large enough to
//read entire line, and remove newline character
//if it exists
if ( p == NULL )
{
if ( !feof( input ) )
{
fprintf( stderr, "Line was too long for input buffer!\n" );
exit( EXIT_FAILURE );
}
}
else
{
//remove newline character
*p = '\0';
}
//determine whether line is duplicate
for ( int i = 0; i < num_strings; i++ )
{
if ( strcmp( line, strings[i] ) == 0 )
{
is_duplicate = true;
break;
}
}
if ( !is_duplicate )
{
//remember string
strcpy( strings[num_strings++], line );
//write string to output file
fprintf( output, "%s\n", line );
}
}
//cleanup
fclose( output );
fclose( input );
}
Given the input
String1
String2
String3
String4
String5
String1
String6
String2
String1
String7
String8
String1
String2
this program has the following output:
String1
String2
String3
String4
String5
String6
String7
String8
As you can see, all duplicate strings were properly filtered out of the output.
However, using a statically sized array is a bit of a waste of space, and it also imposes a hard limit. Therefore, it may be better to use dynamic memory allocation instead:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define INITIAL_CAPACITY 100
#define MAX_LINE_LEN 200
int main( void )
{
FILE *input, *output;
char **strings;
size_t strings_capacity;
int num_strings = 0;
char line[MAX_LINE_LEN];
//open input file
input = fopen( "input.txt", "r" );
if ( input == NULL )
{
fprintf( stderr, "Error opening input file!\n" );
exit( EXIT_FAILURE );
}
//open output file
output = fopen( "output.txt", "w" );
if ( output == NULL )
{
fprintf( stderr, "Error opening output file!\n" );
exit( EXIT_FAILURE );
}
//set capacity of "strings" array to INITIAL_CAPACITY
strings_capacity = INITIAL_CAPACITY;
strings = malloc( strings_capacity * sizeof *strings );
if ( strings == NULL )
{
fprintf( stderr, "Memory allocation failure!\n" );
exit( EXIT_FAILURE );
}
//read one line of input per loop iteration
while ( fgets( line, sizeof line, input ) != NULL )
{
bool is_duplicate = false;
char *p;
//find newline character
p = strchr( line, '\n' );
//make sure that input buffer was large enough to
//read entire line, and remove newline character
//if it exists
if ( p == NULL )
{
if ( !feof( input ) )
{
fprintf( stderr, "Line was too long for input buffer!\n" );
exit( EXIT_FAILURE );
}
}
else
{
//remove newline character
*p = '\0';
}
//determine whether line is duplicate
for ( int i = 0; i < num_strings; i++ )
{
if ( strcmp( line, strings[i] ) == 0 )
{
is_duplicate = true;
break;
}
}
if ( !is_duplicate )
{
//expand capacity of "strings" array if necessary
if ( num_strings == strings_capacity )
{
strings_capacity *= 2;
strings = realloc( strings, strings_capacity * sizeof *strings );
if ( strings == NULL )
{
fprintf( stderr, "Memory allocation failure!\n" );
exit( EXIT_FAILURE );
}
}
//remember string
strings[num_strings] = malloc( strlen( line ) + 1 );
if ( strings[num_strings] == NULL )
{
fprintf( stderr, "Memory allocation failure!\n" );
exit( EXIT_FAILURE );
}
strcpy( strings[num_strings], line );
num_strings++;
//write string to output file
fprintf( output, "%s\n", line );
}
}
//cleanup
//free all dynamically allocated memory
for ( int i = 0; i < num_strings; i++ )
free( strings[i] );
free( strings );
//close file handles
fclose( output );
fclose( input );
}

is this right way of opening a .txt file

This part of code is responsiable for opening my data.txt file and reading a couple numbers from it (size of arrays and numbers to fill it with) but both Virtual Programming Lab and C say "can not find the program "" in executable files". I tried this way by writing a program what will only read 1 number from .txt and same error appeares so i guess im doing this completely wrong. Is there any other way of reading from .txt file? Thanks
Array* input() {
int x,y;
int i;
Array *p;
FILE *f=fopen("data.txt", "r");
p = (Array*) malloc(sizeof(Array));
fscanf(f, "&d",&x);
fscanf(f, "&d",&y);
p->n1 = x;
p->n2 = y;
p->p1 = (int*) malloc(sizeof(int) * p->n1);
p->p2 = (int*) malloc(sizeof(int) * p->n2);
for(i=0; i < p->n1; i++)
fscanf(f, "%d", &p->p1[i]);
for(i=0; i < p->n2; i++)
fscanf(f, "%d", &p->p2[i]);
fclose(f);
return p;
}
the following proposed code:
may cause the compiler to output: "untitled.c:114:9: warning: unused variable ‘ptrToArray’ [-Wunused-variable]"
performs the desired functionality
properly checks for I/O errors
properly cleans up after any I/O error
separates the definition of the struct from the typedef for that struct, for flexibility
the function: malloc() expects a parameter of type size_t. This results in several other changes being needed from int to size_t
for ease of readability and understanding: separates code blocks: for if else while do...while switch case default via a single blank line
for readability, inserts a space around C operators, inside parens, after commas, after semicolons, inside braces, inside brackets
follows the axiom: only one statement per line and (at most) one variable declaration per statement.
properly declares the parameter list for function: input() as void
for readability (by humans) consistently indents the code. indents after every opening brace '{'. Unindents before every closing brace '}'. Uses a indent width of 4 spaces.
for ease of readability and understanding: separates functions via 2 blank lines.
limits the scope of local variable i to the code block it is declared within rather than to the scope of the function: input()
and now, the proposed code:
#include <stdio.h>
#include <stdlib.h>
struct array
{
size_t n1;
size_t n2;
int *p1;
int *p2;
};
typedef struct array ARRAY;
ARRAY* input( void )
{
size_t x;
size_t y;
ARRAY *p;
FILE *f = fopen( "data.txt", "r" );
if( !f )
{
perror( "fopen for reading data.txt failed" );
exit( EXIT_FAILURE );
}
p = malloc( sizeof(ARRAY) );
if( !p )
{
perror( "malloc for an instance of struct array failed" );
fclose( f );
exit( EXIT_FAILURE );
}
if( fscanf( f, "%zu", &x ) != 1 )
{
fprintf( stderr, "fscanf for first data from file failed\n" );
fclose( f );
free( p->p1 );
free( p->p2 );
free( p );
exit( EXIT_FAILURE );
}
if( fscanf( f, "%zu", &y ) != 1 )
{
fprintf( stderr, "fscanf for second data from file failed\n" );
fclose( f );
free( p );
exit( EXIT_FAILURE );
}
p->n1 = x;
p->n2 = y;
p->p1 = malloc(sizeof(int) * p->n1);
if( !p->p1 )
{
perror( "malloc failed for pointer 'p1'" );
free( p );
fclose( f );
exit( EXIT_FAILURE );
}
p->p2 = malloc(sizeof(int) * p->n2);
if( !p->p2 )
{
perror( "malloc failed for pointer 'p2'" );
free( p->p1 );
free( p );
fclose( f );
exit( EXIT_FAILURE );
}
for( size_t i=0; i < p->n1; i++ )
{
if( fscanf(f, "%d", &p->p1[i]) != 1 )
{
fprintf( stderr, "fscanf for %zu value in array 'p1' failed\n", i );
fclose(f);
free( p->p1 );
free( p->p2 );
free( p );
exit( EXIT_FAILURE );
}
}
for( size_t i=0; i < p->n2; i++ )
{
if( fscanf(f, "%d", &p->p2[i]) != 1 )
{
fprintf( stderr, "fscanf for %zu value in array 'p2' failed\n", i );
fclose(f);
free( p->p1 );
free( p->p2 );
free( p );
exit( EXIT_FAILURE );
}
}
fclose(f);
return p;
}
int main( void )
{
ARRAY *ptrToArray = input();
free( ptrToArray->p1 );
free( ptrToArray->p2 );
free( ptrToArray );
return 0;
}

Why is my program suddenly terminating before executing scanf()?

I am trying to write code to replace a line from a text file. It compiles successfully, but it terminates out of nowhere as soon as it tries to scan the line number to be replaced.
I really have no idea what I am doing wrong. I have also tried with fgets() but it still doesn't work.
#include <stdio.h>
#include <stdlib.h>
#define MAXNAME 30
#define MAXLINE 256
int main(){
char fileName[MAXNAME];
FILE *originalFileCheck;
printf("Input the name of the file to be opened: ");
scanf("%s", fileName);
originalFileCheck = fopen(fileName, "r");
if(originalFileCheck == NULL){
printf("The file %s was not opened successfully. The program will now terminate.\n", fileName);
exit(1);
}
else{
FILE *tempFileWrite;
char tempName[MAXNAME] = "temp.txt";
tempFileWrite = fopen(tempName, "w");
char newLine[MAXLINE];
int lineNum;
printf("Input the content of the new line: ");
scanf("%s", newLine);
printf("Input the number of the line you want to replace: ");
scanf("%d", &lineNum); /* it terminates WITHOUT scanning this int*/
char str[MAXLINE];
int counter = 1;
while(fgets(str, MAXLINE, originalFileCheck) != NULL){
if(counter != lineNum){
for(int i = 0; str[i] != '\0' && str[i] != '\n'; i++){
fputc(str[i], tempFileWrite);
}
fprintf(tempFileWrite, "\n");
}
else{
fprintf(newLine, "%s\n", tempFileWrite);
}
counter++;
}
fclose(tempFileWrite);
fclose(originalFileCheck);
...
return 0;
}
the following proposed code:
cleanly compiles
checks for input errors
checks for output errors
performs the desired functionality
properly cleans up when an error occurs
and now, the proposed code:
#include <stdio.h>
#include <stdlib.h>
#define MAXNAME 30
#define MAXLINE 256
int main( void )
{
char fileName[MAXNAME];
FILE *originalFileCheck;
printf("Input the name of the file to be opened: ");
if( !fgets( filename, sizeof( fileName ), stdin) )
{
fprintf( stderr, "fgets to input 'original' file name failed\n" );
exit( EXIT_FAILURE );
}
// remove trailing newline
fileName[ strcspn( fileName, "\n" ) ] = '\0';
originalFileCheck = fopen( fileName, "r" );
if( !originalFileCheck )
{
perror( "fopen original file for read failed" );
exit( EXIT_FAILURE );
}
FILE *tempFileWrite;
char tempName[ MAXNAME ] = "temp.txt";
tempFileWrite = fopen( tempName, "w" );
if( !tempFileWrite )
{
perror( "fopen to write new file failed" );
fclose( originalFileCheck );
exit( EXIT_FAILURE );
}
char newLine[ MAXLINE ];
int lineNum;
printf("Input the content of the new line: ");
if( !fgets( newLine, sizeof( newLine ), stdin ) )
{
perror"fgets to input new line content failed" );
fclose( originalFileCheck );
exit( EXIT_FAILURE );
}
printf("Input the number of the line you want to replace: ");
if( scanf("%d", &lineNum) != 1 )
{
fprintf( stderr, "scanf for replacement line number failed\n" );
fclose( originalFileCheck );
fclose( tempFileWrite );
exit( EXIT_FAILURE );
}
char str[MAXLINE];
int counter = 1;
while( fgets(str, sizeof( str ), originalFileCheck) )
{
if(counter != lineNum)
{
if( fputs( str, tempFileWrite ) == EOF )
{
perror( "fputs for original line failed" );
fclose( originalFileCheck );
fclose( tempFileWrite );
exit( EXIT_FAILURE );
}
}
else
{
if( fputs( newLine, tempFileWrite ) == EOF )
{
perror( "fputs for replacement line failed" );
fclose( originalFileCheck );
fclose( tempFileWrite );
exit( EXIT_FAILURE );
}
}
counter++;
}
fclose(tempFileWrite);
fclose(originalFileCheck);
return 0;
}

how can i input a text from a text file (c)

how can i input a text from a text file using fgets while using a 2D array for input?
main(){
char text[1000][1000];
FILE *fptr;
char fname[100];
printf("input file name:");
scanf("%s",fname);
fptr=fopen(fname,"w");
if(fptr==NULL){
printf("Error in opening file");
exit(1);
}
else{
}
}
the following proposed code:
cleanly compiles
performs the desired functionality
properly checks for errors
properly cleans up before exiting
documents which header file exposed which functions and which #defines
And now the proposed code:
#include <stdio.h> // FILE, printf(), scanf(), fprintf()
// fopen(), fclose(), stderr, fflush()
#include <stdlib.h> // exit(), EXIT_FAILURE, realloc()
#include <string.h> // strdup()
#define MAX_FILENAME_LEN 99
#define MAX_LINE_LEN 1000
int main( void )
{
FILE *fptr;
char filename[ MAX_FILENAME_LEN +1 ];
printf("input file name:");
fflush( stdout );
if( scanf( "%99s", filename ) != 1 )
{
fprintf( stderr, "scanf failed to read the file name\n" );
exit( EXIT_FAILURE );
}
// implied else, scanf successful
fptr = fopen( filename, "w" );
if( !fptr )
{
perror( "fopen failed" );
exit( EXIT_FAILURE );
}
// implied else, fopen successful
char **savedText = NULL;
size_t numLines = 0;
char line[ MAX_LINE_LEN ];
while( fgets( line, sizeof(line), fptr ) )
{
char *temp = realloc( savedText, (numLines+1)*sizeof(char*) );
if( !temp )
{
perror( "realloc failed" );
fclose( fptr );
for( size_t i=0; i<numLines; i++ )
{
free( savedText+i );
}
free( savedText );
exit( EXIT_FAILURE );
}
// implied else, realloc successful
*savedText = temp;
savedText[ numLines ] = strdup( line );
if( !savedText+numLines )
{
perror( "strdup failed" );
fclose( fptr );
for( size_t i=0; i<numLines; i++ )
{
free( savedText+i );
}
free( savedText );
exit( EXIT_FAILURE );
}
// implied else, strdup successful
numLines++;
} // end while()
fclose( fptr );
for( size_t i=0; i<numLines; i++ )
{
free( savedText[ i ] );
}
free( savedText );
return 0;
}

Resources