Stack Overflow em Português Asked on November 10, 2021
Eu não sei se consegui me fazer entender no título, mas ao usar strcpy()
para copiar um char*
para outro quando coloco um formato assim "teste"
ele funciona normalmente, mas quando coloco uma string com formato 3 letras (dígitos no caso), por exemplo "2000"
ele acaba mesclando esse valor para o destino com o próximo valor da próxima vez que uso strcpy()
, segue o código:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
char nome[80];
char ano[4];
char diretor[80];
} Filme;
void analise(Filme *filme, const char *arg1, const char *arg2, const char *arg3)
{
Filme _filme = {
.nome = malloc(2),
.ano = malloc(2),
.diretor = malloc(2)
};
strcpy(_filme.nome, arg1);
strcpy(_filme.ano, arg2);
strcpy(_filme.diretor, arg3);
memcpy(filme, &_filme, sizeof _filme);
}
void carregar(Filme filmes[])
{
analise(&filmes[0], "E o Vento Levou", "1939", "Victor");
analise(&filmes[1], "teste", "998", "bar");
analise(&filmes[2], "Os Passaros", "1963", "Alfred Hitchcock");
}
int main()
{
Filme filmes[1000];
carregar(filmes);
printf("nmain:n");
printf("- Nome: %sn", filmes[0].nome);
printf("- Ano: %sn", filmes[0].ano);
printf("- Diretor: %sn", filmes[0].diretor);
printf("----------------n");
printf("- Nome: %sn", filmes[1].nome);
printf("- Ano: %sn", filmes[1].ano);
printf("- Diretor: %sn", filmes[1].diretor);
printf("----------------n");
printf("- Nome: %sn", filmes[2].nome);
printf("- Ano: %sn", filmes[2].ano);
printf("- Diretor: %sn", filmes[2].diretor);
return 0;
}
Notem que executei isto:
analise(&filmes[0], "E o Vento Levou", "1939", "Victor");
analise(&filmes[1], "teste", "998", "bar");
analise(&filmes[2], "Os Passaros", "1963", "Alfred Hitchcock");
Ao executar o problema a saída é esta:
main:
- Nome: E o Vento Levou
- Ano: 1939Victor
- Diretor: Victor
----------------
- Nome: teste
- Ano: 998
- Diretor: bar
----------------
- Nome: Os Passaros
- Ano: 1963Alfred Hitchcock
- Diretor: Alfred Hitchcock
Vejam que em “E o Vento Levou” e “Os Passaros” os anos ficaram mesclados com o nome do diretor, 1939Victor
e 1963Alfred Hitchcock
, já no caso do:
analise(&filmes[1], "teste", "998", "bar");
Tem a saída correta. Eu entendo que deveria fazer o ano com int
, mas estou aprendendo C e gostaria de entender melhor esta parte da memória, presumo que tenha sido algum erro de digitação meu.
O que ocorre é que o seu struct
ocupa 164 bytes na memória:
O compilador vai atribuir os seguintes deslocamentos para cada um desses campos:
nome
: 0 bytes de deslocamento desde o início da struct
na memória.ano
: 80 bytes de deslocamento desde o início da struct
na memória.diretor
: 84 bytes de deslocamento desde o início da struct
na memória.Assim sendo, se pergarmos o primeiro caso por exemplo, o layout fica assim (onde ∅ é o terminador nulo e □ é lixo, que pode ter qualquer valor):
E o Vento Levou∅□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□1939Victor∅□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□
Quando você faz isso:
printf("- Ano: %sn", filmes[0].ano);
Em tempo de execução, o código gerado vai carregar o endereço de memória de filmes
, somar 164×0 para obter filmes[0]
(164 = sizeof Filme
, 0 é o índice) e então somar 80 para obter a posição de filmes[0].ano
(80 é a posição do ano
dentro do struct
). Dessa posição ele vai imprimir uma string (devido ao %s
) que começa nessa posição calculada e termina no primeiro terminador nulo encontrado. Ocorre que o ano não tem um terminador nulo, e portanto ele vai acabar invadindo a região de memória subsequente do campo diretor
.
Além disso, esse código não têm nenhum sentido:
Filme _filme = {
.nome = malloc(2),
.ano = malloc(2),
.diretor = malloc(2)
};
O que você queria provavelmente era isso:
void analise(Filme *filme, const char *arg1, const char *arg2, const char *arg3) {
strcpy(filme->nome, arg1);
strcpy(filme->ano, arg2);
strcpy(filme->diretor, arg3);
}
Para resolver o seu problema sem usar int
para o ano, uma possibilidade é mudar o tamanho do campo ano
para 5. Se os demais campos devem ter no máximo 80 caracteres ao invés de 79, então mude o tamanho deles para 81 a fim de se certificar que o terminador nulo está lá.
Outra alternativa que evita ter que redimensionar o tamanho dos campos é especificar uma tamanho máximo para as strings no printf
:
printf("- Nome: %.80sn", filmes[0].nome);
printf("- Ano: %.4sn", filmes[0].ano);
printf("- Diretor: %.80sn", filmes[0].diretor);
Answered by Victor Stafusa on November 10, 2021
Este código tem alguns problemas.
malloc()
se a área que a string deve ficar já está reservada dentro da estrutura. Até poderia alocar se desejar, e talvez faça sentido para os nomes, mas aí precisa declarar como const char *
e não [tamanho]
. Tem que ser bem mais cuidadoso quando faz isso. O que inclusive está vazando memória. Em grande volume isso seria trágico. E alocar apenas 2 caracteres onde precisa de vários também não dá muito certo, é que neste caso coincidentemente funciona.Assim funciona:
#include <string.h>
#include <stdio.h>
typedef struct {
char nome[81];
char ano[5];
char diretor[81];
} Filme;
void analise(Filme *filme, const char *arg1, const char *arg2, const char *arg3) {
strcpy(filme->nome, arg1);
strcpy(filme->ano, arg2);
strcpy(filme->diretor, arg3);
}
void carregar(Filme filmes[]) {
analise(&filmes[0], "E o Vento Levou", "1939", "Victor");
analise(&filmes[1], "teste", "998", "bar");
analise(&filmes[2], "Os Passaros", "1963", "Alfred Hitchcock");
}
int main() {
Filme filmes[1000];
carregar(filmes);
printf("nmain:n");
for (int i = 0; i < 3; i++) {
printf("- Nome: %sn", filmes[i].nome);
printf("- Ano: %sn", filmes[i].ano);
printf("- Diretor: %sn", filmes[i].diretor);
printf("----------------n");
}
}
Veja funcionando no ideone. E no repl.it. Também coloquei no GitHub para referência futura.
Answered by Maniero on November 10, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP