I've been working on a program to read data from file into a program and print it:
Here is my code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *p;
int e;
float f;
static char a[50];
FILE *fp;
fp = fopen("new_input.txt", "r");
if (fp == NULL)
exit(0);
while (1)
{
p = fgets(a, 50, fp);
if (p == NULL)
break;
printf("%s", a);
printf("\n");
fscanf(fp, "%d", &e);
printf("%d", e);
printf("\n");
fscanf(fp, "%f", &f);
printf("%f", f);
printf("\n");
}
fclose(fp);
return 0;
}
Contents of file new_input.txt are:
Girik
12
19.98
Nikhil
13
90.89
On running on OnlineGdb however I get the following output:
Girik
12
19.980000
12
19.980000
khil
13
90.889999
Can someone explain the problem with my code?
I'm concerned about incomplete name "Nikhil" in output and printing of the value 12 and 19.99 twice.
Link to code:
https://onlinegdb.com/r1ufoP8-d
The problem arises because the last fscanf does not parse the \n, so when the cycle restarts the fgets will parse it and print it, naturally the next fscanf is not able to parse the string ("Nikhil", which was not parsed), because it expects an int, it's downhill from there, as the values are not parsed, what's printed is the old values of e and f from the previous cycle.
If you change your last fscanf so it parses the \n everything works fine:
Live demo
while (1)
{
p = fgets(a, 50, fp);
if (p == NULL)
break;
printf("%s", a);
fscanf(fp, "%d", &e);
printf("%d", e);
printf("\n");
fscanf(fp, "%f\n", &f); //<--here
printf("%.2f", f);//.2f specifier so it prints only 2 decimal places
printf("\n");
}
The pointer is also unnecessary you can use fgets itself as a condition i.e.:
while (fgets(a, sizeof a, fp)) //will read until the end of the file
{
printf("%s", a);
//... same code
}
Anyway, here is a version you can use that will render you the expected result and output, and, I would argue, is better:
Live demo
#include <stdio.h>
#include <stdlib.h>
int main()
{
int e;
float f;
static char a[50];
FILE *fp;
fp = fopen("new_input.txt", "r");
if (fp == NULL){
return EXIT_FAILURE;
}
// will parse until \n or 49 characters max (given the container size)
while (fscanf(fp, " %49[^\n]", a) > 0)
// ^ space - will discard any blank characters
{
printf("%s\n", a);
if(fscanf(fp, "%d", &e) > 0){
printf("%d\n", e);
}
if(fscanf(fp, "%f", &f) > 0){
printf("%.2f\n", f);
}
}
fclose(fp);
return EXIT_SUCCESS;
}
I also added the checks for the fscanf returns which is always a good practise.
Or even:
//...
while (fscanf(fp, " %49[^\n]%d%f", a, &e, &f) == 3)
{
printf("%s\n%d\n%.2f\n", a, e, f);
}
//...
However, the best solution, I believe, is to parse everything with fgets and convert the values with sscanf or strtol/strtof, it's a more robust option. Give it a try.
For "read data from file into a program and print it", you can use e.g. fgets or fscanf. Both uses are included in the following adaption of your example:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *p;
int e;
float f;
static char a[50];
FILE *fp;
// use fgets
printf("\nVersion with using fgets\n\n");
fp = fopen("new_input.txt", "r");
if (fp == NULL) exit(0);
while(fgets(a, 50, fp)!=NULL)
{
printf("%s", a);
}
fclose(fp);
// use fscanf
printf("\nVersion with using fscanf\n\n");
fp = fopen("new_input.txt", "r");
if (fp == NULL) exit(0);
while(fscanf(fp,"%s\n",a)!=EOF)
{
printf("%s\n", a);
}
fclose(fp);
return 0;
}
COMMENTS:
Size of a[50] needs to be larger than maximum line size.
You can also fscanf for numbers (if you are sure, that it is a number).
Check, if string is integer or float (locale) is a new topic.
Another option: With the assumption that you can rely on the format in "new_input.txt" (to account for the comment of Devolus).
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *p;
int g;
float f;
static char a[50];
FILE *fp;
fp = fopen("new_input.txt", "r");
if (fp == NULL) exit(0);
while(fscanf(fp,"%s\n",a)!=EOF){
printf("%s\n", a);
fscanf(fp,"%d\n",&g);
printf("%d\n", g);
fscanf(fp,"%f\n",&f);
printf("%f\n", f);
}
fclose(fp);
return 0;
}
Related
When i run my code, it returns "ERROR" in terminal. Basically fopen not work, and arq receive NULL. The "leitura.txt" is a file only to be read.
#include <stdio.h>
int main(){
FILE * arq = NULL;
char c;
int x;
arq = fopen( "leitura.txt", "r" );
if (arq == NULL){
printf ("ERROR\n");
exit(0);
}
while (fscanf(arq, "%c", &c) != EOF){
printf("%c", c);
}
x = ftell(arq);
printf("NUMBER OF BYTES: %d", x);
fclose(arq);
return 0;
}
You must include stdlib.h in your pre-compiler directives:
#include <stdio.h>
#include <stdlib.h> // missing library in your code
int main()
{
FILE *arq = NULL;
char c;
int x;
arq = fopen("leitura.txt", "r");
if (arq == NULL)
{
printf("ERROR\n");
exit(0);
}
while (fscanf(arq, "%c", &c) != EOF)
{
printf("%c", c);
}
x = ftell(arq);
printf("NUMBER OF BYTES: %d", x);
fclose(arq);
return 0;
}
In file I need to read some inputs:
this is an example:
8 15
[1,1] v=5 s=4#o
[4,2] v=1 s=9#x
typedef struct{
int red2;
int stupac2;
int visina;
int sirina;
char boja[10];
}Tunel;
FILE* fin = fopen("farbanje.txt", "r");
Tunel* tuneli = malloc(sizeof(Tunel)*50);
// if(fin!=0)
fscanf(fin,"%d %d", &r,&s);
printf("%d %d", r,s);
int p=0;
while (fscanf(fin, "[%d,%d]", &tuneli[p].red2, &tuneli[p].stupac2) == 2)
{
p++;
}
for(i=0;i<p;i++)
{
printf("[%d,%d]", tuneli[i].red2, tuneli[i].stupac2);
}
Problem is that it wont read me properly inputs from here: [1,1] v=5 s=4#o
Last line where i use printf shows some random numbers.
Agree it is better to use fgets
But if you want to continue to use your current approach,
#include <stdio.h>
#include <stdlib.h>
typedef struct{
int red2;
int stupac2;
int visina;
int sirina;
char boja[10];
}Tunel;
int main(){
int r, s, i;
FILE*fin=fopen("farbanje.txt", "r");
if(fin==NULL) {
printf("error reading file\n");
return 1;
}
Tunel *tuneli=(Tunel*)malloc(sizeof(Tunel)*50);
fscanf(fin,"%d %d\n", &r,&s);
printf("%d %d", r,s);
int p=0;
while (fscanf(fin, " [%d,%d]%*[^\n]", &tuneli[p].red2, &tuneli[p].stupac2) == 2)
{
p++;
}
fclose(fin);
for(i=0;i<p;i++)
{
printf("[%d,%d]", tuneli[i].red2, tuneli[i].stupac2);
}
}
Last line where i use printf shows some random numbers....
The random numbers you see are because the buffers to print were not properly populated yet.
This example shows how to read the file, using fgets() to read a line buffer, then use sscanf() to parse the first two values from the lines. (read in-code comments for a few other tips.)
int main(void)//minimum signature for main includes 'void'
{
int r = 0;
int s = 0;
char line[80] = {0};//{initializer for arrays}
int p = 0;
Tunel *tuneli = malloc(sizeof(*tuneli)*50);
if(tuneli)//always test return of malloc before using it
{
FILE *fin = fopen(".\\farbanje.txt", "r");
if(fin)//always test return of fopen before using it
{
fgets(line, sizeof(line), fin);
sscanf(line, "%d %d", &r, &s);
while(fgets(line, sizeof(line), fin))
{
sscanf(line, " [%d,%d]", &tuneli[p].red2, &tuneli[p].stupac2);
//note space ^ here to read only visible characters
printf("[%d,%d]\n", tuneli[p].red2, tuneli[p].stupac2);//content is now populated corretly
p++;
}
fclose(fin);//close when finished
}
free(tuneli);//free when done to prevent memory leaks
}
return 0;
}
I am trying to make a program that generates a string given user input, and then passes that string to a function that will change stdin to a dummy file, write the string to the file, use scanf on said file, then delete the file, but I'm having trouble redirecting stdin to the dummy file, any help on the best action that will only extend into the scope of the function?
int scan(const char* __restrict__ _format, ...){
FILE* original = stdin, *mod = calloc(1, sizeof(FILE));
mod = freopen("testFile.txt", "w+", stdin);
fputs(_format, stdin);
int a, b;
scanf("%d %d", &a, &b);
printf("%d, %d", a, b);
// freopen(orig)
return 1;
}
void swap(char* a, char* b) {
if (*a != ' ' && *b != ' ') {
char temp = *a;
*a = *b;
*b = temp;
}
}
void permiate(char* str, int start, int end){
int i;
if(start == end){
printf("%s\n", str);
}else{
for(i = start; i<=end; i++){
swap(str+start, str + i);
permiate(str, start + 1, end);
swap(str + start, str + i);
}
}
}
int main(){
int a, b;
char str[] = "1 3";
//function to put string to stdio
scan(str);
scanf("%d %d", &a, &b);
printf("%d, %d", a, b);
return 0;
}
after someone pointed out fscanf, a function i was never aware of becasue my teacher never covered it, i have found a working solution to the scan function:
int scan(const char* __restrict__ _format, ...){
int *a = malloc(sizeof(int)), i = 0;
FILE *fp1 = fopen("testfile.txt", "w");
fputs(_format, fp1);
freopen("testFile.txt", "r", fp1);
while(fscanf(fp1, "%d", &a[i]) != EOF){
i++;
a = realloc(a, sizeof(int)*i);
}
for(int j = 0; j < i; j++){
printf("%d, ", a[j]);
}
fclose(fp1);
return 1;
}
but whenever i give str a value like "1 2 3 4 5 6 ..." or anything that has more than 5 numbers, the 5th number is always 0 if i leave realloc in, if i comment that line out, then it is fine. any idea on what that is about? ps my labs at uni only got to basic uses of arrays, no dynamic memory or anything, so if im using anything wrong it would b greatly appriciated
Alright, I think I understand what you are attempting to do, and it is doable, but I certainly would not recommend it. Whenever you freopen() one of the standard streams, there is no portable way to restore the original standard stream. You can remove original from your function as it will not work. Also do not allocate for mod.
With that said, you can write your scan function as:
int scan(const char* __restrict__ format)
{
int a, b;
FILE *mod = freopen ("dat/freopenab.txt", "w", stdin);
if (!mod) {
perror ("freopen-mod-write");
return 0;
}
fputs (format, stdin); /* write to file as stdin */
stdin = freopen (NULL, "r", mod); /* reopen file "r" as stdin */
if (!stdin) {
perror ("freopen-stdin-read");
return 0;
}
if (scanf("%d %d", &a, &b) != 2) { /* read values from file */
fputs ("error: read of int values failed.\n", stderr);
return 0;
}
printf("%d, %d\n", a, b); /* output resutls */
return 1;
}
stdin is reopened as file "dat/freopenab.txt" above. The format string is written to the file via the reopened stdin. Then freopen() is called again with NULL as the pathname which allows you to change the mode of the existing stream mod to read and assign the return to stdin (making stdin read from the file)
(note: variable names with leading underscores are best avoided)
A full example would be:
#include <stdio.h>
int scan(const char* __restrict__ format)
{
int a, b;
FILE *mod = freopen ("dat/freopenab.txt", "w", stdin);
if (!mod) {
perror ("freopen-mod-write");
return 0;
}
fputs (format, stdin); /* write to file as stdin */
stdin = freopen (NULL, "r", mod); /* reopen file "r" as stdin */
if (!stdin) {
perror ("freopen-stdin-read");
return 0;
}
if (scanf("%d %d", &a, &b) != 2) { /* read values from file */
fputs ("error: read of int values failed.\n", stderr);
return 0;
}
printf("%d, %d\n", a, b); /* output resutls */
return 1;
}
int main (void) {
scan ("12 34\n");
}
Example Use/Output
$ ./bin/freopenab
12, 34
Resulting Output/Input File
$ cat dat/freopenab.txt
12 34
Again, there is no portable way to restore stdin to it original state, though on Linux you can look at using "/dev/tty" or "/dev/stdin". Look things over, and give it a try. Then avoid freopen() unless there is no other way to do what you need to do in favor of just using fopen, fclose, and fopen again.
//ok, thanks for help. i edited the code, passed a pointer and now the it prints the number from particular row, prints the number of that row, and prints the sum off all consiquent numbers. Good so far, but...
What i want do do next, is to assign each of the sums to an array, so i can use for loop to check whether the resulting sum equals to any previous resulting sums. i use tab[n]==result;
unfortunatelly after the while loop is done, all the array elements are empty...thanks//
include
include
int main()
{
int result =0;
read_ints("numbers.txt", &result);
}
void read_ints (const char* file_name, int *result)
{
FILE* file = fopen ("numbers.txt", "r");
int i = 0;
int n=1; //row number//
int tab[n]; //array
if (file == NULL)
{
printf("unable to open file %s", file_name);
}
fscanf (file, "%d", &i);
while (!feof (file))
{
printf ("%d ", i);
*result += i;
tab[n]==result;
printf("row number: %d \n", n);
n++;
printf("\n sum of this number and all numbers before is: %d\n", *result);
fscanf (file, "%d", &i);
}
printf("\nnumber from row number one is ... : %d\n", tab[1]);
fclose (file);
}
Your code is mostly right. You're just calling read_ints incorrectly. You should pass in a pointer to result if you want a value returned.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void read_ints (const char* file_name, int *result) {
FILE* file = fopen (file_name, "r");
int i = 0;
if (file == NULL) {
printf("unable to open file %s\n", file_name);
return;
}
fscanf (file, "%d", &i);
while (!feof (file))
{
printf ("%d ", i);
*result += i;
printf("\n suma tej liczby ze wszystkimi poprzednimi wynosi: %d\n", *result);
fscanf (file, "%d", &i);
}
fclose (file);
}
int main() {
int result =0;
read_ints("liczby.txt", &result);
}
the following proposed code:
properly checks for errors
properly passes the error text to stderr, including the text reason the system thinks the error occurred.
uses the returned value from fscanf() to control the loop
properly contains a 'prototype' for the sub function
properly uses void inside the parens of main() and the prototype of the sub function that receives no parameters.
consistently indents the code, for readability
cleanly compiles
documents why each header file is included
And now, the proposed code:
#include <stdio.h> // FILE, perror(), fopen(), printf(), fclose()
#include <stdlib.h> // exit(), EXIT_FAILURE
void read_ints ( void );
int main( void )
{
read_ints();
}
void read_ints ()
{
FILE* file = fopen ("liczby.txt", "r");
if( !file )
{
perror( "fopen to read liczby.txt failed" );
exit( EXIT_FAILURE );
}
int i = 0;
int result = 0;
while ( fscanf ( file, "%d", &i) == 1 )
{
printf ("%d ", i);
result=result+i;
printf("\n suma tej liczby ze wszystkimi poprzednimi wynosi: %d\n", result);
}
fclose (file);
}
//ok, the code looks better now, but still, the result values doesnt seem to store in the tab[] array. this is due to lack of a pointer or bad declaration of the array(?).
i intented it to be a dynamic array, so that i dont need to declare the specific size of the array.//
#include <stdio.h>
#include <stdlib.h>
void read_ints(const char* file_name, int *result);
int main()
{
int result =0;
read_ints("numbers.txt", &result);
}
void read_ints (const char* file_name, int *result)
{
FILE* file = fopen ("numbers.txt", "r");
int i = 0;
int n=0; //row number//
int m;
int tab[m]; //array//
if (file == NULL)
{
printf("unable to open file %s", file_name);
}
while ( fscanf (file, "%d", &i) ==1)
{
n++;
printf ("%d\n ", i);
*result += i;
printf("\n we are at row nr. %d sum of this number and all numbers before is: %d\n", n, *result);
tab[n]==*result;
}
printf("\nnumber from row number one is ... : %d\n", tab[1]); //this does not work properly //
fclose (file);
}
What I want to do for now is have an input text file, load its content into a 2d array, perform something on it and then put it out into another file. Essential problem for me is keeping the original files' structure. This is my code:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *ifp, *ofp;
char buffer[100];
int i, c;
ifp=fopen("test.in", "r");
ofp=fopen("test.out", "w");
while (!feof(ifp)){
if(fscanf(ifp, "%s", buffer) != 1)
break;
fprintf(ofp, "%s", buffer);
}
return 0;
}
my input:
aaa bb bbb
bbbbb bbbb aa
and output:
aaabbbbbbbbbbbbbbaa
Everything I tried for EOL or EOF recognition caused infinite loops. Performing anything with "%c" instead of "%s" resulted in worse outputs. Thanks in advance.
edit: I'm aware I can get the output to be words with spaces between them or have every word in a new line but I don't know how to get from here to final result.
Use "%c"
#include <stdio.h>
int main(void)
{
FILE *ifp, *ofp;
char buffer;
ifp=fopen("test.in", "r");
if(ifp==NULL)return 1;
ofp=fopen("test.out", "w");
if(ofp==NULL){
fclose(ifp);
return 1;
}
for(;;){
if(fscanf(ifp, "%c", &buffer) != 1)
break;
fprintf(ofp, "%c", buffer);
}
fclose(ifp);
fclose(ofp);
return 0;
}
or getc().
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *ifp, *ofp;
int buffer;
ifp=fopen("test.in", "r");
if(ifp==NULL)return 1;
ofp=fopen("test.out", "w");
if(ofp==NULL){
fclose(ifp);
return 1;
}
for(;;){
if((buffer = getc(ifp)) != EOF)
break;
putc(buffer, ofp);
}
fclose(ifp);
fclose(ofp);
return 0;
}
You won't neeed feof() because the functions used to read will detect EOF.
Also, don't forget to check if the files are successfully opened and to close the files opened.
Use getline function instead fscanf. Because fscanf can't read the full string which contain the space character
while ((read = getline(&line, &len, stream)) != -1)
{
printf("Retrieved line of length %zu :\n", read);
printf("%s", line);
}
See full detail about getline:
http://man7.org/linux/man-pages/man3/getline.3.html