Ir ao conteúdo

Posts recomendados

Postado

Olá pessoal, estou com dificuldade em realizar um programa pra facul. É a única questão da Lista que está me dando dor de cabeças.

O Programa deve lêr um arquivo .txt que está organizado dessa maneira:

 

Julio Cesar 2.500 M 86                

Maria Helena 12.300 F 53

Francisco Souza 7.350 M 60

Yasmin Moura 3.590 F 95

Bruna Lopes 18.000 F 66

Eddie Murphy  3.000 M 18

 

O programa deve me retornar todos esse ítens: 

A quantidade de itens existentes no arquivo (quantidade de pessoas);

• Quantas pessoas tem os nomes começados com vogal e quantas tem nomes começados com consoantes?

• Quem é a pessoa mais jovem e quem é a pessoa mais velha?

• A média de idade das pessoas; • Quem possui o maior salário?

• Qual o sexo da pessoa com o maior salário?

• Qual a idade da pessoa que possui o maior sobrenome

 

Bom, só consegui realizar o primeiro requisito que é a contagem dos nomes(Baseado em um algoritmo que encontrei).

Estou com muita dificuldade em realizar os outros, até mesmo em encontrar uma lógica para chegar ao resultado de todos. É a primeira vez que trabalho com essa função em C de lêr um arquivo externo

e realizar comparações dentro dele.

Estou precisando de auxilio nessas questões, em como posso chegar até o resultado e etc.

E aqui abaixo está o que consegui realizar, ele fez a contagem, mas teria outra maneira também de reduzir esse código? (Uma lógica melhor)

 

#include <stdio.h>

#include <string.h>

int main () {

    FILE *arq;
    char c, letra = '\n';
    int vezes;
    arq = fopen("teste.txt","r");

        while(fread (&c, sizeof(char), 1, arq)) {
            if(c == letra) {
                vezes++;
            }
        }


    printf("\nPessoas: %i\n",vezes + 1);
    fclose(arq);
}

 

 

Encontrei esse Blog com um código feito, o programa é bem parecido com o que devo desenvolver. Eu poderia me basear nele também? 

https://codigosfontes-ccplus-plus.blogspot.com/2015/10/arquivo-inserindo-dados-em-struct.html

Obrigado.

  • Obrigado 1
Postado

@vangrant Existem muitas formas de separar os dados, por exemplo:

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

int main() {
    FILE *arq;
    arq = fopen("arquivo.txt", "r");
    char linha[40], nome[15], sobrenome[15], sx;
    float sal;
    int idade;
    while(fgets(linha, 40, arq) != NULL) {
        sscanf(linha, "%s %s %f %c %d", nome, sobrenome, &sal, &sx, &idade);
        printf("Nome: %s\n", nome);
        printf("Sobrenome %s\n", sobrenome);
        printf("Salario: %f\n", sal);
        printf("Sexo: %c\n", sx);
        printf("Idade: %d\n", idade);
    }
    fclose(arq);
    return(0);
}

Nesse caso o salário vai sair errado devido ao "." como separador de milhar, você pode simplesmente multiplicar o valor por 1000, mas o mais adequado seria ler o valor como uma string, verificar se há um ".", e caso haja, converter o valor para float e então multiplicar por 1000, caso contrário apenas fazer a conversão e a atribuição.

 

Para saber se o nome começa com uma vogal basta verificar se nome[0] é igual a 'A' ou 'E' ou 'I' etc. Obviamente caso não comece então a primeira letra é uma consoante.

  • Obrigado 1
Postado
5 horas atrás, vangrant disse:

Bom, só consegui realizar o primeiro requisito que é a contagem dos nomes(Baseado em um algoritmo que encontrei).

 

Sobre esse trecho do programa que postou

 

int main () {

    FILE *arq;
    char c, letra = '\n';
    int vezes;
    arq = fopen("teste.txt","r");

        while(fread (&c, sizeof(char), 1, arq)) {
            if(c == letra) {
                vezes++;
 // ...

 

Ok, vezes é um int e aí entra nesse loop e começa somando. Mas quanto tinha em vezes? Pensou em dar um valor inicial a essa coisa? Não é garantido que as variáveis começam por zero.

 

O que esse programa faz é apenas contar o número de ' \n', o símbolo que termina as linhas num arquivo texto. Note que deve ter cuidado se editar esse arquivo para não deixar linhas em branco no final, o que é muito comum em arquivos editados no IDE por exemplo.

 

5 horas atrás, vangrant disse:

É a primeira vez que trabalho com essa função em C de lêr um arquivo externo

e realizar comparações dentro dele.

 

Logo vai ver que não há nenhuma dificuldade em usar arquivos em C. É muito mais simples que tentar ler coisas do teclado. Isso porque você não precisa escrever um editor de texto nem arrumar nada. Basta definir um formato e digitar de acordo ou esperar que o usuário do programa faça isso. Alguém escreveu o editor para você e essa é a pior parte. 

 

Escreva em torno dos dados.

 

Há duas maneiras de tratar arquivos em .C. mas arquivos são apenas sequências de bytes, de char como C os vê:

  • como arquivos texto, considerando os dados como registros separados por '\n', as populares linhas
  • como arquivos binários, simples sequências de bytes

Contrariando o imaginário popular um arquivo não é arquivo texto ou arquivo binário. E você pode tratar como for mais adequado. 

 

Em geral num arquivo dito binário os dados são considerados em registros de tamanho fixo. E esse tamanho pode ser 1 byte, como em seu exemplo, e aí você lê o arquivo uma letra, ou um byte por vez.

 

Num arquivo texto considerando os dados separados em linhas delimitadas por '\n' o tal registro é uma linha e pode ter um tamanho qualquer. Dois '\n' em seguida serão contados como duas linhas em seu programa por exemplo.

 

Você pode tratar um arquivo binário como um vetor, e ler os dados em registros de 1 byte, ou 200 ou 1 megabyte. Não faz diferença. E pode ir e voltar pelos registros, como fazer com um vetor. E mesmo regravar partes do arquivo. Só que demora uma eternidade se comparado a um vetor. Por outro lado pode ter um arquivo de de qualquer tamanho, e um vetor estará limitado pela memória e outras capacidades do computador... E um vetor some assim que o programa termina, por bem ou por mal. 

 

De volta ao seu programa

 

Há funções mais adequadas para tratar texto e linhas, e outras mais adequadas para tratar registros de tamanho fixo nos arquivos.

 

Para tratar texto é mais confortável usar fgets(), fprintf(), fscanf() ou fgetc(), e recomendo ver isso no manual. Um bom IDE também pode ter documentação embutida, e não vou falar de uma a uma dessas coisas.

 

Para tratar registros fread() e fwrite(), fseek() e ftell() são as ferramentas básicas.

 

Você usou fread() para tratar texto, e não tem nada demais se feito de propósito, mas aqui não foi o caso. fread() é uma função de baixo nível e você vai ter que processar o texto toda por sua conta. Não é boa ideia.

 

Exemplo 1

 

Para você se acostumar com essas coisas escreva pequenos programas. Bem pequenos. E teste as coisas.

 

Escreva em torno dos dados

 

Sim, já escrevi isso.

 

Veja seu exemplo
 

Julio Cesar 2.500 M 86               
Maria Helena 12.300 F 53
Francisco Souza 7.350 M 60
Yasmin Moura 3.590 F 95
Bruna Lopes 18.000 F 66
Eddie Murphy  3.000 M 18

 

Se ainda não fez isso, esse deve ser seu primeiro arquivo. E chame de teste.txt.
 

    FILE *arq;
    char c, letra = '\n';
    int vezes;
    arq = fopen("entrada.txt","r");

 

Como está começando é um bom momento para evitar certas coisas... Escreveu como acima, mas procure escrever
 

    FILE*    arq = fopen("teste.txt","r");
    char     c = 0;
    char     letra = '\n';
    int      vezes = 0;

 

Porque?

 

Em C você declara nomes, variáveis. aí tem 4. E os nomes tem um tipo. arq é FILE*, um ponteiro para arquivo. Está declarando arq e não *arq, o que o compilador pode mostrar pra você... Essa é a realidade: o nome é arq e o tipo é FILE*. 

 

Claro, se arq é FILE* então o inverso é verdade: *arq é FILE. Tem muitas religiões a respeito, mas uma realidade apenas.

 

Em casos simples como esses programas declare o arquivo e abra na mesma linha...

 

Inicialize todas as variáveis.

 

Declare uma por linha. É grátis e facilita sua vida e a de outros que venham a ler seu programa.

 

Um programa
 

#include <stdio.h>
int main (void)
{
    unsigned char area[8 * 1024] = {0};
    unsigned registro = sizeof(char); // :) 1 byte
    unsigned registros = sizeof(area) / registro; // quanto cabe em area?
    FILE*    arquivo = fopen("teste.txt","r");
    if ( arquivo == NULL ) return -1;
    int res = fread ( area, registro, registros, arquivo);
    printf("fread() leu %d registros de %d bytes\n", res, registro );
    fclose(arquivo);
    return 0;
}

 

Esse programa supõe registros de uma letra e uma area para ler de 8K, 8192 bytes. Essas linhas de teste.txt tem 162. Então você espera que fread() retorne quanto? 162, certo?

 

fread() leu 162 registros de 1 bytes

 

Se o arquivo for maior vai ler, claro, os primeiros 8K. Quer ler mais? chame de novo.

 

Onde vão estar os dados? 162 bytes estão entre area[0] e area[161], inclusive. Isso é tudo.

 

Pra que um programa desses? Só pra você se acostumar com as coisas, causa e efeito.

 

E se não abriu retorna -1 e termina logo o programa. Se for importante saber porque deu erro depois você vê. Cuide primeiro do normal e depois da exceção.

 

E se fosse ler a primeira linha?

 

Exemplo 2

 

#include <stdio.h>
int main (void)
{
    char area[8 * 1024] = {0};
    FILE*    arquivo = fopen("teste.txt","r");
    if ( arquivo == NULL ) return -1;
    char* res = fgets( area, sizeof(area), arquivo);
    if ( res == NULL ) return -2;
    printf("fgets() leu \"%s\"\n", area );
    fclose(arquivo);
    return 0;
}

 

Então fgets() tenta ler uma linha por vez e retorna esses dados no endereço apontado no primeiro parêmetro. Mas também retorna esse endereço se conseguir ler algo. Ou NULL se não ler p. nenhuma. E o programa então retorna -1 se não abrir o arquivo, -2 se fgets der pau por alguma razão.

 

Não importa, desde que saiba onde deu erro. E siga o normal, que é ler algo:

 

fgets() leu "Julio Cesar 2.500 M 86               
"

 

Veja que se era pra linha lida estar entre aspas então fgets() pulou uma linha! Essa é a razão de ter aspas em volta da linha lida: espaços em branco são assim, em branco. Ao usar as aspas no printf para delimitar o campo se vê que fgets() leu e guardou o '\n' que terminou a tal linha.

 

de volta aos dados

 

Olhando bem para seus dados dá pra imaginar que o formato é uma palavra com o nome, outra com o sobrenome, um número com o salário, uma letra para o sexo e um número para a idade.

 

Isso é um formato tabular de dados muito comuns nos anos 70/80. E em C se pode ler isso com uma outra função, sscanf(), que dá uma força e converte os dados do mesmo modo que printf(), e assim o número virá número, o número com ponto decimal e sinal fica certinho e tal. Muito gentil. 

 

E C tem um formato para agrupar dados com um nominho, a tal struct. Vem em a calhar:

 

Exemplo 3

 

#include <stdio.h>

typedef struct ex3
{
    char        nome[20];
    char        sobrenome[20];
    double      salario;
    char        sexo;
    int         idade;

}   Registro;

int main(void)
{
    Registro grupo[20];
    Registro chefe = { "James", "Bond", 12.34,'M', 70 };

    grupo[19].idade = 18;
    printf("Idade do ultimo cara = %d anos\n", grupo[19].idade);
    printf("Nome do chefe: %s %s\n",chefe.nome, chefe.sobrenome);
    
    return 0;
}

 

Assim por exemplo você pode criar um vetor com 20 caras ou um registro com um só e manipular os valores como conjunto ou em partes...

 

Idade do ultimo cara = 18 anos
Nome do chefe: James Bond

 

 

Cansei de escrever.

 

Teste essas coisas em seu computador.

 

Quem pediu pra você fazer esse programa já deveria ter te ensinado isso :( 

 

 

 

 

  • Obrigado 1
Postado

Esses dias fiz algo um pouco parecido.
De cara já vejo que o que iria te ajudar bastante seria saber regex.
Olha o resultado do que fiz em javaScript:
http://tivideotutoriais.blogspot.com/2021/08/planilhas-e-listas-em-javascript.html
Para ver o fonte, basta visualizar o codigo fonte da pagina.
Para aprender regex, eu mesmo deixo dicas pra mim on-line:
http://tivideotutoriais.blogspot.com/2020/08/regex-em-javascript.html

Regex é legal porque funciona pra qualuqer linguagem. Basta apenas saber como funcionam os metodos para tal de cada linguagem.
Esse eu encontrei na internete:

#include <regex.h>
#include <stdio.h>

int main() 
{
  int r;
  regex_t reg;

  if (r = regcomp(&reg, "\\b[A-Z]\\w*\\b", REG_NOSUB | REG_EXTENDED)) 
  {
    char errbuf[1024];

    regerror(r, &reg, errbuf, sizeof(errbuf));
    printf("error: %s\n", errbuf);

    return 1;
  }

  char* argv[] = { "Moo", "foo", "OlOlo", "ZaooZA~!" };

  for (int i = 0; i < sizeof(argv) / sizeof(char*); i++) 
  {
    if (regexec(&reg, argv[i], 0, NULL, 0) == REG_NOMATCH)
      continue;

    printf("matched: %s\n", argv[i]);
  }

  return 0;
}


origem do fonte:
https://stackoverflow.com/questions/5179451/gcc-regular-expressions

Postado
Em 06/08/2021 às 02:59, arfneto disse:

de volta aos dados

 

Olhando bem para seus dados dá pra imaginar que o formato é uma palavra com o nome, outra com o sobrenome, um número com o salário, uma letra para o sexo e um número para a idade.

 

Isso é um formato tabular de dados muito comuns nos anos 70/80. E em C se pode ler isso com uma outra função, sscanf(), que dá uma força e converte os dados do mesmo modo que printf(), e assim o número virá número, o número com ponto decimal e sinal fica certinho e tal. Muito gentil.

 

Eu mostrei uns exemplos e a diferença entre usar funções orientadas a texto e a bytes para ler os arquivos, mas depois eu escrevi esse trecho acima, e acho que deve considerar isso, @codigo rápido . Talvez não tenha feito algo assim tão parecido: esse é um arquivo csv. Em javascript talvez fosse o caso de usar alguma biblioteca, como jquery-csv para ler csv, ou usar apenas split() e parseXXX() quando for o caso, mas aí é para outro forum ;) regex, eu  acho, não é apropriado: é melhor escrever em torno dos dados e já sabe onde estão os números.

 

De volta ao programa, esses são os  dados do arquivo exemplo

 

Julio Cesar 2.500 M 86
Maria Helena 12.300 F 53 
Francisco Souza 7.350 M 60 
Yasmin Moura 3.590 F 95 
Bruna Lopes 18.000 F 66 
Eddie Murphy 3.000 M 18 

 

E são tabulares. Usar expressões regulares aqui seria um caminho muito muito longo para o que pode ser feito em uma única linha. E ficaria a cada campo com os dados para converter para o formato desejado, com pouca se alguma vantagem em relação a usar uma FSA, a popular máquina de estados,. que deixaria você na mesma situação: isolar os campos e ter que compor os dados por sua conta. 

 

Como eu disse, scanf() e família são mais gentis aqui.

 

Exemplo 1: lendo e interpretando o arquivo exemplo
 

#include <stdio.h>
#include <string.h>
int main(void)
{
    char  area[8 * 1024] = {0};
    FILE* arquivo        = fopen("teste.txt", "r");
    if (arquivo == NULL) return -1;

    const char* mascara = "%19s %19s %d.%d %19s %3d";
    char        nome[20];
    char        sobrenome[20];
    int         milhares;
    int         ate999;
    char        sexo[20];
    int         idade;
    char*       res = NULL;

    while ((res = fgets(area, (int)sizeof(area), arquivo)) != NULL)
    {
        area[strlen(area) - 1] = 0;
        printf("\nfgets() leu: \"%s\"\n", area);
        int n = sscanf(
            area, mascara,
            nome, sobrenome, &milhares, &ate999, sexo, &idade);
        if (n != 6) return -1;
        printf(
            "sscanf() leu: %s, %s, %d, %c, %3d\n", nome, sobrenome,
            (milhares*1000+ate999), sexo[0], idade);
    };
    fclose(arquivo);
    return 0;
}

 

Pois é, umas 10 linhas de código, mais as óbvias variáveis.

 

Eis o resultado:
 

fgets() leu: "Julio Cesar 2.500 M 86"
sscanf() leu: Julio, Cesar, 2500, M,  86

fgets() leu: "Maria Helena 12.300 F 53 "
sscanf() leu: Maria, Helena, 12300, F,  53

fgets() leu: "Francisco Souza 7.350 M 60 "
sscanf() leu: Francisco, Souza, 7350, M,  60

fgets() leu: "Yasmin Moura 3.590 F 95 "
sscanf() leu: Yasmin, Moura, 3590, F,  95

fgets() leu: "Bruna Lopes 18.000 F 66 "
sscanf() leu: Bruna, Lopes, 18000, F,  66

fgets() leu: "Eddie Murphy 3.000 M 18 "
sscanf() leu: Eddie, Murphy, 3000, M,  18

 

O programa compara as linhas do arquivo original, o do enunciado, com os valores interpretados pela única linha que faz o serviço:

 

        int n = sscanf(
            area, mascara,
            nome, sobrenome, &milhares, &ate999, sexo, &idade);

 

Claro que há incontáveis maneiras alternativas de fazer isso, nem vou dizer que essa é uma boa, mas é uma linha só então eu tenho um argumento ;) 

 

  • O enunciado claramente só usa nomes duplos, porque acho que o instrutor quer apenas avaliar a noção de consumir e agrupar os dados
  • o salário tem um problema chato com o ponto decimal, que vai depender da configuração do sistema de cada máquina, e é muito chato esperar que um iniciante se preocupe com isso em Unix/Linux, Windows ou sei lá

Exemplo 2: lendo para poder usar no programa

 

O tal exemplo 1 é o programa que eu postei no tópico anterior, com umas linhas a mais e lendo o mesmo arquivo. Como parece ter funcionado, podemos apagar aquelas mensagens todas e ler os dados direto para as variáveis.

 

Claro. uma struct já está até descrita no enunciado: basta ler os dados. Mas para não perder tempo o conhecido conceito de encapsulamento do C++ vem ajudar:

 

O programa vai tratar um grupo de funcionários, com N funcionários. Não é preciso usar alocação dinâmica porque não parece ser esse o propósito. É um exercício para iniciantes, então vamos limitar o tamanho do grupo e seguir adiante.

 

Escrevendo em torno dos dados
 

Esse parece ser um bom começo:

 


typedef struct
{
    char nome[20];
    char sobrenome[20];
    int  salario;
    char sexo;
    int  idade;

} Funcionario;

typedef struct
{
    int         max_N;  // maximo de funcionarios
    int         N;      // total atual
    Funcionario f[40];  // os caras

} Grupo;

 

Tem os dados do exemplo e tem um agrupamento para facilitar, o tal encapsulamento:

  • Assim se mudar o layout de funcionário não precisa mexer no grupo.
  • Pode ter vários grupos no mesmo programa.
  • Pode usar alocação dinâmica sem mexer em funcionário

E pra testar vamos só ler os dados e listar assim:
 

      Lidos 6 funcionarios [MAX 40]

      [Sobrenome,Nome (idade) Sexo Salario]:

 1    Cesar,Julio               ( 86) M     2500.00
 2    Helena,Maria              ( 53) F    12300.00
 3    Souza,Francisco           ( 60) M     7350.00
 4    Moura,Yasmin              ( 95) F     3590.00
 5    Lopes,Bruna               ( 66) F    18000.00
 6    Murphy,Eddie              ( 18) M     3000.00

 

O programa exemplo

 

#include <stdio.h>
#include <string.h>

typedef struct
{
    char nome[20];
    char sobrenome[20];
    int  salario;
    char sexo;
    int  idade;

} Funcionario;

typedef struct
{
    int         max_N;  // maximo de funcionarios
    int         N;      // total atual
    Funcionario f[40];  // os caras

} Grupo;

int main(void)
{
    char  area[8 * 1024] = {0};
    FILE* arquivo        = fopen("teste.txt", "r");
    if (arquivo == NULL) return -1;

    const char* mascara = "%19s %19s %d.%d %19s %3d";
    Funcionario f       = {0};
    Grupo       grupo   = {0};
    grupo.N             = 0;  // vazio, claro
    // pra não usar alocacao dinamica
    grupo.max_N = 40;  // so um brinquedo
    int   milhares;
    int   ate999;
    char  sexo[20];
    char* res = NULL;

    while ((res = fgets(area, (int)sizeof(area), arquivo)) != NULL)
    {
        area[strlen(area) - 1] = 0;
        int n = sscanf(
            area, mascara, &f.nome, &f.sobrenome, &milhares, &ate999,
            sexo, &f.idade);
        if (n != 6) return -1;
        f.salario        = milhares * 1000 + ate999;
        f.sexo           = sexo[0];
        grupo.f[grupo.N] = f;  // copia o funcionario para o grupo
        grupo.N += 1;
        if (grupo.N == grupo.max_N) break;
    };
    fclose(arquivo);
    printf("\
      Lidos %d funcionarios [MAX %d]\
\n\
\n\
      [Sobrenome,Nome (idade) Sexo Salario]:\n\n", grupo.N,
        grupo.max_N);
    for (int i = 0; i < grupo.N; i += 1)
        printf(
            "%2d    %s,%s\t\t(%3d) %c %8d.00\n", 1 + i,
            grupo.f[i].sobrenome, grupo.f[i].nome, grupo.f[i].idade,
            grupo.f[i].sexo, grupo.f[i].salario);
    return 0;
}

 

É quase o mesmo.

 

E agora?

 

Se preciso, o provável próximo passo seria trocar os vetores por ponteiros, usando
 

typedef struct
{
    char* nome;
    char* sobrenome;
    int  salario;
    char sexo;
    int  idade;

} Funcionario;

typedef struct
{
    int          max_N;  // maximo de funcionarios
    int          N;      // total atual
    Funcionario* f[40];  // os caras

} Grupo;

 

E seguir para a fase4 :) 

  • Curtir 1
  • Obrigado 1
Postado

 

4 horas atrás, arfneto disse:

Usar expressões regulares aqui seria um caminho muito muito longo para o que pode ser feito em uma única linha.

você se refere a curva de aprendizado longa... Só que regex não é tão complicado assim. Mesmo pra quem tá começando.

Agora veja:
 

Em 05/08/2021 às 20:24, vangrant disse:

• Quantas pessoas tem os nomes começados com vogal e quantas tem nomes começados com consoantes?


O regex pra match disso é uma linha... Algo como por exemplo isso:
/[^aeiou].*/i
Não utilizando algo equivalente a um regex, você utilizaria o que? um laço for a mais pra testar cada vogal, incluindo algum que possa ser acetuado, como o nome por exemplo de Özdemir?

 

4 horas atrás, arfneto disse:

Em javascript talvez fosse o caso de usar alguma biblioteca, como jquery-csv para ler csv, ou usar apenas split() e parseXXX() quando for o caso, mas aí é para outro forum ;) regex, eu  acho, não é apropriado: é melhor escrever em torno dos dados e já sabe onde estão os números.


