Ncurses 程序甚至没有创建窗口就退出了

问题描述

我写了一个简单的 C 语言抽认卡程序;它将文件名作为第二个参数,然后逐行读取该文件并使用 ncurses,将问题显示用户,按 Enter 时会显示答案,再次按会刷新 ncurses 窗口,以便下一个行被读取。读取的文件一个简单的 TSV(尽管我已经编写了它以便它可以是任何分隔符)。这是名为 f.c文件

注意:我使用了非 C 标准函数 readline(),因为这是一个我只会在 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,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

我一无所获 - 甚至没有错误,根本没有。相反,程序立即运行并立即退出。我在格式错误文件上对其进行了测试,然后在无错误的抽认卡文件上对其进行了测试 - 格式错误文件会引发所有正确的错误,这告诉我它不起作用的原因与块主文件开头的代码检查文件是否有效 - 我认为这与 ncurses 部分有关 - 但我不知道是什么。

感谢您的帮助。

解决方法

它真的很简单,与 ncurses 无关:

您永远不会倒带您的文件!

您的 valid_file 函数读取您文件中的所有数据,在 main 中不为循环留下任何内容。

由于您从未在该函数之后重置文件位置,因此永远不会执行 main 中的循环,因为 readline 没有任何内容可供读取,并且您的程序结束。

您必须在 fseek(stream,SEEK_SET); 之前的 valid_file 末尾添加 return true

另请注意,您永远不会free为您分配内存readline,您必须在每次调用后执行此操作,并将line指针重置为NULL和{{1} } 到 0,让它分配一个新的缓冲区。

否则会导致内存泄漏。
如果您的文本文件很小,可能不会引起注意,但这仍然是一种糟糕的编程习惯!