Le langage SMS est exclu sur les forums ProgBoards, tout message ne respectant pas la charte sera déplacé, modifié, ou supprimé par nos modérateurs.

Forum Langages » C & Cie. » C : probleme de tableau dans une structure.

Amwus
ProgBoarder
RemonterCiter Linux Firefox 2 - Posté le 26/10/2007 à 21:45
Oki, ça va etre un peu long, mais voila le code :

fancontrol.h :

/*---------------------------------------------------------------------*
* fancontrol.h Osmalskyj Julien 2007-10-03
*
* Interface for fancontrol.c
*---------------------------------------------------------------------*/


#include <stddef.h>

#define SENSORS 17

typedef struct Thm_t Thermal;

/***********************************************************************
* int getThm(FILE* file_in) : get temperatures from the file pointed *
* by char* file_in. *
**********************************************************************/
int getThm(FILE* file_in, struct Thm_t* fandata);



fancontrol.c :

/*-------------------------------------------------------------------------*
* fancontrol.c Osmalskyj Julien 2007-10-26
*
* Implementations for functions and routines declared in file
* fancontrol.h
*-------------------------------------------------------------------------*/


#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include "fancontrol.h"

//Thermal sensors structure

struct Thm_t {
int temp_vect[SENSORS]; // temperatures vector
int cycle; // cycle for temperatures check
bool active; // modify fan or just monitor temperatures
int fan_off; // 0x2F
int fan_low_speed; // 0x02
int fan_medium_speed; // 0x04
int fan_max_speed; // 0x07
int fan_bios_control; // 0x80
};


//getThm function

int getThm(FILE* file_in, struct Thm_t* fandata) {
if (file_in == NULL) { // error opening file
fprintf(stderr, "error: unable to open thermals file.");
return 1;
}

char* getInput;
char getLine[100] = "";

getInput = fgets(getLine, 100, file_in);

if (getInput == NULL) {
return 1;
}

char* nptr = getLine;
char* endptr = nptr;
int sensorNB = 0; // sensor number

while (*endptr != '\0') {
while (*nptr == ' ') // skip white spaces
nptr++;

errno = 0;
int result = (int)strtod(nptr, &endptr);

if (result == 0) { // Skip if not conversible value
nptr++;
}
else {
fandata->temp_vect[sensorNB] = result; //SIGSEV HERE (exclamation)
sensorNB++;

if (errno == ERANGE)
printf("Warning: Overflow or underflow on next value\n");

if (nptr == endptr)
nptr++;
else if (nptr != endptr)
nptr = endptr;
}
}

int i = 0;

//Prints temperatures on screen

printf("Temperatures : ");

while (i < 17) {
printf("%d ", fandata->temp_vect[i]);
i++;
}

printf("\n");

return 0;

}



enfin main.c :

/*---------------------------------------------------------------------------*
* main.c Osmalskyj Julien 2007-26-03
*
* Linux TP-Fancontrol : fan control program for IBM / Lenovo Thinkpad
* laptop computers. This program sets fan speed according to temperatures
* defined in a config file.
*---------------------------------------------------------------------------*/


#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <getopt.h>
#include <time.h>
#include <errno.h>
#include "fancontrol.h"

int main(int argc, char* argv[]) {

FILE* open = fopen("/proc/acpi/ibm/thermal", "r");

if (open == NULL) {
fprintf(stderr, "error loading thermal file\n");
return 1;
}

//Thermal* test_struct;
struct Thm_t test_struct = malloc(sizeof(struct Thm_t));

getThm(open, test_struct);
fclose(open);

return 0;
}



C'est bien sympa de votre part merci les gars (sourire)

Edité par Amwus ( 26/10/2007 21:48:01 )
"Engl Amps are the best i've ever used... Not only are they powerfull, but they have charachter too..." R. Blackmore
Francesco
Modérateur
RemonterCiter Linux Mozilla 5 - Posté le 26/10/2007 à 21:52
C'est exactement ce que je pensais. Donc, comme dit plus haut dans mon précédant post, lorsque tu compile ton fichier main.c, il inclu le fichier fancontrol.h. Or, tu ne fais que déclarer dans ce fichier ta structure sans la définir !

Donc, ce que tu peux faire, c'est manipuler des pointeurs. Ce que tu ne peux pas faire, c'est travailler directement une variable de type Thm_t ou thermal !
Quand tu fais un sizeof(Thermal), le compilo à besoin de connaitre l'organisation de ta structure, pour en déterminer la taille. Mais toi, tu n'as fait que la déclarer.

La solution :
met la définition de ta structure dans le fichier .h et non le fichier .c

Le souci, est que cela te coupe l'encapsulation que tu essayais de créer. Ou alors, il faut que tu ne travaille qu'avec des pointeurs. Chose qu'il est possible de faire, mais dans ce cas, au lieu de faire un malloc(sizeof(thermal)), il faut que tu créé une fonction dans ton fichier fancontrol.c, qui réalisera l'allocation pour toi (donc, appel au malloc), et te renverra un pointeur. En gros, un truc comme

thermal* thermal_alloc()
{
return malloc(sizeof(thermal));
}
Gates gave you the windows.
GNU gave us the whole house.(Alexandrin)
Freem
Modérateur
RemonterCiter Windows NT Firefox 2 - Posté le 27/10/2007 à 00:33
Mais, de rien, voyons (sourire) a condition que tu en fasses autant pour les autres, pas de problème (cool)
Tu me dis, j'oublie. Tu m'enseignes, je me souviens. Tu m'impliques, j'apprends. - Benjamin Franklin
Amwus
ProgBoarder
RemonterCiter Linux Firefox 2 - Posté le 27/10/2007 à 11:44
Bon finalement, j'ai simplement définit le tableau en dehors de la structure dans le fichier.h. Ce n'est pas plus mal... Il sera accessible par n'importe quel fichier qui aura le .h en headers comme ça...

Puisque j'en suis a poser des questions, j'ai un autre probleme... Oui oui jsuis chiant je sais. En fait c'est pas vraiment un probleme. J'ai un fichier de config de la forme suivante :
#-----------------------------------------------------------------------------#
# Thinkpad Linux Fan Control v1.0 Osmalskyj Julien
#
# Configuration file for temperatures and fan speed settings.
#
#-----------------------------------------------------------------------------#


# Set Active=1 to allow program to modify fan speed.
# Active=0 will just monitor temperatures.

Active=1

# Cycle : check temperatures every x seconds (default 5)

Cycle=5

# Temperatures settings : 0 = off; 2 = low speed; 4 = medium speed;
# 7 = max speed; 128 = automatic bios control

Level=47 0
Level=51 2
Level=56 4
Level=63 7
Level=75 128



Ma question est donc, quelle serait la méhode, pour enregistrer les valeurs dans des bonnes variables correspondantes ? Bon en parcourant, si j'ai un '#' je skip, mais dans le cas contraire, comment feriez vous pour déterminer que le prochain nombre est le temps de check, ou les bonnes températures ?

Merci !

Edité par Amwus ( 27/10/2007 11:45:02 )
"Engl Amps are the best i've ever used... Not only are they powerfull, but they have charachter too..." R. Blackmore
Freem
Modérateur
RemonterCiter Windows NT Firefox 2 - Posté le 27/10/2007 à 11:57
Je pense que j'utiliserai fscanf...
Bon, tu vas me dire "Oui, mais pour reconnaître les textes?"...
Et bien, fscanf permet d'utiliser les expressions régulière, ainsi que quelques autres fonctions bien pratiques et peu connues, par exemple, si tu fait "%*d" il ne stockera pas la valeur, et il y a un parametre qui permet d'écrire le nombre de paramètres lus correctement.
En utilisant ces possibilités, tu peux le faire assez facilement.
Sinon, il y a aussi strcmp.
Sûrement la solution la plus simple xD
Tu me dis, j'oublie. Tu m'enseignes, je me souviens. Tu m'impliques, j'apprends. - Benjamin Franklin
Francesco
Modérateur
RemonterCiter Linux Mozilla 5 - Posté le 27/10/2007 à 21:26
lex et yacc ?
Gates gave you the windows.
GNU gave us the whole house.(Alexandrin)
kod128
ProgBoarder
RemonterCiter Windows NT Firefox 2 - Posté le 28/10/2007 à 14:42
Utiliser lex et yacc (ou plutot flex et bison) pour un fichier de configuration simple comme celui ci, c'est comme prendre une .22 long rifle pour tuer un puceron.

