how to read multiple lines of a file in c - c

Am trying to read a file which contains the coordinate values for my code. each time i use scanf it reads only the first line...(60,70,200,200). my question is how do i make my code read all the contents of my file and print it out on the screen.here is my code and file.
FILE.txt:
S (60,70)(200,200)
S (30,40)(100,200)
S (10,20)(80,10)
S (60,400)(700,200)
S (160,70)(240,20)
MY CODE:
#include <stdio.h>
int a;
int b;
int c;
int d;
int data[4][5];
int main ( int argc, char *argv[] )
{
if ( argc != 2 ) /* argc should be 2 for correct execution */
{
/* We print argv[0] assuming it is the program name */
printf( "usage: %s filename", argv[0] );
}
else
{
// We assume argv[1] is a filename to open
FILE *file = fopen( argv[1], "r" );
/* fopen returns 0, the NULL pointer, on failure */
if ( file == 0 )
{
printf( "Could not open file\n" );
}
else
{
int i,j;
for (j=0; j < 5; j++)
{
for (i=0; i < 4; i++) {
fscanf(file, "S (%d,%d)(%d,%d)", &a, &b, &c, &d);
data[i][j] = (a, b, c, d);
printf("%d,%d,%d,%d\n",a, b, c, d);
}
}
fclose( file );
}
}
}

You must check the return value of I/O calls such as fscanf(). If it's failing, it will return 0 without changing your variables.
Also, this:
data[i][j] = (a, b, c, d);
Doesn't make a lot of sense in C. Remember that C doesn't have tuples like Python. The above is equivalent to:
data[i][j] = d;

Use while loop:
const int NumberOfValuesIamGoingToReadAtOnce = 4;
while (fscanf(file, "S (%d,%d)(%d,%d)", &a, &b, &c, &d) == NumberOfValuesIamGoingToReadAtOnce)
{
// do some actions with obtained values
}
as fscanf returns number of read values by return value you can judge if EOF achieved or file wrongly written

Try reading the newline as well:
fscanf(file, "S (%d,%d)(%d,%d)\n", &a, &b, &c, &d);
But why the double loop: you're already reading 4 values at the same time.
Instead, make it one infinite loop and check whether you've read 4 values; break when you did not read 4 values.
Lastly:
data[i][j] = (a, b, c, d);
does not make any sense (as any decent compiler warning will tell you). This, instead, may be where you want your second loop: around the assignement, not the scanf statement.

declar data[4][5] to data[5][4]
modify the loop
for (i=0; i < 5; i++)
{
fscanf(file, "S (%d,%d)(%d,%d)", &a, &b, &c, &d);
data[i][0] =a;
data[i][1] =b;
data[i][2] =c;
data[i][3] =d;
printf("%d,%d,%d,%d\n",a, b, c, d);
}

If you are going to fscanf(), you have to careful as you have to make sure the file is in correct format with exact number of spaces like how read in fscanf().
I would recommend using fgets() then reading numbers from the string using sscanf().
data[i][j] = (a, b, c, d);
This line doesn't do what you think it does. You really don't need another loop as you read all numbers in a line at once.
for (j=0; j < 5; j++)
{
fscanf(file, "S (%d,%d)(%d,%d)", &a, &b, &c, &d);
data[j][0] = a;
data[j][1] = b;
data[j][2] = c;
data[j][3] = d;
printf("%d,%d,%d,%d\n",a, b, c, d);
}
}
And change data[4][5] to data[5][4];

I used fgets to read file line per line and I used sscanf instead of fscanf
#include <stdio.h>
#include <string.h>
int data[4][5];
char line[128];
int main ( int argc, char *argv[] )
{
if ( argc != 2 ) /* argc should be 2 for correct execution */
{
/* We print argv[0] assuming it is the program name */
printf( "usage: %s filename", argv[0] );
}
else
{
// We assume argv[1] is a filename to open
FILE *file = fopen( argv[1], "r" );
/* fopen returns 0, the NULL pointer, on failure */
if ( file == 0 )
{
printf( "Could not open file\n" );
}
else
{
int i=0;
line[0] = 0;
while(fgets(line,sizeof(line),file))
{
sscanf(line, "S (%d,%d)(%d,%d)", &data[i][0], &data[i][1], &data[i][2], &data[i][3]);
printf("%d,%d,%d,%d\n", data[i][0], data[i][1], data[i][2], data[i][3]);
i++;
}
fclose( file );
}
}
}

