Negated scanset in fscanf and EOF - c

I've got a comma-separated list of strings in my file:
Name 1, Name 2, Name 3,
I want to read those names skipping all commas. I've written the following loop:
while(true)
{
if(fscanf(file, "%[^,],", my_string) != 1)
{
break;
}
//...
}
However, it is always executing one more time than it supposed to. Given 3 names in the file, the loop will execute its statements 4 times. Why is this happening? Does EOF indicator rank to my negated scanset [^,]? If so, then how can I solve this issue?

I'm pretty sure this is doing exactly what you want it to. The only modification to the algorithm I made is added the leading whitespace-clear before the % in the format string. Also,I modified this to open the file from a command-line arg. Easier to test that way. Hope thats ok.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
if (argc != 2)
return EXIT_FAILURE;
FILE *fp = fopen(argv[1], "r");
if (NULL == fp)
return EXIT_FAILURE;
char str[100];
int count=0;
while (1)
{
if(fscanf(fp, " %[^,],", str) != 1)
break;
printf("%s\n", str);
++count;
}
printf("Parsed %d strings.", count);
return EXIT_SUCCESS;
}
Output
Name 1
Name 2
Name 3
Parsed 3 strings.
I believe the "fourth" execution in the loop you're seeing is the failure condition, which breaks the loop due to failure to parse, unless I'm missing something or not understanding what you're witnessing.

Why are your loop statements executing 4 times. The loop breaks after 4th fscanf statement and codes below aren't executed.EOF indicator doesn't rank to your negated set However maybe you are looking for a more compact solution like this:
while(fscanf(file, "%[^,],", my_string)!=EOF )
{
//do something
}
If not, please post more detailed code and your test file

Related

Check multiple files with "strstr" and "fopen" in C

Today I decided to learn to code for the first time in my life. I decided to learn C. I have created a small program that checks a txt file for a specific value. If it finds that value then it will tell you that that specific value has been found.
What I would like to do is that I can put multiple files go through this program. I want this program to be able to scan all files in a folder for a specific string and display what files contain that string (basically a file index)
I just started today and I'm 15 years old so I don't know if my assumptions are correct on how this can be done and I'm sorry if it may sound stupid but I have been thinking of maybe creating a thread for every directory I put into this program and each thread individually runs that code on the single file and then it displays all the directories in which the string can be found.
I have been looking into threading but I don't quite understand it. Here's the working code for one file at a time. Does anyone know how to make this work as I want it?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
//searches for this string in a txt file
char searchforthis[200];
//file name to display at output
char ch, file_name[200];
FILE *fp;
//Asks for full directory of txt file (example: C:\users\...) and reads that file.
//fp is content of file
printf("Enter name of a file you wish to check:\n");
gets(file_name);
fp = fopen(file_name, "r"); // read mode
//If there's no data inside the file it displays following error message
if (fp == NULL)
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
//asks for string (what has to be searched)
printf("Enter what you want to search: \n");
scanf("%s", searchforthis);
char* p;
// Find first occurrence of searchforthis in fp
p = strstr(searchforthis, fp);
// Prints the result
if (p) {
printf("This Value was found in following file:\n%s", file_name);
} else
printf("This Value has not been found.\n");
fclose(fp);
return 0;
}
This line,
p = strstr(searchforthis, fp);
is wrong. strstr() is defined as, char *strstr(const char *haystack, const char *needle), no file pointers in it.
Forget about gets(), its prone to overflow, reference, Why is the gets function so dangerous that it should not be used?.
Your scanf("%s",...) is equally dangerous to using gets() as you don't limit the character to be read. Instead, you could re-format it as,
scanf("%199s", searchforthis); /* 199 characters + \0 to mark the end of the string */
Also check the return value of scanf() , in case an input error occurs, final code should look like this,
if (scanf("%199s", searchforthis) != 1)
{
exit(EXIT_FAILURE);
}
It is even better, if you use fgets() for this, though keep in mind that fgets() will also save the newline character in the buffer, you are going to have to strip it manually.
To actually perform checks on the file, you have to read the file line by line, by using a function like, fgets() or fscanf(), or POSIX getline() and then use strstr() on each line to determine if you have a match or not, something like this should work,
char *p;
char buff[500];
int flag = 0, lines = 1;
while (fgets(buff, sizeof(buff), fp) != NULL)
{
size_t len = strlen(buff); /* get the length of the string */
if (len > 0 && buff[len - 1] == '\n') /* check if the last character is the newline character */
{
buff[len - 1] = '\0'; /* place \0 in the place of \n */
}
p = strstr(buff, searchforthis);
if (p != NULL)
{
/* match - set flag to 1 */
flag = 1;
break;
}
}
if (flag == 0)
{
printf("This Value has not been found.\n");
}
else
{
printf("This Value was found in following file:\n%s", file_name);
}
flag is used to determine whether or not searchforthis exists in the file.
Side note, if the line contains more than 499 characters, you will need a larger buffer, or a different function, consider getline() for that case, or even a custom one reading character by character.
If you want to do this for multiple files, you have to place the whole process in a loop. For example,
for (int i = 0; i < 5; i++) /* this will execute 5 times */
{
printf("Enter name of a file you wish to check:\n");
...
}

