Print the contents of the file - c

I am trying to print the contents of my file byte by byte. However, I do get the compiler error "invalid type argument of unary *(have int)
my code is :
void print_the_file ()
{
void *file_hndl;
UINT32 file_size = 2048;
UINT8 *hndl;
file_hndl = fopen("my_bin_file.bin", "r") ;
if ( file_hndl == NULL )
{
printf("file open failed");
}
hndl = (UINT8*)file_hndl;
/* print the contents */
for ( UINT32 i = 0; i< 2048; i++ )
{
printf ("%02x", *hndl[i] );
}
}
Please advise me where i am going wrong and right way to print the contents of the file.

fopen returns a FILE * so your file_hndl should be of that type. Whilst you're checking the return value from fopen to print out an error message, you then ignore it and continue on trying to read from the file.
You're not actually reading from the file though - you need to call other functions such as fgetc to do that. But using fopen/fgetc is probably not want you want anyway as you're trying to read in a binary file. For that you want to use open and read.
The code below does what you're actually trying to do.
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
void print_the_file(void)
{
int file_desc;
char a_byte;
size_t err;
file_desc=open("my_bin_file.bin",O_RDONLY,S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if(file_desc==-1)
{
printf("file open failed\n");
return;
}
do
{
err=read(file_desc,&a_byte,1);
if(err>0)
{
printf("%02x",a_byte);
}
}
while(err>0);
}

the error was fired because of * in front of the variable hndl
for ( UINT32 i = 0; i< 2048; i++ )
{
// printf ("%02x", *hndl[i] );
printf ("%02x", fgetc(hndl) );
// remove * if you are using [] or write like this *(hndl+i)
}
make sure that you are compiling it with C99 or higher standard. for this
for ( UINT32 i = 0; i< 2048; i++ )

Try something like this:
void print_the_file()
{
FILE* file_hndl = fopen("my_bin_file.bin", "rb");
if (file_hndl == NULL)
{
printf("file open failed");
}
else
{
while (!feof(file_hndl) && !ferror(file_hndl))
{
int c = fgetc(file_hndl);
if (c != EOF) /* should be redundant */
{
printf("%02x", c);
}
}
fclose(file_hndl);
}
}
Note the file mode to fopen is "rb" to open the file for read as binary.
Also, the routine processes the entire file character by character until EOF or error occurs.

Related

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.

Can't get fwrite to work properly

I'm trying to write a program that is able to open a text file and split it so I can save it in two new ones to save files faster. But with the code I have now I'm not able to print the chars that I pick from the orignal file to the new ones.
In my text file I have the text "Dutch people are tall".
In my new files I want to get:
File 1: Dthpol r tl
File 2: uc epeaeal
This is the code I have got so far:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char cUsb1;
char cUsb2;
char str[128];
FILE *ptr_readfile;
FILE *ptr_usb1;
FILE *ptr_usb2;
ptr_readfile = fopen("Dutch People.txt","r"); // open readfile
while(ptr_readfile != NULL) // keep running while readfile != null
{
if (ptr_readfile != EOF) // keep running while readfile != eof
{
cUsb1 = fgetc(ptr_readfile); // to get a char out of the readfile
ptr_usb1 = fopen("USB1.txt", "w"); // create and open USB1 file
fwrite(cUsb1 , str , str , ptr_usb1); //writing get c to file
cUsb2 = fgetc(ptr_readfile); // to get a char out of the readfile
ptr_usb2 = fopen("USB2.txt", "w"); // create and open USB2 file
fwrite(cUsb2 , str , str, ptr_usb2); //writing get c to file
fclose(ptr_usb1); // closing the file
fclose(ptr_usb2); // closing the file
}
break; // to stop the while loop
fclose(ptr_readfile); // closing the file
}
return 0;
}
Many things are not quite right. You need to look carefully through the warnings reported by the compiler - enable all warnings if possible (e.g. "-Wall") - and resolve them all. Then single-step through your program with a debugger until it does something you didn't expect.
As a starting point, instead of:
fwrite(cUsb1 , str , str , ptr_usb1);
you might mean
fwrite(&cUsb1 , 1 , 1 , ptr_usb1);
There should be a warning for that line to tell you that you shouldn't try to pass cUsb1 (a char) as the first parameter of fwrite, as that parameter expects a pointer, i.e. an address of something. Use &cUsb1 to mean "the address of cUsb1".
You can use fputc for writing one character at a time. Also the while loop is not needed.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int c;
int i = 0;
FILE *ptr_readfile = NULL;
FILE *ptr_usb1 = NULL;
FILE *ptr_usb2 = NULL;
ptr_readfile = fopen("Dutch People.txt", "r"); // open readfile
if (ptr_readfile != NULL) {
ptr_usb1 = fopen("USB1.txt", "w"); // create and open USB1 file
ptr_usb2 = fopen("USB2.txt", "w"); // create and open USB2 file
if (ptr_usb1 != NULL && ptr_usb2 != NULL) {
while ((c = fgetc(ptr_readfile)) != EOF) {
if (i % 2 == 0) {
fputc(c, ptr_usb1);
}
else {
fputc(c, ptr_usb2);
}
i++;
}
}
fclose(ptr_readfile); // closing the file
}
if (ptr_usb1 != NULL) {
fclose(ptr_usb1);
}
if (ptr_usb2 != NULL) {
fclose(ptr_usb2);
}
return 0;
}

