I have this problem with my code. Im was copying some numbers from a file i had opened into an array using a for loop. And at the same time, i put a printf statement after the fscanf statement to see whether the value i wanted actually entered the arr. This works fine except that it puts an extra number at the end of the array when it's done. i don't understand why this happens. At first, i thought that I was using a wrong count of the number of elements in the file or that i had messed up while using malloc but those are completely fine. Can anyone pls tell what wrong. I can't share the code until a specific date cause i am a student and it would be considered cheating.
EDIT: Below is a link to a segment of what is happening in the code. THE LANGUAGE IS C. The code is meant to read the numbers 1
7
5
6
8
3
9
4
2
10
from a file a made but instead it always reads 1
7
5
6
8
3
9
4
2
10
1
EDIT: In the function declaration i meant char* file_name not int char*filename.
the image but i cant embed yet so a link
There are multiple problems in your code:
there is a syntax error in the function prototype: int char* filename should just be const char *filename.
you do not test the return value of fopen(). You will have undefined behavior if the program cannot open the file.
you do not test if fscanf() succeeds at converting the file contents as an integer. You should verify the it returns 1 and handle the error if it does not.
It is quite likely that the number of values passed to the function exceeds the number of values actually present in the file. In this case, the contents of the destination array is not changed beyond the last value read and printf outputs whatever happens to be present there.
You should post the whole program as text in your question for a more complete analysis and potential corrections.
Related
This question already has an answer here:
C, reading from file into structure
(1 answer)
Closed 5 years ago.
I'm currently trying to write a programme to solve the knapsack problem in C. As part of this assignment, we have been asked to open a text file which has the contents as follows, read the objects, weights, value and cost of each object from the file. I just have no idea how I would go about importing this information and storing it in the correct order in terms of a structure.
Heres an example of the format in which the text files are presented is objects.txt:
Blockquote
Value Weight Cost
7 1 4
6 5 10
6 11 15
5 4 8
4 2 20
3 6 8
2 4 9
2 10 3
1 6 7
Yes, it is Sunday, and your assignment is probably due tomorrow... We don't do homework, but we can give some guidelines.
To read data from a text file you open it with FILE *fp=fopen(.... After opening the file (and checking it has succesfully been opened), you can read lines in two ways:
by calling fscanf(fp, "%d %d %d ",... and checking the number of arguments you want have been read (and if not, you are probably at end-of-file), or
by calling fgets to read a line into a buffer, and then processing the buffer, for which you can use sscanf much like fscanf.
Note: you do this in a loop until fscanf or fgets cannot read anything anymore. You do not loop while (!feof(fp)) because feof reports there is nothing more to read after a read failed.
You read the data into the members of the structure. I assume you have an array of structures and I assume the array is large enough to hold all data (dynamic allocation will be later on in your course).
Finally you close the file with fclose.
I would like to read an array from a .txt file in Fortran. I tried it with the following code:
PROGRAM test_performance
IMPLICIT NONE
DOUBLE PRECISION, DIMENSION(:), ALLOCATABLE :: ARRAYONE
OPEN(UNIT=20,FILE='testfile.txt',STATUS='OLD', ACTION='READ')
READ (20,*) ARRAYONE
print *, 'here I am!'
CLOSE(UNIT=20)
write(*,*)ARRAYONE
OPEN(UNIT=30,FILE='TEXTFILE.txt', STATUS='REPLACE', ACTION='WRITE')
WRITE(30,*)ARRAYONE
END PROGRAM test_performance
There is no error when I compile it. The point is that the array ARRAYONE as well as the file TEXTFILE.txt are empty.
The file testfile.txt Looks like this:
1 2 3 4 5 6 7 8 9 10 11
I have got a book in front of me according to which this should actually work. What puzzles me is the fact that if I put just one number in the input file, i.e., 1, and I want to write it on an integer, there is no problem and everything works fine :o!
In the vainglorious pursuit of rep, and with the noble intention that this question get an answer
You can't automatically allocate an array in a read statement, the rules forbid it (or, if you prefer, do not make allowance for it). You could either:
allocate the array to some size that you expect to be large enough, populate it with a guard value unlikely to be found in your inputs, and then read the data you have into the first n elements; or
read the data, figure out how many elements there are, allocate the array to that size, pass the data to the array; you could do this in two passes over the input file (one to determine the contents, the second to read it) or you could get clever and read the data into, say, a large string and parse it to find out how many numbers it contains (so simple it's scarcely worthy of the name 'parsing').
There are other ways, I'm sure you can think of some.
I have test.csv (300 lines) file as below
10 20 100 2 5 4 5 7 9 10 ....
55 600 7000 500 25
3 10
2 5 6
....
Each line has different number of integers (maximum number of records =1000) and I need to proceed these records line by line. I tried as below
integer,dimension(1000)::rec
integer::i,j
open(unit=5,file="test.csv",status="old",action="read")
do i=1,300
read(unit=5,fmt=*) (rec(j),j=1,1000)
!do some procedue with rec
enddo
close(unit=50)
but it seems like that rec array is not constructed by line by line. It means that when i=n, rec get the numbers from non-nth line. How can I solve this problem.
thank you
List directed formatting (as specified by the star in the read statement) reads what it needs to satisfy the list (hence it is "list directed"). As shown, your code will try and read 1000 values each iteration, consuming as many records (lines) as required each iteration in order to do that.
(List directed formatting has a number of surprising features beyond that, which may have made sense with card based input forms 40 years ago, but are probably misplaced today. Before using list directed input you should understand exactly what the rules around it say.)
A realistic and robust approach to this sort of situation is to read in the input line by line, then "manually" process each line, tokenising that line and extracting values as per whatever rules you are following.
(You should get in touch with whoever is naming files that have absolutely no commas or semicolons with an extension ".csv", and have a bit of a chat.)
(As a general rule, low value unit numbers are to be avoided. Due to historical reasons they may have been preconnected for other purposes. Reconnecting them to a different file is guaranteed to work for that specific purpose, but other statements in your program may implicitly be assuming that the low value unit is still connected as it was before the program started executing - for example, PRINT and READ statements intended to work with the console might start operating on your file instead.)
Please refer to the following code snippet, I will be referring to the line numbers on it:
https://gist.github.com/wilbertcr/474c6a13e377dc8ce51a
As you can see on line 172-200, I created a modified version of the original back_over function, which just moves the pointer without erasing the character that's moving over.
Outside of the function in_process, and as a global variable, I created int verase, see line 1, which I use on line 82 to indicate CTRL+H has been pressed(ch == tp->tty_termios.c_cc[VERASED]).
My idea is to use this as a flag so I can catch the next character, which should be the number of spaces I need to back_over, and do that by calling back_over the number of times indicated by that next character.
The problem I am having is that I don't know how to turn that next character into its corresponding int so that I can use it on the for loop. Lines 27-38 show a failed attempt to do that, however, no matter how small the key I press(I've tried 1 and 2 and 3), it always takes me to the beginning of the line(luckily back_over doesn't go beyond a line break--see line 185).
It seems like the for loop is being executed more than the it should, which I suspect is happening because "number" is not really 1 or 2 or 3 but something else, something the for loop is interpreting as much bigger than the number I am pressing in the keyboard. I would appreciate some help on how can I turn it into an int.
It turned out it was just a matter of doing:
ch=ch-'0'
I'm writing a business application in C in which I'm keeping track of a timer by writing the value to a temporary file. The counter starts at 96, and counts backwards all the way to 0. The logic works fine, except when it switches over from 10 to 9, the 9 only overwrites the 1, so instead of 10 -> 9, the value goes 10 -> 90, causing the countdown to start back from this point. Is there a way I can have my application write the value successfully?
I'm using the following two functions to control output to the file"
fprintf(fileFd, "%d" , counter);
rewind(fileFd);
I print the value to my file, then move the access point back to the head of the file for the next entry. Any advice on how this can be done? Thanks, all.
EDIT: Thank you all for the suggestions. I tried the methods suggested below, by calling %02d to write to two place values, and for some reason that completely broke the application. The loops won't happen at all.....then when I recompile, it still won't work until I delete my temp file and create a new one. Now, when writing to the file, it tells me at the bottom (this is a UNIX system) the filename, [Incomplete last line], 1 line 2 characters. Would this make any kind of difference to specifying the number of places to write to?
fprintf(fileFd, "%02d", counter);
Check with:
fprintf(fileFd, "%02d" , counter);
write to the file taking up certain number of digits, and fill unused digit with 0.
fprintf(fileFd, "%07d", counter);
The above code will allow time values upto 7 digits.