Ajuda em C [RESOLVIDO]

1. Ajuda em C [RESOLVIDO]

Gustavo Samuel Bacagine Azevedo
Bacagine

(usa Arch Linux)

Enviado em 15/10/2019 - 15:25h

Estou tendo problemas em um trabalho na faculdade sobre linguagem C

Meu professor pediu para fazermos um programa que quando minha entrada for _texto_ ou *texto* a saída deve ser <i>texto</i> ou <b>texto</b>

Estamos tendo problemas em substituir os simbolos de _ e de * por <i><b>

Esse é o arquivo my_html.h criado pelo meu professor:
/* my_html.h
* Protótipo das funções para transformar para itálico e negrito
* o texto informado pelos autores do weblog.
* Ciro Cirne Trindade
* 02/10/2019 */

#ifndef _MY_HTML_H
#define _MY_HTML_H

/* função que converte os atalhos de itálico do texto passado
* como argumentos para as tags HTML <i> e </i> */
void italico(char *);

/* função que converte os atalhos de negrito do texto passado
* como argumentos para as tags HTML <b> e </b> */
void negrito(char *);

/* função que substitui o caractere da posição dada pelo 2o argumento
* no texto dado pelo 1o argumento pela tag passada como 3o
* argumento(<i>, </i>, <b> ou </b>) */
void replace(char *, int, const char *);

#endif


esse e o nosso fonte desenvolvendo os prototipos da biblioteca my_html.h:

#include <stdio.h>
#include <string.h>
#include "my_html.h" // --> Biblioteca contendo o protótipo \
das funções para transformar o texto digitado em \
tags de negrito e itálico

void italico(char * str) // função que converte os atalhos de itálico do texto passado
{ // como argumentos para as tags HTML <i> e </i>
int i; // indice da string
for(i = 0; str[i] != '\0'; i++){ // percorre a string
if (str[i] == '_'){ // e procura pelo sinal de _
replace(str, i, "<i>"); // substitui o sinal de _ pela tag <i>
i+=2; //
}
}
}

void negrito(char * str) // função que converte os atalhos de negrito do texto passado
{ // como argumentos para as tags HTML <b> e </b>
int i; // indice da string
for(i = 0; str[i] != '\0'; i++){ // percorre a string
if (str[i] == '*'){ // e procura pelo sinal de *
replace(str, i, "<b>"); // substitui o sinal de _ pela tag <b>
i+=2;
}
}
}

void replace(char * str, int i, const char * tag) // Em faze de testes
{
for(i = 0; str[i] != '\0'; i++){
if (tag[i] == '_'){
strcpy(tag[i], "<i>");
}
else if(tag[i] == '*'){
strcpy(tag[i], "<b>");
}
}
}


e esse e o nosso arquivo main:

#include <stdio.h>
#include <string.h>
#include "my_html.h" // --> Biblioteca contendo o protótipo \
das funções para transformar o texto digitado em \
tags de negrito e itálico
int main()
{
char texto[101]; // Conteudo a ser digitado para o weblog
// system("clear"); // Limpa o terminal
printf("\n");
scanf("%100[]", texto);
while(fgets(texto, 100, stdin) != NULL){
italico;
negrito;
printf("%s\n", str);
}

// getchar(); // Pausa a tela do terminal (equivalente ao system("pause") do Windows)
return 0;
}



  


2. MELHOR RESPOSTA

Paulo
paulo1205

(usa Ubuntu)

Enviado em 15/10/2019 - 23:19h

Bacagine escreveu:

Estou tendo problemas em um trabalho na faculdade sobre linguagem C

Meu professor pediu para fazermos um programa que quando minha entrada for _texto_ ou *texto* a saída deve ser <i>texto</i> ou <b>texto</b>

Estamos tendo problemas em substituir os simbolos de _ e de * por <i><b>

Esse é o arquivo my_html.h criado pelo meu professor:
/* my_html.h
* Protótipo das funções para transformar para itálico e negrito
* o texto informado pelos autores do weblog.
* Ciro Cirne Trindade
* 02/10/2019 */

#ifndef _MY_HTML_H
#define _MY_HTML_H

/* função que converte os atalhos de itálico do texto passado
* como argumentos para as tags HTML <i> e </i> */
void italico(char *);

/* função que converte os atalhos de negrito do texto passado
* como argumentos para as tags HTML <b> e </b> */
void negrito(char *);

/* função que substitui o caractere da posição dada pelo 2o argumento
* no texto dado pelo 1o argumento pela tag passada como 3o
* argumento(<i>, </i>, <b> ou </b>) */
void replace(char *, int, const char *);

#endif


Acho que seu professor não foi muito feliz com essas funções. Ele deveria ter incluído em cada uma delas um parâmetro a mais, para especificar o tamanho máximo do array de caracteres contendo a string a ser alterada. Do jeito como estão expressas em suas declarações, as funções, por mais bem implementadas que sejam, correm sempre o risco de extrapolar o tamanho máximo do array, e provocar corrupção de memória.

esse e o nosso fonte desenvolvendo os prototipos da biblioteca my_html.h:
#include <stdio.h>
#include <string.h>
#include "my_html.h" // --> Biblioteca contendo o protótipo \
das funções para transformar o texto digitado em \
tags de negrito e itálico

void italico(char * str) // função que converte os atalhos de itálico do texto passado
{ // como argumentos para as tags HTML <i> e </i>
int i; // indice da string
for(i = 0; str[i] != '\0'; i++){ // percorre a string
if (str[i] == '_'){ // e procura pelo sinal de _
replace(str, i, "<i>"); // substitui o sinal de _ pela tag <i>
i+=2; //
}


Se eu fosse você, em lugar de sair trocando caracteres assim que os encontro, eu procuraria por um bloco de texto delimitado por dois desses caracteres — até porque foi isso o que foi pedido no enunciado. Assim, eu tentaria encontrar o primeiro sinal “_”, seguido por um (ou zero, se você preferir) ou mais caracteres diferentes de “_” e, por fim, um segundo caráter “_”, e substituiria todo esse bloco por “<i>”+sequência intermediária+“</i>”. Isso tem a vantagem de eliminar eventuais inconsistências quando você tiver um caso de número impar de sinais “_”.

Eventualmente, você poderia até ter o cuidado de não considerar como delimitadores sinais de “_” que aconteçam no meio de palavras (por exemplo, em “my_html.h”), mas apenas que ocorram no começo ou no final de palavras.

Raciocínio semelhante pode ser usado na função que trata negritos.

    }
}

void negrito(char * str) // função que converte os atalhos de negrito do texto passado
{ // como argumentos para as tags HTML <b> e </b>
int i; // indice da string
for(i = 0; str[i] != '\0'; i++){ // percorre a string
if (str[i] == '*'){ // e procura pelo sinal de *
replace(str, i, "<b>"); // substitui o sinal de _ pela tag <b>
i+=2;
}
}
}

void replace(char * str, int i, const char * tag) // Em faze de testes
{
for(i = 0; str[i] != '\0'; i++){
if (tag[i] == '_'){


Provavelmente você quis dizer “str[i]”, não?

Mas note que, de acordo com o enunciado, a função não tem de fazer esse teste. Ele já foi feito por italico() ou por negrito(), e esta função, como o próprio nome diz, tem apenas de substituir o que já foi identificado. em outro lugar,

			strcpy(tag[i], "<i>"); 


Os dois parâmetros de strcpy() estão errados. O primeiro deveria ser um ponteiro de caracteres que designa o array que vai receber o conteúdo copiado, e o segundo deveria ser um ponteiro para caracteres que designa a string cujo conteúdo será copiado, que, de acordo com o enunciado, a função deveria receber (e recebe!) como parâmetro.

Ao usar “tag[i]” você indica o valor de um único caráter (nem ao menos o endereço de onde tal caráter está), e ainda por cima da string errada.

Quando você acertar a função, verá que terá de trocar um único caráter por múltiplos caracteres. Isso implica que você terá de empurrar mais para diante os caracteres que vêm após o caráter a ser substituído, a fim de criar espaço para os caracteres excedentes. Se você não o fizer, acabará sobrescrevendo parte do texto original.

Os mesmos problemas ocorrem no bloco abaixo.

		}
else if(tag[i] == '*'){
strcpy(tag[i], "<b>");
}
}
}


e esse e o nosso arquivo main:
#include <stdio.h>
#include <string.h>
#include "my_html.h" // --> Biblioteca contendo o protótipo \
das funções para transformar o texto digitado em \
tags de negrito e itálico
int main()


