How read a large number of float from file? - c

I have a file with a large quantity of number and I need to read every single line, and then put every number in that line in an array.
This is two line of my file:
7.7560198e+002 8.2334910e+002 9.7819197e+002 1.4330775e+003 3.0535763e+003 3.3218925e+003 1.7164341e+003 3.1848433e+003 4.9317846e+002 3.4466984e+002 4.7654154e+002 4.9282917e+002 9.5322001e+001 1.2369945e+002 5.3310001e+001 1.0394150e+002 3.1919280e+003 2.1591746e+003 2.1608040e+003 3.6585112e+003
7.1244665e+002 1.4142187e+003 1.7148456e+003 1.3126353e+003 3.4328919e+003 2.8380069e+003 2.8432808e+003 3.6142229e+003 3.3866501e+002 3.9236491e+002 5.0149915e+002 5.9447907e+002 1.3568213e+002 5.9164038e+001 7.1649000e+001 1.3451865e+002 2.2922576e+003 1.8212714e+003 2.9237970e+003 5.1605066e+003
I tried with this code:
FILE *f = fopen(pathInput,"r");
if(f==NULL) {
printf("Error\n");
return -1;
}
int i, j, columnsNumber=0, rowsNumber=0;
char c;
c = fgetc(f);
// count number of column with the first line
for(i=0;c != '\n'; i++) {
if (c==' ') {
while(c==' ')
c = fgetc(f);
numCol++;
}
c = fgetc(f);
}
// count the rows
while(!feof(f)){
c = fgetc(f);
if(c == '\n'){
rowsNumber++;
}
}
float input[(rowsNumber)* columnsNumber];
for(j=0; j< rowsNumber;j++){
for (i = 0; i < columnsNumber; i++){
fscanf(f, "%f ", input[i] );
}
}
for(i=0;i<10; i++){
printf("%f\n", input[i]);
}
fclose(f);
But it doesn't work and the I obtain this warning:
warning: format ‘%f’ expects argument of type ‘double’, but argument 2 has type ‘float *’ [-Wformat=]
printf("%f\n", input[i]);

In your code, you create an array of pointers to floats. You're actually looking to create an array of floats. That declaration would look like the following. Note the lack of a float *.
float input[rowsNumber * columnsNumber];
At that point, you'll get a warning from fscanf(). You're supposed to pass a pointer to an allocated piece of memory. So:
fscanf(f, "%f ", &input[j*columnsNumber + i]);
And, you'll also have problems because you are attempting to read the file twice. You'll want to either close and reopen the file, or reset the file to be looking at the beginning of the file with fseek().
Finally, and I'm not 100% sure on this, but I think it's likely that between when you count the number of floats in a column and the number of floats in a row, you'll possibly miss one '\n' character.

Related

Reading Rows and Columns from File in C

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;
}

how to read from text file and store in matrix in c

