La map doit être fermée/entourée de murs, sinon le programme doit renvoyer
une erreur
J'ai fait un mini programme test et si j'en viens a poster ce message c'est que j'ai besoin d'aide svp Voici ce que j'ai fait pour l'instant
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <unistd.h>
# include <fcntl.h>
# include <stdbool.h>
# define BUFF_SIZE 1
# define BLANK '0'
# define WALL '1'
# define PERSO 'W'
char **ft_split(char const *s, char c);
void ft_realloc(char **dst, const char *src)
{
char *res;
int i;
if (*dst && **dst)
{
i = 0;
while ((*dst)[i])
i++;
res = malloc(strlen(src) + i + 1);
if (res)
{
strcpy(res, *dst);
strcpy(res + i, src);
free(*dst);
*dst = res;
}
return ;
}
*dst = strdup(src);
}
void print_array(char const **map, const size_t size)
{
for (size_t i = 0; i < size; i++) {
printf("[%lu] - %s\n", i, map[i]);
}
}
bool isok(char const **map, const size_t y, const size_t x)
{
return ((map[y - 1][x] != WALL || map[y - 1][x] != PERSO)
&& (map[y + 1][x] != WALL || map[y + 1][x] != PERSO)
&& (map[y][x - 1] != WALL || map[y][x - 1] != PERSO)
&& (map[y][x + 1] != WALL || map[y][x + 1] != PERSO));
}
bool parsing(char const **map, const size_t size)
{
for (size_t i = 0; i < size; i++) {
for (size_t j = 0; map[i][j]; j++) {
if (map[i][j] == BLANK)
{
if (i == 0 || i == size - 1 || j == 0 || map[i][j + 1] == '\0')
return (false);
printf("Map %lu: %s\n", i, map[i]);
if (isok(map, i, j))
{
fprintf(stderr, "Failed at: %lu:%lu\n", i, j);
return (false);
}
}
}
}
return (true);
}
int main(int ac, char const **av)
{
if (ac != 2) {
fprintf(stderr, "Wrong arguments count\n");
return (1);
}
int fd = open(av[1], O_RDONLY);
if (fd < 0) {
fprintf(stderr, "Can't open file\n");
return (1);
}
char const ** map = 0;
size_t size = 0;
char *line_tmp = 0;
char tmp = 0;
int content = 0;
do {
content = read(fd, & tmp, BUFF_SIZE);
if (content < 0) {
fprintf(stderr, "Failed while reading file\n");
return (1);
}
ft_realloc(& line_tmp, & tmp);
if (tmp == '\n' || content == 0)
size++;
} while (content);
map = ft_split(line_tmp, '\n');
// print_array(map, size);
printf("Result: %d\n", parsing(map, size));
return (0);
}
Mais mon programme me renvoie constamment 0 ( pour signifier une erreur mais je suppose que ça, vous l'aurez remarqué ), avez vous une idée d'où viens le problème svp Merci
Il y a un gros problème lignes 25, 29 et 35: dans les faits, src n'est pas une chaine de caractères, mais un caractère (déclaré ligne 89). D'où UB. Je me suis arrêté là.
Edit au cas où: la plupart des fonctions str_xxx(s) se basent sur le fait que s est une chaîne de caractères, càd une suite contiguë de caractères en mémoire, terminée par le caractère NUL (0, '\0') dont elles se servent pour déterminer où s'arrête la chaîne. Mais dans ton cas, si src a bien le type nécessaire pour appeler les fonctions str_xxx(), sa représentation mémoire ne correspond pas à celle d'une chaine de caractères.
- Edité par edgarjacobs 24 mars 2023 à 0:28:31
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
Et cava déjà un peu mieux, car quand je tentais d'afficher la taille de chaque ligne ca me renvoyait pas la bonne taille
EDIT: j'ai pas compris, vous faites référence à tmp[2] ? Si oui, je comprend pas pourquoi car c'est bien une chaine de caractère terminant par NULL '\0', car il lira toujours 1 et read écrira forcément que au premier
Et cava déjà un peu mieux, car quand je tentais d'afficher la taille de chaque ligne ca me renvoyait pas la bonne taille
EDIT: j'ai pas compris, vous faites référence à tmp[2] ? Si oui, je comprend pas pourquoi car c'est bien une chaine de caractère terminant par NULL '\0', car il lira toujours 1 et read écrira forcément que au premier
-
Code d'origine
antoinelds a écrit:
char tmp = 0;
int content = 0;
do {
content = read(fd, & tmp, BUFF_SIZE);
if (content < 0) {
fprintf(stderr, "Failed while reading file\n");
return (1);
}
ft_realloc(& line_tmp, & tmp);
Non, je fais référence au char tmp du 1er code.
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
Merci pour vos commentaires et voici le code maintenant, mais je suis toujours bloqué sur le problème de base
PierrotLeFou a écrit:
Pourquoi ne pas faire un realloc si dst existe?
Aussi, je n'ai pas compris ce n'est pas déjà ce que je fais Pierrot?
Et si je l'ai pas ajouté simplement a la fin c'est parce-que j'utilise déjà cette fonction, donc il m'est inutile d'en créer une autre et d'en faire un cas spécial
Ah, et dernière question: je croyais que char const **ptr ou const char **ptr on ne pouvait pas modifier le contenu alors pourquoi quand je fais char **const ptr qui là, le pointeur est constant je ne peux pas l'assigner par exemple une fonction qui retourne un char ** ?
Je ne suis pas sûr de bien comprendre (il manque beaucoup de contexte), mais j'ai l'impression que la phrase
> La map doit être fermée/entourée de murs
peut s'interpréter comme
la première et la dernière colonne doivent être des murs
pareil pour les lignes.
Ce qui est très simple à tester, et n'a rien à voir avec le code de lecture (*) :
bool map_is_closed_by_walls(char **map, int size)
{
bool closed = true;
for (int i = 0; i < size; i++) {
if ( map[i][0] != WALL
|| map[0][i] != WALL)
|| map[i][size-1] != WALL
|| map[size-1][i] != WALL
) {
closed = false;
break;
}
return closed;
}
(*) qui a l'air bien compliqué, mais il faudrait nous donner une *spécification* du format que doivent respecter les fichiers d'entrée, plutôt que nous faire jouer aux devinettes sur la base de code qui ne fait pas ce qu'il doit.
Ce truc-là m'a l'air particulièrement chelou
for (size_t i = 0; i < size; i++) {
for (size_t j = 0; map[i][j]; j++) {
on fait évoluer i entre 0 et la taille - 1, et j ???? Dans la map, il y a des octets qui représentent des caracteres, qui peuvent être '0', '1' ou peut-être 'W' : aucun n'est nul.
Je pensais à quelque chose du genre où tu donnerait le caractère et non une chaîne en paramètre.
void ft_realloc(char **dst, const char src) { size_t len; if(*dst) { len = strlen(*dst); *dst = realloc(*dst, len + 2); } else { len = 0; *dst = malloc(2); } if(dst == NULL) { // je te laisse afficher le message d'erreur ... } (*dst)[len] = src; (*dst)[len+1] = '\0'; }
- Edité par PierrotLeFou il y a environ 8 heures
Merci pour ta proposition mais si j'utilise pas realloc c'est parce-que je n'ai pas le droit aux fonctions standard, je vais devoir remplacer tous les str.. par ft_..
Aussi,
michelbillaud a écrit:
Je ne suis pas sûr de bien comprendre (il manque beaucoup de contexte), mais j'ai l'impression que la phrase
> La map doit être fermée/entourée de murs
peut s'interpréter comme
la première et la dernière colonne doivent être des murs
pareil pour les lignes.
Disons que c'est pas tout à fait ça, c'est ma faute, j'ai très mal expliqué l'énoncé.
Alors oui la map doit il faut l'interpreter de la même facon que vous avez dit mais pas que! IL faut aussi checker si des 0 sont bien entourés de murs example:
for (size_t i = 0; i < size; i++) {
for (size_t j = 0; map[i][j]; j++) {
on fait évoluer i entre 0 et la taille - 1, et j ???? Dans la map, il y a des octets qui représentent des caracteres, qui peuvent être '0', '1' ou peut-être 'W' : aucun n'est nul.
Alors si, toutes les lignes finissent par '\0' grace à cette ligne
map = ft_split(line_tmp, '\n');
J'ai la size(taille des colonnes(y)) mais pas le x car elle change selon la ligne, toutes les lignes peuvent ne pas avoir le même nombre de chars. C'est soit ça soit stocké la longueur pour toutes les lignes ou simplement aussi appelé strlen mais ça revient au même.
Aussi, je crois arrivé sur quelque chose, ça m'a l'air de bien fonctionner mais j'ai encore 2-3 soucis à régler avec valgrind
bool isok_vertical(char const **map, int y,int x, int add)
{
for (int i = y; i >= 0 && map[i]; i += add)
if (map[i][x] == WALL)
return (true);
return (false);
}
bool isok_horizontal(char const *line, int x, int add)
{
for (int i = x; i >= 0 && line[i]; i += add)
if (line[i] == WALL)
return (true);
return (false);
}
bool isok(char const **map, const size_t y, const size_t x)
{
return ((strlen(map[y - 1]) >= x && ((map[y - 1][x] == WALL || map[y - 1][x] == PERSO) || (map[y - 1][x] == BLANK && isok_vertical(map, y - 1, x, -1))))
&& (strlen(map[y - 1]) >= x && ((map[y + 1][x] == WALL || map[y + 1][x] == PERSO) || (map[y + 1][x] == BLANK && isok_vertical(map, y + 1, x, +1))))
&& ((map[y][x - 1] == WALL || map[y][x - 1] == PERSO) || (map[y][x - 1] == BLANK && isok_horizontal(map[y], x - 1, -1)))
&& ((map[y][x + 1] == WALL || map[y][x + 1] == PERSO) || (map[y][x + 1] == BLANK && isok_horizontal(map[y], x + 1, +1))));
}
bool parsing(char const **map, const size_t size)
{
for (size_t i = 0; i < size; i++) {
for (size_t j = 0; map[i][j]; j++) {
if (map[i][j] == BLANK)
{
if (i == 0 || i == size - 1 || j == 0 || map[i][j + 1] == '\0')
return (false);
if (!isok(map, i, j))
{
fprintf(stderr, "Failed at: %lu:%lu\n", i, j);
return (false);
}
}
}
}
return (true);
}
int main(int ac, char const **av)
{
if (ac != 2) {
fprintf(stderr, "Wrong arguments count\n");
return (1);
}
int fd = open(av[1], O_RDONLY);
if (fd < 3) {
fprintf(stderr, "Can't open file\n");
return (1);
}
char const ** map = 0;
size_t size = 0;
char *line_tmp = 0;
char tmp[BUFF_SIZE + 1] = {0};
int content = 0;
do {
content = read(fd, tmp, BUFF_SIZE);
if (content < 0) {
fprintf(stderr, "Failed while reading file\n");
return (1);
}
ft_realloc(& line_tmp, tmp);
if (tmp[0] == '\n' || content == 0)
size++;
} while (content);
map = ft_split(line_tmp, '\n');
print_array(map, size);
printf("Result: %d\n", parsing(map, size));
// free ..
return (0);
}
> Merci pour ta proposition mais si j'utilise pas realloc c'est parce-que je n'ai pas le droit aux fonctions standard Donc tu ne peux pas utiliser malloc ?
Le Tout est souvent plus grand que la somme de ses parties.
Réallouer pour un octet de plus, c'est une mauvaise stratégie, avec un coût quadratique (proportionnel au carré de la taille du truc).
Ce qui serait peut être plus malin (et c'est classique, je ne l'ai évidemment pas inventé):
dans la fonction qui lit un fichier pour en tirer une grille (fonction qui ne devrait pas être main...), allouer un tampon assez grand pour lire une ligne entière (genre 1024). C'est une variable temporaire, on la rendra rapidement, pas de problème
si il se révèle trop petit pour la ligne (who knows?), DOUBLER sa taille. Ce qui veut dire que c'est un tableau alloué dynamiquement, et qu'on va garder quelque part sa taille.
quand, à partir de la ligne (de texte) on construit la ligne de la structure de données, on donne à cette dernière la taille qui va bien.
Et aussi : faire de map un type de données à part entière, genre une structure avec
le nombre de lignes
le tableau des chaînes de caractères qui représentent les lignes
Yes merci des conseils, après je vous ai fournit un mini programme de test, ce ne sera pas le final et biensur que non, je suis pas fou au point d'écrire dans le main.
J'appliquerai vos conseils quand je débuterai vraiment, merci encore.
Ah et si, quelqu'un peut me répondre svp
antoinelds a écrit:
Ah, et dernière question: je croyais que char const **ptr ou const char **ptr on ne pouvait pas modifier le contenu alors pourquoi quand je fais char **const ptr qui là, le pointeur est constant je ne peux pas l'assigner par exemple une fonction qui retourne un char ** ?
Non justement avec le const de l'autre côté, au lieu de const char **p, on a char **const p, ce qui veut dire que le pointeur est en const mais pas le contenu, on est d'accord ?
Si tel est le cas pourquoi j'ai un warning ou erreur avec -Werror conversion const vers non const ?
Non justement avec le const de l'autre côté, au lieu de const char **p, on a char **const p, ce qui veut dire que le pointeur est en const mais pas le contenu, on est d'accord ?
Si tel est le cas pourquoi j'ai un warning ou erreur avec -Werror conversion const vers non const ?
Pourrais-tu donner un code minimum qui montre ce que tu voudrais faire ?
Parce que trouver l'erreur dans du code qu'on ne voit pas, comment dire, on est d'accord ?
Desole de répondre que maintenant, mais je vous rassure j'ai trouvé une solution à mon problème, d'ailleurs sur un de vos précèdent ( https://openclassrooms.com/forum/sujet/chdir-et-fork ) post M. Billaud qui explique bien ce que je cherchais merci!
Verifier que le "vide" est entoure de "mur"
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.