从 C 中的 stem 文件读取时出现问题
Problem while reading from the stem file in C
我有一个名为 myfile
的主干文件,它有 2 个子文件:myfile.data
和 myfile.names
。
现在我想写一段代码,它首先检查 .names
文件的最后一行,看看是否有零,如果有除零以外的任何其他数字,那么它会说 noisy data
。如果 .names
文件最后一行有一个零,那么我需要读取 .data
文件并对那个 .data
文件做一些操作以产生有效的输出。
下面我给出了我尝试做的事情:
int main(int argc, char **argv)
{
char *path = argc > 1 ? argv[1] : "stdin";
sprintf(path, "%s.names", argv[1]);
FILE *in = argc > 1 ? xfopen(path, "r") : stdin;
char buff[1024];
int check = 0;
fseek(in, 0, SEEK_SET);
while(!feof(in))
{
memset(buff, 0x00, 1024);
fscanf(in, "%[^\n]\n", buff);
}
if(strchr(buff, '0') != NULL){
check = 1;
}
if(check == 0){
printf("Noisy data...\n");
}
else if(check == 1){
char *path = argc > 1 ? argv[1] : "stdin";
sprintf(path, "%s.data", argv[1]);
FILE *in = argc > 1 ? xfopen(path, "r") : stdin;
char buf[1024];
if( fgets(buf, sizeof buf, in) == NULL ){
fputs("Input error\n", stderr);
return 1;
}
...
...
produces the perfect output.
}
}
}
要执行此操作:<./executable_filename> <stemFileName> > <outputFileName>
所以每当我做的时候:./myFileName myfile output
它给我看:myfile.names.data: No such file or directory
为什么会这样?请帮忙
下面的示例展示了如何打开 *.names
文件,并包含检查文件的最后一行是否满足各种属性的逻辑。
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(int argc, char **argv)
{
if( argc < 2 ){
fprintf(stderr, "root filename required\n");
return 1;
}
const char *base = argv[1];
char input_path[PATH_MAX];
snprintf(input_path, sizeof input_path, "%s.names", base);
FILE *ifp = fopen(input_path, "r");
if( ifp == NULL ){
perror(input_path);
return 1;
}
char buf[1024];
/* Read the entire file one line at a time. You could fseek to the
end of the file and seek backwards to the start
of the last line, but that seems to be an unnecessary
complication for this example. */
while( fgets(buf, sizeof buf, ifp) != NULL ){
;
}
/* When you get to the end, the last `fgets` returned NULL
but did not write anything into buf, so buf contains the last
line of the file */
/* Check for read errors.
ferror does not modify errno, but I can't find that
in the language standard, so we'll make a copy. Restoring
errno ensures that `perror` reports the error that occurred
during fgets rather than an error that occurs in the call to
ferror. This is probably overkill for this simple example. It
would be more important to check that `fgets` read a full line
and handle that. If the last line of the file is too large
to fit in `buf`, the program should handle it; probably by aborting
with an error message, but I don't know what you want to do in that
case so I'm not bothering to check.
*/
int errno_sav = errno;
if( ferror(ifp) ){
errno = errno_sav;
perror(input_path);
return 1;
}
puts("The last line is:");
fputs(buf, stdout);
/* Check if the last line contains a '0' */
if( strchr(buf, '0') ){
puts("The last line contains a 0");
}
/* Check if the last line is exactly the string "0\n" */
if( strcmp(buf, "0\n") == 0 ){
puts("The last contains nothing but a single 0");
}
char *end;
/* Check if the last line is exactly some string representation
of the integer 0. (ie, "0000\n" "0x0") */
if( strtol(buf, &end, 0) == 0 && end != buf && *end == '\n'){
puts("The last line is the integer 0");
}
return EXIT_SUCCESS;
}
请注意,您可能需要检查 snprintf
是否有足够的 space 来写入文件名,但这实际上不是必需的。如果路径太长而成为问题,则 fopen 将失败并且您将收到一条不错的错误消息。这可能会导致您的程序错误地处理名称被截断的文件,例如 ...bas.nam
,学习如何处理该文件可能是一个很好的练习。
我有一个名为 myfile
的主干文件,它有 2 个子文件:myfile.data
和 myfile.names
。
现在我想写一段代码,它首先检查 .names
文件的最后一行,看看是否有零,如果有除零以外的任何其他数字,那么它会说 noisy data
。如果 .names
文件最后一行有一个零,那么我需要读取 .data
文件并对那个 .data
文件做一些操作以产生有效的输出。
下面我给出了我尝试做的事情:
int main(int argc, char **argv)
{
char *path = argc > 1 ? argv[1] : "stdin";
sprintf(path, "%s.names", argv[1]);
FILE *in = argc > 1 ? xfopen(path, "r") : stdin;
char buff[1024];
int check = 0;
fseek(in, 0, SEEK_SET);
while(!feof(in))
{
memset(buff, 0x00, 1024);
fscanf(in, "%[^\n]\n", buff);
}
if(strchr(buff, '0') != NULL){
check = 1;
}
if(check == 0){
printf("Noisy data...\n");
}
else if(check == 1){
char *path = argc > 1 ? argv[1] : "stdin";
sprintf(path, "%s.data", argv[1]);
FILE *in = argc > 1 ? xfopen(path, "r") : stdin;
char buf[1024];
if( fgets(buf, sizeof buf, in) == NULL ){
fputs("Input error\n", stderr);
return 1;
}
...
...
produces the perfect output.
}
}
}
要执行此操作:<./executable_filename> <stemFileName> > <outputFileName>
所以每当我做的时候:./myFileName myfile output
它给我看:myfile.names.data: No such file or directory
为什么会这样?请帮忙
下面的示例展示了如何打开 *.names
文件,并包含检查文件的最后一行是否满足各种属性的逻辑。
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(int argc, char **argv)
{
if( argc < 2 ){
fprintf(stderr, "root filename required\n");
return 1;
}
const char *base = argv[1];
char input_path[PATH_MAX];
snprintf(input_path, sizeof input_path, "%s.names", base);
FILE *ifp = fopen(input_path, "r");
if( ifp == NULL ){
perror(input_path);
return 1;
}
char buf[1024];
/* Read the entire file one line at a time. You could fseek to the
end of the file and seek backwards to the start
of the last line, but that seems to be an unnecessary
complication for this example. */
while( fgets(buf, sizeof buf, ifp) != NULL ){
;
}
/* When you get to the end, the last `fgets` returned NULL
but did not write anything into buf, so buf contains the last
line of the file */
/* Check for read errors.
ferror does not modify errno, but I can't find that
in the language standard, so we'll make a copy. Restoring
errno ensures that `perror` reports the error that occurred
during fgets rather than an error that occurs in the call to
ferror. This is probably overkill for this simple example. It
would be more important to check that `fgets` read a full line
and handle that. If the last line of the file is too large
to fit in `buf`, the program should handle it; probably by aborting
with an error message, but I don't know what you want to do in that
case so I'm not bothering to check.
*/
int errno_sav = errno;
if( ferror(ifp) ){
errno = errno_sav;
perror(input_path);
return 1;
}
puts("The last line is:");
fputs(buf, stdout);
/* Check if the last line contains a '0' */
if( strchr(buf, '0') ){
puts("The last line contains a 0");
}
/* Check if the last line is exactly the string "0\n" */
if( strcmp(buf, "0\n") == 0 ){
puts("The last contains nothing but a single 0");
}
char *end;
/* Check if the last line is exactly some string representation
of the integer 0. (ie, "0000\n" "0x0") */
if( strtol(buf, &end, 0) == 0 && end != buf && *end == '\n'){
puts("The last line is the integer 0");
}
return EXIT_SUCCESS;
}
请注意,您可能需要检查 snprintf
是否有足够的 space 来写入文件名,但这实际上不是必需的。如果路径太长而成为问题,则 fopen 将失败并且您将收到一条不错的错误消息。这可能会导致您的程序错误地处理名称被截断的文件,例如 ...bas.nam
,学习如何处理该文件可能是一个很好的练习。