J'ai un fichier texte bien formé contient deux champs: objet et
attribut.
tous les objets sont des entiers et tous les attributs sont de chaines
de caractères de même taille.
chaque ligne contient un objet et son attribut par exemple:
essai.txt:
1 11100
2 10101
3 01001
4 10001
Je voudrais supprimer les 0 de même position dans chaque chaine de
caractère.
Par exemple dans notre cas, nous allons supprimer les 0 dans la
position 4 de chaque chaine car dans cette position nous avons toutes
les chaines sont à 0.
le résultat est :
1 1110
2 1011
3 0101
4 1001
j'ai trouvé une difficulté de résoudre ce problème, de plus imaginez
si nous avons un fichier volumineux.
SVP, j'ai besoin de vos aides.
"contenant" ?
> tous les objets sont des entiers et tous les attributs sont de chaines
> de caract�res de m�me taille.
des "bitstrings" de m�me taille ?
(cha�ne ne contenant que des '0' et '1')
> chaque ligne contient un objet et son attribut par exemple:
>
> essai.txt:
> 1 11100
> 2 10101
> 3 01001
> 4 10001
>
> Je voudrais supprimer les 0 de m�me position dans chaque chaine de
> caract�re.
et quel est le probl�me ?
> j'ai trouv� une difficult� de r�soudre ce probl�me
laquelle ?
> de plus imaginez si nous avons un fichier volumineux.
"nous" ?! non, tu as (peut �tre) un fichier volumineux, moi je
n'aurais que des entiers (possiblement long) � traiter de mani�re
simple et rapide.
> SVP, j'ai besoin de vos aides.
pour faire quoi ?
Sylvain.
> Je voudrais supprimer les 0 de m�me position dans chaque chaine de
> caract�re.
> Par exemple dans notre cas, nous allons supprimer les 0 dans la
> position 4 de chaque chaine car dans cette position nous avons toutes
> les chaines sont � 0.
Par exemple =>
{
DWORD dwFileSize;
DWORD dwBytesRead, dwBytesWritten;;
char *lpBuffer = NULL;
BOOL bStatus = FALSE;
char *sToken;
char sSep[] = "\r\n";
char sBuffer[255];
HANDLE hFile = CreateFile ("test.txt", GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
HANDLE hFileOut = CreateFile("test2.txt", GENERIC_WRITE,
FILE_SHARE_READ, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE && hFileOut != INVALID_HANDLE_VALUE)
{
dwFileSize = GetFileSize(hFile, NULL);
lpBuffer = (PCHAR)LocalAlloc(LPTR, dwFileSize+1);
if (lpBuffer)
{
bStatus = ReadFile(hFile, lpBuffer, dwFileSize, &dwBytesRead, NULL);
if (bStatus)
{
lpBuffer[dwBytesRead] = 0;
sToken = strtok(lpBuffer, sSep);
while (sToken != NULL)
{
strcpy(sBuffer, sToken);
int nLength = strlen(sBuffer);
memmove(&sBuffer[4], &sBuffer[5], strlen(&sBuffer[5]) + 1);
memcpy (&sBuffer[strlen(sBuffer)], sSep, 2);
sBuffer[nLength + 1] = '\0';
bStatus = WriteFile(hFileOut, sBuffer, strlen(sBuffer),
&dwBytesWritten, 0);
if (!bStatus)
{
CloseHandle(hFile);
CloseHandle(hFileOut);
if (lpBuffer)
LocalFree(lpBuffer);
return 1;
}
sToken = strtok(NULL, sSep);
}
}
}
CloseHandle(hFile);
CloseHandle(hFileOut);
if (lpBuffer)
LocalFree(lpBuffer);
}
}
Pouvez-vous m'expliquer votre idée ?
Quel langage de programmation vous utilisez dans ce code ?
On 4 juil, 20:39, Christian ASTOR <casto...@club-internet.fr> wrote:
> programmation wrote:
> > Je voudrais supprimer les 0 de même position dans chaque chaine de
> > caractère.
> > Par exemple dans notre cas, nous allons supprimer les 0 dans la
> > position 4 de chaque chaine car dans cette position nous avons toutes
> > les chaines sont à 0.
Salut,
- SVP, pouvez-vous détailler votre idée ?
- Quel langage de programmation vous utilisez ?
> Pouvez-vous m'expliquer votre idée ?
> Quel langage de programmation vous utilisez dans ce code ?
C'est juste du C/Win32 de base..
On lit et charge le fichier dans un buffer puis on découpe les lignes
et on déplace dans chaque ligne de la position 5 à 4 pour supprimer
ton '0'
En C standard, remplace les CreateFile()-ReadFile()-CloseHandle() par
fopen()-fgets()-fclose() en lisant ligne à ligne (ça évite même de
découper par strtok()..)
Salut,
- Je n'arrive pas à adapter votre solution pour supprimer les
colonnes.
Pouvez-vous me fournir une version en C ?
- J'ai résolu la partie de suppression des lignes. Mais, elle me reste
la partie du suppression des colonnes.
donnée:
Chaque ligne du fichier texte contient deux champs: un objet présenté
par un entier et un attribut présenté par une chaine de caractère.
Le fichier est bien formé puisque il est rempli de manière suivante:
fprintf("%10d%s",objet,attribut);
- Pour la suppression des colonnes, j'ai trouvé une difficulté à
programmer mon idée suivante:
Je positionne sur le premier caractère de chaine de caractère
(deuxième champ) du première ligne du fichier. Je teste caractère par
caractère si égale à 0, par exemple si on trouve 0 à la position k du
la chaine du caractère alors je dois positionner sur la même position
k du la chaine du caractère de deuxième ligne alors je teste si ce
caractère égale à 0 alors je dois positionner sur la même position k
du la chaine du caractère de troisième ligne jusqu'à la fin du
fichier. Dans le cas que si n'est pas égale à 0 alors j'arrête ce
n'est pas la peine de continuer de voir les autres lignes restantes
mais je dois retourner seulement à la position k +1 du chaine du
première ligne pour tester si égale à 0 ou non . Si ce n'est pas égale
à 0 alors je teste de même manière les caractères restantes jusqu'à la
fin du ligne.
Autre optimisation, Si je ne trouve aucun 0 dans la chaine du
caractère du première ligne alors c'est inutile de voir les autres
lignes donc on s'arrête et on a aucun colonne à supprimer.
Cette idée permet de trouver les positions à supprimer. Mais, je ne
sais pas comment je vais les supprimer.
Avez-vous une idée ?
S'il vous plait, j'ai besoin de vos aides pour programmer cette idée
et pourquoi pas à améliorer.
Merci.
> - Je n'arrive pas � adapter votre solution pour supprimer les
> colonnes.
> Pouvez-vous me fournir une version en C ?
>
> - J'ai r�solu la partie de suppression des lignes. Mais, elle me reste
> la partie du suppression des colonnes.
Pour identifier les colonnes ne contenant que des "0", tu peux faire une
premi�re lecture du fichier pour mettre les valeurs (num + attribut)
dans un tableau de structures et utiliser un tableau d'entier pour
compter le nombre de '0' total par colonne : si c'est �gal au nombre de
lignes, c'est qu'il n'y a que des "0" dans la colonne donn�e.
Ensuite tu lis ton tableau de structures et tu supprimes les "0" pour
chaque position de ton attribut correspondant au compteur pr�c�dent
lorsque le compteur est �gal au nombre de lignes ("if (nColumn[i] ==
nCpt)" ci-dessous)
Par exemple =>
#include <tchar.h>
#include <iostream>
#define MAXLINE 1024
#define STEP 10
typedef struct dataStruct
{
char sNum[6];
char sAttrib[32];
} dataStruct;
int _tmain(int argc, _TCHAR* argv[])
{
char sLine[MAXLINE];
int nColumn[32] = {0}, nCpt = 0, nAttribLength= 0, nMaxAttribLength = 0;
FILE *pFile, *pFileOut;
pFile = fopen("test.txt","r");
pFileOut = fopen("test2.txt","w");
int dataTabStringMax = STEP;
dataStruct *dataTabString;
if (pFile && pFileOut)
{
dataTabString = (dataStruct *) malloc(dataTabStringMax *
sizeof(dataStruct));
while (fgets(sLine, MAXLINE, pFile))
{
strncpy(dataTabString[nCpt].sNum, sLine, 5);
dataTabString[nCpt].sNum[5] = '\0';
nAttribLength = strlen(sLine)-6;
if (nAttribLength>0)
{
strncpy(dataTabString[nCpt].sAttrib, &sLine[5], nAttribLength);
dataTabString[nCpt].sAttrib[nAttribLength] = '\0';
for (int i = 0; i<nAttribLength; i++)
{
if (dataTabString->sAttrib[i] == '0')
nColumn[i]+=1;
}
nCpt+=1;
if (nAttribLength > nMaxAttribLength)
nMaxAttribLength = nAttribLength;
}
if (nCpt == dataTabStringMax)
{
dataTabStringMax += STEP;
dataTabString = (dataStruct *) realloc(dataTabString,
dataTabStringMax * sizeof(dataStruct));
if (dataTabString == NULL)
exit(1);
}
}
// Lecture tableau de structures pour supprimer les "0"
for (int j = 0; j<nCpt; j++)
{
int nShift = 0;
for (int i = 0; i<nMaxAttribLength; i++)
{
if (nColumn[i] == nCpt)
{
memmove(&dataTabString[j].sAttrib[i-nShift],
&dataTabString[j].sAttrib[i-nShift+1],
strlen(&dataTabString[j].sAttrib[i-nShift+1]) + 1);
nShift+=1;
}
}
if (strcspn (dataTabString[j].sAttrib, "1") <
strlen(dataTabString[j].sAttrib))
fprintf(pFileOut, "%s%s\n", dataTabString[j].sNum,
dataTabString[j].sAttrib);
}
free(dataTabString);
fclose(pFile);
fclose(pFileOut);
}
return 0;
}
Salut,
- Il manque un accolade fermant qui correspondant à l'accolade ouvert
de if (pFile && pFileOut)
j'ai ajouté cet accolade avant de faire free(dataTabString);
C'est çà ?
- Comme indication, le fichier d'entrée test.txt est construit selon
le format suivant:
fprintf("%10d%s\n", sNum,sAttrib);
Donc, je ne sais pas pourquoi vous mettez sNum comme chaine de
caractère et de taille 6 et sAttrib de taille 32
char sNum[6]; et char sAttrib[32]; ?
- Après la compilation et l'exécution de votre code sur le fichier
d'entrée suivant :
test.txt
1 110101
2 100101
3 110101
4 000101
5 000000
6 110101
7 110101
8 000000
9 010101
10 100101
J'obtiens le fichier de sortie test2.txt suivant:
1 1111
2 1011
3 1111
4 0011
6 1111
7 1111
9 0111
10 101
Je ne sais pas pourquoi l'objet 10 lui manque un caractère 1 pour son
attribut.
c-à-d pour l'objet 10 on doit obtenir "1011"
Le résultat attendu est :
test2.txt:
1 1111
2 1011
3 1111
4 0011
6 1111
7 1111
9 0111
10 1011
Donc comment vous obtenez pour 10 l'attribut "1011" ?
- J'ai remarqué que votre dernier programme permet de supprimer des
colonnes mais aussi des lignes vides.
Comment vous avez supprimé des lignes vides par ce dernier programme ?
Merci.
Non, tu as d� mal copier-coller : je viens de re-tester, il ne manque
pas d'accolade. Mais si tu as corrig� et que �a compile, �a va..
> - Comme indication, le fichier d'entr�e test.txt est construit selon
> le format suivant:
> fprintf("%10d%s\n", sNum,sAttrib);
>
> Donc, je ne sais pas pourquoi vous mettez sNum comme chaine de
> caract�re et de taille 6 et sAttrib de taille 32
> char sNum[6]; et char sAttrib[32]; ?
C'est par rapport � ton fichier d'exemple que j'ai copi�-coll�:
1 110101
...
=> il y a 6 caract�res pour ton Num
Mais c'est � toi de d�cider du format et donc de changer ce que tu veux.
> Je ne sais pas pourquoi l'objet 10 lui manque un caract�re 1 pour son
> attribut.
> c-�-d pour l'objet 10 on doit obtenir "1011"
Parce que tu n'as pas mis de retour chariot apr�s la derni�re ligne.
> - J'ai remarqu� que votre dernier programme permet de supprimer des
> colonnes mais aussi des lignes vides.
> Comment vous avez supprim� des lignes vides par ce dernier programme ?
Tu le vois en lisant le code lors de la cr�ation du 2nd fichier, par la
ligne de test:
if (strcspn (dataTabString[j].sAttrib, "1") <
strlen(dataTabString[j].sAttrib))
Je teste juste s'il y a au moins un "1" dans l'attribut. Si c'est le
cas, on �crit la ligne
Salut,
Oui. Il ne manque pas d'accolade.
Oui. Le problème est résolu si on ajoute un retour chariot après la
dernière ligne.
Le fichier test.txt n'est pas saisi à la main. Mais, il est généré
automatiquement. Il est bien formé et comme vous savez la dernière
ligne ne contient pas de retour chariot. Mais, elle contient la marque
de fin du fichier.
Comment on peut résoudre ce problème sans l'ajout du retour chariot
après la dernière ligne ?
S'il vous plaît, il ne manque ce truc. Je n'oublie pas votre aide.
Merci.
> Oui. Le probl�me est r�solu si on ajoute un retour chariot apr�s la
> derni�re ligne.
>
> Le fichier test.txt n'est pas saisi � la main. Mais, il est g�n�r�
> automatiquement. Il est bien form� et comme vous savez la derni�re
> ligne ne contient pas de retour chariot. Mais, elle contient la marque
> de fin du fichier.
> Comment on peut r�soudre ce probl�me sans l'ajout du retour chariot
> apr�s la derni�re ligne ?
Tu peux modifier :
nAttribLength = strlen(sLine)-6;
par
nAttribLength = strlen(sLine)-6 + 1;
et
fprintf(pFileOut, "%s%s\n", dataTabString[j].sNum,
dataTabString[j].sAttrib);
par
fprintf(pFileOut, "%s%s", dataTabString[j].sNum, dataTabString[j].sAttrib);
Ca permet de garder le retour chariot dans chaque variable
dataTabString[j].sAttrib
et de le recopier tel quel lors de l'�criture dans le 2�me fichier.
Salut,
Oui. Votre programme çà marche bien. Il permet de supprimer des lignes
vides et des colonnes vides de deuxième champ du fichier.
Comme j'ai dit le fichier d'entrée test.txt est généré
automatiquement. Il est bien formé.
Comme j'ai dit on ne sait pas en avance le nombre des lignes et la
taille de la chaine indication mais cette taille est unique dans tout
le fichier.
je peux savoir le nombre de lignes du fichier et la taille de deuxième
champ.
pour savoir la taille de deuxième champ puis le nombre des lignes des
fichiers j'ai fait successivement :
int main()
{
FILE *pFile, *pFileOut;
char sLine[MAXLINE];
int i,j,k=0,nColumn[32] = {0}, nCpt = 0, nAttribLength= 0,
nMaxAttribLength = 0;
int dataTabStringMax = STEP;
dataStruct *dataTabString;
pFile = fopen("test.txt","r");
pFileOut = fopen("test2.txt","w");
if (pFile && pFileOut)
{
dataTabString = (dataStruct *) malloc(dataTabStringMax
* sizeof(dataStruct));
fgets(sLine, MAXLINE, pFile); //lecture seulement du
première ligne du fichier
sscanf(sLine,"%s%s",dataTabString
[nCpt].sNum,dataTabString[nCpt].sAttrib);
nAttribLength = strlen(dataTabString[nCpt].sAttrib);
printf("%s %s :%d\n",dataTabString
[nCpt].sNum,dataTabString[nCpt].sAttrib,nAttribLength);
rewind(pFile); //retourner au début du fichier
while (fgets(sLine, MAXLINE, pFile)) // parcoure tout le
fichier
k++;
printf("%d\n",k); // afficher le nombre des lignes du
fichier
rewind(pFile); //retourner au début du fichier
while (fgets(sLine, MAXLINE, pFile))
{
.....
....
}
.....
}
- Quelle est modification à faire dans votre programme pour qu'il
tourne dans tous les cas quelque soit le nombre des lignes du fichier
et la taille de deuxième champ du fichier ?
- Vous mettez #define STEP 10;
10 présente quoi ?
- Vous mettez char sAttrib[32]; et nColumn[32] = {0};
pourquoi vous fixez la taille à 32 ? car on peut avoir la taille de
chaine en général supérieure à 32 ou inférieur à 32 .
- Vous avez alloué et réalloué un tableau
Pouvez m'expliquer le principe d'utilisation d'un tableau avec
réserve et rallouable et car j'ai découvert cette structure avec
vous ? Dans quels cas à utiliser ? les avantages et les limites de
cette structure ?
Merci.
> - Quelle est modification � faire dans votre programme pour qu'il
> tourne dans tous les cas quelque soit le nombre des lignes du fichier
> et la taille de deuxi�me champ du fichier ?
Aucune normalement (tes histoires de rewind, c'est � �viter : il ne faut
pas lire n fois un m�me fichier, surtout s'il fait des millions de lignes..)
La taille du 2�me champ d�pend ici de la longueur de la ligne moins la
taille fixe du premier champ
Le nombre de lignes n'a pas d'importance.
> - Vous mettez #define STEP 10;
> 10 pr�sente quoi ?
Tu le vois bien dans le code : c'est le nombre d'�l�ments qu'on r�alloue
� chaque fois qu'on a atteint le nombre d'�l�ments max d�j� allou�s.
> - Vous mettez char sAttrib[32]; et nColumn[32] = {0};
> pourquoi vous fixez la taille � 32 ? car on peut avoir la taille de
> chaine en g�n�ral sup�rieure � 32 ou inf�rieur � 32 .
C'est juste pour l'exemple.
C'est pour d�finir une taille max pour le 2�me champ.
Tu peux mettre 1000 si tu veux avoir de la marge...
> - Vous avez allou� et r�allou� un tableau
> Pouvez m'expliquer le principe d'utilisation d'un tableau avec
> r�serve et rallouable et car j'ai d�couvert cette structure avec
> vous ? Dans quels cas � utiliser ? les avantages et les limites de
> cette structure ?
Il y a divers sites o� c'est mieux expliqu� que je ne le ferais
("Dynamic Arrays" dans Google)
Par ex, http://www.utdallas.edu/~rxc064000/dynamicArrays.html
Salut,
- Quelle est la différence et l'effet de prendre STEP petit ou
grand ? Est ce que je peux prendre STEP comme la taille maximale de
fichier ?
- Est ce que il y a une fonction définie qui nous donne la taille de
fichier sans le parcourir ?
- C'est possible dans votre programme de sauvegarder les positions
des colonnes supprimées ( c'est à dire les positions dans la chaîne de
caractère de deuxième champ) car j'ai besoin de ces positions ?
C'est oui. Comment je fasse ? Est ce que je dois utiliser autre
structure ou bien il aura une modification à faire?
- Maintenant, Je voudrais compléter votre programme pour trier ce
fichier résultat obtenu selon le deuxième champ attribut de sorte que
l'objet qui contient de plus de 1 (la carctère 1) dans son attribut
alors il sera placé en premier lieu.
c'est à dire l'attribut qui contient plus de 1 au niveau nombre de
caractère 1.
par exemple:
test.txt:
1 1111
2 1011
3 1111
4 0011
6 1111
7 1111
9 0111
10 1011
il devient après le tri:
1 1111
3 1111
6 1111
7 1111
2 1011
9 0111
10 1011
4 0011
J'ai commencer à faire le programme. Mais, il me manque la partie de
tri.
Voici le programme:
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#define MAXLINE 1024
typedef struct dataStruct
{
int cin;
char indication[32];
} dataStruct;
void main()
{
dataStruct *dataTabString;
FILE *pFile, *pFileOut;
char sLine[MAXLINE];
int nCpt = 0, nAttribLength= 0, nMaxAttribLength = 0,j;
int dataTabStringMax = STEP;
pFile = fopen("essai.txt","r");
pFileOut = fopen("essai2.txt","w");
if (pFile && pFileOut)
{
dataTabString = (dataStruct *) malloc(dataTabStringMax
*sizeof(dataStruct));
while (fgets(sLine, MAXLINE, pFile))
{
sscanf(sLine,"%d%s",&dataTabString
[nCpt].cin,dataTabString[nCpt].indication);
nCpt+=1;
if (nCpt == dataTabStringMax)
{
dataTabStringMax += STEP;
dataTabString = (dataStruct *) realloc
(dataTabString,
dataTabStringMax * sizeof
(dataStruct));
if (dataTabString == NULL)
exit(1);
}
}
// il me manque ici la partie de trier le tableau dataTabString selon
le deuxième champ indication.
// le critère est que l'indication qui possède plus de 1 donc elle
sera en premier ordre et etc.
// remplir le fichier de sortie
for (j = 0; j<nCpt; j++)
{
fprintf(pFileOut, "%-10d%s\n",
dataTabString[j].cin,
dataTabString[j].indication);
}
free(dataTabString);
fclose(pFile);
fclose(pFileOut);
}
// return 0;
}
Je vous remercie pour votre aide.
> - Quelle est la diff�rence et l'effet de prendre STEP petit ou
> grand ? Est ce que je peux prendre STEP comme la taille maximale de
> fichier ?
Ca n'a pas de sens, puisque �a revient � un tableau statique.
(si le fichier fait 1 million de lignes, on ne va pas allouer 1 million
d'�l�ments !)
> - Est ce que il y a une fonction d�finie qui nous donne la taille de
> fichier sans le parcourir ?
Pas en nombre de lignes. Et on n'en a pas besoin.
> - C'est possible dans votre programme de sauvegarder les positions
> des colonnes supprim�es ( c'est � dire les positions dans la cha�ne de
> caract�re de deuxi�me champ) car j'ai besoin de ces positions ?
C'est d�j� sauvegard� dans le tableau de compteurs comme d�j� expliqu� !
Salut,
Je vous remercie pour vos réponses.
- Maintenant, Je voudrais compléter votre programme pour trier ce
fichier résultat obtenu selon le deuxième champ attribut de sorte que
l'objet qui contient de plus de 1 (la carctère 1) dans son attribut
alors il sera placé en premier lieu.
c'est à dire l'attribut qui contient plus de 1 au niveau nombre de
caractère 1.
par exemple, test.txt
1 1111
2 1011
3 1111
4 0011
6 1111
7 1111
9 0111
10 1011
il devient après le tri:
1 1111
3 1111
6 1111
7 1111
2 1011
9 0111
10 1011
4 0011
J'ai fait une fonction de tri rapide d'un tableau en général. Voici
le code:
void échangerÉléments(int t[], int m, int n)
{
int temp = t[m];
t[m] = t[n];
t[n] = temp;
}
int partition(int t[], int m, int n)
{
int v = t[m]; // valeur pivot
int i = m-1;
int j = n+1; // indice final du pivot
while (true) {
do {
j--;
} while (t[j] > v);
do {
i++;
} while (t[i] < v);
if (i<j) {
échangerÉléments(t, i, j);
} else {
return j;
}
}
}
void triRapide(int t[], int m, int n)
{
if (m<n) {
int p = partition(t, m, n);
triRapide(t, m, p);
triRapide(t, p+1, n);
}
}
C'est bon ce tri rapide ? Je vais appeler cette fonction dans le
main.
Mais, il me manque la partie concernant le calcul de nombre de
caractère 1 dans le deuxième champ.
- Est ce que j'ajoute un autre champ dans votre structure qui
présente le nombre de caractère 1 dans le deuxième champ (sAttrib)
pour chaque ligne ?
Voici votre structure:
typedef struct dataStruct
{
char sNum[6];
char sAttrib[32];
} dataStruct;
- Est ce que j'ajoute une fonction qui permet de calculer le nombre de
caractère 1 dans le deuxième champ ou bien on peut avoir ce nombre
directement à partir de votre programme ?
Merci.
> On 21 juil, 09:06, Christian ASTOR <casto...@club-internet.fr> wrote:
> 2 1011
> 9 0111
> 10 1011
> 4 0011
Comme signal� dans un autre thread, ici avec 1011, 0111, 1011, �a ne
colle pas.
> J'ai fait une fonction de tri rapide
Pour les tris, qsort() existe d�j�...
Salut,
Ce n'est pas une comparaison binaire. Mais, c'est une comparaison au
niveau le nombre de 1 (le caractère 1).
Si il y a en 4 dans les deux alors on garde le même ordre pour les
deux comme existent dans le fichier.
Par exemple:
2 1011 ici on a trois 1
9 0111 ici on a trois 1
10 1011 ici on a trois 1
Donc dans ce cas on laisse le même ordre. c'est à dire:
2 1011
9 0111
10 1011
Je voudrais faire un tri décroissant qui possède plus de caractere 1
il sera en premier ordre etc .. pour obtenir le résultat suivant:
1 1111
3 1111
6 1111
7 1111
> Ce n'est pas une comparaison binaire. Mais, c'est une comparaison au
> niveau le nombre de 1 (le caract�re 1).
Oui, c'est que j'ai dit : qsort() , avec la fonction de comparaison en
dernier param�tre o� l'on fait ce que l'on veut (compter les "1" ou
n'importe quoi d'autre)
Salut,
- Où est la fonction qsort() ?
- Quelle est la fonction de comparaison ?
> - O� est la fonction qsort() ?
> - Quelle est la fonction de comparaison ?
Ta fonction pour compter les "1" pour trier !
Salut,
Je trouve la fonction prédefinie qsort() dans le lien suivant:
http://www.cplusplus.com/reference/clibrary/cstdlib/qsort/
- C'est cette fonction que vous me parlez ?
- Est ce que cette fonction est implémenté par un tri rapide ou
autre ?
- Cette fonction fait un tri croissant alors comment je vais la
changer pour quelle puisse faire un tri décroissant ?
> Je trouve la fonction pr�definie qsort() dans le lien suivant:
> http://www.cplusplus.com/reference/clibrary/cstdlib/qsort/
> - C'est cette fonction que vous me parlez ?
Bein s�r, qsort() est une fonction standard.
> - Est ce que cette fonction est impl�ment� par un tri rapide ou
> autre ?
> - Cette fonction fait un tri croissant alors comment je vais la
> changer pour quelle puisse faire un tri d�croissant ?
Un tri croissant ?!
Elle fait un quick sort comme son nom l'indique, avec la fonction de
comparaison en 4�me param�tre o� tu mets ton test sur le nombre de "1"
Ici dans l'exemple, en premier param�tre, c'est donc dataTabString..
Salut,
Voici un exemple de l'utilisation de la fonction qsort() :
/* qsort example */
#include <stdio.h>
#include <stdlib.h>
int values[] = { 40, 10, 100, 90, 20, 25 };
int compare (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
int main ()
{
int n;
qsort (values, 6, sizeof(int), compare);
for (n=0; n<6; n++)
printf ("%d ",values[n]);
return 0;
}
Voici la fonction qui compte le nombre de 1 dans le deuxième champ:
int compte( ch)
char ch[32]
{
int i,k=0;
for(i=0; i < strlen (ch) ; i++)
{
if (ch[i] = '1');
k++;
}
return (k);
}
je vais appeler cette fonction pour chaque ligne de fichier lors de
chargement de fichier dans le tableau dataTabString.
Donc on a besoin de troisième élément par exemple nombre dans la
structure dataStruct:
typedef struct dataStruct
{
char sNum[6];
char sAttrib[32];
int nombre
} dataStruct;
dataStruct *dataTabString;
nombre = compte (dataTabString.sAttrib) ;
- Donc, avec quels paramètre je vais appeler la fonction qsort() ?
- Quel est le contenu et le code de quatrième paramètre du fonction
qsort() ?
- c'est possible d'adapter le qsort() pour faire un tri décroissant
sur le tableau et au niveau de deuxième champ sAttrib ?
Merci.
> Voici un exemple de l'utilisation de la fonction qsort() :
Pourquoi mets-tu l'exemple de la doc ?
> Donc on a besoin de troisi�me �l�ment par exemple nombre dans la
> structure dataStruct:
Non, pas utile.
> - Quel est le contenu et le code de quatri�me param�tre du fonction
> qsort() ?
Comme le code de la doc (compare()).
Avec � l'int�rieur ton calcul de "1" pour d�terminer le tri, sur le
membre sAttrib de la structure.
Salut,
Voici une partie de programme :
typedef struct dataStruct
{
int cin;
char indication[32];
int nombre; //contient le nombre de 1 dans le deuxème champ
indication donc je vais faireun tri décroissant sur ce nombre
} dataStruct;
int callbackfunc(const void* va,const void* vb)
{
dataStruct* a,b;
a = (dataStruct*)va;
b = (dataStruct*)vb;
return (b.nombre - a.nombre);
// ici, tu as 2 elements a et b, a toi de coder la comparaison : si
a<b (selon ton critere) renvoie 1, sinon renvoie 0.
}
int main()
{
....
....
qsort(dataTabString,nCpt,sizeof(dataStruct),callbackfunc);
...
}
Après la compilation, j'ai le message d'erreur dans le fonction
callbackfunc :
Error: incompatible types assignment
Error: request for member 'nombre' in something not a structure or
union
Merci.
Salut,
Voici une partie de programme :
typedef struct dataStruct
{
int cin;
char indication[32];
int nombre; //contient le nombre des 1 dans le deuxème champ
indication donc je vais faireun tri décroissant sur ce nombre
} dataStruct;
int compare(const void* va,const void* vb)
{
dataStruct* a,b;
a = (dataStruct*)va;
b = (dataStruct*)vb;
return (b.nombre - a.nombre);
// ici, tu as 2 elements a et b, a toi de coder la comparaison : si
a<b (selon ton critere) renvoie 1, sinon renvoie 0.
}
int main()
{
....
....
qsort(dataTabString,nCpt,sizeof(dataStruct),compare);
...
}
Après la compilation, j'ai le message d'erreur dans le fonction
compare:
Error: incompatible types assignment
Error: request for member 'nombre' in something not a structure or
union
Avez-vous une idée ?
Salut,
Je vous remercie pour votre aide.
Après le tri de fichier. Il me manque une partie concernant
l'indexation du ce fichier. Je ne sais pas si s'appelle indexation ou
autre.
Soit essai.txt le fichier trié:
3 1111
6 1111
1 1111
10 1011
9 0111
2 1011
4 0011
Ce fichier contient deux champs: cin (un entier) et indication (une
chaine de caractère)
Je voudrais décomposer ce fichier en sous fichiers de manière que
chaque sous ficher contient le même nombre du caractère 1 dans son
deuxième champ appelé indication.
Puisque le fichier est trié dans le sens décroissant ceci nous aide
pour faire ceci.
Après la décomposition, Je vais exécuter le même traitement sur chaque
sous fichier obtenu.
Je dois obtenir le résultat suivant:
essai1.txt :
3 1111
6 1111
1 1111
essai2.txt :
10 1011
9 0111
2 1011
essai3.txt :
4 0011
Comme vous voyez le fichier essai1.txt contient les cin qui ont quatre
1 dans leurs indications,
le fichier essai2.txt contient les cin qui ont trois 1 dans leurs
indications,
le fichier essai3.txt contient les cin qui ont deux 1 dans leurs
indications.
S'il vous plaît, Avez-vous une idée comment je vais décomposer le
fichier trié de grande taille en sous fichiers de taille moins ?
et comment je vais accéder après à ces sous fichiers ?
Merci.
Salut Christian ASTOR ,
Je voudrais afficher les positions qui contiennent le caractère 0 dans
le deuxième champ attribut du fichier.
Je n'arrive pas comment je vais déterminer ces positions dans votre
programme suivant :
#include <tchar.h>
#include <iostream>
#define MAXLINE 1024
#define STEP 10
typedef struct dataStruct
{
char sNum[6];
char sAttrib[32];
} dataStruct;
int _tmain(int argc, _TCHAR* argv[])
{
char sLine[MAXLINE];
int nColumn[32] = {0}, nCpt = 0, nAttribLength= 0,
nMaxAttribLength = 0;
FILE *pFile, *pFileOut;
pFile = fopen("test.txt","r");
pFileOut = fopen("test2.txt","w");
int dataTabStringMax = STEP;
dataStruct *dataTabString;
if (pFile && pFileOut)
{
dataTabString = (dataStruct *) malloc(dataTabStringMax
*
sizeof(dataStruct));
while (fgets(sLine, MAXLINE, pFile))
{
strncpy(dataTabString[nCpt].sNum, sLine, 5);
dataTabString[nCpt].sNum[5] = '\0';
nAttribLength = strlen(sLine)-6;
if (nAttribLength>0)
{
strncpy(dataTabString[nCpt].sAttrib,
&sLine[5], nAttribLength);
dataTabString[nCpt].sAttrib
[nAttribLength] = '\0';
for (int i = 0; i<nAttribLength; i++)
{
if (dataTabString->sAttrib[i]
== '0')
nColumn[i]+=1;
}
nCpt+=1;
if (nAttribLength > nMaxAttribLength)
nMaxAttribLength =
nAttribLength;
}
if (nCpt == dataTabStringMax)
{
dataTabStringMax += STEP;
dataTabString = (dataStruct *) realloc
(dataTabString,
dataTabStringMax * sizeof
(dataStruct));
if (dataTabString == NULL)
exit(1);
}
}
// Lecture tableau de structures pour supprimer les
"0"
for (int j = 0; j<nCpt; j++)
{
int nShift = 0;
for (int i = 0; i<nMaxAttribLength; i++)
{
if (nColumn[i] == nCpt)
{
memmove(&dataTabString
[j].sAttrib[i-nShift],
&dataTabString[j].sAttrib[i-nShift+1],
strlen(&dataTabString[j].sAttrib[i-nShift+1]) + 1);
nShift+=1;
}
}
if (strcspn (dataTabString[j].sAttrib, "1") <
strlen(dataTabString[j].sAttrib))
fprintf(pFileOut, "%s%s\n",
dataTabString[j].sNum,
dataTabString[j].sAttrib);
}
free(dataTabString);
fclose(pFile);
fclose(pFileOut);
}
return 0;
}
S'il vous plaît, pouvez- vous m'aider ?
> Je voudrais afficher les positions qui contiennent le caract�re 0 dans
> le deuxi�me champ attribut du fichier.
Je ne comprends pas : tu les as les positions, par exemple quand tu fais
ta fonction pour compter les "1", tu scannes bien ta cha�ne et testes si
chaque caract�re (donc position dans la cha�ne) est == '1' ...
Salut,
- La fonction compte permet de compter les 1 pour chaque deuxième
champ dans le fichier après le tri.
Mais, moi je cherche les positions communes des colonnes que vous avez
supprimées.
Si je vais appliquer la fonction compte sur le fichier non trié
suivant:
1 110101
2 100101
3 110101
4 000101
5 000000
6 110101
7 110101
8 000000
9 010101
10 100101
Voici la fonction qui compte les "1" où j'ai ajouté un tableau
dynamique pour stoker les positions des colonnes supprimées:
int compte(ch)
char ch[32];
{
int *tabPos;
int i,p=0,k=0,m;
tabPos = (int *) malloc(tabPos * sizeof(int));
for(i=0; i < strlen(ch) ; i++)
{
if (ch[i] == '1')
k=k+1;
else
{
tabPos[p]=ch[i];
p++;
}
}
// afficher le contenu du tableau
for(m=0;m<p;m++)
printf("%c : ",tabPos[m]);
// libérer le tableau
free(tabPos);
return (k);
}
- Après la compilation, j'ai ce message d'erreur :
error : invalid operands to binary *
cet erreur porte sur l'instruction suivant : tabPos = (int *) malloc
(tabPos * sizeof(int));
comment je vais corriger cet erreur ?
- J'ai remarqué que on stocke à chaque fois les positions de caractère
"0" de deuxième champ (chaine caractère) du chaque ligne du fichier
dans un tableau dynamique.
à chaque deuxième champ de chaque ligne du fichier, on aura un tableau
des positions 0. Mais, ce tableau il sera effacer dans l'itération
suivant car on travaille sur le même tableau.
C'est juste ou non ?
par exemple, pour la première ligne :
1 110101 on aura un tableau qui contient les positions 2 et 4
2 100101 on aura un tableau qui contient les positions 1,2 et 4.
etc
- Mais le résultat souhaité est d'obtenir un tableau (ou fichier) qui
contient les positions 2 et 4 dans notre exemple.
je ne sais pas le mieux d'utiliser un tableau ou un fichier pour
stocker les positions 2 et 4 car je vais parcourir ce tableau ou ce
fichier pour utiliser après dans mon programme ?
- Vous avez supprimé des lignes vides et des colonnes vides dans votre
programme.
Pouvez - vous savoir et afficher les positions communes des "0" pour
chaque deuxième champ de chaque ligne du fichier ?
Où vous allez faire une modification dans votre programme pour faire
ceci ?
Merci.
> Mais, moi je cherche les positions communes des colonnes que vous avez
> supprim�es.
C'est donc dans le tableau nColumn[]
Salut,
Lorsque j'ajoute le code suivant à votre programme pour afficher le
contenu du tableau nColumn[]:
for (j = 0; j<nCpt; j++) // j : indice de tableau et nCpt la taille
de tableau nColumn[]:
printf("%d :%d\n",j,nColumn[j]); // nColumn[j] le
contenu de tableau nColumn[]: dans la position j
J'obtiens :
0 : 0
1 : 0
2 : 0
3 : 0
4 : 0
5 : 0
6 : 0
7 : 0
Voici le contenu du fichier "essai.txt" avant la suppression des
lignes vides et colonnes vides :
1 110101
2 100101
3 110101
4 000101
5 000000
6 110101
7 110101
8 000000
9 010101
10 100101
Après la suppression:
1 1111
2 1011
3 1111
4 0011
6 1111
7 1111
9 0111
10 1011
Mais, le résultat souhaité est d'obtenir un tableau dans la taille est
le nombre des caractères '0' communes qui ont été supprimés et don le
contenu est la position de caractèe '0' supprimé.
Si ceci ça passe bien alors j'obtiens le tableau suivant :
nColumn[0] = 2 et nColumn[1] = 4
Avec 2 et 4 sont les positions communes dont les chaines des
caractères de deuxième champ contient '0'.
S'il vous plaît, je serais très contente pour votre aide.
> Mais, le r�sultat souhait� est d'obtenir un tableau dans la taille est
> le nombre des caract�res '0' communes qui ont �t� supprim�s et don le
> contenu est la position de caract�e '0' supprim�.
>
> Si ceci �a passe bien alors j'obtiens le tableau suivant :
> nColumn[0] = 2 et nColumn[1] = 4
>
> Avec 2 et 4 sont les positions communes dont les chaines des
> caract�res de deuxi�me champ contient '0'.
Non, le tableau contient apr�s la lecture du fichier de nCpt lignes:
nColumn[2] = nCpt et nColumn[4] = nCpt
Ce qui signifie qu'il y a autant de "0" que de lignes (donc que des "0")
dans ces colonnes et c'est ce qui est test� dans la 2�me boucle � :
if (nColumn[i] == nCpt)
pour supprimer les colonnes n'ayant donc que des "0".
Salut,
Voici une partie de votre programme où j'ai ajouté deux instructions:
- printf ("pos = %d\n",i); // pour afficher la position de colonne
supprimé à chaque fois.
- printf ("shi = %d \n",nShift); // pour afficher le nombre de
colonnes supprimées.
le résultat d"affichage de ces deux instructions est :
pos = 2
pos = 4
pos = 2
pos = 4
pos = 2
pos = 4
pos = 2
pos = 4
pos = 2
pos = 4
pos = 2
pos = 4
pos = 2
pos = 4
pos = 2
pos = 4
pos = 2
pos = 4
pos = 2
pos = 4
shift = 2
- C'est vraie que l'indice i qui existe dans votre programme au
dessous et exactement dans l'instruction
if (nColumn[i] == nCpt) nous donne à chaque fois la position de
colonne supprimée.
puisque nous avons nCpt = 10 (nombre des lignes du fichier) alors nous
allons obtenir les mêmes positions des colonnes supprimées (la
position 2 et 4 dans notre cas) 10 fois.
1) Comment je vais modifier ce programme pour avoir une seule fois le
résultat ou leiu de 10 fois ?
c'est à dire:
pos = 2
pos = 4
2) Où je vais sauvegarder ce résultat ( les deux positions 2 et 4 )
dans un tableau ou dans un fichier car j'ai besoin de cette
information après ?
3) Dans ce programme, est ce que la variable nShift présente le nombre
des colonnes supprimées ?
Voici une partie du programme :
// Lecture tableau de structures pour supprimer les "0"
for (j = 0; j<nCpt; j++)
{
nShift = 0;
for (i = 0; i<nMaxAttribLength; i++)
{
if (nColumn[i] == nCpt)
{
memmove(&dataTabString
[j].sAttrib[i-nShift], &dataTabString[j].sAttrib[i-nShift+1], strlen
(&dataTabString[j].sAttrib[i-nShift+1]) + 1);
nShift+=1;
printf("pos = %d\n",i);
}
}
if (strcspn (dataTabString[j].sAttrib, "1") <
strlen(dataTabString[j].sAttrib))
fprintf(pFileOut, "%s %s\n",
dataTabString[j].sNum, dataTabString[j].sAttrib);
}
printf("shi = %d \n",nShift);
free(dataTabString);
fclose(pFile);
fclose(pFileOut);
Merci pour votre aide.
> 1) Comment je vais modifier ce programme pour avoir une seule fois le
> r�sultat ou leiu de 10 fois ?
> c'est � dire:
> pos = 2
> pos = 4
Forc�ment � la fin de la boucle sur le nombre de lignes
for (int j = 0; j<nCpt; j++) :
if (nColumn[j] == nCpt)
printf("Pos = %d\n", j);
Salut,
Merci.Oui. j'ai trouvé.
Maintenant, J'ai crée un programme C (application win32 console) avec
visual studio 2008 sous windows. Ce programme tourne bien. il me donne
des résultats sauvegardés dans des fichiers textes et des affichages
dans le console.
Je voudrais faire une interface graphique où il y a des contrôles (des
boutons, des zones textes, des listes...) pour visualiser mes
résultats obtenus par le programme C et aussi je voulais charger dans
des listes qui se trouvent dans l'interface graphique les fichiers
obtenus et pas mal des choses à faire.
Aussi pourquoi pas lancer à partir d'un bouton d'interface le
programme C qui j'ai fait etc...
Je voudrais faire une interface acceptable pour montrer mes résultats
obtenus.
- D'après vous comment je vais utiliser le même outil Visual Studio
2008 pour créer cette interface graphique car cet outil est très riche
puisque elle offre beaucoup des types d'application. J'ai découvert
jusqu'à maintenant les applications console car je suis débutante à
cet outil ?
- Quelle est la différence entre une application console win32 et une
application console CLR ?
- Est ce que je peux créer dans le même espace de travail où j'ai fait
mon programme C une interface graphique ou bien je dois créer dehors ?
- Avez vous autres solutions ?
S'il vous plaît, j'ai besoin de vos aides.
Merci.
Salut,
1) Dans mon travail, j'utilise des fichiers.
je crée un fichier "essai.txt" pour le remplir
fp = fopen("essai.txt","w");
// je fais des traitements
......fprintf(fp,"hhhhhhhhhhh");
//je ferme le fichier
fclose(fp);
//je veux lire ce fichier
rewind(fp);
fp = fopen("essai.txt","r");
//lire de ce fichier
while(fgets(s,100,fp));
...
fclose(fp);
Comme vous remarquez j'ouvre plusieurs fois le même fichier et je les
ferme plus que fois.
Comment je vais résoudre ce problème d'ouverture et fermeture plus que
fois ?
2) Je voudrais positionner sur la ligne numéro k au lieu de lire ligne
par ligne jusqu'à ligne numéro k.
Alors , comment je positionne directement sur le k ième ligne du
fichier ?
3) Est ce que on peut faire l'union, l'intersection et la différence
entre les lignes de deux fichiers ?
Merci.