How to read a multi line using fscanf - c

I want to read my data.txt file which looks like and store it in an array called buffer[i][j]
1 1 1 1
2 2 2 2
3 3 3 3
4 4 4 4
I am writing a code which looks like
#include"stdio.h"
#include"stdlib.h"
int main() {
FILE *fp1;
int i,j;
int buffer[4][4]={0};
fp1 = fopen("exact_enumerated_config_442_cub_mc","r");
for(i=0;i<4;i++) {
for(j=0;j<4;j++) {
fscanf(fp1,"%d", &buffer[i][j]);
}
// fscanf(fp1,"\n");
}
fclose(fp1);
for(i=0;i<4;i++) {
for(j=0;j<4;j++) {
printf("%d ",buffer[i][j]);
}
printf("\n");
}
}
but i get the output...
1 1 2 1
5 1 6 1
17 1 18 1
21 1 22 1
why????

Always check the result of fopen() to ensure the file has been opened.
Always check the result of fscanf() to ensure it was successful and prevent subsequent code processing variables that may not have been assigned a value (it returns the number of assignments made).
Add a leading space character to the format specifier to skip whitespace, including newline characters: " %d".
The code will treat a single line with sixteen ints the same as four lines with four ints. If it is important that the format of the file is four ints per line then read a single line using fgets() and then use sscanf() to extract the ints with the %n format specifier to ensure full buffer was processed:
int ints[4][4] = { { 0 } };
char buffer[1024];
for (int i = 0; i < 4 && fgets(buffer, 1024, fp); i++)
{
int pos;
if (sscanf(buffer,
"%d %d %d %d%n",
&ints[i][0],
&ints[i][1],
&ints[i][2],
&ints[i][3],
&pos) != 4 || pos != strlen(buffer) - 1)
{
fprintf(stderr, "Invalid format: <%s>\n", buffer);
exit(1);
}
}

Add space at the beginning of the string format it should be " %d" to avoid the newline problems
fscanf(fp1," %d", &buffer[i][j]);
BTW you could use the following code instead
for(i=0;i<4;i++) {
fscanf(fp1," %d %d %d %d", &buffer[i][0], &buffer[i][1], &buffer[i][2], &buffer[i][3]);
}

To get required output (1111,2222,...) change:
fp1 = fopen("exact_enumerated_config_442_cub_mc","r");
to:
fp1 = fopen("data.txt","r");
Clarification: when using fopen you should write the name of file you want to read. In you case you have to write data.txt, not exact_enumerated_config_442_cub_mc...
There is no file with this name, moreover there is no any data like 1 1 1 1, 2 2 2 2, 3 3 3 3, 4 4 4 4...
For more detailes visit:
wikibooks.org/wiki/C_Programming/C_Reference/stdio.h/fopen
Here is your "modified" (excess/waste/extra { } removed and data.txt is written) code that gives you required output: 1 1 1 1, 2 2 2 2, 3 3 3 3, 4 4 4 4.
It prints the array named buffer. It means that...
...data was successfully copied! from "data.txt" to buffer[4][4]:
#include"stdio.h"
#include"stdlib.h"
int main()
{
FILE *fp1;
int i,j;
int buffer[4][4];
for ( i = 0; i < 4; i++ )
for ( j = 0; j < 4; j++ )
buffer[i][j] = 0;
fp1 = fopen("data.txt","r");
for(i=0; i<4; i++)
for(j=0; j<4; j++)
fscanf(fp1,"%d", &buffer[i][j]);
fclose(fp1);
for(i=0; i<4; i++)
{
for(j=0; j<4; j++)
printf("%d ",buffer[i][j]);
printf("\n");
}
return 0;
}
P.S.
If data.txt will contain not
1 1 1 1
2 2 2 2
3 3 3 3
4 4 4 4
but
1 1 1 1
2 2 2 2
3 3 3 3
4 444 // the last two elements are absent
the program will read 1-st, 2-nd and 3-rd line properly, and the output of the 4-th line will be
4 444 0 0
It prints 4, then 444, and then 0 and 0: the last two elements are '0's because buffer had been initialized by zeros, so all elements changed their values, but the last two remained to be zeros.

You have said you want to read data.txt then why are you opening the file exact_enumerated_config_442_cub_mc
Try changing this
fp1 = fopen("exact_enumerated_config_442_cub_mc","r");
to
fp1 = fopen("data.txt","r");

Related

C program, make user to type multiple dynamic inputs in one line

How can I take one line dynamic input like this -> 1 4 3 5 of course, It can be done with this approach ->
scanf("%d %d %d %d", &variable[0], &variable[1], &variable[2], &variable[3]);
In this example, I am taking only 4 inputs...
But my question is, how can I make it dynamic and work for a random number?
// Sample Input
3 // number of rows
5 // number of columns
// 2d array with dynamic input
1 4 3 5 97
5 6 7 4 51
2 9 8 3 0
Use a loop to read each array entry.
int rows, cols;
if (scanf("%d %d", &rows, &cols) != 2) {
printf("Unable to read rows and cols\n");
exit(1);
}
int variable[cols];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (scanf("%d", &variable[j]) != 1) {
printf("Unable to process input\n");
exit(1);
}
}
// do something with the variable array
}
Note that scanf() doesn't make a distinction between different types of whitespace that separate tokens. So this will read all the numbers on the same line, different lines, or a mixture.

C fscanf input format

I have an input file that contains lines of the following format:
%s %d %d %d %lf %lf ... %lf\n
where the number of double values is unknown, but for my calculations I accept only first 15 of them.
The problem I can't figure out is, when I get to the line like this:
City0 28 2 2016 1 2 3 4 5 6 7 8 9 10
City1 28 2 2016 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
City2 1 3 2016 1 2 3 4 5
and I correctly assign respective values to a certain structure, I get the following:
City0 28 2 2016 Number of measures: 10
City1 28 2 2016 Number of measures: 15
16 17 18 19 Number of measures: 1
City2 1 3 2016 Number of measures: 5
How do I read(to nowhere)/ignore everything until I get to the end of the line, and then start reading the next line as usual? I need the following output:
City0 28 2 2016 Number of measures: 10
City1 28 2 2016 Number of measures: 15
City2 1 3 2016 Number of measures: 5
I tried this but ain't got any more ideas:
i=0; char character;
while (fscanf(fp, "%s %d %d %d", c.name, &c[i].date.day,
&c[i].date.month, &c[i].date.year)==4 && i<number_of_cities) {
while (fscanf(fp, "%lf", &c[i].measures[j])==1 && j<15) {
j++;
}
if (j==15) {
while (fscanf(fp, "%s", character)!='\n') {}
}
c[i].mnum = j;
j=0;
i++;
}
You can use fscanf() to read in an entire line of input, use sscanf() to scan the first four values, and use sscanf() again in a loop to read the double values. The trick here is to use the %n directive to save the position of the next read location in the string.
Here is an example. Note that size_t is used for array indices, as this is an unsigned integer type that is guaranteed to hold any array index. Also note that there is some error-checking when opening the file, and when scanning the beginning of a line. If the initial elements of the line do not match expected values, the program exits with an error message. This error-checking could be tightened up a bit; for example, if the year is entered as a floating point value, such as 2016.0, the input will be accepted, but the values stored in measures[] will begin with the 0 following the decimal point.
#include <stdio.h>
#include <stdlib.h>
struct Data {
char name[1000];
struct {
int day;
int month;
int year;
} date;
size_t mnum;
double measures[15];
};
int main(void)
{
size_t i = 0, j = 0;
char buffer[1000];
char *read_ptr = buffer;
int n_read = 0;
size_t number_of_cities = 3;
struct Data c[number_of_cities];
FILE *fp;
if ((fp = fopen("datafile.txt", "r")) == NULL) {
fprintf(stderr, "Unable to open file\n");
exit(EXIT_FAILURE);
}
while (fgets(buffer, 1000, fp) != NULL) {
if (sscanf(buffer, "%s %d %d %d %n", c[i].name, &c[i].date.day,
&c[i].date.month, &c[i].date.year, &n_read) != 4) {
fprintf(stderr, "Incorrect input format\n");
exit(EXIT_FAILURE);
}
read_ptr += n_read;
while (sscanf(read_ptr, "%lf %n", &c[i].measures[j], &n_read) == 1 &&
j < 15) {
read_ptr += n_read;
++j;
}
c[i].mnum = j;
++i;
j = 0;
read_ptr = buffer;
if (i == number_of_cities) {
break;
}
}
for (i = 0; i < number_of_cities; i++) {
printf("%s %d %d %d Number of measures: %zu\n",
c[i].name,
c[i].date.day, c[i].date.month, c[i].date.year,
c[i].mnum);
for (j = 0; j < c[i].mnum; j++) {
printf("%5g", c[i].measures[j]);
}
putchar('\n');
}
return 0;
}
Program output using your example data as input:
City0 28 2 2016 Number of measures: 10
1 2 3 4 5 6 7 8 9 10
City1 28 2 2016 Number of measures: 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
City2 1 3 2016 Number of measures: 5
1 2 3 4 5

