Ncurses 程序正在退出,甚至没有创建 window
Ncurses program is exiting without even creating a window
我写了一个简单的C语言抽认卡程序;它以文件名作为第二个参数,然后读取该文件 line-by-line 并使用 ncurses,向用户显示问题,按 enter 后会显示答案,再次按刷新 ncurses window以便读取下一行。读取的文件是一个简单的 TSV(尽管我已经将其编写为可以是任何定界符)。这是文件,标题为 f.c:
注意:我使用了 readline(),一个 non-C-standard 函数,因为这是一个我只会在 POSIX 系统上使用的个人项目,所以使用 fgets 正确管理内存的头痛是不值得的
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ncurses.h>
#include <unistd.h>
#include <errno.h>
#define DELIM "\t"
int count_occ(char* string, char* val)
{
int count = 0;
const char* tmp = string;
while(tmp = strstr(tmp, val))
{
count++;
tmp++;
}
return count;
}
bool valid_file(FILE* stream)
{
char* line = NULL;
size_t len;
while(getline(&line, &len, stream) != -1)
{
if(count_occ(line, DELIM) != 1)
{
return false;
}
}
return true;
}
int main(int argc, char* argv[])
{
if(argc != 2)
{
fprintf(stderr, "File name must be supplied\n");
exit(EXIT_FAILURE);
}
if(!access(argv[1], F_OK) == 0)
{
fprintf(stderr, "File supplied in second argument does not exist\n");
exit(EXIT_FAILURE);
}
FILE* stream = fopen(argv[1], "r");
if(!valid_file(stream))
{
fprintf(stderr, "File supplied is not properly formatted: a line is missing a set of delimited values or too many fields were noticed\n");
exit(EXIT_FAILURE);
}
initscr();
noecho();
raw();
char* line = NULL;
size_t len;
while(getline(&line, &len, stream) != -1)
{
char* qn = strtok(line, DELIM);
char* ans = strtok(NULL, DELIM);
char c;
printw("Question:\n\t%s\nAnswer:\n\t...\n\n", qn);
while((c = getch()) != 10);
refresh();
move(0, 0);
printw("Question:\n\t%s\nAnswer:\n\t%s\n\n", qn, ans);
while((c = getch()) != 10);
refresh();
move(0, 0);
}
endwin();
return 0;
}
我编译它使用:
gcc f.c -o fc -lncurses
..当然安装了正确的库。
然后我使用这个文件 test.txt 作为示例:
What is my name? Teddy Roosevolt
What is my name? Teddy Roosevolt
Where am I from? USA
What is my ethnicity? Caucasian
What is my nationality? British
What is my name? Teddy Roosevolt
Where am I from? USA
What is my ethnicity? Caucasian
What is my nationality? British
What is my name? Teddy Roosevolt
Where am I from? USA
What is my ethnicity? Caucasian
What is my nationality? British
Where am I from? USA
What is my ethnicity? Caucasian
What is my nationality? British
然后我 运行 它与:
./fc test.txt
我什么也没得到 - 甚至没有错误,什么都没有。相反,程序 运行 立即退出。在 error-less 抽认卡文件上测试它之前,我在格式不正确的文件上对其进行了测试 - 格式不正确的文件会引发所有正确的错误,这告诉我它不起作用的原因与主文件开头的代码块检查文件是否有效 - 我认为它与 ncurses 部分有关 - 但我不知道是什么。
感谢您的帮助。
真的很简单,和ncurses无关:
你永远不会倒回你的文件!
您的 valid_file
函数读取文件中的所有数据,不为 main
中的循环留下任何数据。
由于您从未在该函数之后重置文件位置,因此永远不会执行 main
中的循环,因为 readline
没有任何内容可读,您的程序结束。
您必须在 valid_file
的末尾 return true
之前添加 fseek(stream, 0, SEEK_SET);
。
另请注意,您永远不会 free
内存 readline
为您分配,您必须在每次调用后执行此操作,并将 line
指针重置为 NULL 和 len
到 0,让它分配一个新的缓冲区。
否则会导致内存泄漏。
如果您的文本文件很小,它可能不会引起注意,但这仍然是一个糟糕的编程习惯!
我写了一个简单的C语言抽认卡程序;它以文件名作为第二个参数,然后读取该文件 line-by-line 并使用 ncurses,向用户显示问题,按 enter 后会显示答案,再次按刷新 ncurses window以便读取下一行。读取的文件是一个简单的 TSV(尽管我已经将其编写为可以是任何定界符)。这是文件,标题为 f.c:
注意:我使用了 readline(),一个 non-C-standard 函数,因为这是一个我只会在 POSIX 系统上使用的个人项目,所以使用 fgets 正确管理内存的头痛是不值得的
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ncurses.h>
#include <unistd.h>
#include <errno.h>
#define DELIM "\t"
int count_occ(char* string, char* val)
{
int count = 0;
const char* tmp = string;
while(tmp = strstr(tmp, val))
{
count++;
tmp++;
}
return count;
}
bool valid_file(FILE* stream)
{
char* line = NULL;
size_t len;
while(getline(&line, &len, stream) != -1)
{
if(count_occ(line, DELIM) != 1)
{
return false;
}
}
return true;
}
int main(int argc, char* argv[])
{
if(argc != 2)
{
fprintf(stderr, "File name must be supplied\n");
exit(EXIT_FAILURE);
}
if(!access(argv[1], F_OK) == 0)
{
fprintf(stderr, "File supplied in second argument does not exist\n");
exit(EXIT_FAILURE);
}
FILE* stream = fopen(argv[1], "r");
if(!valid_file(stream))
{
fprintf(stderr, "File supplied is not properly formatted: a line is missing a set of delimited values or too many fields were noticed\n");
exit(EXIT_FAILURE);
}
initscr();
noecho();
raw();
char* line = NULL;
size_t len;
while(getline(&line, &len, stream) != -1)
{
char* qn = strtok(line, DELIM);
char* ans = strtok(NULL, DELIM);
char c;
printw("Question:\n\t%s\nAnswer:\n\t...\n\n", qn);
while((c = getch()) != 10);
refresh();
move(0, 0);
printw("Question:\n\t%s\nAnswer:\n\t%s\n\n", qn, ans);
while((c = getch()) != 10);
refresh();
move(0, 0);
}
endwin();
return 0;
}
我编译它使用:
gcc f.c -o fc -lncurses
..当然安装了正确的库。
然后我使用这个文件 test.txt 作为示例:
What is my name? Teddy Roosevolt
What is my name? Teddy Roosevolt
Where am I from? USA
What is my ethnicity? Caucasian
What is my nationality? British
What is my name? Teddy Roosevolt
Where am I from? USA
What is my ethnicity? Caucasian
What is my nationality? British
What is my name? Teddy Roosevolt
Where am I from? USA
What is my ethnicity? Caucasian
What is my nationality? British
Where am I from? USA
What is my ethnicity? Caucasian
What is my nationality? British
然后我 运行 它与:
./fc test.txt
我什么也没得到 - 甚至没有错误,什么都没有。相反,程序 运行 立即退出。在 error-less 抽认卡文件上测试它之前,我在格式不正确的文件上对其进行了测试 - 格式不正确的文件会引发所有正确的错误,这告诉我它不起作用的原因与主文件开头的代码块检查文件是否有效 - 我认为它与 ncurses 部分有关 - 但我不知道是什么。
感谢您的帮助。
真的很简单,和ncurses无关:
你永远不会倒回你的文件!
您的 valid_file
函数读取文件中的所有数据,不为 main
中的循环留下任何数据。
由于您从未在该函数之后重置文件位置,因此永远不会执行 main
中的循环,因为 readline
没有任何内容可读,您的程序结束。
您必须在 valid_file
的末尾 return true
之前添加 fseek(stream, 0, SEEK_SET);
。
另请注意,您永远不会 free
内存 readline
为您分配,您必须在每次调用后执行此操作,并将 line
指针重置为 NULL 和 len
到 0,让它分配一个新的缓冲区。
否则会导致内存泄漏。
如果您的文本文件很小,它可能不会引起注意,但这仍然是一个糟糕的编程习惯!