Why is my regex function only running the first time around? - c

I'm working on some code for a homework assignment which is to search a text file for certain patterns and generate reports. Currently to test it I'm just printing my reports to the screen. But my search function only seems to be running the first time. I've tested the regex individually and they do all pull the correct matches but once I put it inside the function it only works the first time it's run. Could anyone explain to me why this is happening?
#include <stdio.h>
#include <stdlib.h>
#include <regex.h>
// Report expressions
char *reports[5] = {"^ {0,}[0-9]{1,4}", "S", "L", "S {0,1}(1|2)", "^ {0,}[0-9]{1,4} {1,} L | 3$"};
void search(FILE *fp, char *report, int index) {
regex_t reg;
char buf[256];
int reti = regcomp(&reg,report,REG_EXTENDED);
if(reti) {
printf("Regex compilation failed, noob\n");
exit(1);
}
printf("Report %d\n", index);
while(fgets(buf,sizeof(buf),fp) != NULL) {
//printf("%s",buf);
reti = regexec(&reg,buf,0,NULL,0);
if(!reti) { //if there's a match
printf("%s",buf);
} else if(reti == REG_NOMATCH) {
printf("No match\n");
}
}
regfree(&reg);
}
int main(void) {
FILE *fp;
fp = fopen("./Hammer.data","r");
if(fp == NULL) {
perror("Error opening file");
return(-1);
}
for(int i = 0;i < 5;i++) {
search(fp, reports[i],i+1);
}
fclose(fp);
return(0);
}

while(fgets(buf,sizeof(buf),fp) != NULL)
That will result in the fp pointing to the end of the file. So the next time the function is called the fgets will immediately return NULL. One fix is to rewind the file pointer before the fgets loop.

Related

Why is this function not copying the input file?

I'm just getting started into file I/O and am trying to build a function that will simply copy a file to destination.
This program compiles however an empty file is created and nothing is copied. Any advice?
#include <stdio.h>
int copy_file(char FileSource[], char FileDestination[]) {
char content;
FILE *inputf = fopen(FileSource, "r");
FILE *outputf = fopen(FileDestination, "w");
if (inputf == NULL)
;
printf("Error: File could not be read \n");
return;
while ((content = getc(inputf)) != EOF) putc(content, inputf);
fclose(outputf);
fclose(inputf);
printf("Your file was successfully copied");
return 0;
}
int main() {
char inputname[100];
char outputname[100];
printf("Please enter input file name: \n");
scanf("%s", &inputname);
printf("Please write output file name: \n");
scanf("%s", &outputname);
copy_file(inputname, outputname);
return 0;
}
There are few bugs in the code you mentioned. These two below statement
scanf("%s", &inputname);
scanf("%s", &outputname);
Are wrong as inputname and outputname are char array and array name itself address so you no need to give &inputname to scanf(). For e.g
scanf("%s",inputname);
scanf("%s",outputname);
Also ; at the end of if statement is not serving correct purpose as you expected.
This
if(inputf == NULL);
Should be
if(inputf == NULL){
/*error handling */
}
As pointed by other, getc() returns int not char. From the manual page of getc()
int getc(FILE *stream);
And this
putc(content, inputf);
Change to
putc(content, outputf); /* write the data into outputf */
Your line :
putc(content, inputf);
needs to change to
putc(content, outputf);
This code has a lot of problems:
if(inputf == NULL);
printf("Error: File could not be read \n");
return;
It is the equivalent of
if(inputf == NULL)
{
;
}
printf("Error: File could not be read \n");
return;
You have a stray ; that terminates you if statement, and whitespace doesn't matter much at all with C.
So your if statement does nothing, and your code will always emit the "Error: File could not be read" message and return without doing anything else.
What you probably want:
if(inputf == NULL)
{
printf("Error: File could not be read \n");
return;
}
This is a perfect example of why a lot of C programmers always use braces after if statements. ALWAYS.
There are multiple problems in your code:
content must be declared as int: getc() returns an int with the value of the byte read from the file or the special negative value EOF at end of file. Storing that to a char variable loses information, making the test for EOF either ambiguous (if char is signed) or always false (if char is unsigned by default).
you should pass outputf to putc.
you should return from the copy_file function if fopen fails to open either file.
you should pass the maximum number of characters to read for the filenames
you should check the return value of scanf() to avoid undefined behavior on invalid input.
Here is a corrected version:
#include <stdio.h>
int copy_file(const char *FileSource, const char *FileDestination) {
int content;
FILE *inputf, *outputf;
if ((inputf = fopen(FileSource, "r")) == NULL) {
printf("Error: cannot open input file %s\n", FileSource);
return -1;
}
if ((outputf = fopen(FileDestination, "w")) == NULL) {
printf("Error: cannot open output file %s\n", FileDestination);
fclose(inputf);
return -1;
}
while ((content = getc(inputf)) != EOF)
putc(content, inputf);
fclose(outputf);
fclose(inputf);
printf("Your file was successfully copied");
return 0;
}
int main() {
char inputname[100];
char outputname[100];
printf("Please enter input file name: \n");
if (scanf("%99s", inputname) != 1)
return 1;
printf("Please write output file name: \n");
if (scanf("%99s", &outputname) != 1)
return 1;
copy_file(inputname, outputname);
return 0;
}
Use sendfile() is more simple and efficient for copying file. You can view more detail about sendfile() by man sendfile.
#include <stdio.h>
#include <string.h>
#include <sys/sendfile.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
if (argc < 3)
{
printf("Usage: %s <srcfile> <dst_file>\n", argv[0]);
return 1;
}
char *src_file = argv[1];
char *dst_file = argv[2];
int src;
int dst;
ssize_t size;
struct stat stat_buf;
if ((src = open(src_file, O_RDONLY)) < 0)
{
printf("Can not open %s\n", src_file);
return -1;
}
if (fstat(src, &stat_buf) < 0)
{
printf("Can stat %s\n", src_file);
close(src);
return -2;
}
if ((dst = open(dst_file, O_CREAT|O_WRONLY, stat_buf.st_mode)) < 0)
{
printf("Can not open %s\n", dst_file);
return -1;
}
if ((size = sendfile(dst, src, NULL, stat_buf.st_size)) < 0)
{
printf("Fail to copy file, size: %ld\n", size);
}
else
{
printf("Success, size: %ld\n", size);
}
close(src);
close(dst);
return 0;
}

print 5 lines from input file

currently, I am writing code in c program for printing small portion of contents from the input file. Actually, in my code I can able to print just one single line. but, i have to print next 5 lines after that one line.
I am new to programming, please help to solve this problem**
code is given below
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int lineNumber = 2;
int main()
{
FILE *file;
char line[100];
int count = 0;
///Open LS-dyna file to read
file = fopen("P:\\tut_c\\read\\df-read\\in.txt", "r");
if (file == NULL)
{
perror("fopen");
exit(EXIT_FAILURE);
}
else if ( file != NULL )
{
char line[256];
while (fgets(line, sizeof line, file) != NULL)
{
if (count == lineNumber)
{
printf("\n str %s ", line);
fclose(file);
return 0;
}
else
{
count++;
}
}
fclose(file);
}
return 0;
}
The first logical error occurs in your while loop, first iteration, when you close the file and return 0.
Next, there is no reason to have a counter for your lines, since there are many c functions that can handle finding the end of file (eof).
Instead:
Use a while loop for iteration through the file.
Use a standard library c function for file reading.
Check if file has reached the end.
If the line is still valid, then print the line.
Here is some code to reiterate:
int main()
{
FILE *file;
file = fopen("file.txt", "r");
if (!file){ // check if file exists
perror("fopen");
exit(EXIT_FAILURE);
}
else { // if file exists, then...
char line[256];
while(fgets(line, sizeof line, file)){
printf("\n str %s ", line);
}
fclose(file);
}
return 0;
}// end main

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.

Store and eliminating garbage values

Everytime I try to run the code it'll print out the contents of the file, however it will print out a garbage value at the end which I don't know how to get rid of. I am supposed to to store the contents of the file into an array, however I am a bit confused on how to do that???
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char filePrinter(char*arr)
int main (int argc, char**argv)
{
char fileArray[150];
if(argc !=2)
{
printf("Invalid Entry. Please Enter name of program followed by input filename\n");
}
filePrinter(fileArray);
return 0;
}
char filePrinter(char*arr)
{
int i;
FILE*file;
i=0;
file=fopen("assests/room.txt","r");
if(file == NULL)
{
printf("Could not open file\n");
exit(-1);
}
else
{
while(0 ==feof(file))
{
i=fgetc(file);
printf("%c", i);
}
}
fclose(file);
return i;
}
file content:
10x16 ds5 h6,5 g7,8 p3,3
10X16 de4 h5,7 g9,2
10X16 dw6,h2,3 m6,7
10X16 dn3,h2,4 p2,3
10X16 de2 h9,9 m4,5
10X16 dn8 h4,5 g1,1*/
feof returns true if the last call to a read operation hit EOF. You'd want to test it after the fgetc call. Or, even better, just check whether fgetc returned the special value EOF.
(A FILE * has an "end-of-file marker" that says whether some read operation has hit EOF. Read operations set the "end-of-file marker" upon hitting EOF. Before you've hit---meaning tried to read past---the end of the file, that "end-of-file marker" is clear.)
Timing is bad than look at the beginning of the loop by feof because EOF occur in fgetc.
replace to
while(EOF!=(i=fgetc(file))){
printf("%c", i);
}
int filePrinter(char*arr){
int i = 0, ch;
FILE*file;
file=fopen("assests/room.txt","r");
if(file == NULL) {
printf("Could not open file\n");
exit(-1);
} else {
while(EOF!=(ch=fgetc(file))) {
//printf("%c", ch);
arr[i] = ch; //*arr++ = ch;
++i;//i : range check
}
arr[i] = '\0';
}
fclose(file);
return i;
}
I think the code should be:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void filePrinter(char*arr);
int main (int argc, char**argv)
{
char fileArray[150];
memset(fileArray, 0, sizeof(fileArray));
if(argc !=2)
{
printf("Invalid Entry. Please Enter name of program followed by input filename\n");
}
filePrinter(fileArray);
return 0;
}
void filePrinter(char *arr)
{
int c = 0, j = 0;
FILE* file = NULL;
file=fopen("assests/room.txt","r");
if(file == NULL)
{
printf("Could not open file\n");
exit(-1);
}
else
{
while (1)
{
c = fgetc(file);
if (c != EOF)
{
arr[j++] = c;
}
else
{
break;
}
}
}
fclose(file);
return;
}

How do I get the input to cut off or wrap around at a certain point?

Alrighty, so after a day and a bit of being on stackoverflow, I learned it's useful being on this site :) I ended up getting my program to work. I can get an unlimited amount of text files in on the command line and display them as well! So it looks like this:
CMD Console
c:\Users\Username\Desktop> wrapfile.exe hello.txt how.txt. are.txt you.txt random.txt
Hello How are you doing today? I hope you're doing quite well. This is just a test to see how much I can fit on the screen.
Now, I wana build on this program. How would I get this new found text to wrap around? Like, if you wanted to make it that, every 40 characters or so, the text jumps to the next line... how could we go about doing something like that?
Thanks again!
Here's the code I'm working with:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
int l = 1;
while(l != argc)
{
FILE *fp; // declaring variable
fp = fopen(argv[l], "rb");
l++;
if (fp != NULL) // checks the return value from fopen
{
int i = 1;
do
{
i = fgetc(fp); // scans the file
printf("%c",i);
printf(" ");
}
while(i!=-1);
fclose(fp);
}
else
{
printf("Error.\n");
}
}
}
Okay, here we go...this looks a little different to yours, but this is ISO/ANSI C 1989 standard.
int main(int argc, char **argv)
{
FILE *fd = NULL;
char linebuf[40];
int arg = 1;
while (arg < argc) {
fd = fopen(argv[arg], "r");
if (NULL != fd) {
/* fgets(char *buf, size_t buflen, FILE *fd): returns NULL on error. */
while (NULL != fgets(linebuf, sizeof(linebuf), fd)) {
printf("%s\n", linebuf);
}
fclose(fd);
} else {
fprintf(stderr, "Cannot open \"%s\"\n", argv[arg]);
}
++arg;
}
}

Resources