I'm trying to implement a program I wrote on my Mac on Windows systems, and I'm running into a lot of trouble with this last function:
/* clearFiles */
// deletes the section files after the program has executed
// skips any sections listed table that don't appear in the body (b/c no file was written for these)
// also deletes the table & body files
void clearFiles(section_t *tableArray, int *skipArray, char *tableName, char *bodyName)
{
int i, status, index;
char str[SECTNAME];
char command[SECTNAME];
index = 0;
// clear section files
for(i=1; tableArray[i].count!=0;i++)
{
if(i!=skipArray[index])
{
strcpy(str, tableArray[i].shortName);
strcat(str,".txt");
status = remove(str);
if(status!=0)
printf("Warning! File %s not deleted.\n", str);
} else index++;
}
// clear table file
status = remove(tableName);
if(status!=0)
printf("Warning! File %s not deleted.\n", tableName);
// clear body file
status = remove(bodyName);
if(status!=0)
printf("Warning! File %s not deleted.\n", bodyName);
}
The program takes a very large file and first splits it into a table of contents file and a body file. It then takes the body and splits it into hundreds of individual section files, from which it performs the actual task of the program. At the end, I want it to delete all of these extra files, because they just clutter up the directory. It works perfectly on my Unix Mac environment, but when I try to run it in Command Prompt on a PC, my remove() function returns -1 for every section file and doesn't delete it (it does, however, successfully delete the table & body files). I also tried a more brute force method by using system(del fileName), but this didn't work either, because it says that the file is being used by another process. I can't figure out why these files might be open, as every time fopen() appears, I follow it up with an fclose(). The exception is when checking if the files are open, I use
if(fopen(fileName,"r")!=NULL){}
Could this be the problem? Is there either a way to check if a file is open without actually opening it, or is there a way to close a file that was checked this way? I tried assigning a dummy pointer to it and coding:
dummy = fopen(fileName, "r");
if(dummy!=NULL){}
fclose(dummy);
But this didn't work either. Is it possible to pass just a file path to the fclose() function (for example, something similar to fclose(C:\users\USER\desktop\fileName.txt)? Also, I know that the program is attempting to delete the correct fileName, because my error message prints the correct names to the command prompt.
Any input is greatly appreciated!!! Thanks.
NOTE:
The tableArray starts at 1 because of a search function implemented in the program that returns an index if found and 0 if not found. In hindsight, it would have been better to return -1 if not found and start the index at zero, but that is a separate issue
UPDATE:
Below is the code used to create the section files:
if(fopen(word, "r")==NULL){
ofile = fopen(word, "w");
fprintf(ofile, "SECTION %s ", section);
//go until end of file or until found the next section
// bug fix: check the section after that, too (in case the next section isn't there)
while(fscanf(spec, "%s", word)!=EOF && !cease)
{
if(strcmp(word,"SECTION")!=0){
fprintf(ofile, "%s ", word);
}
else{
fscanf(spec, "%s", word);
choice = testNumber(spec,word);
for(j=i+1; tableArray[j].count!=0;j++)
if(strcmp(word,tableArray[j].shortName)==0)
cease = 1;
}
}
fclose(ofile);
}
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.
I am trying to read in a file and it tells me it cant find the file. I built i have a built in checker that looks to see if the file is there. I have the data file in my debug folder. Am I reading the file incorrectly? I am also using codeblocks for the IDE.
Here is my function calling my file:
char fileData[3];
int bound = 96;
//file pointer and file info
FILE *ips;
ips = fopen("data.txt", "r");
if (ips == NULL)
printf("Please check file!\n"); //this is the output I get
else {
//for loop to scan through file, and retrive the letters
int i;
for(i=0; i<bound; i++)
fscanf(ips, "%c", &fileData);
addBoggleData(head1, fileData);
}
//closes the file system
close(ips);
}
you stated the file failed to open.
Since the fopen() file name parameter has no path info.
and you stated the file is in the debug directory.
1) the execution and the file must be in the same directory
2) in this case, both the executable and the data file must be in the debug directory.
You are passing the wrong parameter to fscanf(), you should pass the address of the ith element, like this
fscanf(ips, "%c", &fileData[i]);
and to be able to tell whether the data was read succesfully, you must check the return value of fscanf(), like
if (fscanf(ips, "%c", &fileData[i]) != 1)
{
warningReadingFailure();
}
Also, the fileData array is way too small, you need to make it at least as big, as the number of bytes you intend to read from the file, i.e.
int bound = 96;
char fileData[bound];
I am new to programming in C and I am programming for the Raspberry Pi using a C compiler. All I want to be able to do is create a function that takes a String as a parameter and save it as a text file in a specific location. I want to check that file location to see what files exist and save the new file to that folder with an increment of 1 added to the file name.
For example, folder contains:
TestFile1
TestFile2
And I want to be able to create the new file saved as TestFile3.
This is the code that I have so far and want to know if I am on the right lines and get any tips please:
void WriteToFile(unsigned char *pID)
{
printf("Writing to file. . . . .\n");
/* Checking to see how many files are in the directory. */
int *count = 0;
DIR *d;
struct dirent *dir;
d = opendir("table_orders");
if(d)
{
while((dir = readdir(d)) != NULL)
{
printf("%s\n", dir->d_name);
count = count + 1; // Adds 1 to count whenever a file is found.
}
closedir(d);
}
char str[sizeOf(count)]; // Creates string.
sprintf(str, "%d", count); // Formats count integer into a string.
File *f = fopen("table_orders/Order " + str + ".txt", "a"); // Creates new file.
if(f == NULL)
{
printf("Error opening file!\n");
exit(1);
}
fprintf(f, "Order: %s \n", pID);
fclose(f);
printf("The Order %s has been written to the file\n", pID);
}
int fd = open( "filename", O_RDWR | O_CREAT | O_EXCL, 0644 );
Nothing else is atomic - another process can create the file in between any check for existence and your actual creation of the file.
You can use stat (_stat in Windows) to see if a file exits. If it fails with errno set to ENOENT then the file doesn't exist. access is another possibility.
Of course it's not atomic, some other process could create the file in between your check and your call to fopen.
You are close, but so far off the mark, I think you need to put this on hold. Read some c tutorials with structured examples.
You have an algorithm error when you read through the directory and arbitrarily increase count. The logic should be more like
parse dir->name to 3 tokens "Testfile" 0001 ".log"
Using atoi or similar convert the numeral string to an int
When you declare str there's a lack of understanding of sizeof, it should read more like
char str[25];
This is enough to hold all digits of a 4 byte int as a string. sizeof count will be 4 probably,4 bytes 32 bits.
When you fopen you do something like "Dir/file" + str + ".log"
This isn't how you do this, + is mathematical in c. You need to use strcat or sprintf into a new work string, created and freed on the fly.
When appending a number to a file like here it makes sense to precede short numbers with 0 s . This produces regular filenames which have a good ls order.
Should you need to control create and exclusivity, you'll need to use open to open the file and fdopen it to a FILE type file handle.
When you go live with this you will need to prevent another process causing timing errors with scheduling use semaphores or a ".lock" file.
You will also want some maintenance routine to delete old logs and subsequently renumber all the remaining logs from 001
PS don't know why the down votes
I've written a program that writes information to a file. The output to the file is not in the order that I am expecting. I have a header line and three additional lines with numerical information. The header comes first following by the third, first, and second lines.
Note that the file is open in a mode, not a+. According to various sources, re-positioning operators like fseek() are suppose to be ignored. For a while I was actually getting the third line before the first line after that line was written. If the fseek() line is omitted, the third line actually is written before the header ..
If the fseek() function is left commented (regardless of being in a or a+ mode) the output is as shown in the picture below.
I wrote in a bit of code to see how the output should be written. The text in the file is certainly not what it should be ..
I attempted to use the fseek() function to find the position just before the EOF before each write but to no avail.
I have also noticed that if I use fflush(writeP) then I get the same effect that including the fseek() function would. The file is still out of order as shown, but the third line is no longer before the header line.
What am I missing?
void quickSortHelper(int* num, long startTime, long endTime, int size){
FILE *writeP = fopen(QUICKSORT_FILE, "a");
if(writeP == NULL){
fputs("Error opening file\n", stderr);
exit(1);
}
static int times = 0;
long deltaT; //change in time
if(size < STEPSIZE){//first time, write header to file
printf("Writing header!\n");
fprintf(writeP, " --- QUICKSORT ---\nCOUNT\tTIME\tMEDIAN\n");
}
deltaT = (clock() - startTime)/(CLOCKS_PER_SEC/1000);
//fflush(writeP);
fseek(writeP, -1, SEEK_END);
printf("Writing: %d\t%ld\t%d\n", size, deltaT, findMedian(num, size));
fprintf(writeP, "%d\t%ld\t%d\n", size, deltaT, findMedian(num, size));
if(++times == 3)
fclose(writeP);
return;
}
With the fseek() line commented, the output is:
You do not close writeP the first 3 times when function is called. So, the file is opened by several FILE handles which get closed on exit. The "a" works only for the same FILE handle or when data have reached the disk.
The problem comes from the fact that you open the same file on every function call, but only close it on the third call. I would suggest moving the file opening and closing logic out of that function, and passing the FILE * handle as an argument to the function; this would also avoid having to hard code the call number on which to close into that function.
So the place where you call the function would look something like this:
FILE *writeP = fopen(QUICKSORT_FILE, "w"); // "a" changed to "w"
if (!writeP) {
perror(QUICKSORT_FILE);
exit(1);
}
// perhaps write the header into the file here
for (int i = 0; i < 3; ++i) {
// do the quicksort
write_quicksort_results(writeP, …);
}
(void) fclose(writeP);
I created a C program which will run some system() commands and save the output to a .txt file in a particular folder of C drive (program is to be run on domain clients with startup privileges), from where I'll filter the data and show it on output console screen.
Everything worked fine, but I couldn't design it for those PCs who have OS installed in other drives (e.g. D:, E:, etc), since they will not have this particular folder in their C: drive. I can't write temporary .txt files anywhere else due to group policies.
Is there any method to stream this data directly into any array variable? I went through popen() function, but it would require a very large array of unpredicted size to be defined (since the output of system() command may be very large). For example, exporting the registry keys of HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\uninstall into a .txt file. Its size may be up to 50KB or bigger.
reg export HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\uninstall C:\\..(somewhere)....\\reg_output.txt
There are some more similar commands with large output. I don't know Win API programming yet, thus I am using system command. Can there be an easy alternative to writing to .txt ?
#Megharaj!
As you used
char line[100];
fp = popen("ifconfig eth0", "r");
fgets(line, 100, fp);
I'll have to use
char reg_output[100000];
fp=popen("reg export HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\uninstall ????","r");
fgets(line,100000,fp);
Where do I export the registry values? (Since the DOS command for exporting this needs to write it to a file), as compared to following code I am using.
Assigning a space of 100000 isn't sure that it will not be error prone. And assigning too high value also will affect the memory on startup (I'm not sure but guess so).
While using file handling I do it as:
char line[5000]; FILE* fp_reg; int ch,n=0;
system("reg export HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\uninstall c:\\registries.txt");
fp_reg=fopen("c:\\registries.txt","r");
while((ch=fgetc(fp_reg))!=EOF)
{
if(isalnum(ch) || ch=='\n') //allow only alpha numeric & '\n' to pass to array
{ line[n]=ch;
if(ch=='\n')
{ filter_for_software(line,n); //Send the array for filtering function
n=0; // Reset the array 'line'
}
n++;
}
}
(I didn't copy the code from source, since I am sitting on a different PC. But the code is almost similar to this. Some errors may come if you copy this code & run.)
This way, I take each line from file and send it for filtering to get 'installed software's name'. How do I do it with 'popen()', so that I could pick up a line and throw it onto a function. Plz write some code also for this.
If you want to store the output in an array, you will have to allocate an array of appropriate size. There is just no way around that.
But you don't need to do that if you use popen. You get a FILE * handle and can just read the output in small parts and process it on the go.
from where I'll filter the data and show it on output console screen.
How do you do that? With the shell or in C? If in C, then you read the output of the systemed command just like you would read your txt file. The only difference is that you need to close it with pclose instead of fclose, so there are only advantages to doing it with a text file.
If in shell, then you can start the program you use with another call to popen, this time in a "w" (write) direction and write the output of one pipe as input to the other. However, in this case you could have just called a shell with an anonymous pipe in the first place. ;-)
Edit:
Your own answer makes clear that your requirements are quite different from what you think they are. There is no way to read the output of reg export back via a pipe and popen if it insists on writing to a file.
What you can try is to write a file to your temp folder; you should be allowed to create files there, otherwise Windows will not work correctly. Just specify something like "%TEMP%\reg.out" as file and read your data back from there.
If that doesn't work, you are out of luck with reg export. But you can use some Windows API function for querying the registry directly. Here is a starting point.
Alternatively, you might want to look into the possibility of employing PowerShell. This question might be of interest to you.
In linux to use the values from the system command i use popen, I am just giving an example of code that I had written some time long back, to get the ip address of the pc by system command "ifconfig eth0" to the string/a file. see the example
void get_my_ip(char *ip_mac_address)
{
FILE *fp,*output;
char *start=NULL;
char *end=NULL;
char line[100];
output=fopen("my_ip_address.txt", "w");
if(output == NULL) {
printf("error creating outputfile\n");
return -1;
}
printf("program to self query the ip address\n");
fp = popen("ifconfig eth0", "r");
fgets(line, 100, fp);
start=strstr(line, CHECK_STRING_MAC);
start = start + 7;
fwrite(start, 1, 17, output); start = NULL;
fgets(line, 100, fp);
start=strstr(line, CHECK_STRING_IP);
start = start + 10;
fwrite(start, 1, 14, output);
fclose(output);
pclose(fp);
if( access("my_ip_address.txt", F_OK ) != -1 ) {
printf("found file having ip address\n");
output=fopen("my_ip_address.txt", "r");
fgets(ip_mac_address, 32, output);
}
else
printf("unabe to find file with ip address\n");
fclose(output);
printf("my ip and mac address adress is %s \n",ip_mac_address);
}
You can create a temporary file using some API from Windows, and store your data in it.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa363875(v=vs.85).aspx
There is a C++ example in the link, you should be able to adapt it to your case.
So, I prepared the code to stream the output of a DOS command to a file pointer in read mode and check it line by line:
char array_sys[200]; FILE *fp_sys; int ch,n=0;
fp=popen("systeminfo","r"); //runs a DOS command & read it with a file pointer
if(fp_sys==NULL) printf("can't open file\n");
while((ch=fgetc(fp_sys))!=EOF) //READ CHARACTERS FROM FILE POINTER UNTIL FILE ENDS
{
array_sys[n]=ch; //ASSIGN CH TO EACH ELEMENT OF ARRAY
n++; //INCREMENT ELEMENTS OF ARRAY:-arr_sys
if(ch=='\n') //IF ELEMENTS MEET A NEW LINE CHARACTER
{
disp_date(array_sys,n); //PASS ARRAY TO FUNCTION:-disp_date
n=0; //RESET THE ARRAY
}
}
Now this is how I process array in function to get the name of operating system.
void disp_date(char array_sys[],int ind)
{
char os_name[9]={"OS Name:"};
if(strstr(array_sys,os_name)) //IF 'OS NAME' IS PRESENT IN ARRAY
{
printf("%s",array_sys); //PRINT THE ARRAY
}
}