C Programming File I/O - c

I'm trying to read from a text file and write to one, but every time I execute my code, nothing happens with the text files. By "nothing happens", I mean that the program won't read my input file and no data is exported into my output file. Could someone point out why it is not working? Thanks for any help given in advance. Here is my code:
#include <stdio.h>
#include <stdlib.h>
FILE *inptr, *outptr;
int main() {
int a, b, c;
inptr = fopen("trianglein.txt","r"); //Initialization of pointer and opening of file trianglein.txt
outptr = fopen("triangleout.txt","w"); //Initialization of pointer and opening of file triangleout.txt
while((fscanf(inptr,"%d %d %d",&a, &b, &c))!= EOF){
fprintf(outptr,"\n%2d %2d %2d\n",a,b,c);
if(a+b>c && b+c>a && c+a>b){
fprintf(outptr, "This is a triangle.\n");
if(a !=b && b !=c && a!=c){
fprintf(outptr, "This is a scalene triangle.\n");
if(a==b && a==c && c==b){
fprintf(outptr, "This is an equilateral triangle.\n");
if(a*a+b*b==c*c || b*b+c*c==a*a || a*a+c*c==b*b){
fprintf(outptr, "This is a right trianlge.\n");
}
}
}
}
}
return 0;
}
trianglein.txt contents:
10 12 15
2 3 7
3 4 5
6 9 5
6 6 6
6 8 10
7 7 9

Multiple problems.
Firstly, you need to check if inptr and outptr are valid by testing against NULL.
Secondly, fscanf can return either EOF, 0 or > 0.
If your input file doesn't contain valid input.
Also there are problems in that you can get 3 ints read successfull, or 2 ints or 1 and the value of a, b and c are only optionally set.
If no conversion took place on the input then the value of zero is returned in which case the while loop will exit.
Also bear in mind that with the scanf style functions this input will succeed and return the value of 1.
"1rubbish"
I think what you may want is something like the following:
// Somewhere near the top
#include <stderr.h>
// ... other includes
const char* inname = "trianglein.txt";
const char* outname = "triangleout.txt";
// Any other stuff
// Inside main...
// Initialization of pointer and opening of file trianglein.txt
if ((inptr = fopen(inname,"r")) == 0){
fprintf(stderr, "Error opening file %s: %s", inname, strerror(inname));
return -1;
}
// Initialization of pointer and opening of file triangleout.txt
if ((outptr = fopen(outname,"w")) == 0){
fprintf(stderr, "Error opening file %s: %s", outname, strerror(outname));
return -1;
}
int result;
while(true){
result = fscanf(inptr,"%d %d %d",&a, &b, &c);
if (result == EOF)
break;
if (result < 3) // Ignore incomplete lines
continue;
// do the normal stuff
}

Your program is working fine in my system. I use Code::Blocks 10.05 on Windows 7.
The only possibility of a logical error occurs when you have the file trianglein.txt with less than 3 integer values to be read by the fscanf(). For example trianglein.txt file with values 1, 1 2, 1 2 3 4, 1 2 3 4 5 etc. will give incorrect values to the variables b and/or c. So initialize a=-1, b=-1, c=-1 before the execution of each iteration of the loop and check them after reading.
If you are running the program check the file triangleout.txt for access rights. Some times you may not have write access on that particular file.
By the way the classification logic is wrong. An equilateral triangle can not be a right angled one.

Try putting
fclose(inptr);
and
fclose(outptr);
at the end of your code.

EDIT: As suggested by icktoofay, this answer is wrong.
You have to do fclose() or fflush() in order to get the data written to the file.
Insert these code right before return 0;
fclose(inptr);
fclose(outptr);

Related

Reading integers from a file in C using a while-loop and getw(f) != EOF