No meu caso, eu prefiro o codigo nativo mesmo (Gosto meu). O regex (C++), aqui pra mim, já veio com o proprio Ubuntu. Assim como os outros, eu apenas dei mais uma sugestão. Existe um zilhão de formas de fazer isso. Algumas mais fáceis com curva de conhecimento maior e e outras mais dificieis com curva de conhecimento menor. Usando structs, outras com splits seguidos de splits, sscanf... Eu não faço exercicios pros outros. Só dou as dicas de como um ou outro comando funciona e dou sugestões de outros comandos, livros, paginas, textos... Dica que acabo de pegar aqui no google:
https://www.cplusplus.com/reference/clibrary/

  • Curtir 1
Postado
4 horas atrás, codigo rápido disse:

você se refere a curva de aprendizado longa... Só que regex não é tão complicado assim. Mesmo pra quem tá começando

 

Minha referência não é essa. Expressões regulares são simples. Eu nada disse sobre curva de aprendizado.

 

Eu expliquei porque: as expressões regulares só vão separar os dados, como um simples split, como linha.split() em javascript. Note que o espaço até é o padrão e nem precisa de argumentos. Não há razão para usar expressões regulares. Escreva um programa assim, com regex, outro com com split. Leia seus programas, compare, e entenderá o que te expliquei. Não vou postar esses programas porque nada tem a ver com o forum, mas acho que vai notar que um split() um for e 3 Parse() em javascript podem consumir esses dados. Não é preciso tratar esses dados como expressões regulares, são apenas uma tabela. Como expliquei, trata-se de um arquivo csv, que pode importar em uma linha para um banco de dados ou uma planlha. Veja o exemplo importado para o Planilhas, do Google, e sem recorrer a javascript (a linguagem nativa de programação do Planilhas):

 

