Why wont the program read from the 2 argument file? - c

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.

Related

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.

Is there a way to take text from a file and turn it into an argument for my c program?

I have a C project where the user can type in an 8 bit binary number or open up a text file with an 8 bit binary number. What I'm having trouble with is getting the 8 bit binary number from a file and making that an argument char* argv[] for my program.
This is how I'm reading the 8 bit binary number from the file
fd = open(argv[1], O_RDONLY);
read(fd,jString, 100);
close(fd);
printf("jString: %s\n", jString);
Right now I only know how to put the 8 bit binary number into a string but what I want is to turn each 8 bit binary number input separated by spaces from the file into an argument char* argv[] for my program is this possible if so how do I do it?
Something that I already tried is this.
fd = open(argv[1], O_RDONLY);
read(fd,argv[1], 100);
the problem with this is that it just reads the whole file into argv[1] and doesn't seperate them by spaces and into different arguments for my program.
What I'm having trouble with is getting the 8 bit binary number from a
file and making that an argument char* argv[] for my program
You can not do this. The usual declaration of
int main(int argc, char** argv){};
means that these 2 arguments are provided for you by the operating system when your program is run. What you can do is build something like this for your program, let's say a int myArgCountand char** myArgValues; but it seems that you do not need that.
If task is you program, running task 00001111 will put 00001111 into argv[1]. And set argcto 2, since argv[0] is always the complete path of your program.
At first you say that a binary number can be provided in a file, but in the next paragraph you said
what I want is to turn each 8 bit binary number input separated by spaces
If in fact the input file can have a list of 8-bit binary numbers separated by spaces --- and not just one --- you will need do build a list just like the system does for you, alocating memory for the numbers and creating an array of pointers to them, and an int with the count of numbers. It is not complicated.
The code below tests for an argument on the command line and if not present tries to open source.txt file to get one. May be it helps.
Note the use of scanf()to read the values from the file. The mask in use "%8[01]" is very convenient: it accepts just 0 and 1 for a maximum of 8 digits.
#define _CRT_SECURE_NO_WARNINGS
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
int main(int argc, char** argv)
{
char binary_number[10];
char* mask = "%8[01]"; // for scanf()
const char* FileName = "source.txt";
if (argc < 2)
{ // no number on the command line
fprintf(stderr, "\nNo 8-bit number provided on the command line\n");
FILE* in_file = fopen(FileName, "r");
if (in_file == NULL)
{
fprintf(stderr, "Could not open [%s]\n", FileName);
return -1;
}
int n = fscanf(in_file, mask, binary_number);
printf("\nFrom the file [%s] number is [%s]\n", FileName, binary_number);
fclose(in_file);
}
else
{ // number provided
strncpy(binary_number, argv[1], 9);
fprintf(stderr, "\nFrom the command line: [%s]\n", argv[1]);
};
return(EXIT_SUCCESS);
};
the program shows
From the command line: [101010]
or
No 8-bit number provided on the command line
From the file [source.txt] number is [11110000]
here your program with dynamic memory allocation:
Argument separtor = ' '
Argument from commande = your_program_name "10001010" "01010101"
Argument from file : command-line = your_program_name "...\yourfile.xyz" Example :
#include <malloc.h>
#include <string.h>
#include <stdio.h>
#define DELIMITER ' '
// Tokenize function
int Tokenize(char* pcLine, char ** pcListeArgs, const char* pcDelim)
{
int iNumElet = 0;
size_t len = 0;
// Get line size
int init_size = strlen(pcLine);
char *ptr = strtok(pcLine, pcDelim);
while(ptr != NULL)
{
len = strlen(ptr);
pcListeArgs [iNumElet] = (char*) calloc (len+1, sizeof (char));
memset(pcListeArgs [iNumElet], 0, len+1); // reset content
memcpy (pcListeArgs [iNumElet], ptr, len); // copy data
ptr = strtok(NULL, pcDelim);
iNumElet ++;
}
return iNumElet;
}
int main(int argc, char** argv)
{
FILE * fp;
char * line = NULL;
size_t len = 0;
char ch;
char *pcFileContent;
char cDelim = DELIMITER;
// Case : argument are a file
if (argc == 2)
{
const char* pcFilePath = argv[1];
fp = fopen(pcFilePath, "r");
if (fp == NULL)
{
perror("Error while opening the file.\n");
return (-1);
}
// Put the curso at the end of file
fseek (fp,0, SEEK_END);
// Get number of charactes
len = ftell(fp);
// Allocat memory
pcFileContent = (char*) calloc (len+1, sizeof (char));
//Erase content to zero
memset(pcFileContent,'\0',len+1);
// Put the curso at the begining of file
fseek (fp,0, SEEK_SET);
// Read file char by char
unsigned int i=0;
unsigned int iNbArgs = 1;
while((ch = fgetc(fp)) != EOF)
{
if (ch == DELIMITER)
iNbArgs ++; // We have a new arguments
pcFileContent[i++] = ch;
}
char **pcListeArgs = (char**) calloc (iNbArgs, sizeof (char*));
iNbArgs = Tokenize (pcFileContent, pcListeArgs, &cDelim);
// here you have all you arguments ....
for ( i=0; i< iNbArgs; i++)
{
printf ("Argument %d = %s\n", i, pcListeArgs[i]);
}
// Free memory
for(int i = 0; i < iNbArgs; i++)
free(pcListeArgs[i]);
free(pcListeArgs);
free(pcFileContent);
}else if ( argc > 2) // Case : argument is binary number
{
for ( int i=1; i< argc; i++)
{
printf ("Argument %d = %s\n", i, argv[i]);
}
}
return 0;
}
Result:
Argument from commande = ArgParsor.exe "10001010" "01010101" "01010111"
Argument from file : command-line = ArgParsor.exe "G:\temp.txt"

Read from a file line by line block by block in C

I need to read 4000 lines from a file, do some manipulations with them, then read next 4000 lines, do some manipulations with them, then read next 4000 lines and so on till the end of some BIG file. How to do this correctly?
Here is my basic code which is just reading all lines but not block by block from a file:
#include <stdio.h>
#include <string.h>
#define bufSize 1024
int main(int argc, char *argv[])
{
FILE* fp;
char buf[bufSize];
if (argc != 2)
{
fprintf(stderr, "Usage: %s <soure-file>\n", argv[0]);
return 1;
}
if ((fp = fopen(argv[1], "r")) == NULL)
{ /* Open source file. */
perror("fopen source-file");
return 1;
}
while (fgets(buf, sizeof(buf), fp) != NULL)
{
buf[strlen(buf) - 1] = '\0'; /* eat the newline fgets() stores */
printf("%s\n", buf);
}
fclose(fp);
return 0;
}
What is the problem?
You would need to use 2 loops. The outer one would repeat reading chunks of lines until EOF.
The code could look like the following sketch:
...
while (1)
{
/* read <= 4000 lines and process */
}
The inner would read the lines and stores them away:
size_t lines = 0; /** next index to be used with lineBuffer
(and number of lines already stored)*/
char *lineBuffer[4000];
char buf[bufSize];
while (lines < 4000 && fgets(buf, sizeof(buf), fp) != NULL)
{
buf[strlen(buf) - 1] = '\0';
lineBuffer[lines] = malloc(strlen(buf);
strcpy(lineBuffer[lines], buf);
lines++;
}
if (lines == 0)
{
break; /* we are done*/
}
/* do processing on data */
/* deallocate dynamic memory */
for (int i = lines - 1; lines>=0; i--)
{
free(lineBuffer[i]);
}
lines = 0;
Of course you could use static memory allocation using
char lineBuffer[4000][bufSize];
instead of mallocing. That would save doing alloc/dealloc sequences, or do allocation on top-level (outside the loops) using calloc(400*bufSize);
But this is left to personal preferences given the fact that a total of about 4MB of memory is being used with current settings.
With respect to performance:
having statically allocated memory might give some speed benefit.
You might also try increasing buffer size used by stdio (by a setbuffer() variant to read larger chunks from file.
Whether this will have any noticable effect is subject to some performance measurings you should take (if an issue in the first place)
Ok,then allocate a two dimensional array on the heap and declare a variable n of type size_t to keep track of the number of lines.Try the following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define bufSize 1024
int main(int argc, char *argv[])
{
FILE* fp;
if (argc != 2)
{
fprintf(stderr, "Usage: %s <soure-file>\n", argv[0]);
return 1;
}
if ((fp = fopen(argv[1], "r")) == NULL)
{ /* Open source file. */
perror("fopen source-file");
return 1;
}
size_t n = 0;
char(*buf)[bufSize] = malloc(bufSize * 4000);
if (!buf) {
fprintf(stderr, "Error - Failed to allocate memory.\n");
fclose(fp);
return 1;
}
while (1)
{
if (fgets(buf[n], bufSize, fp) != NULL) {
n++;
if (n == 4000) {
/* do something */
// ...
n = 0;
}
}
else {
// do something with leftover
break;
}
}
free(buf);
fclose(fp);
return 0;
}

Reading line by line from a file in 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]
// ...

Unable to read a file and pass into arguments

1) I'm trying to open a file, read the mix data (ints, chars and strings) and store them into args.
1.1) so in the sample.txt is a total of 13 (excluding args[0])
2) Need to read a file from terminal "./myprog.c < sample.txt"
Heres my code and have no idea where i went wrong:
sample.txt:
123 213 110 90 1
hello my friend
boo bleh
a b c
myprog.c:
#include <stdio.h>
int main()
{
int i = 1;
FILE *fstin=fopen(argv[0], "r"); //open the file
if (fstin == NULL) {
puts("Couldn't fopen...");
return -1;
}
//Getting all the inputs from file
while ((fscanf(fstin, "%d", argv[i])) != EOF){
i++;
}
fclose(fstin);
for (i=0; i<10; i++) {
printf("%d\n",argv[i]);
}
return 0;
}
Any help is greatly appreciated!
PS: Would like if anyone could post their complete solution? Will upload unto this post and let everyone have a review of this problem
PPS: Please excuse the poor level of coding as I am a beginner and completely new to C.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int ac, char *av[]){
int i, argc=0;
char **argv=NULL, data[16];
FILE *fstin = stdin;
if(ac == 2){
if(NULL==(fstin = fopen(av[1], "r"))){
puts("Couldn't fopen...");
return -1;
}
}
while (1==fscanf(fstin, "%15s", data)){
argv = realloc(argv, (argc+1)*sizeof(char*));
argv[argc] = malloc(strlen(data)+1);
strcpy(argv[argc++], data);
}
if(ac == 2)
fclose(fstin);
for (i=0; i<argc; ++i) {
printf("%s\n", argv[i]);
}
//deallocate
return 0;
}
You are making mistake at 2nd point where you divert your file to other file which is wrong. Actually you need to first compile and need to make executable.
gcc -o my_prog ./myprog.c -Wall
You need to execute this program as below to read file from c program:
./my_prog ./sample.txt
As you are new to C programming first go to man pages related to file operations.
Solution:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
//If command line argument is not inserted then stop operation
if (2 != argc) {
printf("Invalid number of arguments : %d\n", argc);
return -1;
}
int size = 0, ret = 0;
char *data = NULL;
FILE *fp = NULL;
//Open file in read mode given from command line argument
if (NULL != (fp = fopen(argv[1], "r")))
{
//Find size of file
fseek(fp, 0L, SEEK_END);
size = ftell(fp);
fseek(fp, 0L, SEEK_SET);
//if file is empty no need to read it.
if (size > 0)
{
//Data pointer which contains file information
data = (char *) calloc(sizeof(char), size);
if (NULL != data)
{
//Read whole file in one statement
fread(data, sizeof(char), size, fp);
printf("File %s is readed successfully\n", argv[1]);
printf("Data:\n");
printf("%s\n", data);
free(data); data = NULL;
}
else
{
perror("memory allocation failed\n");
ret = -1;
}
}
else
{
printf("File %s is empty\n", argv[1]);
}
fclose(fp); fp = NULL;
}
else
{
perror("File open failed\n");
ret = -1;
}
return ret;
}
Now Test it on your setup and if any query please post comments.

Resources