【问题标题】:Vector of linked lists not working properly链表向量无法正常工作
【发布时间】:2016-10-16 19:39:37
【问题描述】:

我是 C 编程的初学者,我正在尝试创建一个算法来查找 firstfollow 给定语法的集合.txt 文件。

输入语法如下:

S-abA|e|bhG|AKX
A-Kb|d
K-j|c|e
X-p

到目前为止,我只是在尝试定义用于查找这些集合的结构(这就是我遇到的问题)。

我正在使用一个列表向量,其中每个列表将包含我的语法的 RHS 值,并且向量中的每个位置(由输入文件中的规则或行数定义)将是指向列表。 下面的函数编译并几乎工作。产品被正确读取并且变量“producao”工作正常,我尝试将其打印出来并且它正确获取每个值,但是当我将这些值添加到列表中时,当我打印整个清单是:

而我应该拥有的是:

我遇到问题的功能发布在下面:

criaListaRegras()
{
    lista *regras;
    regras = cria_lista(); // initialize list pointing to null
    lista **vetor; // declare the vector of list pointers
    vetor = malloc(sizeof(lista)*numLinhas);

    int i = 0;
    int numLinha = 0;
    char producao[10]; // Each production in the RHS will have at most 9 characters and will be added to this variable, one at a time.
    FILE *entrada;
    entrada = fopen("entrada.txt", "r"); // input file
    fseek(entrada, 2, SEEK_SET); // seek to RHS of the rule. (S-ab|AbB), makes fp go to 'a'.
    char linha; // Will be used to parse the input

    while ((linha = getc(entrada)) != EOF){
        if (linha == '\n'){ // checks if a rule has ended, so that we add end of string to production and append that into the list.
            producao[i] = '\0';
            inserir(regras, producao); // append production (producao) into the list (regras).
            imprimir(regras); // should print all values inside "regras" but only print the last value added * "number of productions found so far".
            vetor[numLinha] = regras; // should assign a list into its position in the pre-defined vector of lists at position "numLinha".
            i = 0; // resets string position counter to 0 so we can reuse it for next production.
            numLinha++; // increment line/rule counter.
            fseek(entrada, 2, SEEK_CUR);
        }
        if (linha == '|'){ // our production delim is '|', so if we find it, means a production has ended and we should add it into the list.
            producao[i] = '\0';
            inserir(regras, producao);
            i = 0;
        }
        if(linha != '|' && linha != '\n'){ // this means the current char (linha) is part of some RHS production, so we should concatenate it into the variable producao on position 'i' and increment 'i'.
            producao[i] = linha;
            i++;
        }
    }
}

criaListaRegras() 中使用的其他函数对于测试值工作正常,可以在下面找到:

lista *cria_lista()
{
    lista *novo = (lista*)malloc(sizeof(lista));
    novo->next = NULL;
    return novo;
}

void imprimir(lista *original)
{
    lista * aux = original->next;

    while(aux!= NULL){
        printf("%s\n", aux->nome);
        aux=aux->next;
    }
}

void inserir(lista *original, char *nome)
{
    lista *base = original;
    lista *aux = original->next;
    lista *novo;

    while(aux!= NULL){
        aux=aux->next;
        base=base->next;
    }

    novo=(lista*)malloc(sizeof(lista));
    novo->nome = nome;
    novo->next = aux;
    base->next = novo;
}

如果有人能指出我做错了什么,我会很高兴。

【问题讨论】:

  • 注意:char linha; --> int linha; (since you are using while ((linha = getc(entrada)) != EOF ) {` )

标签: c linked-list grammar


【解决方案1】:

查看提供的源代码并使用criaListaRegras() 函数构建一个完整的示例,我检测到多个错误,并且可能有一个能够创建观察到的输出。

假设 1 - 如何声明结构 lista

解析源码时,lista有2个属性next(用于链表机制)和nome存储加载的“producao”(char producao[10];)。

typedef struct slista {
    char *nome; // or char nome[10];
    struct slista *next;
} lista;

问题 1 - 附加到 lista 结构,函数 inserir() 不存储 char *nome 参数的内容,而只存储指针。

novo=(lista*)malloc(sizeof(lista));
novo->nome = nome; // ERROR storing the pointer
novo->next = aux;
base->next = novo;

通过存储char *nome参数的指针(即局部变量char producao[10];的指针),每个节点lista都会有指针值,当使用imprimir()时,aux->nome会指向到最后一个条目(对于"S-abA|e|bhG|AKX",它是"AKX",...)。

解决方案1.1 - 如果lista的属性声明为char *nome;,则需要分配字符串并复制内容。

最简单的解决方案是使用strdup() 能够分配和复制一个 字符串。

novo=(lista*)malloc(sizeof(lista));
novo->nome = strdup(nome); // allocate and copy
novo->next = aux;
base->next = novo;

解决方案1.2 - 如果lista的属性声明为char nome[10];,则只需复制字符串即可。

输入(来自char producao[10];)被限制为(10-1)char和 可以通过strcpy()函数轻松复制。

novo=(lista*)malloc(sizeof(lista));
strcpy(novo->nome,nome); // copy from nome to novo->nome
novo->next = aux;
base->next = novo;

检测到的其他问题:

1- 分配vetorlista

变量lista **vetor;lista * 的数组,而不是 lista.

lista **vetor; // declare the vector of list pointers
vetor = (lista **)malloc(sizeof(lista *)*numLinhas);

代替

lista **vetor; // declare the vector of list pointers
vetor = (lista **)malloc(sizeof(lista)*numLinhas);

2-在使用fopen()之后和读取数据之前检查FILE *entrada;的值。

3-将完整的lista *regrasvetor[numLinha] = regras;)存入vetor后,需要新建一个。

再次致电regras = cria_lista();

imprimir(regras); // should print all values inside "regras" but only print the last value added * "number of productions found so far".
vetor[numLinha] = regras; // should assign a list into its position in the pre-defined vector of lists at position "numLinha".
i = 0; // resets string position counter to 0 so we can reuse it for next production.
numLinha++; // increment line/rule counter.
fseek(entrada, 2, SEEK_CUR);
regras = cria_lista(); // Next lista

【讨论】:

    猜你喜欢
    • 2021-08-10
    • 2021-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-28
    • 2012-12-27
    • 1970-01-01
    相关资源
    最近更新 更多