Livro avançado programação em C processamento de texto e manipulação de arquivos

Olá.
Tenho conhecimento básico em programação e tenho tido dificuldades para trabalhar com manipulação de arquivos de texto (txt) utilizando a linguagem C. Acho que tem pouca bibliografia e estou procurando um livro que aprofunde mais no assunto. Se alguém puder me indicar algum livro desse tipo, não exite em responder ao tópico. Obrigado.

[quote=JoaoMG]Olá.
Tenho conhecimento básico em programação e tenho tido dificuldades para trabalhar com manipulação de arquivos de texto (txt) utilizando a linguagem C. Acho que tem pouca bibliografia e estou procurando um livro que aprofunde mais no assunto. Se alguém puder me indicar algum livro desse tipo, não exite em responder ao tópico. Obrigado.[/quote]

Qdo vc fala trabalhar com arquivos textos é utilizar “fopen, fputc” por ae vai? se for procure no google “file open c” vai existir vários resultados. Não tem muito mistério não.
Claro se vc quiser reorganizar os elementos e tudo mais, vai mais um pouco de estudo sobre ponteiros.

Conheço boa parte dessas funções, mas trabalhar com arquivo vai muito mais além. Os meus maiores problemas são converter os caracteres para texto, inteiro e formar palavras. Eu quero na verdade, abrir uma arquivo txt, ler caracter por caracter, separando cada palavra e jogar num banco de dados ou gerar outro arquivo txt só que formatado e organizado.

Se tivesse algum livro que trabalha bastante estas funções, ficaria mais fácil entender o processo. Se eu perguntar aqui sobre uma função que faça tal coisa, o pessoal vai jogar um tanto de exemplos, que nem sei se funcionam de verdade e não vão tirar a minha dúvida, entende?

É possível usar C++ em vez de C? Em C++ existem até bastantes bibliotecas para fazer isso.

Dependendo do que você quer fazer em processamento de texto, você pode em vez disso estudar um pouquinho de teoria de compiladores e criar uma gramática para o seu texto de entrada (sei lá o que tem nesse texto). Então você chama o lex/yacc ou o flex/bison para gerar código C que permita a você poder analisar o seu texto de entrada.

Há alguns meses atrás, eu entrei num forum de programação em C e tive que travar uma guerra com um dos usuários para obter um pouco de respeito. Ele tratou meu problema com muita hipocrisia e sabia como me ajudar, mas fez questão de me enrolar até que eu perdesse a paciência. Muitos tem conhecimento, mas não compartilham. Tem muito compatriota egoísta por aqui e acho meio difícil algum brasileiro conseguir ter crédito nesse novo programa do governo “Ciências sem Fronteiras”.Acho que antes de querer o que vem de fora, temos que aprender a ajudar aos colegas daqui de dentro. Obrigado.

Procure um bom livro de C (por exemplo, o C Completo e Total), não precisa ser específico para processamento de arquivos. O livro acaba naturalmente cobrindo o assunto em mais profundidade do que qualquer tutorial na internet.

E para fazer aplicações avançadas você vai usar as mesmas funções normais de manipulação de arquivo (fopen, fclose, fread, fwrite, fgets, fputs, fseek, ftell, etc…), o que fica mais sofisticado é apenas o algoritmo que combina essas funções.

PS: Esse último post eu não entendi… se quis dizer que o pessoal está deixando de ajudar para segurar conhecimento isso não faz sentido, todas as respostas foram totalmente pertinentes!

Quando eu falei sobre teoria de compiladores, eu queria na verdade saber o seguinte: você tem um arquivo-texto e quer fazer uma análise dele.

O que esse arquivo-texto contém?

a) Ele é um arquivo como o CNAB (formato usado pelas instituições bancárias para poder representar transações como cheques ou depósitos. ) Ele tem um formato com campos de tamanho fixo. Nesse caso você não precisa de nada mais sofisticado que fopen/fclose/fgets e um bocadinho de paciência com as funções de strings.

b) É um arquivo como um livro do Projeto Gutenberg (que contém apenas palavras e nada mais). Imagino que você esteja pensando em um livro desses. Se for isso, o fscanf ("%s") já funciona bem porque o %s já sozinho separa as palavras que estão separadas apenas por espaços ou tabs.

c) É um arquivo .csv (ou seja, campos numéricos e texto separados por vírgulas, como um arquivo-texto exportado pelo Excel.

d) Algum formato que não tenho a menor idéia, mas é estruturado como uma linguagem de programação. Nesse caso, recomendo o uso de um gerador de analisadores léxicos como o lex (ou flex), que ajuda a separar os “tokens” (o que você chamou de “palavras”) dentro do seu texto, de acordo com regras que você escreve, usando uma linguagem especial, que é compilada para um conjunto de métodos em C que você pode chamar de seu programa.

Você viu que o problema, como de costume, é mais complicado que parece? Que tal esmiuçar mais o seu problema, para podermos indicar uma direção?

Outro motivo pelo qual eu recomendaria C++ em vez de C é que é bem mais fácil achar coisas em C++ que façam as coisas de nível alto que você precisa. Por exemplo, digamos que você queira fazer uma análise estatística de um texto, achando as palavras, contando-as, listando-as em ordem alfabética e também em ordem de frequência (as mais frequentes primeiro)
Em C++ isso é bastante trivial, mas em C você precisa ralar um bocado.
Vou fazer isso para um livro do Projeto Gutenberg, só para você ter uma idéia.
Daqui a pouco estou com o programa pronto aqui.

/*
Compile este programa como C++. Digamos que o nome do arquivo seja EstatisticaLivro.cpp
Exemplo: baixe o seguinte arquivo do Projeto Gutenberg:
http://www.gutenberg.org/cache/epub/33056/pg33056.txt
Para executar este programa, você pode tentar algo como:
EstatisticaLivro pg33056.txt relatorio.txt
Um arquivo de relatório será criado em alguns segundos. 
*/
#include <iostream> // std::cerr
#include <fstream>
#include <cstdlib>
#include <map>
#include <vector>
#include <string>

using namespace std;

int main (int argc, char *argv[]) 
{
    
    if (argc != 3) 
    {
        cerr << "Sintaxe: EstatisticaLivro arquivoEntrada relatorioSaida" << endl;
        exit (1);
    }
    ifstream arquivoEntrada;
    char* buf = new char [1024 * 1024]; // alocando um grande buffer para acelerar a leitura
    arquivoEntrada.rdbuf()->pubsetbuf (buf, 0);
    arquivoEntrada.open (argv[1]);
    if (!arquivoEntrada) 
    {
        cerr << "Arquivo nao pode ser aberto para leitura: " << argv[1] << endl;
        exit (1);
    }
    ofstream relatorioSaida (argv[2]);
    if (!relatorioSaida) 
    {
        cerr << "Arquivo nao pode ser aberto para escrita: " << argv[2] << endl;
        exit (1);
    }

    map<string, int> palavra2contagem;
    // Lendo o arquivo palavra por palavra. Para facilitar, nao vou tirar as virgulas ou outros sinais
    // de pontuacao, embora pudesse fazer isso. Isso fica como exercicio
    while (! arquivoEntrada.eof()) 
    {
        string palavra;
        arquivoEntrada >> palavra; // lendo uma palavra
        palavra2contagem [palavra]++; // incrementando a frequencia dessa palavra
    }
    // Uma vez lido o arquivo palavra por palavra, podemos entao determinar as palavras com mesma frequencia
    map<int, vector<string>> palavrasComMesmaFrequencia;
    int i = 0;
    for (map<string, int>::const_iterator it = palavra2contagem.begin(); it != palavra2contagem.end(); it++) 
    {
        vector<string> palavras = palavrasComMesmaFrequencia [it->second];
        palavras.push_back (it->first);
        palavrasComMesmaFrequencia [it->second] = palavras;
    }


    // Aqui listamos as palavras por ordem alfabetica,
    // assim como as suas frequencias.
    relatorioSaida << "Listagem por ordem alfabetica" << endl << endl;
    for (map<string, int>::const_iterator it = palavra2contagem.begin(); it != palavra2contagem.end(); it++) 
    {
        relatorioSaida  << it->first << ": " << it->second << endl;
    }
    // Aqui estamos listando as palavras por ordem decrescente de frequencia.
    // Palavras com mesma frequencia irao aparecer juntas.
    // Note o uso de "rbegin" e "rend" para percorrer em ordem decrescente em vez de ordem crescente.
    relatorioSaida << endl << endl << "Listagem por ordem decrescente de frequencia" << endl << endl;
    for (map<int, vector<string>>::reverse_iterator it = palavrasComMesmaFrequencia.rbegin(); it != palavrasComMesmaFrequencia.rend(); it++)
    {
        relatorioSaida << "Palavras que apareceram " << it->first << " vez(es):" << endl;
        for (vector<string>::const_iterator it2 = it->second.begin(); it2 != it->second.end(); it2++) 
        {
            relatorioSaida << *it2 << ", " ;
        }
        relatorioSaida << endl;
    }
    arquivoEntrada.close();
    delete[] buf; // uma vez que fechamos o arquivo de entrada, devemos devolver o buffer alocado
    relatorioSaida.close();
    cout << "Processamento terminado. " << endl;
    exit (0);
}

Eu agradeço todos, mas vou tentar ser mais claro.
Eu copio informações de tabelas na internet e como a maioria dessas tabelas podem ter alguma imperfeição, mudança de padrão ou um formato difícil de trabalhar, eu jogo no excel de uma forma que separa tudo em linhas, mas as colunas viram uma coluna só. Isso acontece porque o excel enxerga tudo como texto. E como no Excel não dá para trabalhar desta forma e como não sou especialista em funções do excel, apesar de conhecer bastante e também porque seria muito mais viável ser um conhecedor de programação em C ao invés de começar do zero a estudar uma outra linguagem, achei melhor copiar as informações do excel e jogar num arquivo do bloco de notas (txt). Já tentei pegar da internet e jogar diretamente no bloco de notas, fica pior.
Depois de salvar as informações no arquivo txt, elas precisarão ser formatadas só que através de um algorítimo, pois é muita informação. Minha intensão é deixar as informações o mais fácil para trabalhar. Sabendo manipular os caracteres, separar cada palavra e diferenciar o que é palavra do que é número, crio um novo arquivo do jeito que for necessário. Aí, ficaria mais fácil jogar de volta no excell ou em qualquer banco de dados. Eu poderia trabalhar diretamente no arquivo txt, pois ficaria até mais rápido usando a linguagem C.
Entenderam?

[quote=entanglement][code]
/*
Compile este programa como C++. Digamos que o nome do arquivo seja EstatisticaLivro.cpp
Exemplo: baixe o seguinte arquivo do Projeto Gutenberg:


Para executar este programa, você pode tentar algo como:
EstatisticaLivro pg33056.txt relatorio.txt
Um arquivo de relatório será criado em alguns segundos.
*/

Entanglement, C++ é bem parecido, mas tem muito mais detalhes. Eu vou acabar me confundindo e seria ainda pior. Sua dica é valiosíssima, obrigado.

[quote=gomesrod]Procure um bom livro de C (por exemplo, o C Completo e Total), não precisa ser específico para processamento de arquivos. O livro acaba naturalmente cobrindo o assunto em mais profundidade do que qualquer tutorial na internet.

E para fazer aplicações avançadas você vai usar as mesmas funções normais de manipulação de arquivo (fopen, fclose, fread, fwrite, fgets, fputs, fseek, ftell, etc…), o que fica mais sofisticado é apenas o algoritmo que combina essas funções.

PS: Esse último post eu não entendi… se quis dizer que o pessoal está deixando de ajudar para segurar conhecimento isso não faz sentido, todas as respostas foram totalmente pertinentes![/quote]

Gomesrod, eu vou dá uma olhada no livro que vc me indicou. Obrigado.

[quote=entanglement]Outro motivo pelo qual eu recomendaria C++ em vez de C é que é bem mais fácil achar coisas em C++ que façam as coisas de nível alto que você precisa. Por exemplo, digamos que você queira fazer uma análise estatística de um texto, achando as palavras, contando-as, listando-as em ordem alfabética e também em ordem de frequência (as mais frequentes primeiro)
Em C++ isso é bastante trivial, mas em C você precisa ralar um bocado.
Vou fazer isso para um livro do Projeto Gutenberg, só para você ter uma idéia.
Daqui a pouco estou com o programa pronto aqui.[/quote]

Um outro motivo para continuar usando a linguagem C, é que programa PIC e acho que não existe biblioteca em C++ para controladores. Tenho mais contato com essa linguagem. Não digo que nunca vou usar C++, mas no momento disponho de pouco tempo para aprender uma outra linguagem.

[quote=JoaoMG]Eu agradeço todos, mas vou tentar ser mais claro.
Eu copio informações de tabelas na internet e como a maioria dessas tabelas podem ter alguma imperfeição, mudança de padrão ou um formato difícil de trabalhar, eu jogo no excel de uma forma que separa tudo em linhas, mas as colunas viram uma coluna só. Isso acontece porque o excel enxerga tudo como texto. E como no Excel não dá para trabalhar desta forma e como não sou especialista em funções do excel, apesar de conhecer bastante e também porque seria muito mais viável ser um conhecedor de programação em C ao invés de começar do zero a estudar uma outra linguagem, achei melhor copiar as informações do excel e jogar num arquivo do bloco de notas (txt). Já tentei pegar da internet e jogar diretamente no bloco de notas, fica pior.
Depois de salvar as informações no arquivo txt, elas precisarão ser formatadas só que através de um algorítimo, pois é muita informação. Minha intensão é deixar as informações o mais fácil para trabalhar. Sabendo manipular os caracteres, separar cada palavra e diferenciar o que é palavra do que é número, crio um novo arquivo do jeito que for necessário. Aí, ficaria mais fácil jogar de volta no excell ou em qualquer banco de dados. Eu poderia trabalhar diretamente no arquivo txt, pois ficaria até mais rápido usando a linguagem C.
Entenderam? [/quote]

Para fazer processamento desse tipo de texto, acho melhor fazer em alguma linguagem como Java ou Python.

(Veja que não estou recomendando Perl ou AWK embora também sejam muito usadas para fazer esse tipo de processamento de texto, porque Perl é “write-only” - não se deixe levar pela semelhança aparente com a linguagem C - e AWK é um pouco antiguinha, para ser sincero.)

Para exportar dados para o Excel, você pode exportar em formato CSV (que no caso do Excel em português acaba sendo separado por “ponto-e-vírgula” em vez de vírgulas.

Não C (pelo que você nos disse, as tabelas são puxadas da Internet e não devem ter centenas de gigabytes de texto) ou mesmo C++.

Eu conheço suficientemente C (mexo com ele desde 1986 - estou dizendo desde o milênio passado) para saber que para corrigir os programas que você vai ter de escrever vai levar mais tempo que para aprender a fazer as coisas direito em Java, C# ou Python. Quando preciso fazer alguma coisa que tem de ser em C, escrevo um protótipo em alguma linguagem de nível mais alto (como Java ou C++) e só se o desempenho não for suficiente por algum motivo é que reescrevo em C.

Em C a parte de manipulação de texto é terrivelmente trivial (no seu caso em particular, basta usar fopen / fgets / fputs / fclose e talvez setvbuf, para acelerar a leitura e escrita dos dados alterando o tamanho do buffer de disco que essas rotinas usam) mas a parte de manipulação de strings, que é o que você vai precisar afinal, é terrivelmente pobre se você só usar as funções da biblioteca-padrão do C.

Quem só tem strcmp, strtok, strchr, strcat, strstr e mais meia dúzia de funções para trabalhar com strings, acaba dando um tiro na cabeça quando precisa de algo mais complexo.

Concordo. Isso é um trabalho ingrato, mas se você quer um bom livro recomendo o C Completo e Total, mas pelo tempo que vai levar para fazer o que você quer é mais fácil apreender java! Outra linguagem muito fácil de apreender e que resolve bem o seu caso é Delphi. C nesse caso, somente se você tivesse muita experiência, o que parece não ser o caso.

Ao que me parece você está escolhendo a linguagem errada para o seu problema, isso é uma coisa que eu falo aqui. A meu ver não vale a pena perder tempo com C para fazer isso, só porque você já tem alguma experiência com essa linguagem.

[quote=thingol]Em C a parte de manipulação de texto é terrivelmente trivial (no seu caso em particular, basta usar fopen / fgets / fputs / fclose e talvez setvbuf, para acelerar a leitura e escrita dos dados alterando o tamanho do buffer de disco que essas rotinas usam) mas a parte de manipulação de strings, que é o que você vai precisar afinal, é terrivelmente pobre se você só usar as funções da biblioteca-padrão do C.

Quem só tem strcmp, strtok, strchr, strcat, strstr e mais meia dúzia de funções para trabalhar com strings, acaba dando um tiro na cabeça quando precisa de algo mais complexo. [/quote]

Concordo, até dá para fazer, mas vai ser extremamente trabalhoso!