Essa declaração de main não está de acordo com o que o padrão prescreve.

Se seu programa não deseja receber argumentos do ambiente de execução, o certo seria dizer “int main(void)”. Se ele tiver de receber argumentos, que virão numa série de strings, o certo seria dizer “int main(int argc, char **argv)” (os nomes argc e argv podem ser trocados, mas seus valores representam um contador de argumentos, e um array de strings contendo cada argumento; por convenção, o primeiro argumento, argv[0], indica o nome usado para invocar o programa, e o argc+1-ésimo argumento, argv[argc], é um ponteiro nulo).

{
char texto[101]; // Conteudo a ser digitado para o weblog
// system("clear"); // Limpa o terminal
printf("\n");
scanf("%100[]", texto);


Essa chamada a scanf() usa uma string de formatação inválida. Na prática, essa chamada deve estar sendo ignorada, e a leitura mesma só acontece mais abaixo, quando você chama fgets().

	while(fgets(texto, 100, stdin) != NULL){
italico;
negrito;


Essas duas linhas não fazem nada. Se você quiser invocar as funções, tem de colocar parênteses após seus nomes e, dentro desses parênteses, os argumentos correspondentes aos parâmetros.

        printf("%s\n", str);
}

// getchar(); // Pausa a tela do terminal (equivalente ao system("pause") do Windows)
return 0;
}




... “Principium sapientiae timor Domini, et scientia sanctorum prudentia.” (Proverbia 9:10)

3. Re: Ajuda em C [RESOLVIDO]

Gustavo Samuel Bacagine Azevedo
Bacagine

(usa Arch Linux)

Enviado em 19/10/2019 - 12:07h

paulo1205 escreveu:

Bacagine escreveu:

Estou tendo problemas em um trabalho na faculdade sobre linguagem C

Meu professor pediu para fazermos um programa que quando minha entrada for _texto_ ou *texto* a saída deve ser <i>texto</i> ou <b>texto</b>

Estamos tendo problemas em substituir os simbolos de _ e de * por <i><b>

Esse é o arquivo my_html.h criado pelo meu professor:
/* my_html.h
* Protótipo das funções para transformar para itálico e negrito
* o texto informado pelos autores do weblog.
* Ciro Cirne Trindade
* 02/10/2019 */

#ifndef _MY_HTML_H
#define _MY_HTML_H

/* função que converte os atalhos de itálico do texto passado
* como argumentos para as tags HTML <i> e </i> */
void italico(char *);

/* função que converte os atalhos de negrito do texto passado
* como argumentos para as tags HTML <b> e </b> */
void negrito(char *);

/* função que substitui o caractere da posição dada pelo 2o argumento
* no texto dado pelo 1o argumento pela tag passada como 3o
* argumento(<i>, </i>, <b> ou </b>) */
void replace(char *, int, const char *);

#endif


Acho que seu professor não foi muito feliz com essas funções. Ele deveria ter incluído em cada uma delas um parâmetro a mais, para especificar o tamanho máximo do array de caracteres contendo a string a ser alterada. Do jeito como estão expressas em suas declarações, as funções, por mais bem implementadas que sejam, correm sempre o risco de extrapolar o tamanho máximo do array, e provocar corrupção de memória.

esse e o nosso fonte desenvolvendo os prototipos da biblioteca my_html.h:
#include <stdio.h>
#include <string.h>
#include "my_html.h" // --> Biblioteca contendo o protótipo \
das funções para transformar o texto digitado em \
tags de negrito e itálico

void italico(char * str) // função que converte os atalhos de itálico do texto passado
{ // como argumentos para as tags HTML <i> e </i>
int i; // indice da string
for(i = 0; str[i] != '\0'; i++){ // percorre a string
if (str[i] == '_'){ // e procura pelo sinal de _
replace(str, i, "<i>"); // substitui o sinal de _ pela tag <i>
i+=2; //
}


Se eu fosse você, em lugar de sair trocando caracteres assim que os encontro, eu procuraria por um bloco de texto delimitado por dois desses caracteres — até porque foi isso o que foi pedido no enunciado. Assim, eu tentaria encontrar o primeiro sinal “_”, seguido por um (ou zero, se você preferir) ou mais caracteres diferentes de “_” e, por fim, um segundo caráter “_”, e substituiria todo esse bloco por “<i>”+sequência intermediária+“</i>”. Isso tem a vantagem de eliminar eventuais inconsistências quando você tiver um caso de número impar de sinais “_”.

Eventualmente, você poderia até ter o cuidado de não considerar como delimitadores sinais de “_” que aconteçam no meio de palavras (por exemplo, em “my_html.h”), mas apenas que ocorram no começo ou no final de palavras.

Raciocínio semelhante pode ser usado na função que trata negritos.

    }
}

