Concatener du texte en C dans un argument

Statut
N'est pas ouverte pour d'autres réponses.

Carambar

Elite
Salut,

Un ami m'as contacté pour avoir un conseil en C mais j'ai un trou de mémoire. En fait, dans l'exemple ci-dessous il s'agit de concatener le nom de fichier avec le chemin présent sous forme de texte dans le fopen. Je sais qu'on peut utiliser le . en PHP mais en C ?

Code:
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
	char filename;
	printf("Donnez le nom du fichier\n");
	scanf("%s",&filename);
	FILE *pfile = NULL;
	fopen=fopen("/home/mes_progs/essais_examen/"[color=red]ici[/color]","w");
}
 

Jereck

Α & Ω
Staff
Il faut passer par une variable séparée :

Code:
#include<stdio.h>
#include<stdlib.h>
 
int main(void)
{
	[color=red]char filename;[/color]
	[color=deepskyblue]char[[/color]***[color=deepskyblue]] path;[/color]
	printf("Donnez le nom du fichier\n");
	scanf("%s",&filename);
	[color=deepskyblue]sprintf (path, "/home/mes_progs/essais_examen/%s", filename);[/color]
	FILE *pfile = NULL;
	fopen=fopen([color=deepskyblue]path[/color] ,"w");
}
'tention que su tu déclare filename comme ça (simple caractère), tu vas avoir un buffer overflow lors de ton scanf.

pour la longueur de "path", il faut voir ce que l'OS et/ou le système de fichier autorise comme profondeur maximale.
 

bOweL

Intestin
rien à voir avec la question mais c'est pas plutot


pfile=fopen(path,"w");


? si je me trompe on peut m'expliquer? ^^
 

cyse

Elite
bOweL a dit:
rien à voir avec la question mais c'est pas plutot


pfile=fopen(path,"w");


? si je me trompe on peut m'expliquer? ^^
nan c'est bien ça ;) faute de frappe surement
 

Jereck

Α & Ω
Staff
bOweL a dit:
rien à voir avec la question mais c'est pas plutot

pfile=fopen(path,"w");

? si je me trompe on peut m'expliquer? ^^
en effet


tout comme le "FILE *pfile = NULL;" ne peut pas se placer là en C, car toutes les variables doivent être déclarées avant le code à proprement parler
 
G

Gecko64

ex membre
Oui voila c'est moi l'amis de Carambar.
En fait je cherche a faire une demande de nom de fichier a l'utilisateur ou se nom est gardé dans une variable.
Puis ensuite, que la fonction fopen utilise cette variable directement pour ouvrir le fichier.

Si possible avec un code simpliste pcq je debute en C et j'avoue avoir un peu de mal encore la :-(

J'avais trouve a l'époque quelque chose de simpliste comme tout mais plus moyen de remettre la main dessus...

En tout cas merci pour vos reponses mais comme je voyais chez jerek, je me demandais si il n'y avait pas moyen de faire plus simple que d'utiliser des sprinf etc...
Si possible pour faire simple, on va dire que le prog est execute dans le repertoire ou se trouvent les fichiers ;) et on oublie le path :)

Merci d'avance :)
Gecko64
 

Jereck

Α & Ω
Staff
Si le prog tourne dans le même dossier que les fichiers, alors, utilise des chemins relatifs.

Et donc, oublie complètement le chemin d'accès, ça devient : pfile = fopen(filename,"w");

tout simplement
 
G

Gecko64

ex membre
Ha ok un grand merci Jereck :)
Je vais tester ca ;)

Thx!!!
 
G

Gecko64

ex membre
Je viens de tester et apparamment, j'ai un souci:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void)
{
char filename;
FILE *pfile = NULL;
printf("Tapez le nom du fichier à ecrire\n");
scanf("%s",&filename);
pfile = fopen(filename,"w");
if (pfile == NULL)
{
printf("Ouverture du fichier echouée\n");
exit(0);
}
else
{
printf("Ouverture de fichier réussie\n");
}
fclose(pfile);
}

et il me sort a la compilation:

gecko64@geckonline:~/mes_progs$ gcc -o essai10 essai10.c
essai10.c: Dans la fonction « main »:
essai10.c:10: attention : passage de l'argument n°1 de « fopen » transforme un entier en pointeur sans transtypage

Je me demande si fopen aime bien recevoir des données de type string avec mon %s ?
Je vais verifier ca de mon cote et je tien toujours au jus ici ;)
5min apres: Hmm nan j'ai teste et toujours avec le meme souci... :-?

Je ne sais pas si c'est l'heure mais j'ai un peu de mal... :-(
 

neku

Codeur roumain
Voici la méthode que j'utiliserais pour connaître le chemin d'accès de mon executable et y concaténer un sous-répertoire ou un fichier voir les deux ;)

Code:
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>

int _tmain(int argc, _TCHAR* argv[])
{
	char* Directory;
	FILE* Fichier = NULL;
	Directory = new char[512];

	//On récupere le chemin d'acces à notre programme
	GetModuleFileName(0,Directory,511);

	//On supprime le nom de fichier
	//0x5C = "\"
	for (int Index = strlen(Directory); Index >= 0; Index--)
		if (Directory[Index] == 0x5C) { Directory[Index + 1] = '\0'; break; }

	//Maintenant tu peux y mettre à la suite n'importe quel sous répertoire à partir du repertoire de l'executable ou de la DLL
	//Le but de cette méthode est que le code peut être injecté et ne prendra donc pas pas le chemin d'acces
	//De l'executable injecté.

	//Concaténation avec strncat()
	strncat(Directory,"\\MonDossier\\MonFichier.txt",511);

	//On affiche notre chemin d'acces
	printf("%s\n",Directory);

	//On ouvre le fichier
	Fichier = fopen(Directory,"w+");

	//On vérifie l'état
	if (Fichier != NULL) {
		printf("%s\n","Fichier ouvert avec succès");
		//Le traitement du fichier ici !
	}
	else {
		printf("%s\n","Erreur lors de l'ouvertur du fichier :/");
	};

	//On ferme le fichier
	fclose(Fichier);

	system("pause");
	
	delete Directory;

	return 0;
}
Code:
	using namespace std;

	char* File;
	FILE* Fichier = NULL;
	File = new char[512];

	//Donnons le fichier que l'on désire ;)
	cin >> File;
	//scanf("%s",File);

	//Affichons notre nom de fichier désiré :D
	cout << "Notre fichier : " << File << "\n";
        //printf("%s%s\n","Notre fichier :",File);

	Fichier = fopen(File,"a+");

	if (Fichier != NULL) {
		cout << "Fichier ouvert !\n";
		//printf("%s\n","Fichier ouvert !";
	}
	else {
		cout << "Une erreur est survenue lors de l'ouverture du ficher !\n";
		//printf("%s\n","Une erreur est survenue lors de l'ouverture du ficher !";
	}
	
	fclose(Fichier);

	delete File;
 

Jereck

Α & Ω
Staff
neku >
C'est du C++ ton code, de plus, si le fichier a ouvrir est dans le même dossier que l'application, il n'y a pas besoin de donner le chemin d'accès complet au fichier, un chemin relatif suffit amplement.

Gecko64 >
Comme je l'ai dit, ta déclaration de "filename" est erronée : "char filename;" réserve un emplacement mémoire de UN caractère, lors de ton scanf, tu va avoir un écrasement mémoire qu'il faut à tout prix éviter.

Tu dois décider quel sera la longueur maximale du nom du fichier à ouvrir, par exemple, 255 caractères.
Code:
[color=royalblue]#include [/color]<stdio.h>
[color=royalblue]#include[/color] <stdlib.h>
[color=royalblue]#include[/color] <string.h>
 
