Segmentation Fault when using fopen on argv - c

I continue to have a segmentation fault when I try and execute the following code...
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
if (argc < 4){
fprintf (stderr,"usage message");
return (1);
}
FILE *src = fopen(argv[1],"r"); //file pointer to inputFile
FILE *outputFile = fopen(argv[2],"w"); //file pointer to outputFile
int nth = atoi(argv[3]); //nth term value
printf("nth term is %d",nth);
int c;
int currNum;
int currCount = 1;
c = fscanf(src, "%d\n",currNum); //read ints line by line
while( c == 1 ){
fscanf(src,"%d\n",currNum);
++currCount;
if (currCount % nth == 0){
fprintf (outputFile, "%d\n", currNum);
}
}
}
I'm not sure if I have to somehow convert argv[1] and argv[2] before I can use them as the file names.

Did you provide a command line argument? You should check that by using an if statement before opening the files. For example, you could add
if ( argc < 4 )
{
printf ( stderr, "usage message\n" );
return ( 1 );
}
Also, change that stoi for argv[3] to atoi.
You don't need to add \n for fscanf. Just "%d" will do fine.

giving input parameters to "fscanf" is wrong. check below one.......
c = fscanf(src, "%d\n",currNum); // wrong
c = fscanf(src, "%d\n",&currNum);
fscanf(src,"%d\n",&currNum);

You can use atoi to convert to int
int nth = atoi( argv[3] );
You also can NULL check file* src and outfile. If you are not giving correct paths then fopen may fail.

Related

Reading and checking a file's content in C

So I am writing a program in C that takes in a few command-line arguments and also reads a file and prints it to standard out. This is my code thus far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main( int argc, char* argv[] ) {
char* file_path;
float a;
float b;
char filedata[200];
if (argc != 4) {
printf("Error: 4 arguments are required.\n");
return -1;
}
file_path = argv[1];
a = atof(argv[2]);
b = atof(argv[3]);
if( a == 0.0 ) {
printf("Error: bad float arg\n");
return -1;
}
if( b == 0.0 ) {
printf("Error: bad float arg\n");
return -1;
}
FILE* fp = fopen( file_path, "r");
if( fp == NULL ){
printf( "Error: bad file; %s\n", file_path);
return -1;
}
while( fgets( filedata, 200, fp ) ){
printf("%s", filedata);
}
fclose(fp);
}
At the very bottom I have began to read a file. What I am trying to do is find files that contain the characters "#A#" and "#B#" and then print an error message when files containing these characters are not present.
Unfortunately, a simple if statement will not work in this scenario as I am not checking for equality but rather whether or not something is present.
If anybody could tell me about any C functions that are able to read and check the contents of a file, along with a few more specifics, then I would highly appreciate it!
After taking each line (into 'filedata') simply use the strstr function to check if it contains that substring "#A#" etc.
if strstr finds the substring it will return a pointer to it, otherwise it will return a NULL pointer.
So you should write something like this:
if ( strstr(filedata, "#A#") == NULL )
printf("Error\n");
but since you are looking at the entire file for this substring, you need to check all the lines before you conclude that there is an error.

How do I take a file name and an int from the terminal and pass them into a c program to be used as parameters?