image.png.f47a003f7ccafdb199a84bccbc87f115.png E a planilha até converte os dados de modo que pode somar os salários, desde que o ponto decimal seja esse.

 

 

 

 

 


 

 

4 horas atrás, codigo rápido disse:
Em 05/08/2021 às 20:24, vangrant disse:

Quantas pessoas tem os nomes começados com vogal e quantas tem nomes começados com consoantes?


O regex pra match disso é uma linha... Algo como por exemplo isso:
/[^aeiou].*/i

 

Que quer dizer com isso? Só está complicando as coisas. Isso aí não vai te dar a quantidade --- "Quantas pessoas" --- mas sim um grupo de ocorrências. E não tem a ver com o problema aqui.

 

4 horas atrás, codigo rápido disse:

No meu caso, eu prefiro o codigo nativo mesmo (Gosto meu)

 

Sim, você pode escrever um parser para csv. Mesmo usando regex. Recomendo split. Note o próprio nome da coisa: em csv o 's' é de separated. E split faz isso: separa. Pode usar regex para fazer o split, só para mostrar que pode, ou só escrever linha.split() já que espaço é o padrão para split. 

 

Como pode escrever um parser para csv em C. Eu já postei isso aqui no ano passado eu acho. Dá pra pesquisar aqui no forum.

 

