用 C 编写我自己的 'fgets()' 版本
Writing my own version of 'fgets()' in C
我想创建我自己的函数版本 fgets()
。
我尝试这样做,但 运行 遇到了一些问题。
请让我知道哪里出错了。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *my_fgets(char my_string[], int bytes, const char *filename) {
int i = 0;
FILE *fp;
if ((fp = fopen(filename, "wb")) == NULL) {
fprintf(stderr,"Couldn't open the file");
return NULL;
}
while (sizeof(my_string) < bytes || my_string[i] != '\n')
my_string[i++] = getc(fp);
my_string[i] = '[=11=]'; //adding NULL character at the end
/* using pointers
char *p;
for (p = array; p < array + bytes; p++)
*p = getc(fp);
*p = '[=11=]'; */
fclose(fp);
return my_string;
}
int main() {
char my_string[15];
int n;
char *p;
p = my_fgets(my_string, sizeof(my_string), stdin);
printf("\n%s", my_string);
printf("\n%s", p);
return 0;
}
我的输出不是运行ning,它立即崩溃。任何帮助将不胜感激。
您 对 fgets()
的实施 存在许多重大问题:
原型不正确:最后一个参数应该是流指针 (FILE *
),而不是文件名 (const char *
)。你用 stdin
调用你的函数,它确实是一个流而不是文件名。编译器应针对此错误发出警告。恕我直言,这个警告应该是一个错误。启用所有编译器警告并且不要忽略它们:gcc -Wall -W -Werror
.
要打开文件以作为文本读取,您应该使用模式字符串 "r"
,而不是 "wb"
,这将截断文件,但由于函数应该接收a FILE *
,这是一个有争议的问题。
while (sizeof(my_string) < bytes || my_string[i] != '\n')
中的测试不正确的原因有很多:您应该将 i
与数组大小进行比较,而不是 sizeof(my_string)
,它是一个常量,大小一个指针,你应该比较从文件中读取的字节,而不是 my_string[i]
你还没有存储任何东西。此外,您应该使用逻辑与运算符 (&&
) 来组合这些测试,而不是逻辑或 (||
).
最终的 '\n'
应存储到目标数组中。
你没有在文件末尾 return NULL
。
您不处理缓冲区大小为零的特殊情况。
这是一个改进的版本:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *my_fgets(char my_string[], int bytes, FILE *fp) {
int c, i = 0;
if (bytes <= 0)
return my_string;
while (i < bytes - 1 && ((c = getc(fp)) != EOF) {
my_string[i++] = c;
if (c == '\n')
break;
}
my_string[i] = '[=10=]'; //adding NUL character at the end
if (i > 0) {
return my_string;
} else {
return NULL; // no character read at end of file
}
}
int main(void) {
char my_string[15];
int n;
char *p;
p = my_fgets(my_string, sizeof(my_string), stdin);
printf("%s\n", my_string);
printf("%s\n", p);
return 0;
}
我想创建我自己的函数版本 fgets()
。
我尝试这样做,但 运行 遇到了一些问题。
请让我知道哪里出错了。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *my_fgets(char my_string[], int bytes, const char *filename) {
int i = 0;
FILE *fp;
if ((fp = fopen(filename, "wb")) == NULL) {
fprintf(stderr,"Couldn't open the file");
return NULL;
}
while (sizeof(my_string) < bytes || my_string[i] != '\n')
my_string[i++] = getc(fp);
my_string[i] = '[=11=]'; //adding NULL character at the end
/* using pointers
char *p;
for (p = array; p < array + bytes; p++)
*p = getc(fp);
*p = '[=11=]'; */
fclose(fp);
return my_string;
}
int main() {
char my_string[15];
int n;
char *p;
p = my_fgets(my_string, sizeof(my_string), stdin);
printf("\n%s", my_string);
printf("\n%s", p);
return 0;
}
我的输出不是运行ning,它立即崩溃。任何帮助将不胜感激。
您 对 fgets()
的实施 存在许多重大问题:
原型不正确:最后一个参数应该是流指针 (
FILE *
),而不是文件名 (const char *
)。你用stdin
调用你的函数,它确实是一个流而不是文件名。编译器应针对此错误发出警告。恕我直言,这个警告应该是一个错误。启用所有编译器警告并且不要忽略它们:gcc -Wall -W -Werror
.要打开文件以作为文本读取,您应该使用模式字符串
"r"
,而不是"wb"
,这将截断文件,但由于函数应该接收aFILE *
,这是一个有争议的问题。while (sizeof(my_string) < bytes || my_string[i] != '\n')
中的测试不正确的原因有很多:您应该将i
与数组大小进行比较,而不是sizeof(my_string)
,它是一个常量,大小一个指针,你应该比较从文件中读取的字节,而不是my_string[i]
你还没有存储任何东西。此外,您应该使用逻辑与运算符 (&&
) 来组合这些测试,而不是逻辑或 (||
).最终的
'\n'
应存储到目标数组中。你没有在文件末尾 return
NULL
。您不处理缓冲区大小为零的特殊情况。
这是一个改进的版本:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *my_fgets(char my_string[], int bytes, FILE *fp) {
int c, i = 0;
if (bytes <= 0)
return my_string;
while (i < bytes - 1 && ((c = getc(fp)) != EOF) {
my_string[i++] = c;
if (c == '\n')
break;
}
my_string[i] = '[=10=]'; //adding NUL character at the end
if (i > 0) {
return my_string;
} else {
return NULL; // no character read at end of file
}
}
int main(void) {
char my_string[15];
int n;
char *p;
p = my_fgets(my_string, sizeof(my_string), stdin);
printf("%s\n", my_string);
printf("%s\n", p);
return 0;
}