I have a C program which will take one argument as input and, if the argument is matching with the string inside the executable, it will return 1 otherwise 0. The executable file name is prg1. I have some input strings in a file named inputs.txt. I want to get those strings from the input file and call the prg1 inside a C program with each string.
I have tried the following code but it's not working.There is no segmentation fault but when i am calling prg1 it executes, Because the printf() statement inside prg1 is working and i can see the output.it changes variable found to 0I cant change the prg1. Because my friend has given the executable file of that program to me, not the source code. Header files are stdio.h and string.h
int main()
{
FILE *fk;
char text[80],inp[16],test[50]={"./prg1 "};
int found=100;
fk=fopen("inputs.txt","r");
while((fscanf(fk,"%s",inp))!=EOF)
{
strcat(test,inp);
found=system(test);
if(found==1)
{
printf("\nAnswer is : %s",inp);
break;
}
strcpy(test,"./prg1 ");
}
fclose(fk);
return 0;
}
What is wrong with my code?
I am not sure of what you want to achieve but here are some comments:
1 - You should test the return value of fopen:
if (!fk) { ... }
2 - You're not cleaning the test buffer between each test, so you are effectively calling:
system("prg1 first_word");
system("prg1 first_wordsecond_word");
...
You should have something like:
strcpy(test, "prg1 ");
after entering the loop and before strcat.
3 - Do you have spaces in your input strings? You should fix your code to read until a newline in this case.
4 - You might want to use EXIT_SUCCESS and EXIT_FAILURE instead of 0 and 1.
prog1 returns 1 when finding match, but 1 stands for error (at least in linux systems). Try returning EXIT_SUCCESS and EXIT_FAILURE (defined in stdlib.h). Then, when the system() call returns 0, the match is found, when anything else, match is not found.
The fundamental flaw in your code is that you need to reset the contents of the 'test' array to be "prg1 " at the beginning of each iteration of the main loop, before you call strcat to add the next argument to the command line. Otherwise the command to be run will just continue to get longer with each iteration, as each input read is added to the existing command. I don't think that is what you intend.
For example, given two lines of input, "foo" and "bar", the first iteration of the loop will cause the command "prg1 foo" to be executed, while the second will cause "prg1 foobar" to be executed. An easy way to have checked that would be to insert a printf (or similar) before the call to system() to display what command is going to be executed.
You also should check the return code of fopen and check array bounds when assigning to an array using fscanf.
Related
I am completely new to flex, and my experience in programming is rather little. I need to create a scanner using flex that will output a stream of tokens eventually. For the moment, I just need to get the absolute basics up and running. I want the compiled output file "a.exe" to be able to be run from the text within a SINGLE file and not user input. The output should also be to a file. The assignment asks that the program is able to run like so in a cmd/PS window:
.\a.exe inputfile.txt outputfile.txt
Where input and output files are whatever file names are added in that order.
As it stands currently, my program creates the output file I designate, but nothing is written to it. When trying to read the Flex Manual, I am very confused as I am still very new to computer sciences in general.
As per the moment, I just want to get an executable file that will adhere to the rules section and output properly. This said I am generically just counting the characters in the input file and trying to display them to an output file. I also am trying to help the others in my class have a place to begin (as none of us were formally taught in this affair) so I am taking the time to try and create this file generically (with installation and usage instructions) so that I can give them a place to start the actual assignment of making the scanner.
I installed Flex 2.5.4a from http://gnuwin32.sourceforge.net/packages.html. I edited my Path to include the bin file after installation.
I build the file using the command "flex tokenout.l" and then "gcc lex.yy.c" and it generates an a.exe file. The file does not seem to work much at all past creating the output file.
code:
int num_lines = 0;
int num_chars = 0;
FILE *yyin;
FILE *yyout;
%%
\n ++num_lines; ++num_chars;
. ++num_chars;
%%
int yywrap(void) {
return 0;
}
int main(int argc, char *argv[])
{
yyin = fopen(argv[1],"r");
yyout = fopen(argv[2],"w");
yyparse();
yylex();
fprintf(yyout,"# of lines = %d, # of chars = %d\n", num_lines, num_chars);
fclose(yyin);
fclose(yyout);
return 0;
}
The result should be that the line "# of lines = the actual # of lines, # of chars = the actual # of characters" to the file designated as the second argument.
Currently the file designated by the second argument is created but remains blank.
Lex (flex) calls (or more precisely, generates code that calls) yywrap upon reaching the end of its input stream (in yyin). The job of this function is to:
Take care of closing the input file if needed / appropriate.
Switch to the next input file, if there is a next file.
Return nonzero (1, preferably) if flex should finish up, 0 if yyin is now re-opened to the next file.
Or, as the manual puts it:
When the scanner receives an end-of-file indication from YY_INPUT, it then checks the ‘yywrap()’ function. If ‘yywrap()’ returns false (zero), then it is assumed that the function has gone ahead and set up yyin to point to another input file, and scanning continues. If it returns true (non-zero), then the scanner terminates, returning 0 to its caller. Note that in either case, the start condition remains unchanged; it does not revert to INITIAL.
If you do not supply your own version of ‘yywrap()’, then you must either use ‘%option noyywrap’ (in which case the scanner behaves as though ‘yywrap()’ returned 1), or you must link with ‘-lfl’ to obtain the default version of the routine, which always returns 1.
(Modern flex has <<EOF>> rules which are generally a better way to deal with stacked input files, since transitions between files should almost always force a token boundary.)
yyin = fopen(argv[1],"r");
yyout = fopen(argv[2],"w");
yyparse();
yylex();
As it stands currently, my program creates the output file I designate, but nothing is written to it.
You're confused because you don't know what your program is doing, and you don't know what it's doing because it's not telling you. What you need is feedback. In particular, you need to check for errors.
For example, what if the first fopen(3) fails? What if yyparse fails, or doesn't return? (It won't.) Check for errors, and have the program tell you what's happening.
#include <err.h>
if( argc < 3 ) {
errx(EXIT_FAILURE, "syntax: foo in out");
}
if( (yyin = fopen(argv[1],"r")) == NULL ) {
err(EXIT_FAILURE, "could not read '%s'", argv[1]);
}
if (yyout = fopen(argv[2],"w")) == NULL ) {
err(EXIT_FAILURE, "could not write '%s'", argv[2]);
}
printf("starting yyparse\n");
if( 0 != yyparse() ) {
errx(EXIT_FAILURE, "parse error");
}
printf("starting yylex\n");
if( 0 != yylex() ) {
errx(EXIT_FAILURE, "lex error");
}
The above ensures the program is started with sufficient arguments, ensures both files are open successfully, and checks for errors parsing and lexing. That's just an example, though. As John Bollinger advised, you don't need yyparse because you're not using bison, and yyout controls only the file used by the flex ECHO statement. You can use your own global FILE * handle, and fprintf(3) to it in your flex actions.
What i think you will find is that you never see "starting yylex" on the screen, because yyparse never returns, because -- if it is being generated somewhere -- it's not returning, because it's calling yylex, which never returns anything to it.
I would delete those lines, and set flex debugging on with
yy_flex_debug = 1;
before calling yylex. I think you'll find it makes more sense then.
You appear to be starting by adapting an example program from the Flex manual. That's fine, but maybe your very first step should be getting the exact example program working. After that, take it one step at a time. For example, the next step might be to get it to use the first argument as the name of the input file (and no other changes).
With respect to the partial program you have presented, I see two semantic issues:
When you use flex with bison (or yacc), it is the generated parser (accessed via yyparse()) that calls yylex(), and generally it will do so repeatedly until the input is exhausted. It is not useful in that case for the main program to call the lexer directly.
yyout is the file to which flex will direct the output of ECHO statements, nothing more, nothing less. It is not particularly useful to you, and I would ignore it for now.
fairly new to C and have a slight issue,
I have a function which is filled with 'fprintf' statements and some calculations relevant to the output.
When I call it from main() it works correctly and prints to the document, I then want to call it a second time and have the same text but only outputted to the terminal (as in printf).
I have a flag in the function parameters which would specify this choice but no way of accomplishing it aside from an if statement for every fprintf saying:
if (flag == 1)
{
fprintf(pt, "Random text...
} else {
printf("The same random text...
}
Which seems dreadfully inefficient. My other idea was to (with my little understanding of it) use #define within the function in the context:
if (flag== 1)
{
#define fprintf(pt, printf(
}
Which not only seemed very cheap but did not work.
Any ideas would be appreciated,
Thanks
How about something like this:
FILE *out=stdout;
fprintf(out,"Hello World\n");
Since this is a function, you can pass in the out pointer as an argument. When printing to the terminal, just assign stdout to it.
you could do a ternary expression using the fact that printf( is equivalent to fprintf(stdout,:
fprintf(flag == 1 ? pt : stdout, "Random text...");
First of all, I'm new to C so pardon me if asking too much.
I have a function that tokenize an input by the user so let's say
user input: test -f myFile
then after the tokenize function it becomes
abc[0] = test
abc[1] = -f
abc[2] = myFile
However, at the same time, I also need to use the return value from that input (test) statement whether it is FALSE or TRUE (file exist or not exist).
I did (MY PROBLEM)
if (*abc != '1') {
printf ("nope.");
}
in hope for telling me first whether that file is valid / exist or not, before I call some other function. However, it says warning comparison between pointer and integer.
My original plan is:
// ask the user for input
// tokenize the input
if (*abc != '1') { // check the return value from the input
printf ("nope.");
}
// call another function
Any input why MYPROBLEM doesn't work? How do I execute test after I tokenize?
If you want to check whether anything was added to abc, you would have to initialize your array to NULs prior to calling tokenize and then afterwards, if (**abc == '\0') would tell you that nothing was tokenized.
However, it's probably better for your tokenize function to return a flag that indicates success or failure in addition to populating your array.
As for executing test, you can use the system() function or one of the exec() functions.
I am trying to parse a given textfile, but so far, my program does not seem to be reading properly.
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fr; //file pointer
int buildingFloors = 1;
printf("sanity check\n");
fr = fopen (argv[0], "r");
fscanf(fr, "%d", &buildingFloors );
printf("%d\n", buildingFloors);
fclose(fr);
return 0;
}
I compile the program and run it on my redhat linux machine with the following command:
./sjf file.text
file.text is a text document with a "4" as the first character. So I would expect my output to be
sanity check
4
However, when I run my program I instead get
sanity check
1
Which implies that fscanf didn't properly read in the first character -- 4. Do I have some syntax error that's preventing the expected code functionality? Am I supposed to scanf for a character, and then convert that to an int somehow?
argv[0] is the name of the program (./sjf in your case), so you're trying to read in your own program's executable. Use argv[1] instead to get the first real program argument.
One thing which immediatly comes to mind is that the program args include the executable name as the first element
argv[0] is "sjf"
argv[1] is "file.text"
so you should be using
fr = fopen (argv[1], "r");
Remember when debugging to always try and narrow the problem down, if you know the location of the error the cause often becomes obvious or at least investigatable.
In this case you should check argc >= 2, print out argv[1] to ensure you are trying to open the right file, then also check that the file was opened successfully.
Finally check the fscanf error codes to see that fscanf was able to read the number.
Your code looks clear and straight-forward, but there is one important thing missing: error handling.
What happens if the file you want to open does not exist? fopen returns NULL in that case.
What happens if the file does not start with a number? fscanf returns the number of fields that have been successfully read, so you should check that the return value is at least 1.
You need to somehow handle these cases, probably by printing some error message and exiting the program. When you do that, be sure to include the relevant information in the error messages. Then you will find the bug that the other answers have already mentioned.
I am trying to create a a program that does the following actions:
Open a file and read one line.
Open another file and read another line.
Compare the two lines and print a message.
This is my code:
#include <stdio.h>
#include <string.h>
int findWord(char sizeLineInput2[512]);
int main()
{
FILE*cfPtr2,*cfPtr1;
int i;
char sizeLineInput1[512],sizeLineInput2[512];
cfPtr2=fopen("mike2.txt","r");
// I open the first file
while (fgets(sizeLineInput2, 512, cfPtr2)!=NULL)
// I read from the first 1 file one line
{
if (sizeLineInput2[strlen(sizeLineInput2)-1]=='\n')
sizeLineInput2[strlen(sizeLineInput2)-1]='\0';
printf("%s \n",sizeLineInput2);
i=findWord(sizeLineInput2);
//I call the procedure that compares the two lines
}
getchar();
return 0;
}
int findWord(char sizeLineInput2[512])
{
int x;
char sizeLineInput1[512];
File *cfPtr1;
cfPtr1=fopen("mike1.txt","r");
// here I open the second file
while (fgets(sizeLineInput1, 512,cfPtr1)!=NULL)
{
if (sizeLineInput1[strlen(sizeLineInput1)-1]=='\n')
sizeLineInput1[strlen(sizeLineInput1)-1]='\0';
if (strcmp(sizeLineInput1,sizeLineInput2)==0)
//Here, I compare the two lines
printf("the words %s and %s are equal!\n",sizeLineInput1,sizeLineInput2);
else
printf("the words %s and %s are not equal!\n",sizeLineInput1,sizeLineInput2);
}
fclose(cfPtr1);
return 0;
}
It seems to have some problem with file pointers handling. Could someone check it and tell me what corrections I have to do?
Deconstruction and Reconstruction
The current code structure is, to be polite about it, cock-eyed.
You should open the files in the same function - probably main(). There should be two parallel blocks of code. In fact, ideally, you'd do your opening and error handling in a function so that main() simply contains:
FILE *cfPtr1 = file_open("mike1.txt");
FILE *cfPtr2 = file_open("mike2.txt");
If control returns to main(), the files are open, ready for use.
You then need to read a line from each file - in main() again. If either file does not contain a line, then you can bail out with an appropriate error:
if (fgets(buffer1, sizeof(buffer1), cfPtr1) == 0)
...error: failed to read file1...
if (fgets(buffer2, sizeof(buffer2), cfPtr2) == 0)
...error: failed to read file2...
Then you call you comparison code with the two lines:
findWord(buffer1, buffer2);
You need to carefully segregate the I/O operations from the actual processing of data; if you interleave them as in your first attempt, it makes everything very messy. I/O tends to be messy, simply because you have error conditions to deal with - that's why I shunted the open operation into a separate function (doubly so since you need to do it twice).
You could decide to wrap the fgets() call and error handling up in a function, too:
const char *file1 = "mike1.txt";
const char *file2 = "mike2.txt";
read_line(cfPtr1, file1, buffer1, sizeof(buffer1));
read_line(cfPtr2, file2, buffer2, sizeof(buffer2));
That function can trim the newline off the end of the string and deal with anything else that you want it to do - and report an accurate error, including the file name, if anything goes wrong. Clearly, with the variables 'file1' and 'file2' on hand, you'd use those instead of literal strings in the file_open() calls. Note, too, that making them into variables means it is trivial to take the file names from the command line; you simply set 'file1' and 'file2' to point to the argument list instead of the hard-wired defaults. (I actually wrote: const char file1[] = "mike1.txt"; briefly - but then realized that if you handle the file names via the command line, then you need pointers, not arrays.)
Also, if you open a file, you should close the file too. Granted, if your program exits, the o/s cleans up behind you, but it is a good discipline to get into. One reason is that not every program exits (think of the daemons running services on your computer). Another is that you quite often use a resource (file, in the current discussion) briefly and do not need it again. You should not hold resources in your program for longer than you need them.
Philosophy
Polya, in his 1957 book "How To Solve It", has a dictum:
Try to treat symmetrically what is symmetrical, and do not destroy wantonly any natural symmetry.
That is as valid advice in programming as it is in mathematics. And in their classic 1978 book 'The Elements of Programming Style', Kernighan and Plauger make the telling statements:
[The] subroutine call permits us to summarize the irregularities in the argument list [...]
The subroutine itself summarizes the regularities of the code.
In more modern books such as 'The Pragmatic Programmer' by Hunt & Thomas (1999), the dictum is translated into a snappy TLA:
DRY - Don't Repeat Yourself.
If you find your code doing the 'same' lines of code repeated several times, write a subroutine to do it once and call the subroutine several times.
That is what my suggested rewrite is aiming at.
In both main() and findWord() you should not use strlen(sizeLineInputX) right after reading the file with fgets() - there may be no '\0' in sizeLineInput2 and you will have strlen() read beyond the 512 bytes you have.
Instead of using fgets use fgetc to read char by char and check for a newline character (and for EOF too).
UPD to your UPD: you compare each line of mike2.txt with each line of mike1.txt - i guess that's not what you want. Open both files one outside while loop in main(), use one loop for both files and check for newline and EOF on both of them in that loop.