Read numbers from text file and use them as input

I have this text:
0 0 0 0 0 1
0 0 0 0 1 1
0 0 0 1 0 1
0 0 0 1 1 1
I want to read the first 5 numbers from each line and then use them as inputs in a function.
I'm new to c and have only accomplished this code that doesn't do much, if anything really.
int v,o;
FILE *mydata;
if ((mydata = fopen("testinputs.txt", "rt"))==NULL)
{
printf ("file can't be opened'\n");
exit(1);}
fclose(mydata);
How do i complete it?
Thank you.
Well, assuming your file is called "input.txt", then this is all you need to do:
#include <stdio.h>
#include <stdlib.h>
#define LINE_LEN 100
int main ( void )
{
char line[LINE_LEN];
int sum, i, read_cnt, numbers[5];//sum and i are there for my example usage
FILE *in = fopen("input.txt", "r");//open file
if (in == NULL)
{
fprintf(stderr, "File could not be opened\n");
exit( EXIT_FAILURE);
}
while((fgets(line, LINE_LEN, in)) != NULL)
{//read the line
//scan 5 numbers, sscanf returns the number of values it managed to extract
read_cnt = sscanf(
line,
"%d %d %d %d %d",
&numbers[0],
&numbers[1],
&numbers[2],
&numbers[3],
&numbers[4]
);
//check to see if we got all 5 ints
if (read_cnt != 5)
printf("Warning: only read %d numbers\n", read_cnt);//whoops
//just an example, let's add them all up
for (sum= i=0;i<read_cnt;++i)
sum += numbers[i];
printf("Sum of numbers was: %d\n", sum);
}
return EXIT_SUCCESS;
}
With this input.txt file:
1 2 3 4 5
2 2 2 2 2
1 23 2 3 4
12 23
This gives us the following output:
Sum of numbers was: 15
Sum of numbers was: 10
Sum of numbers was: 33
Warning: only read 2 numbers
Sum of numbers was: 35
That should be more than enough to get you started
Here is a small code to read character by character and store only the wanted numbers:
C Code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int c; // Character read from the file
int cpt; // Counter (to get only 5 numbers per line)
int i,j; // Array indexes
int data[4][5]; // 2D integer array to store the data
FILE *f; // File
if ((f = fopen("file.txt", "r")) == NULL) // Open the file in "read" mode
{
printf ("file can't be opened'\n");
exit(255);
}
// Counter and indexes initialization
cpt=0;
i=0;
j=0;
// Read the file till the EOF (end of file)
while ((c = fgetc(f)) != EOF)
{
// If 5 numbers read, go to new line, first index in the data array and to the next line in the file
if(cpt==5)
{
i++;
cpt=0;
j=0;
while(c != '\n' && c != EOF)
c=fgetc(f);
}
// If a number is read, store it at the right place in the array
if(c>='0'&&c<='9')
{
// Convert character to integer (see ascii table)
data[i][j] = c-'0';
j++;
cpt++;
}
}
// Display the array
for(i=0;i<4;i++)
{
for(j=0;j<5;j++)
printf("%d ", data[i][j]);
printf("\n");
}
fclose(f);
}
And here is the output:
0 0 0 0 0
0 0 0 0 1
0 0 0 1 0
0 0 0 1 1
Now you can use your 2D array, for example if you want a variable a to have the 2nd line, 3rd number, you'd do : a = data[1][2]
Don't forget arrays start at index 0
Hope this helps...
It might help you:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
FILE *datafile;
int main()
{
char line[100],*ch;
int count;
datafile = fopen ( "my.txt", "r");
while ( fgets(line , sizeof line , datafile) != NULL )//fgets reads line by line
{
count = 0;
ch = strtok ( line , " ");
while ( count < 5 && ch != NULL )
{
printf("%d ",*ch - 48 );//*ch gives ascii value
//pass to any function
count++;
ch = strtok ( NULL, " ");
}
}
return 0;
}
The above program passes integer by integer.

Reading numbers from a text file into an array in C

