I am trying to read this input txt file with my C code:
4 3
1.4 4.6 1
1.6 6.65 1
7.8 1.45 0
7 -2 2
and separate them into rows and columns so that I can sort. I tried doing that but I kept getting weird numbers.
So I tried printing out the rows and columns after I read them from the file and the output was zero. I realized then that my code is not reading the numbers from my text file properly. I have tried different means to fix to no avail. Any help or pointers will be highly appreciated.
#include <stdio.h>
#include <string.h>
#include <stdbool.h> //for bool
int main(){
setvbuf(stdout, NULL,_IONBF, 0);
int c;
FILE *file;
FILE *infile;
char filename[99];
char choice;
int rows, columns;
//while(choice == 'y' || choice == 'Y'){
printf("%s", "Enter file name: ");
fgets(filename, 99, stdin);
char *p = strchr(filename, '\n'); // p will point to the newline in filename
if(p) *p = 0;
file = fopen(filename, "r");
if (file) {
while ((c = getc(file)) != EOF)
putchar(c);
fclose(file);
}
else{
puts("FILE NOT FOUND");
}
//read rows and columns from file
printf("%s","\n");
fscanf(file, "%d", &rows);
fscanf(file, "%d", &columns);
printf("%d", rows);
printf("%d", columns);
}
Problem 1
int rows = 0;
int columns = 0;
float matrix[rows][columns];
float sumOfRows[rows];
is not right.
After that, the number of elements in matrix and sumOfRows is fixed. They won't change if you change the values of rows and columns later in your program.
You need to read the values of rows and columns first before you define matrix and sumOfRows.
Problem 2
fscanf(file, "%d", &matrix[rows][columns]);
printf("%f",matrix[rows][columns]);
are not right either. Given the defition of matrix, use of matrix[rows][columns] is not right. They access the array using out of bounds indices.
Remember that given an array of size N, the valid indices are 0 to N-1.
Here's one way to proceed to resolve your problems:
fscanf(file, "%d", &rows); // Use %d, not %f
fscanf(file, "%d", &columns); // Use %d, not %f
// Now define the arrays.
float matrix[rows][columns];
float sumOfRows[rows];
// Read the data of matrix
for (int i = 0; i < rows; ++i )
{
for (int j = 0; j < columns; ++j )
{
fscanf(file, "%f", &matrix[i][j]); // Use %f, not %d
}
}
Your problem (actually, two problems) are in the if (file) {... block. First, you use a loop to read all characters from the file. Because of that, at the end of the loop you are also at the end of the file. Any further calls to fscanf result in undefined behavior.
Second, if the file did not open, you print a message (to the wrong output) and still continue to the fscanf part, which definitely leads to undefined behavior.
Solution: Remove the while loop and fix the error handling code:
if(file) {
// Nothing!
} else {
perror(filename);
return 1; // or return EXIT_FAILURE;
}
Related
In C, there are many posts concerning using fgetc after fscanf, dealing with an additional \n, but I am seeing another issue when using them in the reverse order; fscanf after fgetc.
When using fscanf after fgetc, I get a different fscanf-result to if I just omit fgetc (in the example script, just hard-coding num=1000 and commenting-out the block using fgetc).
I can replicate this correct fscanf-result while still using fgetc if I rewrite the file contents to the myFile variable, as in the below script. Removing this line produces the different incorrect fscanf-result.
What is causing the difference in the fscanf-result when using fgetc first, and how can I address the issue?
/* First read tab-delimited 4-digit int data from a text file,
* parsing into an array of the correct size num, then compute
* the mean of the array while avoiding overflow. */
#include <stdio.h>
#include <stdlib.h>
int main(){
FILE *myFile;
myFile = fopen("int_values.txt", "r");
int c=0, i=0;
float mean = 0.0;
// Identifying there are 1000 values in the tab-delimited file.
// Using fgetc
int num = 1;
while ((c=fgetc(myFile)) != EOF ){
if (c == '\t')
++num;
}
int arr[num]; // Array of correct size for all values from file.
// Redeclaring since fgetc seems to break fscanf
myFile = fopen("int_values.txt", "r");
// Read and store each value from file to array.
for (i=0; i<num; i++){
fscanf(myFile, "%d ", &arr[i]);
}
// Compute average cumulatively to avoid overflow.
mean = arr[0]
for (i=1; i<num; i++){
//printf("In the %dth place, arr has value %d.\n", i, arr[i]);
mean *= (float)i / (float)(i+1);
mean += arr[i] / (float)(i+1);
}
fclose(myFile);
printf("The overall mean of the %d values in the file is %f.\n\n", num, mean);
return 0;
}
Identifying there are 1000 values in the tab-delimited file.
Do not count tabs. Instead, read the ints. It's far too easy for the number of tabs to not relate correctly to the number of int.
Sum the int into a long long to avoid overflow. Use double for generic floating-point math.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
FILE *myFile = fopen("seal_weights.txt", "r");
if (myFile) {
int num = 0;
long long sum = 0;
int value;
// return 1 on success, EOF on end-of-file, else 0 on non-numeric input
while (fscanf(myFile, "%d", &value) == 1) {
sum += value;
num++;
}
double mean = num ? (double) sum / num : 0.0;
printf("The overall mean of the %d values in the file is %f.\n\n", num,
mean);
// read in again and save values if truly desired.
// This step not needed to compute average.
rewind(myFile);
int i;
int arr[num];
for (i = 0; i < num; i++) {
if (fscanf(myFile, "%d", &arr[i]) != 1) {
break;
}
}
// Use arr[] in some way.
fclose(myFile);
}
return 0;
}
My code is to find line number and then print all element in it but it is throwing garbage value and main thing to do is to seperate front one as x and y respectively plese help me seperate x[] = [60,15,62.....] and y[] = [229,221,59,....]
Dataset is
60,229
15,221
62,59
96,120
16,97
41,290
52,206
...
#include <stdio.h>
#include <stdlib.h>
int main(){
FILE *myFile;
myFile = fopen("datasetLR1.txt", "r");
int count=0;
char c;
for (c = getc(myFile); c != EOF; c = getc(myFile)) {
if (c == '\n'){
count = count + 1;
}// Increment count if this character is newline
}
int numberArray[count*2];
int i;
if (myFile == NULL){
printf("Error Reading File\n");
exit (0);
}
for (i = 0; i < count*2; i++){
fscanf(myFile, "%d,", &numberArray[i] );
}
for (i = 0; i < count*2; i++){
printf("Number is: %d\n\n", numberArray[i]);
}
fclose(myFile);
return 0;
}
After you count the number of lines in the file with your first for loop, you should use rewind(myFile);. This puts you back to the beginning of the file. Without this, you are reading off the end of the file, which is producing the garbage values. Other than that, your code works fine.
You should also look at doing fscanf("%d,%d\n", &x, &y);, which should read off both numbers at once (and the newline) and assign them to x and y respectively. This should simplify your code significantly, however, your code works fine without it.
i have a file like that :
1 100
2 200
3 300
4 400
1
i want to save it as a matrix and i want to save NULL if there is no second number !
i tried to write the program but it does not work correctly !
#include<stdio.h>
int main() {
int k=0 ,i,j , arr[100][100];
FILE *in= fopen("file.txt","r");
char line[1000];
while(fgets(line,1000,in) !=NULL) k++;
fgets(line,1000,in);
for (i=0;i<k;i++){
for (j=0;j<2;j++){
int tmp ;
fscanf(in ,"%d", &tmp) ;
arr[i][j] = tmp ;
}
}
fclose(in);
return 0; }
Two major problems:
The first is that the first loop will read all lines, even the one with the single number on the line. That means the lonely fgets call will not do anything, and more importantly that the value of k will be wrong.
The second problem is that once you read all data from the file, you don't go back to the beginning of the file, instead you continue to try and read from beyond the end of the file.
The first problem can be solve by skipping the second fgets call, and decreasing k by one.
The second problem can be solved by calling rewind after you counted the number of lines.
Also when you actually read the numbers, you don't need the inner loop, just do e.g.
scanf("%d %d", &arr[i][0], &arr[i][1]);
Actually, you don't need the first line-counting loop at all, you can do it all in a single loop, by using fgets and sscanf and then checking the return value of sscanf. So your program could look something like
#include <stdio.h>
int main(void)
{
int values[100][2];
FILE *input = fopen("file.txt", "r");
size_t entries = 0;
if (input != NULL)
{
char buffer[40];
while (fgets(buffer, sizeof(buffer), input) != NULL && entries < 100)
{
int res = sscanf(buffer, "%d %d", &values[entries][0], &values[entries][1]);
if (res <= 1 || res == EOF)
{
// Read the last line with only one number, or an error happened
values[entries][0] = 0;
values[entries][1] = 0;
break;
}
++entries;
}
if (ferror(input))
{
printf("Error reading file\n");
}
fclose(input);
}
// All done, the number of "records" or "entries" is in the variable entries
// Example code: print the values
for (size_t i = 0; i < entries; ++i)
printf("Line %d: %d %d\n", i + 1, values[i][0], values[i][1]);
return 0;
}
So for a recent USACO problem, the user had to read in a file with Row Col, for the first line, and then following that, lines with a series of either #'s or .'s . When using C to try this, I find that my array that stores the contents of the file is ending prematurely, midway through the 4th row of a 5 row file. There are no errors when executing.
#include <stdio.h>
int main()
{
FILE *fin = fopen("crosswords.in", "r");
FILE *fout = fopen("crosswords.out","w");
int N, M;
fscanf(fin,"%d %d", &N, &M);
int arr[N][M];
char c;
int i,j;
for (i = 0; i < N;i++) {
for (j = 0; j < M; j++) {
fscanf(fin,"%c", &c);
arr[i][j] = c;
printf("%c", c);
}
}
return 0;
}
That is the code. The file is:
5 3
...
#..
...
..#
.##
The output is:
...
#..
...
..
The first line is a newline, but the code block doesnt show it
Why does the code stop early?
EDITS:
When I print N and M, I get 5 and 3
I am using a 2d array because you have to perform calculations based on the position. The problem is: http://usaco.org/index.php?page=viewproblem2&cpid=488.
I also don't know how to respond to comments
\n is also a char and is read by fscanf. To skip \n try this:
fscanf(fin," %c", &c);
// ^A space before %c can skip any number of white-spaces
and use a printf("\n"); statement after the inner loop.
I've got a file which I need to store in a 2-D array so I can perform matrix operations on it. All I know is that the doubles will be separated by spaces and line breaks, e.g:
2.04 3.0 4.0
5.0 6.1 7.0
8.0 9.03 10.0
I won't know how many numbers there will be, so I need a scalable parsing function. So far I have:
int main(int argc, char* argv[])
{
FILE *fp;
char ch;
fp = fopen("matrix.dat","r");
if ( fp == NULL )
{
puts ( "Cannot open source file");
}
/*count the number of lines*/
int lines=1;
char c;
while((c = fgetc(fp)) != EOF)
{
if(c == '\n')
lines++;
}
printf("lines= %i\n",lines);
/*reopen the file to reset the pointer*/
fclose(fp);
fp = fopen("matrix.dat","r");
double m[lines][lines];
/*Load file into array*/
int i,j;
for(i=0;i<lines;i++)
{
for(j=0;j<lines;j++)
{
fscanf( fp, "%lf", &(m[i][j]));
}
fscanf(fp, "\n", NULL);
}
/*print out stored matrix*/
for(i=0;i<lines;i++)
{
for(j=0;j<lines;j++)
{
printf("%lf ",m[i][j]);
}
printf("\n");
}
}
My issues with this method are
It makes the assumption that the number of rows equals the number of doubles per line, which may not be true.**
Any missing doubles in the file will cause the program to load the wrong matrix into memory (remaining values offset by 1).
I'm currently loading the file into memory twice to count the lines.
Is there a more sensible way to input this data into a 2D array? I need to ensure that the input matrix is square and that my program can handle a square matrix of any order. I'm quite new to C, so examples and naming functions will be much appreciated :) (Apologies for the dodgy indenting)
** Sorry for being so vague, I wanted some error handling, i.e making sure the input is not accepted unless there are exactly nxn doubles.
Like Nicolas, I'm curious what you mean by point (1)...if the matrix is square, then won't the number of rows always equal the number of doubles per line? If not, then I suppose you could look through the file for the row with the most values.
Here's your code modified to do that:
/* count the number of lines */
int lines = 1;
int maxValues = 0;
int count = 0;
char junk;
while((junk == fgetc(fp)) != EOF) {
if(junk == '\n') {
lines++
if(maxValues <= count) {
maxValues = ++count;
}
count = 0;
}
else if(junk == 0x20) {
count++;
}
}
To address point (2), maybe try this modification:
/* load file into array */
int i, j;
for(i = 0; i < lines; i++) {
j = 0;
do {
fscanf(fp, "%lf", &(m[i][j]));
j++;
} while((junk = fgetc(fp)) != '\n');
}
Finally for point (3), I'm pretty sure you can use rewind(fp); to reset the pointer to the beginning of the file.
read the first line with fgets
count the values, let's say they're n
make an array of n * n
read n - 1 lines of n values each
calculate the inverse
Voila!