patterncMinor
Reading numbers from a text file into an array
Viewed 0 times
readingfilearrayintotextnumbersfrom
Problem
I work in a project based on C language. I want to read a file that contains two lines of numeric characters.
Example
I want to pass the elements of the second line into an array. As you saw the first line tell us how big needs to be the array. In the above example we want to create an array with size of 9 to hold 9 numbers.
I created a code that does that exactly but it's too complicated and I want to make it more flexible.
The logic of my code it the following:
I try to read the entire file in one go into a single
The function
So, if
I created the code just to hold 2.000.000 numbers as fast as possible so i want to keep the same logic of the code. But if you have a better idea to store so many numbers so fast please proceed to expain.
The problem is that in the second linespace, every element is one space separated so I don't need to kill all the whitespaces. Also I have only two line in the file.
```
#include
#include
#include
#include
#include
int is_end(char* input) {
return *input == 0;
}
int is_linebreak(char* input) {
return input == '\r' || input == '\n' || *input == ' ';
}
char eat_linebreaks(char input) {
while (is_linebreak(input))
++input;
return input;
}
size_t count_lines(char* input) {
char* p = input
Example
9
8 9 5456 32 2 45 34 98 5I want to pass the elements of the second line into an array. As you saw the first line tell us how big needs to be the array. In the above example we want to create an array with size of 9 to hold 9 numbers.
I created a code that does that exactly but it's too complicated and I want to make it more flexible.
The logic of my code it the following:
I try to read the entire file in one go into a single
char, then splits that by line into an array of char and then lastly converts each line to an int by calling atoi.The function
count_lines() counts the number of words and enter key(new line). The function is_linebreaks(p) checks if the character is a space (' '), an enter key (\n) or a carriage return (\r). If this condition is true, it increment rows counter and eats the other breaks. Eating other breaks means, for example, that if you had multiple spaces (' ') it would skip them until the next valid character (or one of the other breaks).So, if
number_of_rows (in the main function) is not actually rows, but number of words, each line will have one word! I created the code just to hold 2.000.000 numbers as fast as possible so i want to keep the same logic of the code. But if you have a better idea to store so many numbers so fast please proceed to expain.
The problem is that in the second linespace, every element is one space separated so I don't need to kill all the whitespaces. Also I have only two line in the file.
```
#include
#include
#include
#include
#include
int is_end(char* input) {
return *input == 0;
}
int is_linebreak(char* input) {
return input == '\r' || input == '\n' || *input == ' ';
}
char eat_linebreaks(char input) {
while (is_linebreak(input))
++input;
return input;
}
size_t count_lines(char* input) {
char* p = input
Solution
Here are some things that may help you improve your code:
Be careful with signed and unsigned
In two cases, the code compares an
Think of the user
What happens when the user does not specify a file name on the command line? The answer on my machine is that I get a segmentation fault and a crash. Not nice. It's easily solved by checking
Free memory that you allocate
This program leaks memory because you have allocated space using
Carefully consider whether memory allocation is required
Reading the entire file into memory is not really a necessary step for this algorithm. Better would be to read from the file using something like
Don't use unnecessary
The code has
Handle error conditions
Whenever one works with file I/O or memory allocation, there is a chance these operations can fail. For that reason, all such operations should not only be checked for errors, but also the program should handle those errors in some appropriate way. For instance, what if the input file claims there are 9 numbers but there are actually on 4 in the file? Your program will need to handle that.
Be careful with signed and unsigned
In two cases, the code compares an
int i with an unsigned size_t length. It would be better to declare i to also be size_t.Think of the user
What happens when the user does not specify a file name on the command line? The answer on my machine is that I get a segmentation fault and a crash. Not nice. It's easily solved by checking
argc to make sure that the user has specified at least one argument and by checking to make sure that fopen has not returned NULL.Free memory that you allocate
This program leaks memory because you have allocated space using
malloc but never released with free. That's bad practice. Carefully consider whether memory allocation is required
Reading the entire file into memory is not really a necessary step for this algorithm. Better would be to read from the file using something like
fscanf since the file is probably buffered in memory anyway. This would make your code more flexible and eliminate the need for both memory allocation for the file contents and the count_lines routine.Don't use unnecessary
#includesThe code has
#include but nothing from that include file is actually in the code. For that reason, that #include should be eliminated. Handle error conditions
Whenever one works with file I/O or memory allocation, there is a chance these operations can fail. For that reason, all such operations should not only be checked for errors, but also the program should handle those errors in some appropriate way. For instance, what if the input file claims there are 9 numbers but there are actually on 4 in the file? Your program will need to handle that.
Context
StackExchange Code Review Q#71501, answer score: 3
Revisions (0)
No revisions yet.