void negrito(char * str) // função que converte os atalhos de negrito do texto passado
{ // como argumentos para as tags HTML <b> e </b>
int i; // indice da string
for(i = 0; str[i] != '\0'; i++){ // percorre a string
if (str[i] == '*'){ // e procura pelo sinal de *
replace(str, i, "<b>"); // substitui o sinal de _ pela tag <b>
i+=2;
}
}
}

void replace(char * str, int i, const char * tag) // Em faze de testes
{
for(i = 0; str[i] != '\0'; i++){
if (tag[i] == '_'){


Provavelmente você quis dizer “str[i]”, não?

Mas note que, de acordo com o enunciado, a função não tem de fazer esse teste. Ele já foi feito por italico() ou por negrito(), e esta função, como o próprio nome diz, tem apenas de substituir o que já foi identificado. em outro lugar,

			strcpy(tag[i], "<i>"); 


Os dois parâmetros de strcpy() estão errados. O primeiro deveria ser um ponteiro de caracteres que designa o array que vai receber o conteúdo copiado, e o segundo deveria ser um ponteiro para caracteres que designa a string cujo conteúdo será copiado, que, de acordo com o enunciado, a função deveria receber (e recebe!) como parâmetro.

Ao usar “tag[i]” você indica o valor de um único caráter (nem ao menos o endereço de onde tal caráter está), e ainda por cima da string errada.

Quando você acertar a função, verá que terá de trocar um único caráter por múltiplos caracteres. Isso implica que você terá de empurrar mais para diante os caracteres que vêm após o caráter a ser substituído, a fim de criar espaço para os caracteres excedentes. Se você não o fizer, acabará sobrescrevendo parte do texto original.

Os mesmos problemas ocorrem no bloco abaixo.

		}
else if(tag[i] == '*'){
strcpy(tag[i], "<b>");
}
}
}


e esse e o nosso arquivo main:
#include <stdio.h>
#include <string.h>
#include "my_html.h" // --> Biblioteca contendo o protótipo \
das funções para transformar o texto digitado em \
tags de negrito e itálico
int main()


Essa declaração de main não está de acordo com o que o padrão prescreve.

Se seu programa não deseja receber argumentos do ambiente de execução, o certo seria dizer “int main(void)”. Se ele tiver de receber argumentos, que virão numa série de strings, o certo seria dizer “int main(int argc, char **argv)” (os nomes argc e argv podem ser trocados, mas seus valores representam um contador de argumentos, e um array de strings contendo cada argumento; por convenção, o primeiro argumento, argv[0], indica o nome usado para invocar o programa, e o argc+1-ésimo argumento, argv[argc], é um ponteiro nulo).

{
char texto[101]; // Conteudo a ser digitado para o weblog
// system("clear"); // Limpa o terminal
printf("\n");
scanf("%100[]", texto);


Essa chamada a scanf() usa uma string de formatação inválida. Na prática, essa chamada deve estar sendo ignorada, e a leitura mesma só acontece mais abaixo, quando você chama fgets().

	while(fgets(texto, 100, stdin) != NULL){
italico;
negrito;


Essas duas linhas não fazem nada. Se você quiser invocar as funções, tem de colocar parênteses após seus nomes e, dentro desses parênteses, os argumentos correspondentes aos parâmetros.

        printf("%s\n", str);
}

// getchar(); // Pausa a tela do terminal (equivalente ao system("pause") do Windows)
return 0;
}




... “Principium sapientiae timor Domini, et scientia sanctorum prudentia.” (Proverbia 9:10)


Muito obrigado pela sua resposta paulo1205.
Muitas coisas que você falou não consegui entende muito bem (talvez porque estou aprendendo ainda).
Consegui terminar meu trabalho e ele está no git hub. Gostaria que você visse e me desse sua opinião: https://github.com/Bacagine/LP-Trab01-2019-2






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts