处理用户输入中的 EOF
Handling EOF in user input
我正在编写一个小程序,允许用户输入矩阵的维度 m
和 n
,然后根据自己的喜好填充该矩阵。为了读取数字,我使用 fgets()
将用户输入读取为字符串,然后通过 strtol()
将其转换。我还删除了通过 strcspn()
附加的换行符 fgets()
,并在用户输入 a
、12a
或只是换行符 \n
时进行了一些错误处理。但是程序通过 Ctrl + D
输入 EOF
让我很头疼。我阅读了几个关于此的 Whosebug 线程,我知道在某些情况下需要输入 EOF
两次。但是当我发送 EOF
到我第一次调用 fgets()
读取 m
维度时,我将被转发到下一次调用 fgets()
读取 [=12] =]-dimensions 并从那里跳转到实际的数组输入,它似乎卡住了,或者我进入了无限循环。我目前不知道原因,也不知道在这种情况下如何处理 EOF
。如果有人可以提供一些提示,我会很高兴。这是代码:
#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] == '[=10=]') {
fprintf(stderr, "Wrong input\n");
exit(EXIT_FAILURE);
}
m_row = strtol(save, &ptr_save, 10);
if (*ptr_save != '[=10=]') {
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] == '[=10=]') {
fprintf(stderr, "Wrong input\n");
exit(EXIT_FAILURE);
}
n_col = strtol(save, &ptr_save, 10);
if (*ptr_save != '[=10=]') {
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] == '[=10=]') {
fprintf(stderr, "Wrong input\n");
exit(EXIT_FAILURE);
}
element = strtol(save, &ptr_save, 10);
if (*ptr_save != '[=10=]') {
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;
}
错误的分配大小:m_row
对比 n_col
。这可能不是 EOF
问题。
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));
}
建议改为初始化 m_row = 0; n_col = 0;
。
即使 arr
由于 EOF
而未完全填充,代码也会尝试打印出 arr
。应该避免这种情况。
如果这些不能解决问题,建议在读取元素之前打印 m_row
和 n_col
以验证矩阵大小是否符合预期。
次要:使用相同大小的整数
// 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++) {
次要:将 strtoul()
与 unsigned long
一起使用,而不是 strtol()
。
轻微:"largest integer that can fit into unsigned long int is a 20-digit number" ... char save[20];
误导。 1) pow(2,64)
需要20个char
,但是输入需要考虑'\n'
和'[=28=]'
,所以应该使用char save[20+2];
2) unsigned long int
可以 大于 64 位 - 它必须至少是 32 位。但这肯定不是本次post.
的主要问题
我正在编写一个小程序,允许用户输入矩阵的维度 m
和 n
,然后根据自己的喜好填充该矩阵。为了读取数字,我使用 fgets()
将用户输入读取为字符串,然后通过 strtol()
将其转换。我还删除了通过 strcspn()
附加的换行符 fgets()
,并在用户输入 a
、12a
或只是换行符 \n
时进行了一些错误处理。但是程序通过 Ctrl + D
输入 EOF
让我很头疼。我阅读了几个关于此的 Whosebug 线程,我知道在某些情况下需要输入 EOF
两次。但是当我发送 EOF
到我第一次调用 fgets()
读取 m
维度时,我将被转发到下一次调用 fgets()
读取 [=12] =]-dimensions 并从那里跳转到实际的数组输入,它似乎卡住了,或者我进入了无限循环。我目前不知道原因,也不知道在这种情况下如何处理 EOF
。如果有人可以提供一些提示,我会很高兴。这是代码:
#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] == '[=10=]') {
fprintf(stderr, "Wrong input\n");
exit(EXIT_FAILURE);
}
m_row = strtol(save, &ptr_save, 10);
if (*ptr_save != '[=10=]') {
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] == '[=10=]') {
fprintf(stderr, "Wrong input\n");
exit(EXIT_FAILURE);
}
n_col = strtol(save, &ptr_save, 10);
if (*ptr_save != '[=10=]') {
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] == '[=10=]') {
fprintf(stderr, "Wrong input\n");
exit(EXIT_FAILURE);
}
element = strtol(save, &ptr_save, 10);
if (*ptr_save != '[=10=]') {
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;
}
错误的分配大小:m_row
对比 n_col
。这可能不是 EOF
问题。
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));
}
建议改为初始化 m_row = 0; n_col = 0;
。
即使 arr
由于 EOF
而未完全填充,代码也会尝试打印出 arr
。应该避免这种情况。
如果这些不能解决问题,建议在读取元素之前打印 m_row
和 n_col
以验证矩阵大小是否符合预期。
次要:使用相同大小的整数
// 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++) {
次要:将 strtoul()
与 unsigned long
一起使用,而不是 strtol()
。
轻微:"largest integer that can fit into unsigned long int is a 20-digit number" ... char save[20];
误导。 1) pow(2,64)
需要20个char
,但是输入需要考虑'\n'
和'[=28=]'
,所以应该使用char save[20+2];
2) unsigned long int
可以 大于 64 位 - 它必须至少是 32 位。但这肯定不是本次post.