[color=royalblue]int[/color] main(void)
{
	[color=royalblue]char[/color][256] filename;
	[color=lime]// 256 = 255 + 1 car il faut terminer la chaine par '\0'[/color]
	FILE *pfile = NULL;
 
	printf("Tapez le nom du fichier à ecrire\n");
	scanf("%s",filename);
	[color=lime]// Pas de '&' car dans un tableau, le nom du tableau est un pointeur vers le 1er élément[/color]
 
	pfile = fopen(filename,"w");
	[color=lime]// De même, ici, "filename" devient le pointeur vers la chaine avec l'adresse du fichier, ce qui est l'argument attendu par fopen[/color]
 
	if (pfile == NULL)
	{
		printf("Ouverture du fichier echouée\n");
		exit(0);
	}
	else
	{
		printf("Ouverture de fichier réussie\n");
	}
 
	fclose(pfile);
	[color=royalblue]return[/color] EXIT_SUCCESS;
	[color=lime]// Tu as déclaré ton main comme renvoyant un entier, il faut en renvoyer un.[/color]
[color=lime]	// Les constantes EXIT_SUCCESS et EXIT_FAILURE sont définies dans stdlib.h. Tu aurais pu remplacer ton [i]exit(0);[/i] par [i]return EXIT_FAILURE;[/i]
[/color]}
 
G

Gecko64

ex membre
Ha ben je viens de regarder ton code Jereck et la j'ai tout saisi du premier coup.
Faut dire aussi que hier ha non ce matin pardon, je n'etais plus trop au top de la forme ^^

Pour les caracteres, je ne sais pas pq mais hier j'etais persuadé qu'on mettait des string dans des char ^^ mais bon, ca va etre effectivement un petit peu etroit...

Juste a la ligne 7 de ton code, ca n'est pas char filename[256] pour declarer un tableau de 256 caracteres?

En tout cas un grand merci pour le code car c'est une question que je me posais depuis un petit temps mais ici avec l'exemple, ca a fait comme qui dirait un declic :p

Une derniere question me reste avec les fonctions fgetc et fputc.
Bon elle sont censées placer un caractère ds un fichier ou en lire un a la fois mais le truc que je ne pige pas, pq on lui passe un int alors que ca devrait etre plustot un char? o_O
On le stock sous son code ascii? (sorte de casting? ou je suis a cote de la plaque...)
J'ai regardé sur le net apres ca mais je dois avouer que je n'ai pas saisi a 100% la chose.
Peut etre un trou ds les bases du C que j'aurais...
Je ne sais pas si tu sais m'expliquer ca avec un exemple de caractere récupéré via un scanf puis passé à la fonction fputc par exemple et inversement?
En general je pige mieux la logique avec des exemples :)

Merci :)
Gecko64
 
1er
OP
Carambar

Carambar

Elite
Gecko64 a dit:
Juste a la ligne 7 de ton code, ca n'est pas char filename[256] pour declarer un tableau de 256 caracteres?
Les informaticiens comptent à partir de zéro ;) .
 

Jereck

Α & Ω
Staff
Gecko64 a dit:
Juste a la ligne 7 de ton code, ca n'est pas char filename[256] pour declarer un tableau de 256 caracteres?
Si, c'est bien possible
Carambar > il parlait de mettre la taille après le nom du tableau et non pas après le type ;)
De plus, le comptage à partir de 0 influe sur les index, pas sur le nombre total d'éléments.


Une derniere question me reste avec les fonctions fgetc et fputc.
Bon elle sont censées placer un caractère ds un fichier ou en lire un a la fois mais le truc que je ne pige pas, pq on lui passe un int alors que ca devrait etre plustot un char? o_O
En gros, c'est parce que si la lecture échoue, fgetc renvoie "-1" ce qui ne saurait se faire en char.

"Si la lecture se fait sans erreur et sans rencontre de la fin de fichier, fgetc rend le caractère lu. Si il y a erreur d'entrée-sortie, ou rencontre de fin de fichier, fgetc rend la valeur EOF. Pour cette raison, le type de la valeur rendue est int et non pas char."