Related

How to read data from a text file and store it in a variable in C language?

I am trying to read a text file in C. The name of the file is test.txt and has the following kind of format.
Nx = 2
Ny = 4
T = 10
I have written this C code to read the values of Nx, Ny, and T which is 2, 4, and 10 respectively.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{
double Data[3]; // I'm interested in this information
char junk1, junk2; // junk variables to avoid first two characters
FILE * file = fopen("test.txt", "r"); // open file
for(int i = 0; i < 3; i++) // each loop will read new line of file; i<3 for 3 lines in file
{
fscanf(file, "%s %s %lf\n", &junk1, &junk2, &Data[i]); //store info in Data array
printf("%f\n", Data[i]); // print Data, just to check
}
fclose(file);
int Nx; // store data in respective variables
int Ny;
double T;
Nx = Data[0];
Ny = Data[1];
T = Data[2];
printf("Value of Nx is %d\n", Nx); // Print values to check
printf("Value of Ny is %d\n", Ny);
printf("Value of T is %f\n", T);
}
But got this as an output. This output is wrong as the values of Nx, Ny, and T are not matching with the data given above.
Please help me to solve this problem.
junk1 and junk2 should be arrays of char to be able to store strings.
But since it is junk you could simply not store it anywhere by using * in the fscanf conversion specifiers:
fscanf(file, "%*s %*s %lf\n", &Data[i]);
fscanf documentation:
https://en.cppreference.com/w/c/io/fscanf
Your program makes strong assumptions about the input file:
the file "test.txt" exists in the current directory and can be read
it contains at least 3 settings, in the order Nx, Ny, T.
It has problems too:
reading a string with %s into a single character variable junk1 will cause undefined behavior, same for junk2, because fscanf() will attempt to store all characters from the string plus a null terminator at the destination address, overwriting other data with potentially catastrophic consequences.
main has a return type int.
Here is a more generic approach:
#include <stdio.h>
#include <string.h>
int main() {
int Nx = 0, Ny = 0;
double T = 0;
int has_Nx = 0, has_Ny = 0, has_T = 0;
char buf[80];
FILE *file;
if ((file = fopen("test.txt", "r")) == NULL) {
fprintf(stderr, "cannot open test.txt\n");
return 1;
}
while (fgets(buf, sizeof buf, file)) {
if (buf[strspn(buf, " ")] == '\n') /* accept blank lines */
continue;
if (sscanf(buf, " Nx = %d", &Nx) == 1)
has_Nx = 1;
else
if (sscanf(buf, " Ny = %d", &Ny) == 1)
has_Ny = 1;
else
if (sscanf(buf, " T = %lf", &T) == 1)
has_T = 1;
else
fprintf(stderr, "invalid line: %s", buf);
}
fclose(file);
// Print values to check
if (has_Nx)
printf("Value of Nx is %d\n", Nx);
if (has_Ny)
printf("Value of Ny is %d\n", Ny);
if (has_T)
printf("Value of T is %g\n", T);
return 0;
}

What happens if characters are assigned into int variables in C