4 horas atrás, codigo rápido disse:

Eu não faço exercicios pros outros. Só dou as dicas de como um ou outro comando funciona e dou sugestões de outros comandos, livros, paginas, textos... Dica que acabo de pegar aqui no google:
https://www.cplusplus.com/reference/clibrary/

 

OK! Muito bem. Sempre é possível usar o Google ou o Bing e ir ao manual extra-oficial de C++ onde tem a referência das bibliotecas C.

 

 

 

  • Curtir 2
Postado
1 hora atrás, arfneto disse:

Isso aí não vai te dar a quantidade --- "Quantas pessoas" --- mas sim um grupo de ocorrências. E não tem a ver com o problema aqui.

Mas isso é lógico, moço!!!  Como eu disse, eu não vou fazer exercicios pra ninguem, apenas dar as dicas dentro dos limites do meu conhecimento.

O fato é que o regex que sugeri é um modo pra encontrar essas ocorrencias. To errado? Ou de alguma outra forma o contador vai adivinhar que linha tem ou não essa ocorrencia? Sem saber que linhas tem essas ocorrencias, como o contador iria fazer a contagem? Ou seja, isso que to falando não é conversa de bebado.

Sugeri fazer isso com regex, mas sem ele ia ser necessário um 'for' a mais passando por cada linha verificando se var[0]==caractere_especial do qual esse caractere_especial é um unico caractere do conjunto de um array de caracteres especiais. Mas você disse que tem caminho mais curto. Eu não sei que caminho é esse. Por isso eu quero saber qual e como seria em C já que em javaScript é pra outro forum. Não precisa nem mostrar nem com esse exercicio porque vai alem do que estou perguntando. Pode mostrar um exemplo simples da sua cabeça pra eu saber como é esse caminho mais curto? E ai... tem mostrar como é?

  • Curtir 1
