Text File Parsing in C - Calling a Batch File Or Not - c

This website is a tremendous source of knowledge, it has helped me countless times in the past.
I just started learning C on my own - up until now I just wrote a few batch files.
So I humbly ask for your help - I'd like some guidelines on how to write a C program that would:
1) Open a text file that contains the following
"batch1.cmd" "argument1" "1"
"batch2.cmd" "argument2" "0"
"batch3.cmd" "argument3" "1"
2) Parse it to find "0" or "1"
If "1" call he specified batch file with its argument
If "0" go next line - I will be updating the text file on a regular basis, so I would just have to change 1 or 0 and not rewrite all of those lines.
I have found a lot of help regarding parsing in C on the internet already, but no tutorial regarding how to achieve that.
I am aware that this might seem very easy and that I must appear as someone very lazy but I assure you I've been at it for three days now, without any success.
I am not necessarily asking for a complete script, just an answer like "look into the following function, its correct syntax is yadda yadda" and so forth.
I think I would have to use
int Search_in_File(char *fname, char *str)
{ FILE *fp;
fp=fopen("c:\\batchlist.txt", "r");
and
system("c:\\batch1.cmd argument1");
but I somehow cannot "connect the dots."
Thanks in advance!

Have a look at http://en.wikipedia.org/wiki/C_file_input/output - you're very close. Once you've opened the file, you need to read the lines or characters from the file, and based on what you find, execute the system command.
That wiki page will show you how - it has some handy example code too :)

int Search_in_File(char *fname, char *str)
{ FILE *fp;
char line[100],a[100],b[100],c[100];
fp=fopen("c:\\batchlist.txt", "r");
if( !fp ) ... errorhandling here ...
while( fgets(line,100,fp) )
{
if( strchr(line,'\n') ) *strchr(line,'\n')=0;
if( 3==sscanf(line,"%s%s%s",a,b,c) && !strcmp(c,"1") ) /* "%s" breaks at whitespaces, attention for whitespaces in your strings here! */
{
sprintf(line,"%s %s",a,b);
system(line);
}
}
...
fclose and so on ...
}

Related

How to make flex use a text-containing file (.txt/.c/etc.) as its input

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.

Creating a new file every time a programme is run in c

I'm creating a programme that writes the results of a questionnaire to a .txt file and wondered if there was any way to create a new file with a new name every time the programme was run?
FILE *fp;
fp = fopen("results.txt","w");
How can the file reults.txt be saved under a different name each time?
so ive done the below which lets a user save the name of their results.
int main(int argc, char *argv[])
{
printf("Please enter a filename to save your results to\n");
char c;
FILE *fp;
if (argc >= 2){
fp = fopen(argv[1], "w");}
while ((c = getchar()) != EOF)
{
putc(c, fp);
}
but i get a core fault.
Use the standard C function meant to be used for this very purpose.
7.21.4.4 The tmpnam function
#include <stdio.h>
char *tmpnam(char *s);
The tmpnam function generates a string that is a valid file name and that is not the same
as the name of an existing file.
Notably, this family of functions have some security concerns addressed by CERT-C here. C11 provides safer versions called tmpfile_s and tmpnam_s, as part of the optional bounds-checking interface. But if your beginner-lever questionnaire program does not need commercial production quality protection against hackers, this shouldn't be a concern.
There is many ways to do this.
You can take the file name as an argument.
You can get the process id (with getpid()), and add it to the end of the name.
You can add an number at the end of the file and increment it each time the program is run (by looking into the directory)
...
Edit:
Answer to your first edit
You only open the file if argv < 2, so what will append if argv >= 2 ? What do you think will append when you do putc(c, fp); ?
If you want your program only run if there is enough arguments, check it at the beging, and exit if it's not ok, with a message to tell why it's not ok. :)
And, always check the return of functions like fopen, malloc,... To be sure everything is ok.
You can generate random number by using rand() function in C and append it to the filename at the end ! Or you can append currentmillis to your file name to get unique name every time ! Of course there are many ways of doing it !
Or char *tmpnam(char *str); can also be used!

C fopen filename parameter as a dynamic variable

I want to have the function fopen's filename parameter as a dynamic variable that takes in a ftp client input for my ftp server. I have tried numerous different ways both on this forum and on google but "filename" will still not be recognized by fopen.
else if (strncmp(client->input, "retr", 4) == 0) {
char fname[1024];
// COMMAND LINE: retr filePATHNAME thats why +5
strcpy(fname, client->input+5);
if(fopen(fname, "r") != NULL) {
...
If I put fopen("/pub/test.txt" , "r"), it works so it has to do with something with spaces or quotations or type.
But if i try to do it on the client command line with retr /pub/test.txt or even retr "/pub/test.txt" fopen does not work and will not open the file.
Been stuck on this for the longest time, any help is appreciated.
Thanks
I found the answer.
Thanks to #user3386109 for the hint.
I basically had to clear all the spaces, new lines for the input
strtok(client->input+5,"\r\n\t");

How to discover which files exist in a folder

I have written a program, where it takes an input file, does some operations on it and gives its corresponding output file. i.e., for inp1.txt output is out1.txt, for inp2.txt output is out2.txt and so on, both in different folders.
Right now I have used a file_count variable and have used switch case method, to open the particular file.
The problem is, if I add one more file to the folder, then I have to re-edit the program with another case statement.
Please suggest me the usage of directory pointer in , I browsed all over the net but didnt get an exact solution.
Thanks a lot in anticipation.
There's no way to read the contents of a directory using only standard C APIs, so you'll have to use platform-specific APIs instead:
On *nix systems, you use opendir(3)/readdir(3)/closedir(3) to read the contents of a directory.
On Windows systems, you use FindFirstFile/FindNextFile/FindClose
If you know the file names in advance ie. they follow a pattern like this: f1.txt f2.txt fn.txt then you can loop over the files:
for (int i = 0 -> num_files)
char * filename;
filename = create_your_filename(i)
open(filename)
dostuff
close(filename)
you can follow the same pattern or even edit the filename for the output files.
Otherwise you can also call the program with all the input files in the command:
your_program *.txt
Then all of the file names will appear in argv[], which you can iterate over.
you have to find the files in input folder in runtime before processing. you can sort the files by extension,file name,created date etc...
Here is a simple function that show you if a file (in parameters) is in the path you put in argument.
Return 0 if file exit, 1 if not.
int is_file_enabled(char *path, char *filename)
{
char exec[255], line[255];
sprintf(exec, "ls %s | grep \"%s\"", path, filename);
FILE* cmd_res = popen(exec, "r");
if (cmd_res != NULL)
while (fgets(line, sizeof(line), cmd_res) != NULL)
if (line != NULL) { pclose(cmd_res); return 0; }
pclose(cmd_res);
return 1;
}

How would I scan phrases from the command line?

I am currently trying to get my program to work the way I want. I am currently at the point where I can open up any text file from the command line (an unlimited amount) and display them. I'd like to expand on this and have users enter phrases that format the displayed text. I have previously posted a similar question and I've gotten some great answers, but I cannot use getopt(). How else would it be possible to scan the command line for a "-w" and a number, so "-w5" and a "-s" with no number. Those are the only two things I'd like to be able to detect. I don't mind if statements, I was hoping for the shortest program in my friends, but at this point, I'd just like to get it done. Any ideas? Multiple if-statements was my friend's idea, I personally think this is unneeded, but if that's what I have to do... If anyone else has any ideas, that would be really useful. I just want my program to detect those two characters from the command line. I'm fairly new to C (I've only made a few programs), but I'm edger to learn and I have tried googling and trying this on my own, but being new to C, trying to find what I need through all the other text and jargon is difficult.
Anything will be useful, thanks.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
int l = 1;
while(l != argc)
{
FILE *fp;
fp = fopen(argv[l], "rb");
l++;
if (fp != NULL)
{
int i = 1;
do
{
i = fgetc(fp);
printf("%c",i);
printf(" ");
}
while(i!=-1);
fclose(fp);
}
else
{
printf("Error.\n");
}
}
}
void scanningForWS(int argc, char **argv)
{
}
You should look at plan9's ARGBEGIN and ARGEND macros in their libc.h file (at the very end of the file), to see how it's done (for an example of its usage, see arg(3)).
Alernatively, you can check the suckless implementation of this mechanism, which is very nice (I have re-implemented a version of it which parses arguments even after incorrect flags have been found, but it's not published anywhere. I can publish it if you need that).
The command line arguments are in argv, and since argv is an array, the only way to find a specific element inside of it is to iterate through, checking each element until you get the one you want. If you don't want to write all that yourself, it looks like C has a method called 'lfind' in search.h that does this. Here is an example of how to use it. Hope that helps :3.
Also, the GNU documentation for it

Resources