我是一名正在进行中的C程序员,刚开始觉得我做对了。习惯了更高级别的语言(比如C#和Python),我真的很想念我的例外。
以下是我编写的一个函数,目前正用于查看流X个字符。
在此功能中可以进行哪些错误检查以确保它不会制动程序?
#include <stdio.h>
#include <string.h>
#include "speek.h"
void speek(char *peek, size_t len, FILE *stream) {
int i;
for (i = 0; i < len; i++) {
peek[i] = fgetc(stream);
if (feof(stream) || i >= len - 1) {
// Null terminate the string if stream is EOF or requested number
// of characters has already been fetched.
peek[i] = '\0';
break;
}
}
for (i = strlen(peek); i >= 0; i--) {
ungetc(peek[i], stream);
}
}
答案 0 :(得分:1)
如Pavan Manjunath所示,您的程序中存在错误。我可以立即看到的至少另外一个是你不处理文件中的NUL字符:在函数的末尾你使用strlen
,它只测量你到第一个NUL字节的刺痛,不一定是你实际阅读的字节数。
但这是一般的错误。您具体询问了错误检查。没有人提到检查错误的最重要的地方:如果读取文件时出错。您应该按照其联机帮助页(首选)中的说明检查fgetc()
的EOF返回值,或者之后使用ferror()
函数来测试是否在读取文件时发生错误。
根据Thiruvalluvar建议检查peek
和stream
是否为NULL是防御性的,但我不会说必要。那些不应该是NULL。如果是,那就是你的来电者的错,而不是你的。
答案 1 :(得分:1)
我会在阅读字符时检查文件*。
我认为这是一种风格化的东西,但我不会放置我通常打算在循环中发生的事情。
最后,成功读取的字符串应始终以'\ 0'结尾。当发生错误时,我经常被撕裂。如果我知道这个功能是什么,我通常可以选择。
所以,使用你的文件检查方式:
void speek(char *peek, size_t len, FILE *stream) {
int i;
for (i = 0; i < len-1 && !feof(stream); i++) {
peek[i] = fgetc(stream);
}
peek[i] = '\0';
for (i = strlen(peek)-1; i >= 0; i--) {
if (ungetc(peek[i], stream) != peek[i]) {
break; // I'd return an error, but function is void
}
}
}
如果这不仅仅是一个快速的实验,或者我正在为别人写这个,我可能会使用assert来检查参数(是的,我知道,我仍然这样做(c = getc(...)),我是旧)
#include <assert.h>
int speek(char *peek, size_t len, FILE *stream) {
assert(peek != NULL);
assert(len > 0); /* Could 0 be okay? */
assert(stream != NULL && !ferror(stream));
int i;
int c;
for (i = 0; i < len-1 && (c=getc(stream)) != EOF; i++) {
peek[i] = c;
}
peek[i] = '\0';
if (ferror(stream)) return -1;
for (int j = i-1; j >= 0; j--) {
if (ungetc(peek[j], stream) != peek[j]) {
return -1;
}
}
return i; /* I like to return something useful */
}
编辑:我试图反映原文,但这不是我做的方式,所以我最终放弃了,写下了我通常打算写的东西。
Edit2:......但我犯了一个错误。正确的方法是检查之前是否有空间阅读它。卫生署!
简单的测试程序:
int main (int argc, const char * argv[]) {
char line0[100];
int n0 = speek(line0, 4, stdin);
fprintf(stderr, "%d '%s'\n", n0, line0);
char line1[100];
int n1 = speek(line1, 8, stdin);
fprintf(stderr, "%d '%s'\n", n1, line1);
return 0;
}
鉴于仅包含abcefghij
的文件提供
3 'abc'
7 'abcdefg'
答案 2 :(得分:0)
添加@Thiruvalluvar注意到的内容,
如果文件为空,peek
只包含NULL
个字符。 i = strlen(peek)
将返回0
,但您仍然进入循环,因为您有i>=0
并尝试将某个角色推回到您从未从那里获得的流中。即使len
为零,也会出现相同的情况!
您还没有监控ungetc
的返回值。失败时可能会返回EOF
。
答案 3 :(得分:0)
除了检查NULL
和if (len > 0)
的指针外,我建议您检查FILE *
是否有效。您可以将其传递给fileno()
并检查它是否返回与-1
不同的值。