LinhaCodigo
001// MAC122 - 2017 - Prof. Leo^nidas O. Branda~o
002// POLI - Computacao
003
004// Introducao a leitura/gravacao de arquivos (usando 'fgets')
005// Modelo de codigo para leitura de arquivo texto, fazendo um processamento simples e gerando
006// como resposta um arquivo HTML.
007// Ilustra o funcionamento das funcoes 'strlen(...)' e 'strcpy(...)' da biblioteca "string.h".
008
009// Para compilar com exame de "estouro" de vetor (e usar padrao o padrao ISO de 1990 para a linguaem C"):
010// $ gcc -fsanitize=address -g -std=c99 -o exemplo_processa_arquivo exemplo_processa_arquivo.c
011
012#include <stdio.h>
013#include <stdlib.h> // para 'malloc(...)'
014// #include <string.h> // se for usar a funcao 'strcpy(...)' da biblioteca (aqui implementei como 'strcpyNosso(...)')a
015
016#define MAXLINHAS    100
017#define MAXCOMPLINHA 255
018#define MAXN          60
019
020// Variaveis globais para gerar um cabelha e um rodape no arquivo de saida.
021// O '\' ao final indica que a linha NAO acabou...
022char CABECALHO[] = "<!DOCTYPE html>\
023<html class=\"client-nojs\" lang=\"en\" dir=\"ltr\">\
024<head>\
025 <meta charset=\"UTF-8\"/>\
026 <title>MAC122 :: modelo para ler/processar/gravar</title>\
027</head>\
028<h3>MAC122 :: modelo para ler/processar/gravar</h3>\
029<font color=\"#0000aa\"><p>Veja os primeiros caracteres das linhas nao vazias do arquivo <tt>%s</tt>.</p></font>\
030<table>\n";
031
032char RODAPE[] = "\n</table>\n</body>\n</html>";
033
034// Verifica comprimento da linha (codificado de modo compacto)
035int strlenNosso (char *strScr) {
036  int tam = 0;
037  while (*strScr++) tam++; // pa'ra quando encontrar '\0' (finalizador de "strings" em C)
038  return tam;
039  }
040
041// Copia os caracteres de 'strorig' em 'strdest'. Note que 'strdest' ja TEM que ter espaco alocado!
042char *strcpyNosso (char *strdest, const char *strorig) {
043  char *apont = strdest;
044  while (*strdest++ = *strorig++) ; // copia caractere a caractere
045  return apont; // devolva o endereca da "string" que recebeu a copia
046  }
047
048// Se linha nao nula, copie um parte inicial e avise tamanho
049// senao devolva -1
050int processaLinha (char linha[], char vet[], int conta) { // 'conta' apenas para ajudar depuracao...
051  int i, j, total = 0;
052  if (conta==-1) printf("processaLinha: %s\n", linha); // para testes
053  if (linha[0]=='\0' || linha[0]=='\n') return -1; // linha vazia, nada a fazer...
054  i = 0;
055  while (linha[i]==' ' || linha[i]==9) i++; // ignora brancos e TAB = encontra primeiro caracter util (ASCII 9 => TAB)
056  j = i;
057  while (linha[j]!='\0' && linha[j]!='\n') j++; // encontrar ultimo caractere (nao final)
058  if (conta==-1) printf(" (i=%d, j=%d): linha[%d]=%c=%d\n", i, j, j-1, linha[j-1], linha[j-1]); // para testes
059  vet[total++] = linha[i++]; // copie primeiro caractere
060  if (i<j) {
061    vet[total++] = linha[i++]; // havendo, copie segundo
062    if (i<j) {
063      vet[total++] = linha[i++]; // havendo, copia terceiro
064      if (i<j) {
065        vet[total++] = linha[i++]; // havendo, copia quarto
066        }
067      }
068    }
069  vet[total] = '\0'; // finaliza "string"
070  if (conta==-1) printf(" vet=%s\n", vet);
071  return i;
072  }
073
074// Funcao para leitura de arquivo com texto.
075// Recebe: 'nomeArqEnt' nome do arquivo e 'vet_nomes' vetor de "strings" para armazenar linhas lidas
076// Devolve: numero de caracteres no arquivo
077int leitura (char *nomeArqEnt, char vet_nomes[][MAXN]) {
078  FILE *in_file  = fopen(nomeArqEnt, "r"); // read only
079  char linha[MAXCOMPLINHA];
080  int conta = 0, resp;
081
082  if (in_file == NULL) { // Arquivo existe?
083    printf("Erro! Nao foi possivel abrir o arquivo %s\n", nomeArqEnt);
084    fclose(in_file);
085    return -1;
086    }
087  printf("---\nInicia leitura do arquivo %s\n", nomeArqEnt);
088
089  conta = 0;
090  while (1) { // elimina linhas iniciais
091    if (fgets(linha, MAXCOMPLINHA, in_file)==NULL || ferror(in_file) || feof(in_file) ) // char *fgets(char *str, int n, FILE *stream)
092      break; // final de arquivo
093    resp = processaLinha(linha, vet_nomes[conta], conta);
094    if (resp>0) { // mais uma "substring" copiada!
095      // printf("%3d : %s", conta, linha);
096      conta++;
097      }
098    }
099  printf("Total de linhas: %ld\n---\n", conta);
100  fclose(in_file);
101  return conta;
102  } // int leitura(char *nomeArqEnt, char vet_nomes[][MAXN])
103
104// Comece por aqui!
105// argv[0]="./programa_compara" e demais os argumentos usados
106int main (int argc, char **argv) {
107  char *arq_entra; //[MAXN];
108  char arq_saida[MAXN];
109
110  char vetDados[MAXLINHAS][MAXN]; // ilustrando como pegar trechos do codigo...
111
112  int conta = 0;
113  int conta_Apolo = 0;
114  int i, n;
115
116  if (argc < 3) {
117    printf("Faltaram os nomes dos arquivos de entrada C ou de saida HTML (na verdade NAO esta gravando, para gravar 'descomente' os \\S)\n");
118    printf("Linha de comando: ./exemplo_processa_arquivo nome_arquivo.c nome_arquivo.html\n");
119    return 1; // faltou um parametro, erro
120    }
121
122  //D printf("#argc=%d\n", argc); n = argc; for (i=0; i<n; i++) printf(" %d : %s\n", i, argv[i]);
123  arq_entra = malloc((strlenNosso(argv[1])+1) * sizeof(char)); // printf(" %d : %s\n", strlenNosso(argv[1]), argv[1]);
124  strcpyNosso(arq_entra, argv[1]); //D printf("arq_entra = %s\n", arq_entra); 
125
126  conta = leitura(arq_entra, vetDados);
127  if (conta<0) {
128    printf("\nErro na leitura do arquivo %s\n", arq_entra, conta);
129    return 1;
130    }
131
132  //D printf("---\nfinal leitura arquivo IME: conta=%d\n", conta);
133  // Gerar a resposta de processamento (imprimir na tela e gerar novo arquivo)
134  FILE *out_file = fopen(argv[2], "w"); // "write only"
135  printf("Lista de primeiros (ate) 4 caracteres de cada linha nao nula\n");
136  fprintf(out_file, CABECALHO, arq_entra);
137  for (i=0; i<conta; i++) {
138    printf("%3d : %s\n", i, vetDados[i]);
139    fprintf(out_file, " <tr><td>Linha %3d : </td> <td> %s </td></tr>\n", i, vetDados[i]);
140    }
141  fprintf(out_file, RODAPE);
142  fclose(out_file);
143
144  return 0;
145  }