I pretty new to C, or well, very new to C. I'm trying to write integers to a file using putw(), and then I try to read them using getw(), I read them using a while loop until EOF. But the loop dies prematurely, and it seems to do so when getw() gets the integer 26 from the file. I'm at a complete loss.
Basically I want to printf the integers that I previously saved to the file, using putw(), every 7th iteration I print a new line. It works all the way until getw() encounters the integer 26, that kills the loop, even if it isnt EOF. No matter how many integers I have in the file, it works only until getw() encounters 26. I´ve tried using fscanf but didnt get that to work either. Please help a beginner.
void readfile() {
FILE *f;
f = fopen("INTEGERS.DAT", "r");
int num, xar=1;
if (f==NULL){
printf("NO file detected.\n");
exit(0);
} else {
while((num = getw(f)) != EOF) {
printf("%d ", num);
if ( xar % 7 == 0) {
printf("\n");
}
xar++;
}
}
fclose(f);
}
Thanks in advance.
You didn't indicate the format of your data file, but noting that you are opening the file with an "r" parameter, that would indicate that the data in the file is in a text format and not a binary format. So using that information and a bit of artistic license, I created a code snippet to build some text data with an integer value per line/record in a file, and then read the data in that file utilizing a tweaked version of your readfile function.
#include <stdio.h>
#include <stdlib.h>
void save_int(void)
{
int entry = 999;
FILE *fp;
fp = fopen("INTEGERS.DAT", "w");
if (fp != NULL)
{
while (1)
{
printf("Enter an integer or enter '0' to quit data entry: ");
scanf("%d", &entry);
if (entry == 0)
{
break;
}
fprintf(fp, "%d\n", entry);
}
}
fclose(fp);
return;
}
void readfile()
{
FILE *fp;
fp = fopen("INTEGERS.DAT", "r");
char number[16];
int value;
if (fp==NULL)
{
printf("NO file detected.\n");
exit(0);
}
else
{
while(1)
{
value = fscanf(fp, "%s", number);
if (value < 0)
{
break;
}
printf("%d ", atoi(number));
}
}
printf("\n");
fclose(fp);
}
int main()
{
save_int();
readfile();
return 0;
}
Some items to point out.
Each integer value is being written with a newline character to the text file, so that would be a caveat if your file actually is in a different format such as storing integers on the same line with some type of delimiter between the integer values.
In reading in the integer data from the created text file, fscanf is used for this task - you might get suggestions and other answers utilizing other functions such as fgets. There are pros and cons, so often it comes down to what is most familiar and comfortable to you.
Since the values were stored as string values, they are read in to a string and then converted to an integer utilizing the standard atoi function. Again, this is just a simple way to do this that I am familiar with. By all means, view any alternative answers you might get and/or comments added later to this answer.
With that, following is some sample output at the terminal.
#Dev:~/C_Programs/Console/Integers/bin/Release$ ./Integers
Enter an integer or enter '0' to quit data entry: 14
Enter an integer or enter '0' to quit data entry: 566
Enter an integer or enter '0' to quit data entry: 65335
Enter an integer or enter '0' to quit data entry: 122
Enter an integer or enter '0' to quit data entry: 18
Enter an integer or enter '0' to quit data entry: 0
14 566 65335 122 18
#Dev:~/C_Programs/Console/Integers/bin/Release$ cat INTEGERS.DAT
14
566
65335
122
18
Go ahead and test this out to see if it meets the spirit of your project.

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).

Format file to have 5 numbers per line

I am working on a text file containing integers separated by spaces, for instance:
1 2 57 99 8 14 22 36 98 445 1001 221 332 225 789 1111115 147 0 1 21321564 544 489 654 61266 5456 15 19
I would like to re-format this file to only contain 5 integers in any line but the last, and at most 5 integers in the last line.
My code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *f; // main file (A.txt)
FILE *g; // file copy (B.txt)
// open A.txt to read data
f = fopen("file/path/here/A.txt", "r");
if (f == NULL) {
printf("Read error.\n");
fclose(f);
return -1;
}
// open B.txt to write data
g = fopen("file/path/here/B.txt", "w");
if (g == NULL) {
printf("Write error.\n");
fclose(g);
return -2;
}
int line = 1; // first line in output file
while (!feof(f)) { // not end-of-file
char number[1000];
int i = 0;
for (i = 0; i <= 4; i++)
if (fscanf(f, "%s", number) == 1) { // one number read
fprintf(g, "%s", line + i, number);
}
line += i;
}
// close files
fclose(f);
fclose(g);
return 0;
}
When I run this in Code::Blocks, I get the 'Segmentation fault (core dumped) Process returned 139' message. I suspect that the problem lies in the 'if' statement and my use of formats. Needless to say, I'm relatively new to C. How might I fix this?
The simple reason for your segmentation fault is expression fprintf(g, "%s", line + i, number);, in which you state to pass a pointer to a string (i.e. char*), but actually pass a number (i.e. line + i); hence, the value of line + i, which is probably 1, ..., is interpreted as a pointer to memory address 1, which is not allowed to be addressed. It is as if you wrote fprintf(g, "%s", 1), which crashes, too;
So basically change this expression into fprintf(g, "%s", number);, and it should at least not crash (unless you have numbers with more than 999 digits).
There are some other issues in your code, e.g. that you open B.txt for write and assign it to g, but then you test and close the file using variable f.
But maybe above "crash solution" brings you forward, such that you can work further on your own. Note that - if B.txt failed opening, then your code would also have crashed because of passing NULL as file stream argument to fprintf.
The issue is with the use of fscanf and then fprintf.
fscanf knows how to parse a string into a number. E.g. fscanf(f, "%d", &var);. This reads a signed integer from the file handle f into the variable var. This can then be printed with fprintf.
As it stands, the first fscanf slurps the entire input into number (assuming that 1000 char is enough) and the following ones are not expected to be called

fscanf reads the last integer twice

I have the following simple program to read from a text file (num.txt). The text file has numbers 1 2 3 4 5 in each line. When I run the program, it prints 5 twice. Can anybody tell me why is this happening, and how to fix it? thanks in advance
int main(void)
{
int number;
FILE *file;
int i = 0;;
file = fopen("num.txt", "r");
while (!feof(file)){
fscanf(file, "%d", &number);
printf("%d\n", number);
}
return 0;
}
Here's my text file num.xtx
1
2
3
4
5
And here's the program output
1
2
3
4
5
5
There is an extra 5
From the man page of scanf family of functions,
The value EOF is returned if the end of input is reached before
either the first successful conversion or a matching failure occurs.
EOF is also returned if a read error occurs, in which case the error
indicator for the stream is set, and errno is set to indicate the
error.
This means that the last successful fscanf call reads the last line from the stream file after which the while loop condition !feof(file) is true because the end of file condition is not met yet. This means the loop is executed one extra time and the previous value of the variable number is printed again.
Please read this - while(!feof(file)) is always wrong
You should check the return value of scanf instead of checking the end of file indicator on the file stream.
#include <stdio.h>
int main(void) {
int number;
FILE *file = fopen("num.txt", "r");
// check file for NULL in case there
// is error in opening the file
if(file == NULL) {
printf("error in opening file\n");
return 1;
}
// check if fscanf call is successful
// by checking its return value for 1.
// fscanf returns the number of input
// items successfully matched and assigned
while(fscanf(file, "%d", &number) == 1)
printf("%d\n", number);
return 0;
}
The second time fscanf failed and didn't write anything to number, that's why it's still 5 from the last time. To know if fscanf succeeded, you have to check its return value.
fscanf returns the number of arguments that it wrote. In your case, if it returns 1, it worked; if it returns 0, it didn't. This is what you should check instead of feof.
while (fscanf(file, "%d", &number) == 1)
{
printf("%d\n", number);
}

Resources