用C构建一个非常简单的解析器

用C构建一个非常简单的解析器,c,parsing,C,Parsing,我试图用C语言为一个类构建一个非常简单的解析器。它所要做的就是从输入文件中读取一个标志,确定该标志是在int、char还是float之前,然后将int/float/char写入相应的.txt文件。例如,I 9898将被打印到int.txt。无论何时使用讲师提供的测试脚本,我都会遇到以下错误: parser.c:1:1:错误:未知类型名称“e” parser.c:1:10:错误:应为“=”,“,”,“;”,”“打开”之前的asm或“属性” parser.c:1:10:错误:未知类型名称“on” 这

我试图用C语言为一个类构建一个非常简单的解析器。它所要做的就是从输入文件中读取一个标志,确定该标志是在int、char还是float之前,然后将int/float/char写入相应的.txt文件。例如,I 9898将被打印到int.txt。无论何时使用讲师提供的测试脚本,我都会遇到以下错误:

parser.c:1:1:错误:未知类型名称“e” parser.c:1:10:错误:应为“=”,“,”,“;”,”“打开”之前的asm或“属性” parser.c:1:10:错误:未知类型名称“on”

这是我的密码,请告诉我。非常感谢:

int main(int argc, char *argv[])
{
#include <stdio.h>
    FILE *input = fopen("input.txt", "r");
    FILE *ints.txt = fopen("ints.txt" "w");
    FILE *chars.txt = fopen("chars.txt", "w");
    FILE *floats.txt = fopen("floats.txt", "w");

    char flag;
    int ipint;
    char ipchar;
    float ipfloat;
    int exitStatus = fscanf(input.txt, "%c", &flag);

    while (exitStatus != EOF)
    {
        if (flag == I)
        {
            fscanf(input.txt, "%i", &ipint);
            fprintf(ints.txt, ipint);
        }
        if (flag == C)
        {
            fscanf(input.txt, "%c", &ipchar);
            fprintf(chars.txt, ipchar);
        }
        if (flag == F)
        {
            fscanf(input.txt, "%f", &ipfloat);
            fprintf(floats.txt, ipfloat);
        }
    }
    fclose(input.txt);
    fclose(ints.txt);
    fclose(floats.txt);
    fclose(chars.txt);
}

将标准头放在文件范围,而不是块范围:

 #include <stdio.h>

 int main(int argc, char *argv[])
 {
    ...

将标准头放在文件范围,而不是块范围:

 #include <stdio.h>

 int main(int argc, char *argv[])
 {
    ...
使用switch语句,而不是多个if语句 fprintf与printf相同,唯一的区别是您可以决定标准输出,所以仍然需要字符格式 变量名不能有空。字符,因为这是为访问对象的成员而保留的 exitStatus需要在每次迭代时更新,以便程序知道何时停止读取文件。我用了fgetc和ungetc 此代码应满足您的需要:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    FILE *input = fopen("input.txt", "r");
    FILE *ints = fopen("ints.txt", "w+");
    FILE *chars = fopen("chars.txt", "w+");
    FILE *floats = fopen("floats.txt", "w+");

    int flag, ipint, exitStatus;
    char ipchar;
    float ipfloat;

    if (NULL == input) {
        perror("File not found [input.txt]");
        return EXIT_FAILURE;
    }

    while ((exitStatus = fgetc(input)) != EOF && ungetc(exitStatus, input))
    {
        fscanf(input, "%d", &flag);
        switch (flag) {

            case 'I':
                fscanf(input, "%i", &ipint);
                fprintf(ints, "%i", ipint);
                break;

            case 'C':
                fscanf(input, "%c", &ipchar);
                fprintf(chars, "%c", ipchar);

                break;

            case 'F':
                fscanf(input, "%f", &ipfloat);
                fprintf(floats, "%f", ipfloat);
                break;

            default:
                puts("Flag not recognized");
                fclose(input);
                fclose(ints);
                fclose(floats);
                fclose(chars);
                return EXIT_FAILURE;
        }

    }
    fclose(input);
    fclose(ints);
    fclose(floats);
    fclose(chars);

    return EXIT_SUCCESS;
}
使用switch语句,而不是多个if语句 fprintf与printf相同,唯一的区别是您可以决定标准输出,所以仍然需要字符格式 变量名不能有空。字符,因为这是为访问对象的成员而保留的 exitStatus需要在每次迭代时更新,以便程序知道何时停止读取文件。我用了fgetc和ungetc 此代码应满足您的需要:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    FILE *input = fopen("input.txt", "r");
    FILE *ints = fopen("ints.txt", "w+");
    FILE *chars = fopen("chars.txt", "w+");
    FILE *floats = fopen("floats.txt", "w+");

    int flag, ipint, exitStatus;
    char ipchar;
    float ipfloat;

    if (NULL == input) {
        perror("File not found [input.txt]");
        return EXIT_FAILURE;
    }

    while ((exitStatus = fgetc(input)) != EOF && ungetc(exitStatus, input))
    {
        fscanf(input, "%d", &flag);
        switch (flag) {

            case 'I':
                fscanf(input, "%i", &ipint);
                fprintf(ints, "%i", ipint);
                break;

            case 'C':
                fscanf(input, "%c", &ipchar);
                fprintf(chars, "%c", ipchar);

                break;

            case 'F':
                fscanf(input, "%f", &ipfloat);
                fprintf(floats, "%f", ipfloat);
                break;

            default:
                puts("Flag not recognized");
                fclose(input);
                fclose(ints);
                fclose(floats);
                fclose(chars);
                return EXIT_FAILURE;
        }

    }
    fclose(input);
    fclose(ints);
    fclose(floats);
    fclose(chars);

    return EXIT_SUCCESS;
}
建议的修改:

#include <stdio.h>

int main(int argc, char *argv[])
{
    FILE fp_input = NULL;
    FILE fp_ints = NULL;
    FILE fp_chars = NULL;
    FILE fp_floats = NULL;

    char flag;
    int ipint;
    char ipchar;
    float ipfloat;
    int exitStatus;

    if (!(fp_input= fopen("input.txt", "r")) {
      perror ("fp_input failed");
      return 1;
    }

    if (!(fp_ints = fopen("ints.txt" "w")) {
      ...
    if (fscanf(fp_input, "%c", &flag)!= 1) { 
      ...

    while (exitStatus != EOF){
      switch (flag) {
        case 'I' :
          fscanf(fp_input,"%i",&ipint);
          fprintf(fp_ints, "%d", ipint);
          break;
        case 'C' :
          ...
        default :
          ...
    }
换言之:

1包含项位于错误的位置

2我不会使用像input.txt这样的变量名,在名称中加句点

我想你指的是常数‘I’,而不是变量I

4您应尽可能随时检查错误,如fopen、fscanf等

5您需要fprintf的格式字符串

建议的更改:

#include <stdio.h>

int main(int argc, char *argv[])
{
    FILE fp_input = NULL;
    FILE fp_ints = NULL;
    FILE fp_chars = NULL;
    FILE fp_floats = NULL;

    char flag;
    int ipint;
    char ipchar;
    float ipfloat;
    int exitStatus;

    if (!(fp_input= fopen("input.txt", "r")) {
      perror ("fp_input failed");
      return 1;
    }

    if (!(fp_ints = fopen("ints.txt" "w")) {
      ...
    if (fscanf(fp_input, "%c", &flag)!= 1) { 
      ...

    while (exitStatus != EOF){
      switch (flag) {
        case 'I' :
          fscanf(fp_input,"%i",&ipint);
          fprintf(fp_ints, "%d", ipint);
          break;
        case 'C' :
          ...
        default :
          ...
    }
换言之:

1包含项位于错误的位置

2我不会使用像input.txt这样的变量名,在名称中加句点

我想你指的是常数‘I’,而不是变量I

4您应尽可能随时检查错误,如fopen、fscanf等


5您的fprintf需要一个格式字符串

include属于文件的开头,而不是main中。还有一个提醒:常规变量名不能有一个。在他们里面。在C中,I、F和C将被视为未声明的变量名。代码中还有其他几个问题,fopen可能会失败,您需要检查返回代码。你需要在引号之间加上字符,比如:ifflag=='I',变量名中也禁止有点,这是无效的:FILE*ints.txt。不要用C写解析器。这已经完成了,你可以做得更好的可能性很小。相反,看看lex和yacc,从标记和语法生成解析器。@AndreasGrapentin-他说这是为了类赋值,所以我怀疑他是否有语言选择。include属于文件的开头,而不是main内部。还有一个提醒:常规变量名不能有一个。在他们里面。在C中,I、F和C将被视为未声明的变量名。代码中还有其他几个问题,fopen可能会失败,您需要检查返回代码。你需要在引号之间加上字符,比如:ifflag=='I',变量名中也禁止有点,这是无效的:FILE*ints.txt。不要用C写解析器。这已经完成了,你可以做得更好的可能性很小。相反,看看lex和yacc,从标记和语法生成解析器。@AndreasGrapentin-他说这是一个类赋值,所以我怀疑他是否有语言选择。太棒了,谢谢。除了fopen和上面的评论之外,还有什么值得你关注的吗?太棒了,谢谢。除了fopen和上面的评论之外,还有什么值得你关注的吗?非常感谢,我的if语句有什么问题吗?或者开关是否工作得更好?因为如果我的if没有问题,我想保留它们,我们还没有学习switch语句。是的,if语句没有问题。这只是一个我推荐切换的偏好问题。我喜欢使用switch-case语句,因为它们看起来更具可读性,而程序看起来更少clustered@Smac89:程序中存在错误,如果标志无效,则不关闭文件。另外,从main返回-1不是标准的,您应该返回EXIT_FAILURE,对于posix系统,它是1。@Smac89 switch case比if快一点,因为switch case可以直接编译为jmp指令,但if可能不会。非常感谢,我的if语句或does switch有什么问题吗
只是工作得更好?因为如果我的if没有问题,我想保留它们,我们还没有学习switch语句。是的,if语句没有问题。这只是一个我推荐切换的偏好问题。我喜欢使用switch-case语句,因为它们看起来更具可读性,而程序看起来更少clustered@Smac89:程序中存在错误,如果标志无效,则不关闭文件。另外,从main返回-1也不是标准的,您应该返回EXIT_FAILURE,对于posix系统为1。@Smac89开关大小写比if快一点,因为开关大小写可以直接编译为jmp指令,但if可能不会。