I am trying to get a integer value from argv[1].
I want to know what happens if the user inputs a character so that I can avoid it. I tried '\0' and currently this doesn't work.
int main(int argc, char* argv[]){
int MAX_SIZE;
MAX_SIZE=atoi(argv[1]);
while(MAX_SIZE=='\0'){
printf("plz input in correct format: ");
scanf("%d", &MAX_SIZE);}
Any help would be appreciated.
Your code is a bit weird but from what I understand you want to check if a character is a number or not, for that you can use the function isdigit() to check if the entered value is a number or not, something like this:
char c='a';
if(isdigit(c)) //if true, i.e. it returns non-zero value
cout<<"number";
else // if false, i.e. it returns zero
cout<<"Char";
I have written C++ code as I am more comfortable in C++ but the function isdigit() works in both C and C++.
# include <stdio.h>
# include <stdlib.h>
int main ( int argc, char *argv[] )
{
int i, n, a;
printf("\n argv[0] = %s\n", argv[0] );
if ( argc <= 1 )
{
printf("\n");
printf(" argc = %d, no arguments given on command line\n", argc );
printf("\n");
}
for ( i = 1; i < argc; i++ )
{
n = sscanf( argv[i], "%d", &a );
if ( n == 1 )
{
printf(" read %d off command line in argv[%d]\n", a, i );
}
else
{
printf(" sscanf failed, n = %d, argv[%d] = %s\n", n, i, argv[i] );
}
}
return 0;
}

Reading combinations of string and integer from file in C

I am novice to C langugage, so please bear with me. I've tried to read a file which contains strings but output obtained is single character.
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define CALLOC(num, type) ((char*)calloc (num, sizeof(char)))
#define FREE(addr) (free((void*) (addr)))
int i, count;
char *x, *y, *z;
int main (void)
{
FILE *stream;
if ( (stream = fopen ( "test.txt", "r" )) == NULL )
{ printf ("Cannot read the new file\n");
exit (1);
}
count = 3;
x=CALLOC(count, char);
y=CALLOC(count, char);
z=CALLOC(count, char);
for ( i=0; i<count; i++ )
{ fscanf (stream,"%c %c %c", &x[i], &y[i], &z[i]);
printf ("\n %d %c %c %c ", i, x[i], y[i], z[i]);
}
FREE(x);
FREE(y);
FREE(z);
fclose (stream);
}
Input test.txt file contains
1 ab 1
2 aa 5
1 cc 1
current output
0 1 a b
1 1 2
2 a a
Expected output
0 1 ab 1
1 2 aa 5
2 1 cc 1
I doubt whether I should use a character array but it seems not working and I feel reading a int using char is acceptable. Here I require the expected output, for this any method/suggestion is appreciated.
%c reads in only one char. So it's not going to read ab as a single char. Your lines in file and your formats don't correctly to read an entire line.
A simple approach is to use fgets() and print the entire line:
char line[256];
i = 0;
while(fgets(line, sizeof line, stream))
{
printf ("%d %s", i, line);
i++;
}
By the way, macros for calloc and free are unnecessary. They really don't make the code any easier to read than directly using those functions.
And the casts in them are also unnecessary.
The problem is you have the scan file. %c read a 8bit value. You scanned 3 char, but the file is contain 4 characters. If you don't use to be the value of the x, y, z I don't understand why use malloc.
Here a working source:
#include <stdio.h>
#include <stdlib.h>
int main() {
int count,i;
char w,x,y,z;
FILE *stream;
if((stream = fopen("test.txt","r")) == NULL) {
printf("Cannot read the new file\n");
return 1;
}
count = 3;
for(i=0;i<count;++i) {
fscanf(stream,"%c %c%c %c\n",&w,&x,&y,&z);
printf("%d %c %c%c %c\n",i,w,x,y,z);
}
return 0;
}
for ( i=0;i<count; i++ )
{
fscanf (stream,"%s %s %s", x, y, z);
printf ("\n %d %s %s %s ", i, x, y, z);
}
You can modify your loop to this.This loop will read file until end of file and you have to use %s as ab is a string not charater so it can't be stored in a char variable.

fscanf can't read the first integer of my file input in C but reads the rest

My program needs to read input from a file. The file has a format "int int int" and then some asterisks to indicate that you need to stop reading there. I want to store them in an array of struct and I did. But it seems like my program can't read the very first integer of the input file. I checked it with printf and I can't do anything about it. Help please. Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct points{
int i;
int x;
int y;
};
int main(){
int lines = 0;
char c, e;
int i, j, x ,y, a, b, temp ;
FILE *fp;
fp = fopen("input.txt", "r");
if (fp != NULL){
while ((e = fgetc(fp)) != '*'){
if (c == '\n'){
lines++;
}
fscanf(fp, "%d%d%d", &i, &x, &y);
struct points pt[lines];
for (j = 0; j <= lines; j++){
pt[j].i = i;
pt[j].x = x;
pt[j].y = y;
printf("%d ", pt[j].i);
}
for (a = 0; a<=lines; a++){
for (b = a + 1; b <= lines; b++){
if (pt[a].x > pt[b].x){
temp = pt[a].x;
pt[a].x = pt[b].x;
pt[b].x = temp;
}
}
}
}
}
else{
printf("Cannot open File!\n");
}
printf("lines = %d\n", lines);
return 0;
}
Your code:
while ((e = fgetc(fp)) != '*') {
if (c == '\n'){
lines++;
}
fscanf(fp, "%d%d%d", &i, &x, &y);
will read the first character and throw it away if it is NOT an asterisk, and will then attempt to read 3 integers AFTER that first character it threw away. If that first character was a digit, then it will look like you 'lost' (part of) the first number.
You also have the problem that you seem to be trying to read the values into a block-local array pt that exists for a single iteration of the while loop (so its recreated with no (garbage) contents each iteration), and then you want to use it after the loop where it is out of scope (so this code won't compile).
What you want is probably something more like:
#define MAX_POINTS 100
struct points pt[MAX_POINTS];
int i = 0;
while (i < MAX_POINTS && 3 == fscanf(fp, "%d%d%d", &pt[i].i, &pt[i].x, &pt[i].y)) {
printf("%d ", pt[i].i);
i++;
}
for (int a = 0; a <= i; a++) {
for (int b = a+1; b <= i; b++) {
:
Note that this reads integers up until it finds something that doesn't look like an integer (such as an asterisk, but could be anything else, including an end-of-file), rather than reading until it finds an asterisk. If you want to read until you see an asterisk, you need to decide what to do with anything that is neither an asterisk or an integer.
Edit
for your alternate question of how to read numbers up to *** and then read more numbers after them (and possibly more stars), you could use something like:
int val;
char buffer[20];
do {
/* start of a group */
while (1 == fscanf(fp, "%d", &val)) {
/* read an integer within a group */
}
/* fp is at EOF or something not an integer. */
/* so read it and loop if its '***' */
} while (1 == fscanf(" %19[*]", &buf) && !strcmp(buf, "***"));
Have you tried using the format string "%d %d %d" instead of "%d%d%d" (i.e. with spaces)?
Also, there are several other problems I see:
You use a while loop to find the first '*' in the line, but then you ask fscanf to parse 3 ints starting at that location. It may not be able to find an int by looking at a '*'...
You also declare the variable struct points pt[lines]; in the middle of a block; that is not valid C syntax.
Once you fix these things, the problem may be fixed.

C Read until end of file

I currently have code that reads 4 lines and I want to be able to change that until EOF or my MAX const int value. I can not get the !EOF to work right and was wondering how would I change my code to accomplish this?
Thanks in advance
#include <stdio.h>
struct record{
char name[2];
int arrival_time;
int job_length;
int job_priority;
};
const int MAX = 40;
int main(void)
{
struct record jobs[MAX];
int i = 0;
int j;
FILE *f = fopen("data.dat","rb");
while (fscanf(f, "%s %d %d %d", &jobs[i].name, &jobs[i].arrival_time,
&jobs[i].job_length, &jobs[i].job_priority) == 4 && i < MAX)
i++;
for (j = 0; j < i; j++)
printf("%s %d %d %d\n", jobs[j].name, jobs[j].arrival_time,
jobs[j].job_length, jobs[j].job_priority);
fclose(f);
return(0);
}
Something like
while (fscanf(f, " %s ", &etc) != EOF) {
}
Then use feof(f) to check if it was a fscanf error or actually EOF.
Your code seems to do what you want, except:
char name[2];
Names will probably be longer than 1 character.
FILE *f = fopen("data.dat","rb");
You seem to be reading text ("r") file, not binary ("rb").
&jobs[i].name should be jobs[i].name
You need to change the order of the tests in your while() loop - you must test i < MAX before calling fscanf(), or else you'll potentially call it one too many times (you should also be passing jobs[i].name without the & to fscanf):
while (i < MAX && fscanf(f, "%s %d %d %d", jobs[i].name, &jobs[i].arrival_time,
&jobs[i].job_length, &jobs[i].job_priority) == 4)
Personnaly, I would code like this:
for(i=0 ; i<MAX ; ++i) {
fscanf(f, "%s %d %d %d", &jobs[i].name, &jobs[i].arrival_time,
&jobs[i].job_length, &jobs[i].job_priority);
if(ferror(f) || feof(f)) break;
}
The key point is that, at the best of my knowledge, you cannot know that a file is come to end without trying to read it. That is the reason why I check feof() and ferror() after having read data.
At the end of the loop, the variable i contains the number of read data

Resources