Reading line by line from a file in C - c

What I am trying to do is print out the contents of a file line by line. I run the program in terminal by doing: ./test testText.txt. When I do this, random characters are printed out but not what is in the file. The text file is located in the same folder as the makefile. What's wrong?
#include <stdio.h>
FILE *fp;
int main(int argc, char *argv[])
{
char line[15];
fp = fopen(*argv, "r");
while((fgets(line, 15, fp)) != NULL)
{
printf(line);
printf("\n");
}
}

When I do this, random characters are printed out but not what is in the file
These characters are not random, and in fact they are coming from a file. It's not the file that you are trying to read, though - it's the executable file which you are running.
*argv represents the name of the executable; add this line to see what's in *argv:
printf("%s\n", *argv);
The actual command line arguments start at argv[1], so you need
fp = fopen(argv[1], "r");

The first argument passed on the command line is at argv[1], while *argv refers to argv[0]. argv[0] contains the filename of the executable - you are printing out the content of the executable.
The following code prints out the entire argv[] array, then reads your file and prints it.
#include <stdio.h>
int main( int argc, char *argv[] )
{
for( int i = 0; i < argc; i++ )
{
printf( "argv[%d] : %s\n", i, argv[i] ) ;
}
if( argc >= 2 )
{
FILE* fp = fopen( argv[1], "r" ) ;
if( fp != NULL )
{
char line[15];
while( fgets( line, sizeof(line), fp ) != NULL )
{
printf( "%s", line ) ;
}
}
}
return 0 ;
}
Note that fgets() will read an entire line including the , so there is no need to print '\n', especially because with only 15 characters, your line buffer may well not contain an entire line. Note also the tighter localisation of variables - your code needlessly made fp global.
Other refinements are the safe use of the array size rather than literal 15, and the use of a literal constant string for the format specifier. You should avoid passing a variable string for the printf() format string - if your input itself contains format specifiers, printf() will try to read data from arguments that do not exist with undefined results.

Q: What's wrong?
A humble critique:
#include <stdio.h>
FILE *fp; // Perhaps this should be declared inside main?
int main(int argc, char *argv[])
{
char line[15]; // Are the file lines all 14 characters or less? (seems small)
fp = fopen(*argv, "r"); // Opening the binary executable file (argv[0])? Intereting.
// Should check here to ensure that fopen() succeeded.
while((fgets(line, 15, fp)) != NULL)
OK... well, remember that this isn't a text file.. it's an executable (due to *argv). This will read some wacky (but not random) characters from the executable.
{
printf(line); // Bad practice. Should be: printf("%s", line);
Ok... now print the wacky characters?
printf("\n"); // Redundant. The '\n' characters will be supplied in 'line'.
}
// fclose() call missing.
// Integer return value for main() is missing.
}
Here is (perhaps) what was actually intended:
#include <stdio.h>
#include <errno.h>
int main(int argc, char *argv[])
{
int rCode = 0;
FILE *fp = NULL;
char line[255+1];
if(argc != 2)
{
printf("Usage: %s {filepath}\n", *argv);
goto CLEANUP;
}
errno=0;
fp = fopen(argv[1], "r");
if(NULL == fp)
{
rCode=errno;
fprintf(stderr, "fopen() failed. errno:%d\n", rCode);
goto CLEANUP;
}
while(fgets(line, sizeof(line), fp)) /* --As per 'chux' comment */
printf("%s", line);
CLEANUP:
if(fp)
fclose(fp);
return(rCode);
}
Or, if the intent is truly to print the content of the executable, perhaps this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
int main(int argc, char *argv[])
{
int rCode = 0;
FILE *fp = NULL;
off_t offset = 0;
errno=0;
fp = fopen(*argv, "r");
if(NULL == fp)
{
rCode=errno;
fprintf(stderr, "fopen() failed. errno:%d\n", rCode);
goto CLEANUP;
}
for(;;)
{
char line[16];
size_t bytesRead;
int index;
char ascii[16+1];
memset(ascii, 0, sizeof(ascii));
bytesRead = fread(line, 1, sizeof(line), fp);
if(0==bytesRead)
break;
printf(" %08zX | ", offset);
for(index=0; index < bytesRead; ++index)
{
printf("%02hhX%c", line[index], 7==index ? '-' : ' ');
ascii[index] = isprint(line[index]) ? line[index] : '.';
}
printf("%*s %s\n", (16 -index) * 3, "", ascii);
offset += bytesRead;
}
if(errno)
{
rCode=errno;
fprintf(stderr, "fgets() failed. errno:%d\n", errno);
}
CLEANUP:
if(fp)
fclose(fp);
return(rCode);
}