I need to write a program that reads through a given text file from the terminal and counts the number of times a given number from the command line occurs in the text file.
Example test.txt file:
"here is your class CSC 1010"
Running the program:
$./countD test.txt 1
'1' appeared 2 times
The proper prototypes for the main function are:
int main (int argc, char **argv)
(you will also see it written with the equivalent char *argv[])
or
int main (void)
The first case provides an integer argument count argc that holds the number of arguments passed to your program. The arguments are indexes to and array of pointers to strings held in argv where the next entry after the last is a sentinel NULL. The program name is always the first argument (with the zero index) in the list, next all commands passed to the program on the command line.
The second case for main (int main (void)) makes explicit that no arguments are passed to the program.
In your case, you simply want to take two arguments, (1) the filename to read from and (2) the character to search for, can both be handled very easily. The first argument can be used to open the file, and the second can be use as a search char to check against each character in the file. You can use a ternary operator to provide default values for both, e.g.
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
int c, srchc = argc > 2 ? *argv[2] : '1', n = 0;
Above, argv[1] is used as the filename (or it will default to reading from stdin, the first character in argv[2] is your search character.
Next you need do little more than validate the file is opened for reading, e.g.
if (!fp) { /* validate file open for reading */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
and then loop over every character in the file keeping count of the number of times your srchc matches the current char, e.g.
while ((c = fgetc (fp)) != EOF) /* read from file until EOF found */
if (c == srchc) /* compare srchc against each char in file */
n++;
Putting it altogether, you can do something like the following:
#include <stdio.h>
int main (int argc, char **argv) {
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
int c, srchc = argc > 2 ? *argv[2] : '1', n = 0;
if (!fp) { /* validate file open for reading */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
while ((c = fgetc (fp)) != EOF) /* read from file until EOF found */
if (c == srchc) /* compare srchc against each char in file */
n++;
printf ("'%c' appeared %d times\n", srchc, n);
return 0;
}
Example Input File
$ cat dat/cscfile.txt
here is your class CSC 1010
Example Use/Output
$ ./bin/charinfile dat/cscfile.txt 1
'1' appeared 2 times
Look things over and let me know if you have any further questions.
Try this code:
It takes command line arguments from main by int main(int
argc,char* argv[]) and opens the file which is gotten by the command line arguments.
" argc " gives the number of arguments needed and gives an error if they are not as required.
atoi converts the number taken as string to integer.
getc() is used to iterate through the file.
fscanf takes the integers from the file and stores them in num.
a while loop is used to get the digits of each numbers and count the number of ones.
#include<stdio.h>
#include<stdlib.h>
int main(int argc,char* argv[])
{
int c=0;
if(argc != 3)
{
printf("usage: ./a.out file number\n");
return 1;
}
char* file = argv[1];
int n = atoi(argv[2]);
FILE *inptr = fopen(file,"read");
if(inptr == NULL)
{
printf("error\n");
return 2;
}
int num=0;
int ch = getc(inptr); //to get to the end of file
while(ch != EOF)
{
fscanf(inptr,"%d",&num);//scanning numbers one by one
while(num!=0) //as it was given by you in your example
{ //you require the appearances of digit 1
int d = num%10; //1 can also appear multiple times in a
if(d == n) //single number and hence i had to extract
{ //the digits of the number also
c++;
}
num/=10;
}
ch = getc(inptr);
}
printf("'%d' appeared %d times\n",n,c);
fclose(inptr);
return 0;
}

Command line error

The following code is supposed to read a text file character by character and count the frequency of their occurrence. However, on the Linux command line, it compiles and when I try to run it by the command ./program<file.txt it shows
useage: huffman <filename>
I don't know what's the error.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int count[26];
int main(int argc, char ** argv)
{
unsigned char c;
FILE * file;
int i;
if ( argc != 2 ) {
fprintf(stderr, "Useage: huffman <filename>\n");
exit(1); // exit with error code
}
file = fopen(argv[1], "r");
assert( file != NULL );
c = fgetc(file);
while( !feof(file) ) {
c = fgetc(file);
count[c-'a']++;
}
for(i=0; i<26; i++)
printf("count[%c]=%d\n",65+i,count[i]);
fclose(file);
return 0;
As you execute it as
$ ./program < file.txt
you are calling the program with zero arguments and set its standard input stream to read from file.txt. Therefore, argc in your main is 1 and you get the error message you have placed for this case.
To solve this, you can either
run the program as it's supposed to (without shell redirection)
$ ./program file.txt
or modify your program such that it reads from standard input if called with no arguments. It may then be called either way.
Many POSIX commands use the convention that if called with no file names, they read from standard input instead. For example,
$ cat file.txt
outputs the contents of file.txt while
$ cat
parrots back at you everything you type.
To implement this, you'd need something like this.
FILE * file = NULL;
if (argc == 1)
{
file = stdin;
}
else if (argc == 2)
{
file = fopen(argv[1], "r");
if (file == NULL)
{
fprintf(stderr, "error: %s: %s: %s\n",
"cannot read file", argv[1], strerror(errno));
return EXIT_FAILURE;
}
}
else
{
fprintf(stderr, "error: %s\n", "too many arguments");
return EXIT_FAILURE;
}
assert(file != NULL); /* we have made this sure */
c must be an int.
Make sure c is in proper range before indexing the array.
c = fgetc(file);
if (islower((unsigned char)c)) count[c-'a']++; // assumes 'a' thru 'z' are sequential
You need to #include <ctype.h> for the correct prototype for islower()

How would I get more then one text file accepted?

Right now, I have something like this...
CMD console window:
c:\users\username\Desktop> wrapfile.txt hello.txt
Hello
How would I get something like this?
CMD console window:
c:\users\username\Desktop> wrapfile.txt hello.txt hi.txt
Hello Hi
with this code?
#include <stdio.h>
#include <stdlib.h>
int main(int argc[1], char *argv[1])
{
FILE *fp; // declaring variable
fp = fopen(argv[1], "rb");
if (fp != NULL) // checks the return value from fopen
{
int i;
do
{
i = fgetc(fp); // scans the file
printf("%c",i);
printf(" ");
}
while(i!=-1);
fclose(fp);
}
else
{
printf("Error.\n");
}
}
Well, first of all: in your main declaration, you should use int main(int argc, char* argv[]) instead of what you have right now. Specifying an array size makes no sense when declaring an extern variable (that's what argv and argc are). On the top of that, you are not using the correct types. argc is integer and argv is array of strings (which are arrays of chars). So argv is an array of arrays of chars.
Then, simply use the argc counter to loop through the argv array. argv[0] is the name of the program, and argv[1] to argv[n] will be the arguments you pass to your program while executing it.
Here is a good explanation on how this works: http://www.physics.drexel.edu/courses/Comp_Phys/General/C_basics/#command-line
My 2 cents.
EDIT: Here is a commented version of the working program.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
FILE *fp;
char c;
if(argc < 3) // Check that you can safely access to argv[0], argv[1] and argv[2].
{ // If not, (i.e. if argc is 1 or 2), print usage on stderr.
fprintf(stderr, "Usage: %s <file> <file>\n", argv[0]);
return 1; // Then exit.
}
fp = fopen(argv[1], "rb"); // Open the first file.
if (fp == NULL) // Check for errors.
{
printf("Error: cannot open file %s\n", argv[1]);
return 1;
}
do // Read it.
{
c = fgetc(fp); // scans the file
if(c != -1)
printf("%c", c);
} while(c != -1);
fclose(fp); // Close it.
fp = fopen(argv[2], "rb"); // Open the second file.
if (fp == NULL) // Check for errors.
{
printf("Error: cannot open file %s\n", argv[2]);
return 1;
}
do // Read it.
{
c = fgetc(fp); // scans the file
if(c != -1)
printf("%c", c);
} while(c!=-1);
fclose(fp); // Close it.
return 0; // You use int main and not void main, so you MUST return a value.
}
I hope it helps.
argv[2] would be the second file name.
Do not forget to check the value of argc to see if enough arguments are valid.
Better: use boost::program_options.
Caution: this code is not unicode-aware on Windows system, which makes it not portable. Refer to utf8everywhere.org about how to make it support all file names on this platform.

Replace string with another

I am just not sure why my replaceWord isn't going in to the file at all i have used all the commented out and so on and so forth. I am just trying to replace with with the text received from the command line argument. I know i might be far off I was just looking for a relatively easy way to do it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main ( int argc, char *argv[] )
{
if ( argc != 4 ) /* argc should be 2 for correct execution */
{
/* We 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;
/* read one character at a time from file, stopping at EOF, which
indicates the end of the file. Note that the idiom of "assign
to a variable, check the value" used below works because
the assignment statement evaluates to the value assigned. */
while ( (fscanf( file, "%s", string ) ) != EOF )
{
len = strlen(string);
printf( "%s\n", string );
if(strcmp(string, wordReplace) == 0){
//fseek (file, (-strlen(string) + 1), 1);
//fputc(*replaceWord,file);
//replaceWord++;
//strcpy(string, replaceWord);
fprintf(file,"%s",replaceWord);
fputs(replaceWord, file);
printf("\n%d\n", len);
}
}
fclose( file );
}
}
printf("\n");
return 0;
}
You've opened the file in r ie read mode and trying to write to it.
Also after correcting that, note that, the replaced word and word to be replaced have to be of the same size, if you want to replace the file in place. Else you will end up overwriting other data. And you need to use functions like fseek to reposition the internal file pointer as fp would have moved ahead after fscanf

Resources