My program creates a file named date.in but it is not inserting all the numbers

Write a C program that reads from the keyboard a natural number n
with up to 9 digits and creates the text file data.out containing the
number n and all its non-zero prefixes, in a single line, separated by
a space, in order decreasing in value. Example: for n = 10305 the data
file.out will contain the numbers: 10305 1030 103 10 1.
This is what I made:
#include <stdio.h>
int main()
{
int n;
FILE *fisier;
fisier=fopen("date.in","w");
printf("n= \n");
scanf("%d",&n);
fprintf(fisier,"%d",n);
while(n!=0)
{
fisier=fopen("date.in","r");
n=n/10;
fprintf(fisier,"%d",n);
}
fclose(fisier);
}
Few things:
Function calls may return error. You need to check that every time.
fisier=fopen("date.in","w");
This should have been followed by an error check. To understand more on what it return, first thing you should do is read the man page for that function. See man page for fopen(). If there is an error in opening the file, it will return NULL and errno is set to a value which indicates what error occurred.
if (NULL == fisier)
{
// Error handling code
;
}
Your next requirement is separating the numbers by a space. There isn't one. The following should do it.
fprintf(fisier, "%d ", n);
The next major problem is opening the file in a loop. Its like you are trying to open a door which is already open.
fisier=fopen("date.in","r");
if(NULL == fisier)
{
// Error handling code
;
}
while(n!=0)
{
n=n/10;
fprintf(fisier,"%d",n);
}
fclose(fisier);
A minor issue that you aren't checking is the number is not having more than 9 digits.
if(n > 999999999)
is apt after you get a number. If you want to deal with negative numbers as well, you can modify this condition the way you want.
In a nutshell, at least to start with, the program should be something similar to this:
#include <stdio.h>
// Need a buffer to read the file into it. 64 isn't a magic number.
// To print a 9 digit number followed by a white space and then a 8 digit number..
// and so on, you need little less than 64 bytes.
// I prefer keeping the memory aligned to multiples of 8.
char buffer[64];
int main(void)
{
size_t readBytes = 0;
int n = 0;
printf("\nEnter a number: ");
scanf("%d", &n);
// Open the file
FILE *pFile = fopen("date.in", "w+");
if(NULL == pFile)
{
// Prefer perror() instead of printf() for priting errors
perror("\nError: ");
return 0;
}
while(n != 0)
{
// Append to the file
fprintf(pFile, "%d ", n);
n = n / 10;
}
// Done, close the file
fclose(pFile);
printf("\nPrinting the file: ");
// Open the file
pFile = fopen("date.in", "r");
if(NULL == pFile)
{
// Prefer perror() instead of printf() for priting errors
perror("\nError: ");
return 0;
}
// Read the file
while((readBytes = fread(buffer, 1, sizeof buffer, pFile)) > 0)
{
// Preferably better way to print the contents of the file on stdout!
fwrite(buffer, 1, readBytes, stdout);
}
printf("\nExiting..\n\n");
return 0;
}
Remember: The person reading your code may not be aware of all the requirements, so comments are necessary. Secondly, I understand english to a decent level but I don't know what 'fisier' means. Its recommended to name variables in such a way that its easy to understand the purpose of the variable. For example, pFile is a pointer to a file. p in the variable immediately gives an idea that its a pointer.
Hope this helps!
To draw a conclusion from all the comments:
fopen returns a file handle when successfull and NULL otherwise. Opening a file twice might result in an error (it does on my machine), such that fisier is set to NULL inside the loop. Obvioulsy fprintf to NULL wont do anything.
You only need to call fopen once, so remove it from the loop. After that it will work as intended.
It's alwas good to check if the fopen succeeded or not:
FILE *fisier;
fisier=fopen("date.in","w");
if(!fisier) { /* handle error */ }
You print no spaces between the numbers. Maybe that's intended, but maybe
fprintf(fisier,"%d ",n);
would be better.

