I am writing a small program that allows a user to input the dimensions m
and n
of a matrix and then to fill that matrix as to her liking. To read in the numbers I use fgets()
to read the user input as a string and then convert it via strtol()
. I also remove the newline fgets()
appends via strcspn()
and do some error handling when the user types in a
, 12a
or simply a newline \\n
. But the program gives me headache with EOF
input via Ctrl + D
. I read several stackoverflow threads about this and I know that one needs to type in EOF
two times in some cases. But when I send EOF
to my first call to fgets()
reading in the m
-dimension I will be forwarded to the next call to fgets()
which reads in the n
-dimensions and from there on it will jump to the actual array input and there it seems stuck or I goes into an infinite loop. I do currently not know the cause and I do not know how to handle EOF
in this scenario. I would be happy if someone could give some hints. Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main(int argc, char *argv[]) {
/* We use "m_row" and "n_col" to keep track of the matrix dimensions and "m"
* and "n" to keep track of the size of dynamically allocated memory. */
unsigned long int m_row;
unsigned long int n_col;
unsigned long int element;
/* Initializing at dummy value to silence compiler. */
m_row = 1;
n_col = 1;
/* The largest integer that can fit into unsigned long int is a 20-digit
* number. */
char save[20];
char *ptr_save;
printf("Enter number of rows:\n");
if (fgets(save, sizeof(save), stdin) != NULL) {
save[strcspn(save, "\n")] = 0;
if (save[0] == '\0') {
fprintf(stderr, "Wrong input\n");
exit(EXIT_FAILURE);
}
m_row = strtol(save, &ptr_save, 10);
if (*ptr_save != '\0') {
fprintf(stderr, "Wrong input\n");
exit(EXIT_FAILURE);
}
}
printf("Enter number of columns:\n");
if (fgets(save, sizeof(save), stdin) != NULL) {
save[strcspn(save, "\n")] = 0;
if (save[0] == '\0') {
fprintf(stderr, "Wrong input\n");
exit(EXIT_FAILURE);
}
n_col = strtol(save, &ptr_save, 10);
if (*ptr_save != '\0') {
fprintf(stderr, "Wrong input\n");
exit(EXIT_FAILURE);
}
}
errno = 0;
unsigned long int **arr = calloc(m_row, sizeof(unsigned long int *));
if (arr == NULL) {
fprintf(stderr, "%s", strerror(errno));
exit(EXIT_FAILURE);
}
int i;
errno = 0;
for(i = 0; i < m_row; i++) {
arr[i] = calloc(m_row, sizeof(unsigned long int));
if (arr[i] == NULL) {
fprintf(stderr, "%s", strerror(errno));
exit(EXIT_FAILURE);
}
}
int j;
for(i = 0; i < m_row; i++) {
for(j = 0; j < n_col; j++) {
if (fgets(save, sizeof(save), stdin) != NULL) {
save[strcspn(save, "\n")] = 0;
if (save[0] == '\0') {
fprintf(stderr, "Wrong input\n");
exit(EXIT_FAILURE);
}
element = strtol(save, &ptr_save, 10);
if (*ptr_save != '\0') {
fprintf(stderr, "Wrong input\n");
exit(EXIT_FAILURE);
}
arr[i][j] = element;
}
printf("\n");
}
}
for (i = 0; i < m_row; i++) {
for(j = 0; j < n_col; j++) {
printf("%lu\t", arr[i][j]);
}
printf("\n");
}
free(arr);
return 0;
}
Wrong allocation size: m_row
vs n_col
. This may not be an EOF
issue.
for (i = 0; i < m_row; i++) {
// arr[i] = calloc(m_row, sizeof(unsigned long int));
arr[i] = calloc(n_col, sizeof(unsigned long int));
}
Suggest initializing m_row = 0; n_col = 0;
m_row = 0; n_col = 0;
instead.
Code attempts to print out arr
even if arr
was not fully populated due to EOF
. Should avoid that.
If these do not fix the issue, suggest printing the m_row
ands n_col
prior to reading the elements to verify the matrix size is as expected.
Minor: Use same size integers
// Rather than
unsigned long int m_row;
...
int i;
for(i = 0; i < m_row; i++) {
// Use same type: recommend `size_t`
size_t m_row;
...
size_t i;
for(i = 0; i < m_row; i++) {
Minor: use strtoul()
with unsigned long
, not strtol()
.
Minor: "largest integer that can fit into unsigned long int is a 20-digit number" ... char save[20];
mis-leads. 1) pow(2,64)
takes 20 char
, but the input needs to account for '\\n'
and '\\0'
, so should use char save[20+2];
2) unsigned long int
could be larger than 64-bit - it must be at least 32-bit. But this is certainly not the main problem of this post.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.