Reading file input into a char array in c - c

I am in an introductory programming class in C, and I am having some problem with our final project for the semester. We have to take an input file that will have polynomial equations on separate lines, and we have to then take the derivative of each of those equations. I am trying to read the equations into a character array so that I can then process that array to take the derivative. My logic currently calls for the program to read in one line at a time so that I can then run the corresponding array through my functions and take the derivative. I am, however, struggling to figure out how to do this, as we do not know the length of equations that will be tested.
My main function looks like this currently, and the code to execute what is described above would need to go inside the do loop before function one is called. All three functions are of type void.
int main(void)
{
char input [40], output [40];
do
{
function1( &input);
function2 (&input, &output);
function3(&output);
}while(!feof(ifp))
}
Thanks for your help.

the following code will get you started.
It is up to you to implement the calculateDerative() function
at the end of C programming course, the following code
should be something you can do in your sleep
#include <stdio.h>
#include <stdlib.h> // exit(), EXIT_FAILURE
#define MAX_INPUT_LEN (40)
#define MAX_OUTPUT_LEN (40)
//void function1( char * pInput );
//void function2( char * pInput, char * pOutput );
//void function3( char * pOutput );
void calculateDerivative( char* pInput, char* pOutput );
int main(void)
{
FILE *ofp = NULL;
FILE *ifp = NULL;
if( NULL == (ifp = fopen( "inputFileName", "r" ) ) )
{ // then fopen failed
perror( "fopen for read failed" );
exit( EXIT_FAILURE );
}
// implied else, fopen successful
if( NULL == (ofp = fopen( "outputFileName", "w" ) ) )
{ // then fopen failed
perror( "fopen for write failed" );
fclose( ifp );
exit( EXIT_FAILURE );
}
// implied else, fopen successful
char input [MAX_INPUT_LEN], output [MAX_OUTPUT_LEN];
while( fgets( input, sizeof(input), ifp ) ) // stay in loop until NULL returned
{
//function1( input ); // already have input available
//function2 (input, output ); // process from input to output
calculateDerivative( input, output );
//function3( output) ; // write output to output file
if( 1 != fwrite( output, strlen(output), 1, ofp ) )
{ // then fwrite failed
perror( "fwrite failed" );
fclose( ifp );
fclose( ofp );
exit( EXIT_FAILURE )
}
// implied else, fwrite successful
} // end while
fclose( ifp );
fclose( ofp );
return (0);
} // end function: main

Related

can i store 'mode' in a variable and use it at fopen()

char mode;
printf("---------------------------------------")
scanf(" %c", mode);
FILE * fpointer = fopen("kkkkkkkk.txt", mode);`
I tried but no result. compiler doesn't gives me error but not getting the program run completely.
Welcome to Stack Overflow.
The second argument of fopen(3) should be a of type const char * (essentially, a string). However, you've used a single char which will not work. Also, I don't think you've initialised it. Here's a working example.
#include <stdio.h>
int main(void) {
char mode[5];
scanf("%s", mode);
printf("Received mode is '%s'\n", mode);
FILE *fp = fopen("sample.txt", mode);
if (fp == NULL) {
perror("Couldn't open file ");
} else {
printf("Done! Closing\n");
fclose(fp);
}
}
Here are two runs to indicate what's going on.
ن ./sample
r
Received mode is 'r'
Couldn't open file : No such file or directory
Opening it in "r" mode here. Since sample.txt doesn't exist, we get an error.
ن ./sample
w
Received mode is 'w'
Done! Closing
ن ./sample
r
Received mode is 'r'
Done! Closing
The first time, it opens in "w" mode and creates it. The next time, "r" will work since the sample.txt file exists.
The mode argument needs to be a string, not a single character, since you have modes like r+, wb, wbx+, etc. So your mode variable needs to be an array of char that’s at least 5 elements wide:
char mode[5]; // up to 4 characters plus string terminator
You’d then use the %s conversion specifier with scanf (or, preferably, fgets) to read the input string:
#define MODE_LEN 4
#define FILENAME_LEN 255
FILE *fp = NULL;
char filename[FILENAME_LEN+1] = {0}; // +1 for string terminator
char mode[MODE_LEN+1] = {0}; // initialize to all 0
printf( "Gimme a file name: " );
if ( !fgets( filename, sizeof filename, stdin ) )
{
// input error, bail out here
exit( 0 );
}
printf( "Gimme the fopen mode: " );
if ( !fgets( mode, sizeof mode, stdin ) )
{
// input error, bail out here
exit( 0 );
}
fp = fopen( filename, mode );
if ( !fp )
{
fprintf( stderr, "Could not open %s with mode %s\n",
filename, mode );
exit( 0 );
}
// read/write fp here
fclose( fp );

Printing sections of a text file with C

I'm looking for a solution on how to print only relevant sections from a log file where I want to display the code and its contents which spans multiple lines.
The log file is structured like this:
----- start -----
CODE: 1111
DESC: this is some descriptions
which spans multiple lines.
----- end -----
----- start -----
CODE: 2222
DESC: this is some information
for another code.
----- end -----
----- start -----
CODE: 1111
DESC: here is some more info
for the code again.
----- end -----
What I like to achieve if to parse the log file using C, to generate a result similar
to this.
----- start -----
CODE: 1111
DESC: this is some descriptions
which spans multiple lines.
----- end -----
----- start -----
CODE: 1111
DESC: here is some more info
for the code again.
----- end -----
I have tried various while loops reading the file into a buffer and compared the strings with strstr() etc. but haven't find any logic with if statements that works for me. I have tried to explore the use of fseek(), fgetpos(), fsetpos() etc. I have searched forums and blogs for answer that can help me forward with little success.
If anyone reading this has a solution to share or any pointer on how I should tackle this, or places to find such information would be much appreciated.
Forget about the "---start---" to begin with. Just look for the target that means an interesting section is beginning. Then output until the "---end---" is encountered.
Here's a sample that works for the sample input you provided. Just uses fgets() until it finds the target string, sets a flag and outputs the preamble (that is given) and loops until it clears the flag. If the current line is neither the start nor the finish, output (or not) is controlled by the flag.
You can adapt this to your particular needs with passing logfile names and target string(s) through command line parameters.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
int main() {
char buf[ 1024 ];
FILE *ifp = fopen( "log.txt", "rt" );
if( ifp == NULL )
exit( EXIT_FAILURE );
char *target = "CODE: 1111";
char *start = "----- start -----";
char *end = "----- end -----";
char *blankrow = "";
bool inRegion = false;
while( fgets( buf, sizeof buf, ifp ) ) {
if( inRegion && strncmp( buf, end, strlen( end ) ) == 0 ) {
inRegion = false;
printf( "%s", buf );
} else if( strncmp( buf, target, strlen( target ) ) == 0 ) {
inRegion = true;
printf( "%s%s\n%s", blankrow, start, buf );
blankrow = "\n";
} else if( inRegion ) {
printf( "%s", buf );
}
}
fclose( ifp );
return 0;
}
In order to solve the problem, you can read until you encounter the line
----- start -----
then read the next line to see if it contains the code that you are looking for. If it does, then you output the log entry, and if it does not, then you read and ignore the rest of the log entry.
Since the end of the log entry is clearly marked with the line
----- end -----
you can compare every line inside the log entry with that string.
These steps should be repeated until you encounter end-of-file.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
const char start_marker[] = "----- start -----";
const char end_marker[] = "----- end -----";
const char target_string[] = "CODE: 1111";
bool read_exactly_one_line( char buffer[], int buffer_size, FILE *fp );
int main( void )
{
char line[4096];
bool should_print;
//read log entries until end-of-file encountered
for (;;) //infinite loop, equivalent to "while(1)"
{
//read until start marker encountered
for (;;)
{
if ( ! read_exactly_one_line( line, sizeof line, stdin ) )
{
//we are unable to read any further lines due to
//end-of-file, so we have finished
exit( EXIT_SUCCESS );
}
//determine whether line is empty
if ( line[0] == '\0' )
continue;
//determine whether line is a start marker
if ( strcmp( line, start_marker ) == 0 )
break;
//line is neither empty nor a start marker, which
//should not occur
fprintf( stderr, "Parse error: Unexpected input!\n" );
exit( EXIT_FAILURE );
}
//read the line with the code
if ( ! read_exactly_one_line( line, sizeof line, stdin ) )
{
fprintf( stderr, "Error: Encountered end-of-file inside log entry!\n" );
exit( EXIT_FAILURE );
}
//determine whether the line contains the target string
if ( strcmp( line, target_string ) == 0 )
{
//we should print the log entry
should_print = true;
//also print the part that we have already read
printf( "%s\n%s\n", start_marker, line );
}
else
{
//do not print the remainder of the log entry
should_print = false;
}
//read until end marker
for (;;)
{
if ( ! read_exactly_one_line( line, sizeof line, stdin ) )
{
fprintf( stderr, "Error: Encountered end-of-file inside log entry!\n" );
exit( EXIT_FAILURE );
}
//print the line, if appropriate
if ( should_print )
printf( "%s\n", line );
//determine whether line is the end marker
if ( strcmp( line, end_marker ) == 0 )
{
//add one line of spacing between next log entry
if ( should_print )
printf( "\n" );
//break out of inner infinite loop
break;
}
}
}
}
//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;
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 on end of file
if ( !feof(fp) )
{
fprintf( stderr, "Line was too long for input buffer!\n" );
exit( EXIT_FAILURE );
}
}
else
{
//remove newline character
*p = '\0';
}
return true;
}
With the input posted in the question, this program has the following output:
----- start -----
CODE: 1111
DESC: this is some descriptions
which spans multiple lines.
----- end -----
----- start -----
CODE: 1111
DESC: here is some more info
for the code again.
----- end -----

How can I read different lines of a text file with fgets?

For example, if a .txt has
Hello
There.
written in it, no matter how bigger N is in fgets(str, N, file), it will only store "Hello" in str, because it stops when it finds a '\n' character.
So, how could I read the whole file if, for example, I wanted to find a specific word in it?
So, how could I read the whole file
In order to read the whole file into a memory buffer, you could use the function fread. After turning the input into a string by appending a terminating null character, you could then use the function strstr to search the input for a certain word.
Here is a program which does this and searches the input for the word targetword:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main( void )
{
FILE *fp;
char buffer[1000];
size_t read;
//open input file
fp = fopen( "input.txt", "rt" );
if ( fp == NULL )
{
fprintf( stderr, "ERROR: Unable to open input file!\n" );
exit( EXIT_FAILURE );
}
//read entire file into buffer
read = fread( buffer, 1, sizeof buffer, fp );
//verify that buffer was not too small
if ( read == sizeof buffer )
{
fprintf( stderr, "ERROR: Memory buffer is too small to contain entire input!\n" );
exit( EXIT_FAILURE );
}
//add terminating null character to make input a valid
//null-terminated string
buffer[read] = '\0';
//search input for target word
if ( strstr( buffer, "targetword" ) != NULL )
printf( "Found word!\n" );
else
printf( "Did not find word!\n" );
fclose( fp );
}
However, instead of reading the entire file at once (which could require a very large memory buffer), it is more common to read one line at a time in a loop, and in every loop iteration, you check whether the current line contains the word you are looking for. That way, the memory buffer only has to be large enough to store one line of input at once, instead of the entire input.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
int main( void )
{
FILE *fp;
char line[100];
bool found = false;
//open input file
fp = fopen( "input.txt", "rt" );
if ( fp == NULL )
{
fprintf( stderr, "ERROR: Unable to open input file!\n" );
exit( EXIT_FAILURE );
}
//read one line per loop iteration
while ( fgets( line, sizeof line, fp ) != NULL )
{
//verify that line was not too long to fit into buffer
if ( strchr( line, '\n' ) == NULL )
{
fprintf( stderr, "line too long to fit buffer!\n" );
exit( EXIT_FAILURE );
}
//search for target word
if ( strstr( line, "targetword" ) != NULL )
{
found = true;
break;
}
}
if ( found )
printf( "Found word!\n" );
else
printf( "Did not find word!\n" );
fclose( fp );
}
However, both solutions have several possible issues:
If the target word targetword is part of another word, for example thetargetword, then it will state that it found the target word. I'm not sure if this is what you want or if you want the target word to appear by itself.
If the target word is syllabified so that, for example, target-\n appears in one line and word in the next line, then the program won't be able to find the word.
The search is case-sensitive, so it will only find targetword, but not Targetword or TARGETWORD.
All of these issues can be solved, if necessary, but would require additional work.

Getc over-read a \n character

I'm having some problems with this little function that can read a file:
void ReadFile(char *name) {
FILE *fr;
int lenght, i;
fr = fopen(name, "r"); //Open the file reader
fseek(fr, 0, 2); //Set the pointer at the EOF
lenght = ftell(fr); //Read the ending position
printf("\nDEBUG lenght:%d\n", lenght);
fseek(fr, 0, 0); //Return at the beginning of the file
printf("File read:\n\n");
for (i = 1; i <= lenght; i++) {
printf("%c", getc(fr));
fseek(fr, i, 0);
}
fclose(fr);
}
This is the file that it reads:
qwerty
asdfgh
zxcvbn
But this is the output of the program:
DEBUG lenght:24
File read:
qwerty
asdfgh
zxcvbn
It is basically reading an extra "\n" when there is one before.
Any ideas of why the code doesn't work?
Thanks
If you open a file in text mode (as you do), then a call to fseek may only contain offset values that have been previously retrieved by an ftell function (cf, for example, cppreference/fseek):
If the stream is open in text mode, the only supported values for
offset are zero (which works with any origin) and a value returned by
an earlier call to ftell on a stream associated with the same file
(which only works with origin of SEEK_SET).
In your for-loop, however, you are passing the value of i, which is not retrieved by ftell.
Besides that, your fseek in the loop is superflous, as fgetc moves the read pointer forward anyway. So for (i = 1; i <= lenght; i++) { printf("%c", getc(fr)); } should do the job.
the following proposed code:
cleanly compiles
performs the desired functionality
properly checks for errors
and now, the proposed code:
#include <stdio.h> // EOF, fopen(), getc(), putc() fclose() puts() perror()
#include <stdlib.h> // exit(), EXIT_FAILURE
// prototype
void ReadFile(char *filename);
void ReadFile(char *filename)
{
FILE *fp = fopen( filename, "r" );
if( !fp )
{
perror( "fopen failed" );
exit( EXIT_FAILURE );
}
// implied else, fopen successful
puts("File read:\n");
int ch;
while( (ch = getc( fp )) != EOF )
{
putchar( ch );
}
fclose(fp);
}

C code- Not enough free memory to read data from txt file into a 1D dynamic array for debug mode

I wrote a C code to fscanf a .txt file into a 1D dynamic array. The data in txt file is written in a single column with 108x108x108 integers. However, it says "Not enough storage is available to process this command" when I was trying to debug. If I use the Batch Build to build both release and debug, only the Release mode can successfully load the data into the dynamic array. On the other hand, it shows "There is not enough free memory to run this program. Exit one or more programs, and then try again" when I was trying to click the debug mode .exe. By the way, my computer has 16 GB Ram, so it shouldn't overflow the memory. Anyone can take a look at my code and help me with this problem? I would really appreciate your answers.
#define IMMX 108
#define IMMY 108
#define IMMZ 108
int *one;
int Max = IMMX*IMMY*IMMZ;
void input_var(void); // Input
void output_fields(void); // Output
void main(int argc,char *argv[])
{
input_var();
output_fields();
free(one);
one = NULL;
}
void input_var(void)
{
FILE *rf = fopen("108x108x108.txt","r"); //108*108**108 integers in a single column is 108x108x108.txt file
one = (int *)malloc(sizeof(int)*Max);
for(int i=0;i<Max;i++)
{
one[i] = 0;
}
if (rf == NULL){
printf("Unable to open file\n");
} else {
for (int i=0;i<Max; i++)
{
fscanf(rf,"%i",&one[i]);
}
fclose(rf);
}
}
void output_fields(void)
{
FILE *file1 = fopen("one", "w");
for(int i=0;i<Max;i=i++)
{
fprintf(file1,"%i",one[i]);
fprintf(file1,"\n");
}
fclose(file1);
}
I did not create the file of integers,
However, I did fix all the 'oops' items in the posted code including adding the needed error checking, the declaration of the main() function, etc
The following code compiles cleanly and should work correctly
#include <stdio.h>
#include <stdlib.h> // exit(), EXIT_FAILURE
#include <string.h> // memset()
#define IMMX (108) // when #define'ing numerics, always wrap in parens
#define IMMY (108)
#define IMMZ (108)
int *one;
int Max = IMMX*IMMY*IMMZ;
// prototypes
void input_var(void); // Input
void output_fields(void); // Output
int main( void )
{
input_var();
output_fields();
free(one);
one = NULL;
return 0; // added as part of correction to main() declaration
} // end function: main
void input_var(void)
{
FILE *rf = NULL;
if( NULL == (rf = fopen("108x108x108.txt","r") ) ) //108*108**108 integers in a single column is 108x108x108.txt file
{ // then fopen failed
perror( "fopen for 108x108x108.txt for input failed");
exit( EXIT_FAILURE );
}
// implied else, fopen successful
one = malloc(sizeof(int)*Max);
if( NULL == one )
{ // then, malloc failed
perror( "malloc for 108*108*108 ints failed");
fclose( rf ); // cleanup
exit( EXIT_FAILURE );
}
// implied else, malloc successful
memset( one, 0x00, Max); // initialize the array of ints
for (int i=0;i<Max; i++) // note: 'i++', not 'i=i++'
{
if( 1 != fscanf(rf,"%i",&one[i]) )
{ // then fscanf failed
perror( "fscanf failed");
fclose( rf ); // cleanup
free( one ); // cleanup
exit( EXIT_FAILURE );
}
// implied else, fscanf successful
} // end for
fclose(rf);
} // end function: input_var
void output_fields(void)
{
FILE *file1 = NULL;
if( NULL == (file1 = fopen("one", "w") ) )
{ // then fopen failed
perror( "fopen for output file failed");
free( one ); // cleanup
exit( EXIT_FAILURE );
}
// implied else, fopen successful
for(int i=0; i<Max; i++)
{
fprintf(file1,"%i\n",one[i]);
}
fclose(file1);
} // end function: output_fields

Resources