Imprimindo váriavel em arquivo - what's wrong? [RESOLVIDO]

1. Imprimindo váriavel em arquivo - what's wrong? [RESOLVIDO]

Perfil removido
removido

(usa Nenhuma)

Enviado em 04/05/2016 - 10:54h

Bom dia!
Estava adaptando algumas funções do meu programa e no momento dos testes, notei que o valor de uma váriavel do tipo char (ssid) não é impressa no arquivo (wireless_conf), por quê?
separei o trecho que não funciona como o esperado, segue o code;
#include <stdio.h>
#define MAX 100
char custom_path_outputopen[MAX] = "/var/tmp/custom_open";
char default_path_open[MAX] = "/etc/wpa_supplicant/default_open.conf";

int main(void){
FILE *wireless_conf;
FILE *custom_path_out;
char ssid[MAX];
char custom_path[MAX];
char op_path[1];

printf("Network ssid: ");
scanf("%s[a-z|A-Z|0-9/,.-]",ssid);
printf("Custom path file (y/n): ");
scanf("%s",op_path);
if(op_path[0] == 'y')
{
printf("Path (with name file): ");
scanf("%s",custom_path);
wireless_conf = fopen(custom_path,"w");
fprintf(wireless_conf,"network={\nssid=\"%s\"\nkey_mgmt=NONE\n}\n",ssid);
printf("Wireless conf file at: %s\n",custom_path);
custom_path_out = fopen(custom_path_outputopen,"w");
fprintf(custom_path_out,"%s\n",custom_path);
fclose(wireless_conf);
fclose(custom_path_out);
}
if(op_path[0] == 'n')
{
wireless_conf = fopen(default_path_open,"w");
fprintf(wireless_conf,"network={\nssid=\"%s\"\nkey_mgmt=NONE\n}\n",ssid);
printf("Wireless default file at: %s\n",default_path_open);
fclose(wireless_conf);
}
return 0;
}

Não gosto de ficar "pedindo" as coisas, mas recorri ao VOL porque tentei imprimir essa váriavel de varias maneiras mas sem sucesso, ficarei grato se me avisar de qualquer escrita errônea no code.


  


2. MELHOR RESPOSTA

Paulo
paulo1205

(usa Ubuntu)

Enviado em 04/05/2016 - 14:19h

O que você quis dizer com essa string de formatação?

scanf("%s[a-z|A-Z|0-9/,.-]",ssid); 


O que está dito é que você quer ler uma string e, em, seguida a exata sequência de caracteres “[a-z|A-Z|0-9/,.-]”. Se não for assim, a função scanf() vai falhar (não sei se totalmente ou apenas parcialmente, mas seguramente vai interromper a execução antes do fim da string de formatação).

Eu desconfio que você quis dizer o seguinte:

// Aceita letras, algarismos e os símbolos “/”, “,”, “.”, “|” e “-”.
// De quebra, tira do buffer possíveis caracteres inválidos e a marca de fim de linha.
if(scanf("%[a-zA-Z0-9/,.|-]%*[^\n]%*1[\n]", ssid)==1 && strlen(ssid)>0){
/* Leitura bem sucedida. */
}
else {
/* ssid inválido */
}


Mas isso ainda está ruim. Qual o tamanho máximo de ssid? A leitura acima não leva isso em consideração. Melhor seria fazer o seguinte.

size_t len;

// Vale-se do fato de ssid ser um array de caracteres. Se fosse ponteiro
// dinamicamente alocado, não poderia usar sizeof desse modo.
if(
fgets(ssid, sizeof ssid, stdin)==NULL ||
(len=strlen(ssid))==0
){
/* Erro de leitura. */
}
else {
if(ssid[len-1]=='\n')
ssid[--len]='\0'; // Elimina o '\n' retido por fgets().
else if(len==(sizeof ssid)-1){
// Ocupou todo o array mas ainda não achou o '\n'.
int ch=getchar();
if(ch!='\n' && ch!=EOF){
/*
Tudo bem se o próximo caráter for '\n' ou se não houver mais
caracteres -- só que não é o caso, se a eecução cair aqui. Você
provavelmente vai querer imprimir uma mensagem de erro e
abortar (ou voltar para um ponto anterior). Além disso, pode
querer tirar os caracteres excedentes do buffer.
*/
fprintf(stderr, "Mensagem de erro.\n");
while((ch=getchar())!='\n')
if(ch==EOF){
// Erro de leitura ao tentar limpar excedentes.
abort();
}
}
}
}
// Agora faz a validação dos caracteres da string.
if(
strspn(
ssid,
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789|/,.-"
)!=len
){
/* Caracteres inválidos no ssid. */
}
}