Debug Assertion Error in C

got some code here that won't compile correctly because it is saying that my pointer is already null when i am testing for a not null expression in my main function. here is the code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXCODE 53
#define MAXMESSAGE 256
void getCode(char *codeIn, char *filename) {
FILE *codeFile;
/* Open the file with the code */
codeFile = fopen(filename, "r");
if (codeFile == NULL) {
printf("Error opening the code file - program terminated\n");
exit(1);
}
/* Read the first (and assumed only) line from the file */
fgets(codeIn, MAXCODE, codeFile);
/* Terminate the string with /0 */
codeIn[MAXCODE] = '\0';
/* Close the file */
fclose(codeFile);
return;
}
int getMessage(int *message, char *filename) {
FILE *messageFile;
int counter = 0;
/* Open the file with the message */
messageFile = fopen(filename, "r");
if (messageFile == NULL) {
printf("Error opening the message file - program terminated\n");
exit(1);
}
/* Read one number at a time from the file and store it */
while (!feof (messageFile))
{
fscanf (messageFile, "%d", (message+counter));
counter++;
}
/* Close the file */
fclose(messageFile);
return (counter);
}
void sortMessage(int *message, int size) {
int i, j, temp;
for (i=0; i<size-1; i++) {
for (j=i; j<size; j++) {
if (message[i]>message[j]) {
temp = message[i];
message[i] = message[j];
message[j] = temp;
}
}
}
return;
}
void decodeMessage(char *codeIn, int *message, int size) {
FILE *outputFile;
int i = 0;
/* Open the output file */
outputFile = fopen("csis.txt", "w");
if (outputFile == NULL) {
printf("Error opening the output file - program terminated\n");
exit(1);
}
for (i=0; i< size; i++) {
fprintf(outputFile, "%c", codeIn[message[i]%100]);
printf("%c", codeIn[message[i]%100]);
}
printf("\n");
/* Close the file */
fclose(outputFile);
return;
}
int main(int argc, char *argv[])
{
char code[MAXCODE];
int msg[MAXMESSAGE];
int msgSize;
if (argc != 3) {
printf("This program takes two arguments: the name of the file with the code, and the name of the file with the encoded message\n");
}
getCode(code, argv[1]);
msgSize = getMessage(msg, argv[2]);
sortMessage(msg, msgSize);
decodeMessage(code, msg, msgSize);
return;
}
So basically my code is using two files called codefile.txt and msgfile.txt to decode the secret message and write the decoded sequence to a new text file called csis.
As woolstar pointed out in the comments, you don't need to NUL terminate your codeIn array following fgets, because fgets will do that for you. In fact, this constitutes an overflow which we can best see by considering what happens when MAXCODE is 1: codeIn contains only one element: codeIn[0], and accessing codeIn[1] is an error.
Similarly, since MAXCODE is 53 and that's how many elements pointed to by codeIn, codeIn[message[i]%100] is suspicious because there's a potential for message[i]%100 to be an invalid index. While we're on this note, it might be wise to make message[i] an unsigned int so that it can't be negative. The format specifier (for printf and scanf) corresponding to unsigned int is %u.
while ( !feof(messageFile) ) is wrong because the EOF flag isn't set until an attempt is made at reading. Between attempting to read and your EOF test, however, you've incremented counter which means you've counted one too many items. Perhaps your loop should look like this:
while (fscanf(messageFile, "%d", (message+counter)) == 1)
{
counter++;
}
Note that this code assumes you've chosen to keep message[i] as an int. If you've chosen to use unsigned int instead, of course you'll want to use the %u format specifier.
You can probably see that feof is mostly superfluous... You can usually test for erroneous reads by checking the return value. Try to avoid feof in the future.
Your main function has a return type of int, yet at the end of it you have a return; statement which doesn't return an int value. Remove that. It's probably causing errors during compilation.
Presumably, when argv != 3 you want to return from main so you don't end up processing invalid arguments... Make sure you return an int value, e.g.
if (argc != 3) {
printf("This program takes two arguments: the name of the file with the code, and the name of the file with the encoded message\n");
return 0;
}

how to keep file handle open in c after exiting function