your file name found at index 1 of argv.
if (argc <= 1) {
printf("no file was given\n");
exit(-1);
}
// open file from argv[1]
// ...

Related

Rename a file and save it as a another one

I'm trying to get a filename that exists at the beginning. After that I want to add _blabla.txt to the filename and create the another one.
Here the example. --> example.txt (what I get)
Here the what I want. --> example_blabla.txt (what I want to create)
I tried to use sprintf(filename, "%s%s", argv[1], "_blabla.txt") but the created file's name is example.txt_blabla.txt.
How can I remove extension of first filename from the filename that I created ?
Here is my code:
FILE *fp;
FILE *fp2;
char filename[300];
if (argc != 2 || argv[1] == NULL) {
printf(" You did not enter a file name! \n");
exit(-1);
}
sprintf(filename, "%s%s", argv[1], "_blabla.txt");
fp = fopen(argv[1], "r");
fp2 = fopen(filename, "w");
return 0;
Here are some suggestions:
to locate the last '.' in the string, you can use the function strrchr() from <string.h>.
to avoid undefined behavior on overlong strings, use snprintf instead of sprintf.
to copy a portion of a string with snprintf, use %.*s with an int argument before the string pointer.
Here is a modified version:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
FILE *fp;
FILE *fp2;
char filename[300];
char *p;
int pos;
if (argc != 2) {
printf(" You did not enter a file name!\n");
return -1;
}
p = strrchr(argv[1], '.');
if (p != NULL)
pos = p - argv[1];
else
pos = strlen(argv[1]);
// Using the %.*s precision field to limit the number of characters
// copied from `argv[1]`
snprintf(filename, sizeof filename, "%.*s_blabla.txt", pos, argv[1]);
fp = fopen(argv[1], "r");
if (fp == NULL)
return 1;
fp2 = fopen(filename, "w");
if (fp2 == NULL)
return 1;
/* copy the file */
fclose(fp);
fclose(fp2);
return 0;
}
Append the following statements before and after your sprintf() call as follows:
int i;
char *pChar = NULL;
for (i = strlen(argv[1]) - 1; i >= 0: i--) {
if (argv[1][i] == '.') {
pChar = &argv[1][i];
*pChar = '\0';
break;
}
}
sprintf(filename,"%s%s",argv[1],"_blabla.txt");
if (pChar != NULL)
*pChar = '.';
the following proposed code:
demonstrates a method to extract the root name from a filename then append a set of characters.
demonstrates how to inform the user when the command line parameter is missing.
does not perform a stat() to assure the source file actually exists, That is left to the OP to include.
properly checks for I/O errors
documents why each header file is included
suggest getting the length of the argv[1] parameter, add the length of blabla.txt, add 1, then use the VLA feature of C to appropriately size the array filename[]. Note: strlen() works well for obtaining the length of a NUL terminated char array
And now, the proposed code:
#include <stdio.h> // fopen(), fclose(), perror(), fprintf(), FILE
#include <stdlib.h> // exit(), EXIT_FAILURE
#include <string.h> // strrchr(), strcat()
int main( int argc, char (argv[] )
{
FILE *fp;
FILE *fp2;
char filename[300];
if (argc != 2 )
{
fprintf( stderr, "USAGE: %s fileName\n", argv[0] );
exit( EXIT_FAILURE );
}
strcpy(filename, argv[1] );
char *ptr = strrchr( filename, '.' );
if( ptr )
{
*ptr = '\0';
}
strcat( filename, "_blabla.txt");
fp = fopen(argv[1], "r");
if( ! fp )
{
perror( "fopen for input file failed" );
exit( EXIT_FAILURE );
}
fp2 = fopen(filename, "w");
if( ! fp2 )
{
perror( "fopen for output file failed" );
fclose( fp1 );
exit( EXIT_FAILURE );
}
return 0;
}

C program to print given number of lines from beginning of text file. File name and number of lines from command line argument

I'm writing a program said in this post title. I take reference at this webpage.
https://www.includehelp.com/c-programs/c-program-to-print-given-number-of-lines-of-a-file-like-head-command-in-linux.aspx
Here are the codes from that webpage.
#include <stdio.h>
int main(int argc, char * argv[])
{
FILE *fp; // file pointer
char *line = NULL;
int len = 0;
int cnt = 0;
if( argc < 3)
{
printf("Insufficient Arguments!!!\n");
printf("Please use \"program-name file-name N\" format.\n");
return -1;
}
// open file
fp = fopen(argv[1],"r");
// checking for file is exist or not
if( fp == NULL )
{
printf("\n%s file can not be opened !!!\n",argv[1]);
return 1;
}
// read lines from file one by one
while (getline(&line, &len, fp) != -1)
{
cnt++;
if ( cnt > atoi(argv[2]) )
break;
printf("%s",line); fflush(stdout);
}
// close file
fclose(fp);
return 0;
}
My problem is the getline function. Since I'm not using Linux that function's giving error in my compiler. I tried to change it to fgets function. This is my revised codes.
I got two errors in the line ' while (fgets(&line, bufferLength, fp) != -1)'.
Error: passing argument 1 of 'fgets' from incompatible pointer type.
Error: comparison between pointer and integer.
My question is - how can I modify the program using fgets? Many thanks to anyone who can work this out.
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp; // file pointer
char *line = NULL;
int bufferLength = 255;
int cnt = 0;
if( argc < 3)
{
printf("Insufficient Arguments!!!\n");
printf("Please use \"program-name file-name N\" format.\n");
return -1;
}
// open file
fp = fopen(argv[1],"r");
// checking for file is exist or not
if( fp == NULL )
{
printf("\n%s file can not be opened !!!\n",argv[1]);
return 1;
}
// read lines from file one by one
while (fgets(&line, bufferLength, fp) != -1)
{
cnt++;
if ( cnt > atoi(argv[2]) )
break;
printf("%s",line);
fflush(stdout);
}
// close file
fclose(fp);
return 0;
}
Your program should compile and run correctly follows:
//c program to print given number of lines from beginning of a file
//file name and number of lines must be supply as command line argument
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char * argv[])
{
FILE* fp; // file pointer
char* line = malloc(255);
int bufferLength = 255;
int cnt = 0;
if( argc < 3)
{
printf("Insufficient Arguments!!!\n");
printf("Please use \"program-name file-name N\" format.\n");
return -1;
}
// open file
fp = fopen(argv[1],"r");
// checking for file is exist or not
if( fp == NULL )
{
printf("\n%s file can not be opened !!!\n",argv[1]);
return 1;
}
// read lines from file one by one
while (fgets(line,bufferLength, fp))
{
cnt++;
if ( cnt > atoi(argv[2]) )
break;
printf("%s",line);
fflush(stdout);
}
// close file
fclose(fp);
free(line);
return 0;
}
we have two main problems, first
char * line = NULL;
line is a line of characters, a string if you want to call it that, so we must reserve enough memory to accommodate a complete line, and we do this with the malloc function, as seen in the program, the other problem we have with fgets, this function returns a pointer therefore we cannot compare the value returned by fgets with an integer, the declaration
while (fgets (line, bufferLength, fp))
is equivalent to running the loop while fgets is other than NULL. Finally we must use line instead of &line, the latter asks for the address of the line pointer, and not the address it points to.
There's no need to keep track of more than a single character. Reading full lines is overkill. Just do:
#include <stdio.h>
#include <stdlib.h>
FILE *
xfopen(const char *path, const char *mode)
{
FILE *fp = fopen(path, mode);
if( fp == NULL ) {
perror(path);
exit(EXIT_FAILURE);
}
return fp;
}
int
main(int argc, char **argv)
{
int count = argc > 1 ? strtol(argv[1], NULL, 10) : 1;
FILE *in = argc > 2 ? xfopen(argv[2], "r") : stdin;
int line = 0;
int c;
while( line < count && ( c = fgetc(in)) != EOF ) {
putchar(c);
if( c == '\n' ) {
line += 1;
}
}
}
Note that I've reversed the order of the arguments, so that stdin is read if only a count is given.

Converting a binary to char [C]

a lot of times ago, i found an extract of C code, that could read the content of an executable file and that can store it as an array of char, in another file (ex: output.txt). It should work, but when i tried it, it corrupts the output, and it can't copy exactly the content of the exe as a char without damaging it. I don't know where could be the problem.
This is my extract of code in C
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int main(int argc, char *argv[])
{
if(argc != 3)
{
fprintf(stderr, "Usage >NameProgram firstParam Executable.exe\n");
return -1;
}
FILE *output = fopen("output.txt", "a");
[..]
char* input_file = argv[2]; //the name of the exe
FILE* f_input = fopen(input_file, "rb");
fprintf(output,"char byn[] = {\n");
unsigned long n = 0;
while(!feof(f_input))
{
unsigned char c;
if(fread(&c, 1, 1, f) == 0)
break;
fprintf(output,"0x%.2X,", (int)c);
++n;
if(n % 10 == 0)
fprintf(output,"\n");
}
fclose(f_input);
fclose(output);
//truncating file
FILE *output = fopen("output.txt", "r+");
fseek(output, -1, SEEK_END);
fprintf(output,"};\n\n");
fclose(output);
[..]
using your posted code as a guide, I produced the following:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
if(argc != 3)
{
fprintf( stderr, "USAGE: %s outFilename inFileName\n", argv[0] );
exit( EXIT_FAILURE );
}
FILE *fp_out = fopen( argv[1], "a");
FILE* fp_in = fopen( argv[2], "rb");
fprintf(fp_out, "char byn[] = {\n" );
unsigned long n = 0;
unsigned char c;
while(fread(&c, 1, 1, fp_in) == 1)
{
fprintf( fp_out,"0x%.2X,", (int)c);
++n;
if(n % 10 == 0)
fprintf( fp_out,"\n");
}
fprintf( fp_out, "};\n\n");
fclose(fp_in);
fclose(fp_out);
} // end function: main
which I ran on a few executable files
Note: I'm running Ubuntu Linux 14.04
It seems to work correctly.
As with your example, I skipped the error checking (which you should really include in your actual code.)

Why wont the program read from the 2 argument file?

So the assignment is to implement a substring search program using an input file to be searched from and an input to be searched. I created the following code:
#include <stdio.h>
#include <string.h>
int main(int argc,char *argv[])
{
FILE *fp;
fp = fopen(argv[1],"r");
if (fp == NULL)
{
printf("Error");
return 0;
}
char* tmpp[100];
int count = 0;
char* nexts = argv[2];
char* tmp = fgets(tmpp,100,fp);
while(tmp = strstr(tmp,nexts))
{
count++;
tmp++;
}
printf("%d\n\n",count);
fclose(fp);
return 0;
}
The program compiles but when i go to implement it in the ubuntu terminal as:
echo "aabb" >beta
./a.out beta a
1
Why isnt the program using the first argument (argv[1]) as beta and the second argument (argv[2]) as a correctly?
You should open a file and then read bytes from that file into temporary buffer:
FILE *file = fopen("file", "r");
while (1) {
char buffer[BUFSIZ+1];
size_t nread = fread(buffer, 1, sizeof(buffer)-1, file);
if (nread == 0) break; // read error or EOF
buffer[nread] = 0;
// chunk with BUFSIZ amount of bytes is available via buffer (and is zero-terminated)
}
If you want to search for string/pattern in a file, be aware that looked pattern in file may cross your chunk-size boundary, for example: you look for "hello", and BUFSIZ is 512. File contains "hello" at byte 510. Obviously, if you read by 512, you will get the first chunk ending with "he", and the second chunk starting with "llo". Probability of this situation is nonzero for all chunk sizes (except SIZE_MAX, but that buffer size is impossible by other reasons). Dealing with borders may be very complicated.
Close...but this is closer:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
if (argc != 3)
{
fprintf(stderr, "Usage: %s file pattern\n", argv[0]);
return 1;
}
FILE *fp = fopen(argv[1], "r");
if (fp == NULL)
{
fprintf(stderr, "Error: failed to open file %s for reading\n", argv[1]);
return 1;
}
char tmpp[1000];
int count = 0;
char* nexts = argv[2];
while (fgets(tmpp, sizeof(tmpp), fp) != 0)
{
char *tmp = tmpp;
while ((tmp = strstr(tmp, nexts)) != 0)
{
count++;
tmp++;
}
}
printf("%d\n", count);
fclose(fp);
return 0;
}
The main difference is that this loops reading multiple lines from the input file. Yours would only work on files with a single line of input.

File manipulations in C

I am using a simple 'C' code to do the following:
1) Read from a .txt file.
2) Based on the string present in the .txt file, a directory will be created.
I am not able to perform step-2, as I am not clear with type conversions.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <direct.h>
int main()
{
char ch, file_name[25];
FILE *fp;
//printf("Enter the name of file you wish to see\n");
//gets(file_name);
fp = fopen("input.txt","r"); // read mode
if( fp == NULL )
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
printf("The contents of %s file are :\n", file_name);
while( ( ch = fgetc(fp) ) != EOF )
printf("%c",ch);
if( _mkdir(ch ) == 0 )
{
printf( "Directory successfully created\n" );
printf("\n");
}
fclose(fp);
return 0;
}
Here is the error:
*error #2140: Type error in argument 1 to '_mkdir'; expected 'const char *' but found 'char'.*
YES, compiler is right.
You are passing a char c to _mkdir, instead of a string.
You should read the string from file and store it to file_name (I guess you forget) and then
_mkdir(file_name);
See below:
#include <stdio.h>
#include <stdlib.h>
#include <direct.h>
int main()
{
char file_name[25];
FILE *fp;
fp = fopen("input.txt", "r"); // read mode
if (fp == NULL)
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
fgets(file_name, 25, fp);
_mkdir(file_name);
fclose(fp);
return 0;
}
It's because you only have a single char (the c in fgetc stands for char) while _mkdir wants a string (i.e. char *).
You should probably use fgets instead to read the input.
If you dont want to use fgets , then you can use this.
#include <stdio.h>
#include <stdlib.h>
#include <direct.h>
int main()
{
char file_name[25];
String str;
FILE *fp;
char ch;
int i=0;
fp = fopen("input.txt", "r"); // read mode
if (fp == NULL)
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
while( ( ch = fgetc(fp) ) != EOF ){
printf("%c",ch);
file_name[i];
i++
}
str=file_name;
_mkdir(str);
fclose(fp);
return 0;
}

Resources