the first to say is that I'm totally new to coding, so plz forgive my mistakes.
I'm now trying to read from a txt file which is rather large, it has about 1000000 lines and 4 cols
56.154 59.365 98.3333 20.11125
98.54 69.3645 52.3333 69.876
76.154 29.365 34.3333 75.114
37.154 57.365 7.0 24.768
........
........
I want to read them all and store them into a matrix, here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
int main()
{
int i;
int j;
/*matrix*/
int** mat=malloc(1000000*sizeof(int));
for(i=0;i<1000000;++i)
mat[i]=malloc(4*sizeof(int));
FILE *file;
file=fopen("12345.txt", "r");
for(i = 0; i < 1000; i++)
{
for(j = 0; j < 4; j++)
{
if (!fscanf(file, " %c", &mat[i][j]))
break;
mat[i][j] -= '0'; /* I found it from internet but it doesn't work*/
printf("\n",mat[i][j]);
}
}
fclose(file);
}
The result is that I got nothing in my matrix. I hope u can help. Thanks in advance for any help.
Many Issues, consider following, and of course see comments
int main()
{
int i;
int j;
/*matrix*/
/*Use double , you have floating numbers not int*/
double** mat=malloc(1000000*sizeof(double*));
for(i=0;i<1000000;++i)
mat[i]=malloc(4*sizeof(double));
FILE *file;
file=fopen("1234.txt", "r");
for(i = 0; i < 1000; i++)
{
for(j = 0; j < 4; j++)
{
//Use lf format specifier, %c is for character
if (!fscanf(file, "%lf", &mat[i][j]))
break;
// mat[i][j] -= '0';
printf("%lf\n",mat[i][j]); //Use lf format specifier, \n is for new line
}
}
fclose(file);
}
fscanf( "%c", ... ) only scans one single character (e.g. '5'). By subtracting '0' you get the integer value 5 from the character '5'. You can use "%d" to scan integers that consist only of digits (not including formatting characters), or "%f" for floats (not sure if 56.154 is to be read as "56 thousand 154" (continental europe) or "56 plus 154/1000" (GB / USA) (the rest of the world: don't be offended I just don't know)
printf( "\n", ... ): you forgot to use any formatting string such as %d (int), %f (float) ... So your parameter will not be printed, just the newline itself.
int** mat=malloc(1000000*sizeof(int)); You're allocating an array of int * here, so it should be int** mat=malloc(1000000*sizeof(int *));
Edit: I've looked again at your text file and have seen numbers like 98.54 that can't be formatted integers. So it's quite clear you will need float or double instead if int for your array and use "%f" for float or "%lf" for double in both fscanf() and printf()
You have a couple of things wrong with your code here.
First off you create a matrix of int yet you are reading in float values it looks like. You probably want to use double
Second, when you are reading a double you should use
fscanf(file, "%lf", &some_double); // fscanf(file, "%d", &some_int); for integers
Also when you are allocating your matrix, your first malloc you should pass
sizeof(double *) // or int * if you are really trying to use integers
Finally your line that does:
mat[i][j] -= '0'
What are you trying to accomplish here? You're taking the int that you (tried) to read in and subtracting off '0'...
Edit I also notice that you are hard coding the number of lines you are reading, I wouldn't do that unless you know the format of the file.

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.

Read lines of file, put each line into an array, then print

I just figured out how to do this with integers so decided to give it a go with strings and got stuck.
Here is what is in my file "kw":
keyword0
keyword1
keyword2
keyword3
With this current code I'm getting "error: format '%s' expects argument of type 'char *', but argument 3 has type 'char **'
#include <stdio.h>
int main () {
FILE *pFile;
pFile = fopen("kw", "r");
if (pFile != NULL) {
char *a[3];
int i;
for(i = 0; i <= 3; i++) {
fscanf(pFile, "%s", &a[i]);
printf("%s\n", a[i]);
}
}
return 0;
}
Could someone point me in the right direction here? Thank you.
There are several problems with this code:
You are going through four elements of the array a, while the array has only three elements.
You did not allocate space for the strings that you are reading with scanf.
You do not pass the address of address when you read strings.
To fix the first problem, change <= for != or <, like this:
for(i = 0; i != 3; i++)
To fix the second and the third problem, use malloc:
a[i] = malloc(21*sizeof(char));
fscanf(pFile, "%20s", a[i]);
Once you are done with the data that you allocated, don't forget to free the strings:
for(i = 0; i != 3; i++) {
free(a[i]);
}

fscanf results in a segmentation fault

void RdImage(FILE *fpi, char Image1[MAXROW][MAXCOL], int Nrows, int Ncols) {
int i = 0, j = 0, temp;
while (!feof(fpi)) {
if (i % Nrows == 0) {
i = 0;
j++;
}
**fscanf(fpi, "%d", temp);**
if (temp == 1) {
Image1[i][j] == AP;
} else {
Image1[i][j] == PL;
}
i++;
}
}
The line I've inclosed in asterisks is giving me a segmentation fault. The file is definitely NOT empty. I've used the same line twice elsewhere in my program and it doesn't behave this way there.
temp is an integer; you have to pass its address:
fscanf(fpi, "%d", &temp);
Turn on warnings in your compiler to catch bugs like this.
As per C99 Std
7.19.6.2 The fscanf function
%d
Matches an optionally signed decimal integer, whose format is the same as
expected for the subject sequence of the strtol function with the value 10
for the base argument.
The corresponding argument shall be a pointer to signed integer.
so
fscanf(fpi, "%d", &temp); //Here Address of temp is passed.
is the correct one.
please use &temp instead of temp in fscanf
fscanf(fpi, "%d", &temp);

Resources