http://www.linux-kheops.com/doc/ansi-c/node71.htm
 
G

Gecko64

ex membre
Rien à voir Carambar, c'est que chez moi si je met la taille du tableau avant le nom du tableau, ca merdouille quelque peu ;)

Pour le reste, je sais qu'on compte a partir du zero ^^ ;)
 
G

Gecko64

ex membre
heuu ok mais la valeur retournée ne se plasse pas devant la fonction?
Genre si la valeur etait un int:

int nom_de_la_fonction( etc...)

Pcq ici dans les parametres, je vois que l'on passe un caractere sous la forme int:
fputc (carac , flot-de-données) /*Je parle de carac*/

et on dit ceci plus bas:

carac est de type int, c'est le caractère à écrire.

Un caractere en integer :-(
Si je ne me trompe, les integers c'est que pour les nombres? non?

Et devant fputc, pq on ne declare pas de type de retour?
Je dois dire que je ne suis pas la car ca ne colle pas avec les fonctions que j'ai deja pu faire auparavant :-(
 
G

Gecko64

ex membre
Hmm vais essayer un peu de mettre de l'ordre dans mes idées car la j'ai l'impression d'avoir un grosse touille dans tout ca :-(

Moi dans ma tete c'est comme ceci le fonctionnement d'une fonction:

type nom_fonction( int a,float b etc... )

type == Le code de retour ou valeur que peut retourner une fonction.
int a, float b == Ce qu'on passe comme valeur a la fonction pour elle effectuer son traitement.

Et ici avec la fonction fputc j'ai l'impression que dans ce cas ci:

fputc(c,fo) /* Comme decrit sur le tuto que tu m'as file*/

la valeur de retour est faite via c o_O alors que ca me semble etre le caractere a ecrire qui doit etre mis la?
Bref ce qui me bloque, c'est que je vois c a un emplacement qui est destine a passer une valeur a la fonction et non a la renvoyer :-\
Et je ne comprend toujours pas pq cette valeur dans l'etat actuel des choses, comme je le vois dans ma tete actuellement, est un int :-(

Alors soit je suis con et je pige rien aux fonctions ou soit il me manque une brique pour la comprehension de celle-ci...


Moi si j'avais du faire fputc, je l'aurais faite de la sorte:

int fputc(char c,fo);

int == la valeur retournee si ca c'est bien passé ou non.
char c == Caractere a ecrire.
fo == pointeur de fichier.

Je ne sais pas si tu vois un peu mieux le "bug" que apparamment j'ai dans mon raisonnement? :-?

5min plus tard:
Ok j'ai vu jereck sur msn, j'ai pige :)
Thx!
 
1er
OP
Carambar

Carambar

Elite
Jereck a dit:
Carambar > il parlait de mettre la taille après le nom du tableau et non pas après le type ;)
De plus, le comptage à partir de 0 influe sur les index, pas sur le nombre total d'éléments.
Oui, apparemment j'étais à côté de la plaque quand j'ai répondu. Je ne sais pas pourquoi mais je pensais à un compteur. Sinon, pour la longeur de nom de fichier, c'est 255 ou 256 caractères quelque soit l'OS.
 

neku

Codeur roumain
Jereck a dit:
neku >
C'est du C++ ton code, de plus, si le fichier a ouvrir est dans le même dossier que l'application, il n'y a pas besoin de donner le chemin d'accès complet au fichier, un chemin relatif suffit amplement.
Jerek, je me demande si tu as fait l'éffort de lire le commentaire :/
j'ai bien parler de code injecté ...
à tu déjà injecté une dll dans un processus et essayé d'acceder à un fichier ce trouvant dans le répertoire de la dll alors qu'elle est dans un répertoire différent ?
 
Statut
N'est pas ouverte pour d'autres réponses.
Haut