I'm a programming noob so please bear with me.
I'm trying to read numbers from a text file into an array. The text file, "somenumbers.txt" simply holds 16 numbers as so "5623125698541159".
#include <stdio.h>
main()
{
FILE *myFile;
myFile = fopen("somenumbers.txt", "r");
//read file into array
int numberArray[16];
int i;
for (i = 0; i < 16; i++)
{
fscanf(myFile, "%d", &numberArray[i]);
}
for (i = 0; i < 16; i++)
{
printf("Number is: %d\n\n", numberArray[i]);
}
}
The program doesn't work. It compiles but outputs:
Number is: -104204697
Number is: 0
Number is: 4200704
Number is: 2686672
Number is: 2686728
Number is: 2686916
Number is: 2004716757
Number is: 1321049414
Number is: -2
Number is: 2004619618
Number is: 2004966340
Number is: 4200704
Number is: 2686868
Number is: 4200798
Number is: 4200704
Number is: 8727656
Process returned 20 (0x14) execution time : 0.118 s
Press any key to continue.
change to
fscanf(myFile, "%1d", &numberArray[i]);
5623125698541159 is treated as a single number (out of range of int on most architecture). You need to write numbers in your file as
5 6 2 3 1 2 5 6 9 8 5 4 1 1 5 9
for 16 numbers.
If your file has input
5,6,2,3,1,2,5,6,9,8,5,4,1,1,5,9
then change %d specifier in your fscanf to %d,.
fscanf(myFile, "%d,", &numberArray[i] );
Here is your full code after few modifications:
#include <stdio.h>
#include <stdlib.h>
int main(){
FILE *myFile;
myFile = fopen("somenumbers.txt", "r");
//read file into array
int numberArray[16];
int i;
if (myFile == NULL){
printf("Error Reading File\n");
exit (0);
}
for (i = 0; i < 16; i++){
fscanf(myFile, "%d,", &numberArray[i] );
}
for (i = 0; i < 16; i++){
printf("Number is: %d\n\n", numberArray[i]);
}
fclose(myFile);
return 0;
}
for (i = 0; i < 16; i++)
{
fscanf(myFile, "%d", &numberArray[i]);
}
This is attempting to read the whole string, "5623125698541159" into &numArray[0]. You need spaces between the numbers:
5 6 2 3 ...
Loop with %c to read the stream character by character instead of %d.
There are two problems in your code:
the return value of scanf must be checked
the %d conversion does not take overflows into account (blindly applying *10 + newdigit for each consecutive numeric character)
The first value you got (-104204697) is equals to 5623125698541159 modulo 2^32; it is thus the result of an overflow (if int where 64 bits wide, no overflow would happen). The next values are uninitialized (garbage from the stack) and thus unpredictable.
The code you need could be (similar to the answer of BLUEPIXY above, with the illustration how to check the return value of scanf, the number of items successfully matched):
#include <stdio.h>
int main(int argc, char *argv[]) {
int i, j;
short unsigned digitArray[16];
i = 0;
while (
i != sizeof(digitArray) / sizeof(digitArray[0])
&& 1 == scanf("%1hu", digitArray + i)
) {
i++;
}
for (j = 0; j != i; j++) {
printf("%hu\n", digitArray[j]);
}
return 0;
}
enter your file input like this
ex:
12
13
22
45
(after every number hit enter)
then run your programm it will run properly

fgets inside of a For loop causing strange behavior

I'm trying to get user input using fgets and some funky (not correct) things are happening and I can't seem to understand why.
The program is run with an argument that indicates how many values the user is to input.
Here is how the program is supposed to run:
./a.out 6
Enter 6 integer values to place in tree:
5
4
3
2
1
6
Input values:
5
4
3
2
1
6
If I have 1 as the argument, it doesn't even allow me to enter an input, and where did the 0 come from?
./a.out 1
Enter 1 integer values to place in tree:
Input values:
0
If I have 2 as the argument, it only allows me to enter 1 input and the phantom 0 appears again.
./a.out 2
Enter 2 integer values to place in tree:
1
Input values:
1
0
If I have 3 or more arguments, it functions correctly.
Here's the source:
int main (int argc, const char* argv[]){
int numIntegers;
char buffer[20];
if (argc == 1){
printf("Usage: a.out #\n");
return EXIT_FAILURE;
}
else{
numIntegers = atoi(argv[1]);
if (numIntegers <= 0){
printf("# must be greater than 0\n");
return EXIT_FAILURE;
}
else{
int intArray[numIntegers];
printf("Enter %d integer values to place in tree: \n", numIntegers);
for (int i = 0; i < numIntegers; i++){
fgets(buffer, numIntegers, stdin);
intArray[i] = atoi(buffer);
}
printf("Input values:\n");
for (int i = 0; i < numIntegers; i++){
printf(%d\n", intArray[i]);
}
}
}
}//end main
The size argument to fgets() refers to the size of buffer, which should be 20 in your case.
fgets(buffer, sizeof(buffer), stdin);
By the way, your code won't actually compile.
printf(%d\n", intArray[i]); // missing a quotation mark

Resources