Pour sa grammaire simpliste, suffit de faire un

strncmp(ligne_du_fichier, mot_clef, strlen(mot_clef);


dans une boucle et de gérer la ligne pour chaque cas particuliers en fonction du résultat obtenu... (déjà fais personnellement pour un système client-serveur).
Francesco
Modérateur
RemonterCiter Linux Mozilla 5 - Posté le 28/10/2007 à 15:25
Pas d'accord, c'est parfaitement adapté ! Rien n'empeche de faire des grammaires simples, qu'il suffit de faire évoluer si jamais il faut rajouter un élément. Et ce n'est pas parce que la grammaire est simple qu'il s'agit de prendre une "22 long rifle pour tuer un puceron".

Enfin bon, c'est mon avis. Mais des outils existent, alors autant en profiter (langue)
Gates gave you the windows.
GNU gave us the whole house.(Alexandrin)
kod128
ProgBoarder
RemonterCiter Windows NT Firefox 2 - Posté le 28/10/2007 à 21:39
Après chacun son opinion, je trouve Flex et Bison vraiment très puissants mais la tu peut traiter ligne par ligne et espace par espace.
Tu peut y arriver rien qu'avec des fonctions de la lib standard et pas beaucoup de code.

A voir donc. (clein d'oeil)
Amwus
ProgBoarder
RemonterCiter Linux Firefox 2 - Posté le 04/11/2007 à 13:27
Bonjour ! Désolé pour ce long silence j'ai eu pas mal de boulot ces derniers temps, pas bcp le temps de coder !

Merci pour toutes vos informations utiles. Je vais un peu me renseigner sur les diverses méthodes proposées ici.

En attendant le programme définitif, j'en fais un temporaire qui fonctionnera avec le kernel 2.6.23 et sans fichier de config, parce que les commandes de controle du ventilo ont changé dans ce noyau. Bref, j'utilise nanosleep pour lire les températures toutes les 3 secondes.

Et je fais une boucle de ce type, mais ça ne fait pas exactement ce que je veux :


int c;

while ((c = getchar) != EOF)) {
while (1) {
//Lire les températures et changer la vitesse du ventilo si besoin
}
}
// rendre le controle automatique au bios
...



ce que je voudrais, c'est que je tape control-C, il rende le controle au bios avant de quitter le programme.
Mais là, il quitte directement le programme. Logique me direz vous.
Y a -t- il aussi moyen de faire en sorte que lorsque je tape 'q', ça quitte ? Parce si je rempalce EOF par 'q', ça ne fonctionne pas non plus...

J'avais déjà réussi à le faire dans un programme, mais je ne sais plus comment...

Un autre probleme est aussi que je dois taper sur une touche pour lancer l'exécution de la boucle... Y a -t- il moyen de l'éviter ?

Merci d'avance ! (cool)

Edité par Amwus ( 04/11/2007 13:29:19 )
"Engl Amps are the best i've ever used... Not only are they powerfull, but they have charachter too..." R. Blackmore

Poster une réponse

STOP aux fautes volontaires !
Message
Formatage
Note: pour partager du code source, merci d'utiliser le wall !
Smileys (sourire) (yekyek) (clein d'oeil) (désapprouve) (triste) (cool) (langue) (confus) (gêné) (neutre) (eek) (surpris) (diable) (flèche) (exclamation) (question) (diable) (idée) (méchant)
Pseudonyme
Recopiez le code
v6 © Computaid SPRL 2005-2008 - Tous droits réservés - Hébergé par eTigris - Page générée en 0,129 s - Crédits - Stats
1 connecté