I am trying to read proc file /proc/stat at periodic interval but I want to avoid having to open and close the proc file each time I want to access it.
I want to open the file in sort of init function, and then keep using it in some other function, then close it later on.
It seems file handles opened by a function gets closed when the function exits
How can I keep it open ?
Please let me know if I should be doing it in some other manner
Sample of what I am trying to do:
#include <stdio.h>
int printer(FILE* fin)
{
/* I am getting fin as NULL */
if(!fin)
return 1;
char buf[16*1024];
rewind(fin);
size_t sz = fread(buf, 1, sizeof(buf), fin);
if (sz) {
buf[sz]=0;
printf(buf);
}
return 0;
}
int opener(FILE *fin)
{
fin = fopen("/proc/stat", "r");
if (!fin) {
perror("fopen");
return 1;
}
return 0;
}
int main() {
FILE *fin;
/*
* I know it works if I open the file handle in here instead of
* in another function but I want to avoid this
*/
if(opener(fin))
{
printf("ERROR1\n");
return 0;
}
while(1) {
if(printer(fin))
{
printf("ERROR2\n");
break;
}
sleep(1);
}
return 0;
}
Functions in c are pass by value. So when you pass a file handle to a function, it receives a copy of that handle and will update it locally. If you want those updates to propagate to your caller, you need pass file handle pointers. So your open would look like:
int opener(FILE **fin)
{
*fin = fopen("/proc/stat", "r");
if (!(*fin)) {
perror("fopen");
return 1;
}
return 0;
}
And you would call it like:
int main() {
FILE *fin;
/*
* I know it works if I open the file handle in here instead of
* in another function but I want to avoid this
*/
if(opener(&fin))
{
printf("ERROR1\n");
return 0;
}
/...
}
You need to pass a reference to the pointer to fin in order to keep it in main.
if(opener(&fin)) {}
pass it as double pointer :
int opener(FILE **fin) {}
and use it with derefencing
*fin = fopen("/proc/stat", "r");
otherwise you initiate it everytime you call your subfonction.
The C language passes arguments by value, so the fin that opener has is a copy of the fin that main has. Changing fin in opener has no effect on main's copy.
One solution is to use a temporary file pointer in opener and then return that pointer. To indicate an error, return NULL.
FILE *opener( char *name )
{
FILE *temp = fopen( name, "r" );
if ( !temp )
{
perror( "fopen" );
return( NULL );
}
return( temp );
}
int main( void )
{
FILE *fin = opener( "/proc/stat" );
if ( !fin )
printf( "failed\n" );
else
printf( "fin=%p\n", fin );
}

Replace String in Text C language

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main ( int argc, char *argv[] )
{
if ( argc != 4 ) /* argc should be 4 for correct execution */
{
/* Print argv[0] assuming it is the program name */
printf( "usage: %s filename\n", argv[0] );
}
else
{
// We assume argv[1] is a filename to open
char* wordReplace = argv[1];
char* replaceWord = argv[2];
FILE *file = fopen( argv[3], "r+" );
/* fopen returns 0, the NULL pointer, on failure */
if ( file == 0 )
{
printf( "Could not open file\n" );
}
else
{
char string[100];
int len = 0;int count = 0;int i = 0;int k = 0;
while ( (fscanf( file, "%s", string ) ) != EOF )
{
len = strlen(string);
count++;
char charray[len+1];
if(count == 1)
{
for (i = 0; i < len; i++)
{
charray[i] = replaceWord[i];
printf("%c\n", charray[i]);
}
}
//printf("%c\n", charray[0]);
printf( "%s\n", string );
if(strcmp(string, wordReplace) == 0)
{
for(k = 0; k < strlen(replaceWord); k++)
{
fseek (file, (-(long)len), SEEK_CUR);
fputc(charray[k],file);
//replaceWord++;
}
//strcpy(string, replaceWord);
//fprintf(file,"%s",replaceWord);
//fputs(string, file);
//printf("\n%d\n", len);
}
}
fclose( file );
}
}
printf("\n");
return 0;
}
This code currently works in replacing the First word properly, but if there are multiple words that i want overwritten with the replace word or the word appears somewhere else in the text it will not properly change it, and it will change it to ram trash etc. I was curious if anyone could lead me to a reason why thank you.
Assuming the words are the same length (if not you have quite a few more issues):
Let's say you have a 4 character word:
fseek (file, (-(long)len), SEEK_CUR); will go back to position 0 (4-4), fputc(charray[k],file); will update to position 1, then you back 4 more which is an error but since you're not checking the return value from fseek you will not know this. At this point the algorithm is not working any more since your assumed file positions are all wrong
EDIT:
if(strcmp(string, wordReplace) == 0)
{
fseek (file, (-(long)len), SEEK_CUR);
for(k = 0; k < strlen(replaceWord); k++)
{
fputc(charray[k],file);
}
}
fflush(file); //you need to flush the file since you are switching from write to read
EDIT 2: reason for flush: from 4.5.9.2 ANSI C, similar paragraph in C99 7.19.5.3):
When a file is opened with update mode ('+' as the second or third character in the mode argument), both input and output may be performed on the associated stream. However, output may not be directly followed by input without an intervening call to the fflush function or to a file positioning function ( fseek , fsetpos , or rewind ), and input may not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end-of-file.
Between the read and write you have the fseek already so that is not a problem

Resources