How to compare two text files in C and output the differences in a new text file

I am writing a program that inputs two text files
inputtxt1,
inputtxt2
and output
outputtxt file
In these two files information such as
input txt1
S00111111 5 6-Jul-19 09-Aug-19
S00800000 4 1-Jul-19 30-Aug-19
S00000000 1 1-Jul-19 30-Aug-19
input txt2
S00111111 3 6-Jul-19 09-Aug-19
S00222222 1 20-Jul-19 30-Aug-19
S00000000 1 1-Jul-19 30-Aug-19
I am writing a program to input these two txt files and output the differences in SQL queries and the values inside the bracket will change depends on the differences from these text files.
DELETE FROM TABLE WHERE TABLE=[] AND TABLE=[]
INSERT INTO TABLE (TABLE1,TABLE2,TABLE3,TABLE4) VALUES ([ ],[],'[2019-08-30] 00:00:00','[2019-07-01] 00:00:00');
DELETE FROM TABLE WHERE TABLE=[] AND TABLE=[4]
INSERT INTO TABLE (TABLE,TABLE) VALUES ([],[4]);
I wrote my draft in C so what I did id basically a while loop to read each of the line of the first file and each of the line of the second file and output the query.
Here are my two questions:
First it, unfortunately, output the file SQL 3 times, I think there is something wrong with my while loop.
Secondly, how would I make the program detect that specific character from specific line need to be printed in the query for example number 5 in the first line would detect and add to the value of one of the tables in the query.
/* This program will input two text files, output a text file with the differences*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
FILE *in1, *in2, *out;
int a, b;
void main (void)
{
int c;
char* singleline [33];
char* singleline2 [33];
in1 = fopen ("inputtest1.txt", "r"); /* reads from the first file */
in2 = fopen ("inputtest2.txt", "r"); /* reads from the second file */
out = fopen ("outputtest3", "w"); /* writes out put to this file */
// Menu //
printf ("TSC Support Program\n\n");
printf ("This program compare the two files and output the differences in SQL quries \n");
// if the file is empty or something went wrong!
if (in1 == NULL || in2 == NULL)
{
printf("********************Can Not Read File !**************************");
}
else
{
// Checking Every line in the first text file if it equals to the first line of the text file
while (!feof(in1)&&!feof(in2))
{
// a = getc(in1);
// b = getc(in2);
a = fgets(singleline, 33,in1);
b = fgets(singleline2, 33,in2);
if (a!=b)
{
printf("\n SQL will be printed\n");
fprintf (out,
"\n DELETE FROM BADGELINK WHERE BADGEKEY=[27] AND ACCLVLID=75"
"\nINSERT INTO BADGELINK (BADGEKEY,ACCLVLID,ACTIVATE,DEACTIVATE) VALUES ([27],75,'[2010-08-24] 00:00:00','[2010-12-17] 00:00:00'); \n"
"\n DELETE FROM BADGE WHERE BADGEKEY=[27] AND ISSUECODE=[75]"
"\nINSERT INTO BADGE (BADGEKEY,ISSUECODE) VALUES ([27],[1]);\n"
);
}
else
{
printf("Something went wrong");
}
}
}
fclose(in1);
fclose(in2);
fclose(out);
}
It prints the output 5 times
and then it says something went wrong. I am unsure what went wrong.
if (a != b) does not do what you think it is doing. Check strncmp() or memcmp() library functions.
But if you want to find out the first different character in two strings, the code below would do it for you.
Not tested properly, so take it as a quick prototype.
#include <stdio.h>
int strdiff(char *s1, char *s2){
char *p1 = s1;
while(*s1++ == *s2++)
;
if (s1 != s2)
return --s1-p1; /* we have s1++ in the while loop */
return -1;
}
int main(){
char *s1="S00111111 5 6-Jul-19 09-Aug-19";
char *s2="S00111111 3 6-Jul-19 09-Aug-19";
int i = strdiff(s1,s2);
printf("%d %c\n",i, s1[i]);
return 0;
}
Mind you, comparing two files line by line may turn out to be a bigger mission than it sounds if the two files you are comparing do not have exactly the same lines (with minor differences of course).

Return value 3221225725 while scanning two files