Postado

@vangrant Com a função fscanf é bem simples pegar os registros do arquivo. Você pode usar structs para deixar os dados mais organizados e usar os campos nos testes para pegar as informações que o enunciado pede. Para pegar p.ex a quantidade de itens e nomes que começam com vogal ou consoante,

#include <stdio.h>
#include <string.h>

typedef struct{
    char nome[50];
    char sobrenome[50];
    float salario;
    char sexo;
    int idade;
}Registro;

typedef struct{
    int vogal;
    int consoante;
    int mais_velho;
    int mais_novo;
    int item;
}Qtd;

int main(void) {
    FILE *arq = fopen("teste.txt","r");
    Registro reg;
    Qtd qtd;
    
    memset(&qtd, 0, sizeof(qtd));
    while(!feof(arq)){
        fscanf(arq, 
            "%s %s %f %c %d",
            reg.nome, reg.sobrenome,
            &reg.salario, &reg.sexo,
            &reg.idade
        );
        if(strchr("aeiouAEIOU", reg.nome[0])){
            qtd.vogal += 1;        
        }else{
            qtd.consoante += 1;
        }
        qtd.item += 1;
    }
    printf(
        "QUANTIDADES\n"
        "Itens = %d\n"
        "Consoantes = %d\n"
        "Vogais = %d\n",
        qtd.item, qtd.consoante, qtd.vogal
    );
    fclose(arq);
    return 0;
}

 

  • Curtir 2
Postado
1 hora atrás, Midori disse:
if(strchr("aeiouAEIOU", reg.nome[0])){

Muito elegante.

eu colocaria as consoantes e as vogais acentuadas também, pois existem nomes como esses que acho que ficariam de fora: Ágata, Átila, Érica, Érico, Ênia, Ênio, Éfeso, Ícaro, Ítalo, Édson, özdemir... Se o primeiro caractere for '!', por exemplo, ele vai aceitar como nome válido e como consoante.
 

Postado

@codigo rápido No modelo de arquivo postado não parece que haverá ocorrência de caracteres inválidos ou acentos no nome, entendo que os caracteres são só os 26 entre A e Z que normalmente são considerados nesse tipo de exercício.

  • Curtir 1
Postado
6 minutos atrás, Midori disse:

@codigo rápido No modelo de arquivo postado não parece que haverá ocorrência de caracteres inválidos ou acentos no nome, entendo que os caracteres são só os 26 entre A e Z que normalmente são considerados nesse tipo de exercício.


Nome é nome e usuário é doido. Pode aparecer coisa de tudo quanto é tipo.

Postado

No meu código eu poderia ter iniciado a struct com {0} em vez de usar memset. Só usei a função para zerar as variáveis, mas era melhor ter iniciado a struct.

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

LANÇAMENTO!

eletronica2025-popup.jpg


CLIQUE AQUI E BAIXE AGORA MESMO!