Outra forma seria a seguinte.

char ssid_fmt_str[80];
int a, b, c, n;
snprintf(
ssid_fmt_str, sizeof ssid_fmt_str,
"%%%zd[A-Za-z0-9/,.|-]%%n%%*[^\n]%%n%%*1[\n]%%n", (sizeof ssid)-1
);
a=b=c=0;
n=scanf(ssid_fmt_str, ssid);
if(n==EOF){
/ * Erro de leitura. */
}
else if(n!=1 || a==0 || b>a || c<=b){
/* Valor digitado inválido. */
// Se quiser tentar de novo, é bom limpar o buffer antes.
if(scanf("%*[^\n]%*1[\n]")==EOF) // Mas se der erro de leitura...
abort(); // ... talvez seja melhor abortar.
}
else {
/* Aqui você tem um ssid válido. */
}


3. Re: Imprimindo váriavel em arquivo - what's wrong?

Perfil removido
removido

(usa Nenhuma)

Enviado em 04/05/2016 - 11:52h

Na verdade, isso faz parte de um gerenciador de conexão wireless (como você pode observar) que eu estou "tentando" desenvolver. Eu até achei que fosse algum erro de buffer ou algo do tipo, então eu separei a função e coloquei no main() (caso tenha ficado estranho de analisar).

Exatamente SamL! o único jeito de falhar é sem permissão, mas eu executo como root.
Como é uma versão teste do code eu não verifico a criação do arquivo, porém já que você mencionou reescrevi a abertura/criação do arquivo verificando com um if, ficando assim:
if((wireless_conf = fopen(custom_path,"w")) == NULL)
{
perror("Error custom_path\n");
}
else
{
...
}

E o fprintf() imprime do mesmo jeito:

network={
ssid=""
key_mgmt=NONE
}

Detalhe, a váriavel (ssid) não é impressa em nenhuma das duas opções custom/default (y/n).
Não sei o que acontece... mas vou fazer mais alguns testes aqui, ou tentar passar essa váriavel para o arquivo de outras maneiras.

Mas obrigado mesmo, pela ajuda :)

--
Just bring us some beers, and then we can talk about our systems. :)



4. Re: Imprimindo váriavel em arquivo - what's wrong? [RESOLVIDO]

Perfil removido
removido

(usa Nenhuma)

Enviado em 04/05/2016 - 13:37h

SamL, consegui resolver o problema;
reescrevi toda a função para ver se eu identificava o erro, e susbititui o fclose() por fcloseall(), não tenho certeza do que acontecia exatamente, mas dessa maneira com fcloseall funcionou perfeitamente :)
    
if((wireless_conf = fopen(custom_path,"w")) == NULL)
{
....
}
else
{
fprintf(wireless_conf,"network={\nssid=\"%s\"\nkey_mgmt=NONE\n}\n",ssid); //agora imprime valor de ssid em wireless_conf
...
fcloseall();
}

Obrigado pela atenção.

--
Just bring us some beers, and then we can talk about our systems. :)



5. Re: Imprimindo váriavel em arquivo - what's wrong? [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 04/05/2016 - 14:26h

Outro erro:

char op_path[1];

/* ... */

scanf("%s",op_path);


Desse modo você vai gravar pelo menos dois bytes num array preparado para receber apenas um. Isso pode vir a sobrescrever outra variável do seu programa, ou a ter outro efeito indefinido ainda mais destrutivo.

Não faça isso. Se quiser ler apenas um caráter, use getchar(), fgetc() ou scanf("%c", ...), e depois faça a devida limpeza de caracteres excedentes no buffer de entrada.


6. Re: Imprimindo váriavel em arquivo - what's wrong? [RESOLVIDO]

Perfil removido
removido

(usa Nenhuma)

Enviado em 04/05/2016 - 14:55h

Eu realmente não tinha certeza de como fazer uma leitura específica de ssid, e essa sua string de formatação me ajudou a entender isso melhor, era o que eu queria. Em relação ao op_path foi uma desatenção mesmo, já tinha arrumado aqui logo que percebi.
Eu não costumo muito usar fgets, getchar ou strlen, mas eu sei que são funções essenciais na manipulação de strings/caracteres então eu vou ler com calma suas respostas e pesquisar o man para entender tudo um pouco melhor.

Mas uma das dúvidas que eu ainda tenho é como fazer a limpeza do buffer corretamente, como seria?

Enfim, desde já muito obrigado pelos esclarecimentos paulo1205, vai ser de grande ajuda para os meus estudos... e ah, obrigado também pelas ideias de estrutura do código.

--
Just bring us some beers, and then we can talk about our systems. :)







Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts