我正在处理ACM代码挑战,我需要从用户指定的文件中读取。我到目前为止的代码:
int main(){
// Input file name
char filename[80];
printf("\nInput file name: ");
fgets(filename, 79, stdin);
// Read from file
FILE *data_file;
data_file = fopen(filename,"r");
char data[1000];
for(int i=0; i<1000; i++){
fscanf(data_file, "%1d", &data[i]);
}
fclose(data_file);
return 0;
}
然而,有一个错误:'分段错误'。使用一些printf语句,我知道文件名已被正确读取。
运行Ubuntu 14.04 LTS; IDE是Code :: Blocks。
答案 0 :(得分:3)
这里有很多错误。最重要的是,您没有检查fopen
的结果是否成功,这意味着您将尝试在无效的文件句柄上调用fscanf
,从而导致您的段错误。
另一个原因是你没有修剪\n
在文件名缓冲区中跟踪fgets
字符之前离开的尾随换行符NULL
。这意味着你几乎肯定不会成功地超越这条线。
第三,你的fscanf
调用没有检查错误条件(即:文件结束),所以它会尝试读出界限并引入错误。
最后,您的代码中使用了许多硬编码的标记值。如果编译器支持VLA和C99标准,则应使用宏或const int
值替换它们。
示例代码
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#ifndef PATH_MAX
#define PATH_MAX (1024)
#endif
#define BUF_LEN_MAX (1024)
int main() {
/* Declare variables */
int i;
bool err = false;
char filename[PATH_MAX];
char data[BUF_LEN_MAX];
FILE *data_file;
/* Get input file name */
printf("\nInput file name: ");
fgets(filename, PATH_MAX, stdin);
strtok(filename, "\n"); /* Trim trailing newline character left behind by fgets */
printf("Data file to use:%s\n", filename);
// Read from file
if ((data_file = fopen(filename,"r")) == NULL) {
printf("File could not be found or opened; Aborting\n");
return 1;
}
/* Print out the gathered data one character at a time for verification */
for (i=0; i<PATH_MAX && !err; i++) {
if (fscanf(data_file, "%c", &data[i]) == EOF) {
err = true;
}
printf("Character #%04d - '%c'\n", i, data[i]);
}
fclose(data_file);
return 0;
}
示例测试文件 - tmp.txt
total 32
drwxr-xr-x 4 admin darkstar 136B Jun 26 15:00 ./
drwxr-xr-x@ 62 admin darkstar 2.1K Jun 26 13:38 ../
-rw-r--r--@ 1 admin darkstar 12K May 13 05:52 .DS_Store
-rw-r--r-- 1 admin darkstar 0B Jun 26 15:00 tmp.txt
样本运行 - 故意失败测试
Input file name: someone
Data file to use:someone
File could not be found or opened; Aborting
样本运行 - 测试2 - 成功
Input file name: tmp.txt
Data file to use:tmp.txt
Character #0000 - 't'
Character #0001 - 'o'
Character #0002 - 't'
Character #0003 - 'a'
Character #0004 - 'l'
Character #0005 - ' '
Character #0006 - '3'
Character #0007 - '2'
Character #0008 - '
'
Character #0009 - 'd'
Character #0010 - 'r'
Character #0011 - 'w'
Character #0012 - 'x'
Character #0013 - 'r'
Character #0014 - '-'
Character #0015 - 'x'
Character #0016 - 'r'
Character #0017 - '-'
Character #0018 - 'x'
Character #0019 - ' '
Character #0020 - ' '
Character #0021 - ' '
Character #0022 - '4'
Character #0023 - ' '
Character #0024 - 'a'
Character #0025 - 'd'
Character #0026 - 'm'
Character #0027 - 'i'
Character #0028 - 'n'
Character #0029 - ' '
Character #0030 - ' '
Character #0031 - ' '
Character #0032 - 'd'
Character #0033 - 'a'
Character #0034 - 'r'
Character #0035 - 'k'
Character #0036 - 's'
Character #0037 - 't'
Character #0038 - 'a'
Character #0039 - 'r'
Character #0040 - ' '
Character #0041 - ' '
Character #0042 - ' '
Character #0043 - '1'
Character #0044 - '3'
Character #0045 - '6'
Character #0046 - 'B'
Character #0047 - ' '
Character #0048 - 'J'
Character #0049 - 'u'
Character #0050 - 'n'
Character #0051 - ' '
Character #0052 - '2'
Character #0053 - '6'
Character #0054 - ' '
Character #0055 - '1'
Character #0056 - '5'
Character #0057 - ':'
Character #0058 - '0'
Character #0059 - '0'
Character #0060 - ' '
Character #0061 - '.'
Character #0062 - '/'
Character #0063 - '
'
Character #0064 - 'd'
Character #0065 - 'r'
Character #0066 - 'w'
Character #0067 - 'x'
Character #0068 - 'r'
Character #0069 - '-'
Character #0070 - 'x'
Character #0071 - 'r'
Character #0072 - '-'
Character #0073 - 'x'
Character #0074 - '@'
Character #0075 - ' '
Character #0076 - '6'
Character #0077 - '2'
Character #0078 - ' '
Character #0079 - 'a'
Character #0080 - 'd'
Character #0081 - 'm'
Character #0082 - 'i'
Character #0083 - 'n'
Character #0084 - ' '
Character #0085 - ' '
Character #0086 - ' '
Character #0087 - 'd'
Character #0088 - 'a'
Character #0089 - 'r'
Character #0090 - 'k'
Character #0091 - 's'
Character #0092 - 't'
Character #0093 - 'a'
Character #0094 - 'r'
Character #0095 - ' '
Character #0096 - ' '
Character #0097 - ' '
Character #0098 - '2'
Character #0099 - '.'
Character #0100 - '1'
Character #0101 - 'K'
Character #0102 - ' '
Character #0103 - 'J'
Character #0104 - 'u'
Character #0105 - 'n'
Character #0106 - ' '
Character #0107 - '2'
Character #0108 - '6'
Character #0109 - ' '
Character #0110 - '1'
Character #0111 - '3'
Character #0112 - ':'
Character #0113 - '3'
Character #0114 - '8'
Character #0115 - ' '
Character #0116 - '.'
Character #0117 - '.'
Character #0118 - '/'
Character #0119 - '
'
Character #0120 - '-'
Character #0121 - 'r'
Character #0122 - 'w'
Character #0123 - '-'
Character #0124 - 'r'
Character #0125 - '-'
Character #0126 - '-'
Character #0127 - 'r'
Character #0128 - '-'
Character #0129 - '-'
Character #0130 - '@'
Character #0131 - ' '
Character #0132 - ' '
Character #0133 - '1'
Character #0134 - ' '
Character #0135 - 'a'
Character #0136 - 'd'
Character #0137 - 'm'
Character #0138 - 'i'
Character #0139 - 'n'
Character #0140 - ' '
Character #0141 - ' '
Character #0142 - ' '
Character #0143 - 'd'
Character #0144 - 'a'
Character #0145 - 'r'
Character #0146 - 'k'
Character #0147 - 's'
Character #0148 - 't'
Character #0149 - 'a'
Character #0150 - 'r'
Character #0151 - ' '
Character #0152 - ' '
Character #0153 - ' '
Character #0154 - ' '
Character #0155 - '1'
Character #0156 - '2'
Character #0157 - 'K'
Character #0158 - ' '
Character #0159 - 'M'
Character #0160 - 'a'
Character #0161 - 'y'
Character #0162 - ' '
Character #0163 - '1'
Character #0164 - '3'
Character #0165 - ' '
Character #0166 - '0'
Character #0167 - '5'
Character #0168 - ':'
Character #0169 - '5'
Character #0170 - '2'
Character #0171 - ' '
Character #0172 - '.'
Character #0173 - 'D'
Character #0174 - 'S'
Character #0175 - '_'
Character #0176 - 'S'
Character #0177 - 't'
Character #0178 - 'o'
Character #0179 - 'r'
Character #0180 - 'e'
Character #0181 - '
'
Character #0182 - '-'
Character #0183 - 'r'
Character #0184 - 'w'
Character #0185 - '-'
Character #0186 - 'r'
Character #0187 - '-'
Character #0188 - '-'
Character #0189 - 'r'
Character #0190 - '-'
Character #0191 - '-'
Character #0192 - ' '
Character #0193 - ' '
Character #0194 - ' '
Character #0195 - '1'
Character #0196 - ' '
Character #0197 - 'a'
Character #0198 - 'd'
Character #0199 - 'm'
Character #0200 - 'i'
Character #0201 - 'n'
Character #0202 - ' '
Character #0203 - ' '
Character #0204 - ' '
Character #0205 - 'd'
Character #0206 - 'a'
Character #0207 - 'r'
Character #0208 - 'k'
Character #0209 - 's'
Character #0210 - 't'
Character #0211 - 'a'
Character #0212 - 'r'
Character #0213 - ' '
Character #0214 - ' '
Character #0215 - ' '
Character #0216 - ' '
Character #0217 - ' '
Character #0218 - '0'
Character #0219 - 'B'
Character #0220 - ' '
Character #0221 - 'J'
Character #0222 - 'u'
Character #0223 - 'n'
Character #0224 - ' '
Character #0225 - '2'
Character #0226 - '6'
Character #0227 - ' '
Character #0228 - '1'
Character #0229 - '5'
Character #0230 - ':'
Character #0231 - '0'
Character #0232 - '0'
Character #0233 - ' '
Character #0234 - 't'
Character #0235 - 'm'
Character #0236 - 'p'
Character #0237 - '.'
Character #0238 - 't'
Character #0239 - 'x'
Character #0240 - 't'
Character #0241 - '
'
Character #0242 - ''
<强>参考强>
<https://stackoverflow.com/questions/2693776/removing-trailing-newline-character-from-fgets-input>
答案 1 :(得分:1)
字符串:filename
,填充后在NULL之前有一个0x0A:
或者,以另一种方式显示:
这导致fopen()
处的文件未找到错误。此时,您的代码应退出。超出这一点将导致未定义的行为。
这可能不是您唯一的错误,但为了解决此错误,您可以执行以下操作:
(从stdin填充文件名后) 你必须把它清理一下......
int len = strlen(filename);
filename[len-2]=0;
其他错误 位于此部分代码中:
char data[1000]; //You have created char data type
for(int i=0; i<1000; i++){
fscanf(data_file, "%1d", &data[i]);//but your format string "%1d" expects an int.
}
<强> 要么 强>
更改fscanf(data_file, "%1d", &data[i]);
至fscanf(data_file, "%s", data[i]);
或者创建一个int数组:
int data[1000];
并使用原始的fscanf()调用。
顺便说一下,你应该检查fopen()
&amp;的输出值。 fscanf()
表示预期结果,如果发生则处理异常。
答案 2 :(得分:0)
你应该写这样的东西。您始终需要检查是否可以打开该文件。最好只传入命令行上的路径并将其从argv中拉出来。
int main(){
char filename[80];
FILE *data_file;
char data[1000];
int i;
/* Input file name */
printf("\nInput file name: ");
fgets(filename, 79, stdin);
/* Remove '/n' from filename string*/
if (filename && strlen(filename) > 1) {
filename[strlen(filename)-2] = 0;
}
/* Open file */
data_file = fopen(filename,"r");
/* Read data */
if (data_file) {
for (i=0; i<1000; i++){
fscanf(data_file, "%1d", &data[i]);
}
fclose(data_file);
}
else {
printf("Could not open file\n");
}
return 0;
}