For input two files "cl-clean-history" and "cd-clean-history" of similar structure of:
"Lift Convergence"
"Iterations" "cl"
1 1.14094e+00
2 1.14094e+00
and
"Drag Convergence"
"Iterations" "cd"
1 0.14094e+00
2 0.14094e+00
I want to write a program to read the values in second columns in both files and compute its divisor.
My program code is:
#include <stdio.h>
#include <errno.h>
int main (void)
{
double max_cl_cd, cl_cd_temp;
int lines_file;
int tab_line;
double tab_scan_file[200000][4];
int ch=0;
FILE *result_search_cl;
FILE *result_search_cd;
max_cl_cd=0.0;
if((result_search_cl=fopen("cl-clean-history","r"))==NULL)
{
printf("Unable to open input file\n");
}
else
{
lines_file = 0;
FILE *result_search_cd = fopen("cd-clean-history", "r");
FILE *result_search_cl = fopen("cl-clean-history", "r");
while (EOF != (ch=getc(result_search_cd)))
if ('\n' == ch)
++lines_file;
printf("Number of lines in file: %d \n",lines_file);
for (tab_line=0;tab_line<=lines_file;tab_line++) {
fscanf(result_search_cd,"\n");
fscanf(result_search_cd,"\n");
fscanf(result_search_cd,"%d",&tab_scan_file[tab_line][0]);
fscanf(result_search_cd,"\t");
fscanf(result_search_cd,"%f",&tab_scan_file[tab_line][1]);
fscanf(result_search_cd,"\n");
fscanf(result_search_cl,"%d",&tab_scan_file[tab_line][2]);
fscanf(result_search_cl,"\t");
fscanf(result_search_cl,"%f",&tab_scan_file[tab_line][3]);
fscanf(result_search_cl,"\n");
cl_cd_temp=tab_scan_file[tab_line][3]/tab_scan_file[tab_line][1];
if (cl_cd_temp>max_cl_cd)
{
max_cl_cd=cl_cd_temp;
}
printf("%f %f\n",tab_scan_file[tab_line][0],tab_scan_file[tab_line][1]);
}
fclose(result_search_cd);
fclose(result_search_cl);
}
printf("%f %f\n",tab_scan_file[tab_line][0],tab_scan_file[tab_line][1]);
return 0;
}
In my opinion there is something bad in scanf lines, but I don't see what exactly is bad. The first two scans of "\n" are intented to jump two first lines in file. I know that the second option is to perform loop starting from third line (for(tab_line=3; etc.) The %d scans integer value in first column and %f scans float value in second column in both files. Unfortunately, while running in Dev C++ the process exits with return value 3221225725. I found on stackoverflow.com that this value means heap corruption. How to overcome this problem?
I think you should read the fscanf documentation again:
Anyway, fscanf accepts as a second argument a format, so something like "%d" (the one you have used some lines later). When you invoke
fscanf(result_search_cd,"\n");
"\n" is not an identifier. You should replace this line with something like
while (getc(result_search_cd) != "\n"); //Skip first line
while (getc(result_search_cd) != "\n"); //Skip second line

Making Input and Output files in C language according to the code?

This is a first formal C competition I am going through .In the last years paper they had- Specified something called aromatic number and told to find those .I wrote the code and it works well but I am not able to understand these instructions about input and output and how to code them in C for Windows.
I am aware about reading one letter from a file and writing it using fopen() and fprintf and fscanf. But these are letters written in different lines how to extract them as variables from in1.dat and print them in out1.dat?
Means I know
int main()
{
int n;
FILE *fptr;
if ((fptr=fopen("D:\\program.dat","r"))==NULL){
printf("Error! opening file");
exit(1); /* Program exits if file pointer returns NULL. */
}
fscanf(fptr,"%d",&n);
printf("Value of n=%d",n+n);
fclose(fptr);
getch();
}
Which scans the first value in the 1st line .But they ask for multiple lines(3 in sample input) how to do them?
fscanf(fptr,"%d",&n);
printf("Value of n=%d",n+n);
Instead do like this -
while(fscanf(fptr,"%d",&n))
{
printf("Value of n=%d",n+n); //But notice here with every iteration n will be over-written.
}
This will stop at the first conversion failure or end of the file.And then inside this loop you can write into output file .
Try Something Like This:
#include<stdio.h>
int main()
{
FILE *in,*out;
int num;
char line[512],aronum[20];
in = fopen("in.dat", "r");
out = fopen("out.dat","w");
fgets(line, 512, in); //to get number of test cases
sscanf (line, "%d",&num);
while((fgets(line, 512, in) != NULL) && (num--))
{
sscanf (line, "%s",&aronum);
fprintf(out,"%d",calc(aronum)); //use `calc` func to return int ans.
}
fclose(in);
fclose(out);
return 0;
}

Resources