scanf() gör inte det den ska (i C)

Elektronik- och mekanikrelaterad mjukvara/litteratur. (T.ex schema-CAD, simulering, böcker, manualer mm. OS-problem hör inte hit!)
net4all
Inlägg: 538
Blev medlem: 7 februari 2007, 12:06:34

scanf() gör inte det den ska (i C)

Inlägg av net4all »

Hej!
Tidigare så frågade jag efter ett enkelt sätt att styra COM-porten i C.
Valet föll på bibloteket "SPort", som fungerar utmärkt!
( Den tråden)

Nu har jag börjat skriva ett terminalprogram som senare ska kommunicera med bla en robot.
Problemet ligger dock inte i kommunikationen med COM-porten utan i kommunikationen med användaren.

Koden här under skapar variabler som inehåller inställningar, mm för COM-porten.
Standardinställningar läggs in direkt.
Sedan ska användaren få fylla i sina egna inställningar.
(Det är här det går fel, mer längre ner)
Slutligen så ska inställningarna sparas i en fil.

Det här är dock inte hela programmet, men resten fungerar utmärkt.
Det enda som inte fungerar är scanf() funktionerna i den här kodsnutten.
Första gången användaren ska bli tillfrågad så syns ingen text, men man kan skriva in ett värde.
Sedan ignoreras alla scanf(), ingen text, man får ingen möjlighet att skriva in värden.
Slutligen skrivs "Settings Ok" ut....

Varför blir det så?!?

(ALL annan kod har testats separat och fungerar utmärkt!)

Kod: Markera allt

#include <stdio.h>
#include <stdlib.h>
#include <IO.h>

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

        int COM_nr = 2; //Variabler för inställningarna till comporten
        long int baudrate = 9600;
        int nr_stop_bit = 1;
        int parity = 0;
        int IO_nr = 760;
        int IRQ_nr = 3;
        int databits_nr = 8;

        int save_yes_no = 0;

        //-------------------Här börjar problemen----------------------

        scanf("IRQ number [3]: %i", &IRQ_nr); //Denna scanf() skriver inte ut sin text, man kan bara fylla i ett värde
        if(IRQ_nr<0)
        {
            printf("IRQ can't be under 0!");
            return 6;
        }

        scanf("IO number [760]: %i", &IO_nr); //Helt ignorerad, kan inte fylla i ett värde
        if(IO_nr<0)
        {
            printf("IO value must be over 0!");
            return 7;
        }

        printf("Settings Ok!\n"); //Denna är allt som skrivs ut under hela körningen

        scanf("Would you like to save your settings? Y/N: %c", &save_yes_no); //Även denna är helt ignorerad

        //--------------------Och här slutar dom----------------

        if(save_yes_no=='Y' || save_yes_no=='y')
        {
            FILE *settings_file;
            if( (settings_file=fopen("terminal_settings.txt","w+")) == NULL)
            {
                printf("Cannot open the file to save settings in!\n");
                exit(1);
            }
            fprintf(settings_file, "%i %li %i %i %i %i %i",COM_nr,baudrate,nr_stop_bit,parity,IO_nr,IRQ_nr,databits_nr);
            fclose(settings_file);
            printf("Settings has been saved, you can next time load these settings\n");
        }
        if(save_yes_no=='N' || save_yes_no=='n')
        {
            printf("Don't save new settings.\n");
        }

return 0;
}

Användarvisningsbild
speakman
Inlägg: 4838
Blev medlem: 18 augusti 2004, 23:03:32
Ort: Ånge

Inlägg av speakman »

Hur menar du att ingen text visas när användaren blir tillfrågad? Den kod du har där skriver inte ut någon text alls, utan inväntar en input från användaren som skall vara enligt det mönstret du angett i scanf.

Har du verkligen förstått vad scanf innebär?
Användarvisningsbild
kimmen
Inlägg: 2042
Blev medlem: 25 augusti 2007, 16:53:51
Ort: Stockholm (Kista)

Inlägg av kimmen »

För att scanf inte riktigt gör det du tror. Den första parametern är en formatsträng, inget annat. Den skrivs inte ut. Du måste använda printf eller nåt liknande för att skriva ut frågan och sen ex. "scanf("%i", &IRQ_nr);" för att läsa in svaret.
net4all
Inlägg: 538
Blev medlem: 7 februari 2007, 12:06:34

Inlägg av net4all »

Ok, fixat.
(Missupfattade nog scanf)
Fungerar bättre, men sista scanf skippas, man blir inte tilfrågad där.
texten skrivs ut som den ska, det är bara på den sista scanf() som man inte kan skriva i, den drar bara förbi där.
Det är som om man bara tryckte enter när man skulle fylla i...

Kod: Markera allt

#include <stdio.h>
#include <stdlib.h>
#include <IO.h>

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

        int COM_nr = 2; //Variabler för inställningarna till comporten
        long int baudrate = 9600;
        int nr_stop_bit = 1;
        int parity = 0;
        int IO_nr = 760;
        int IRQ_nr = 3;
        int databits_nr = 8;

        int save_yes_no = 0;

        //-------------------Här börjar problemen----------------------
        printf("IRQ number [3]: ");
        scanf("%i", &IRQ_nr); //Denna scanf() skriver inte ut sin text, man kan bara fylla i ett värde
        if(IRQ_nr<0)
        {
            printf("IRQ can't be under 0!");
            return 6;
        }
        printf("IO number [760]: ");
        scanf("%i", &IO_nr); //Helt ignorerad, kan inte fylla i ett värde
        if(IO_nr<0)
        {
            printf("IO value must be over 0!");
            return 7;
        }

        printf("Settings Ok!\n"); //Denna är allt som skrivs ut under hela körningen

        printf("Would you like to save your settings? Y/N: ");
        scanf("%c", &save_yes_no); //Även denna är helt ignorerad

        //--------------------Och här slutar dom----------------

        if(save_yes_no=='Y' || save_yes_no=='y')
        {
            FILE *settings_file;
            if( (settings_file=fopen("terminal_settings.txt","w+")) == NULL)
            {
                printf("Cannot open the file to save settings in!\n");
                exit(1);
            }
            fprintf(settings_file, "%i %li %i %i %i %i %i",COM_nr,baudrate,nr_stop_bit,parity,IO_nr,IRQ_nr,databits_nr);
            fclose(settings_file);
            printf("Settings has been saved, you can next time load these settings\n");
        }
        if(save_yes_no=='N' || save_yes_no=='n')
        {
            printf("Don't save new settings.\n");
        }

return 0;
}

Användarvisningsbild
speakman
Inlägg: 4838
Blev medlem: 18 augusti 2004, 23:03:32
Ort: Ånge

Inlägg av speakman »

En vettig kompilator borde varna att du försöker läsa in chars till int:ar. Men den andra scanf borde fungera. Prova lägg till "\n" i varje scanf:

scanf("%i\n", &IRQ_nr);

osv...
Användarvisningsbild
kimmen
Inlägg: 2042
Blev medlem: 25 augusti 2007, 16:53:51
Ort: Stockholm (Kista)

Inlägg av kimmen »

Troligtvis ligger radmatningen kvar från tidigare inmatning och den blir inläst som det tecken du efterfrågar. Har du inte provat att använda en debugger på koden och se vad returvärdet från den krånglande scanf är och ifall den stoppar in något i variabeln?
Användarvisningsbild
kimmen
Inlägg: 2042
Blev medlem: 25 augusti 2007, 16:53:51
Ort: Stockholm (Kista)

Inlägg av kimmen »

speakman skrev:En vettig kompilator borde varna att du försöker läsa in chars till int:ar. Men den andra scanf borde fungera. Prova lägg till "\n" i varje scanf:

scanf("%i\n", &IRQ_nr);

osv...
Det är ju det som är problemet med vararg-funktioner och varför de är Onda! :) Kompilatorn kan ju inte veta vad funktionen gör om man inte hårdkodar in i kompilatorn vad olika vararg-funktioner gör och deras formatsträngar osv.
Användarvisningsbild
speakman
Inlägg: 4838
Blev medlem: 18 augusti 2004, 23:03:32
Ort: Ånge

Inlägg av speakman »

Just vanliga varargs brukar vara särskilt omhändertagna. GCC varnar direkt om man använder printf eller de andra i libc fel.
net4all
Inlägg: 538
Blev medlem: 7 februari 2007, 12:06:34

Inlägg av net4all »

Att lägga till \n gjorde inte saken bättre...
Utmatningen från programmet med \n i scanf.
På slutet skrivs variablernas värden ut.

Kod: Markera allt

C:\C_program>grund
IRQ number [3]: 3
1
IO number [760]: 760
Settings Ok!
Would you like to save your settings? Y/N:
3 1 7
C:\C_program>
Efter IRQ-frågan blir det en ny rad och man måste mata in ett nytt tal, so dock inte lagras i någon variabel..

Utmatning utan \n

Kod: Markera allt

C:\C_program>grund
IRQ number [3]: 3
IO number [760]: 760
Settings Ok!
Would you like to save your settings? Y/N:
3 760

C:\C_program>
Chars-int problemet fixat..

Debugger?
vararg?
(Ja, jag är nybörjare :) )
Användarvisningsbild
speakman
Inlägg: 4838
Blev medlem: 18 augusti 2004, 23:03:32
Ort: Ånge

Inlägg av speakman »

Sista utskriften tolkar jag som att det fungerar?
net4all
Inlägg: 538
Blev medlem: 7 februari 2007, 12:06:34

Inlägg av net4all »

Nej, man får ingen chans att fylla i sista, programmet bara hoppar förbi den.
Annars fungerar det som det ska.

EDIT: Variabeln save_yes_no innehåller talet 10 (LF, Line Feed, \n) efter scanf()
discomike
Inlägg: 445
Blev medlem: 22 juli 2007, 11:34:13
Ort: Göteborg

Inlägg av discomike »

alla scanf-formatteringar utom %c hoppar över blanksteg och linefeed-tecken, som tidigare sagts så får du in LF tecknet när man tryckte return tidigare.

genom att använda ett mellanslag först i formatsträngen " %c" kommer alla typer av whitespace innan inputten att hoppas över (även LF). (sen bör save_yes_no vara av typen char också).
net4all
Inlägg: 538
Blev medlem: 7 februari 2007, 12:06:34

Inlägg av net4all »

Yes! Nu fungerar det. :D

Tack allihop, bara att fortsätta på det hela.
(save_yes_no var redan char, skrev tidigare "chars-int problemet fixat :) )
sodjan
EF Sponsor
Inlägg: 43249
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> Yes! Nu fungerar det.

Hurdå ?
net4all
Inlägg: 538
Blev medlem: 7 februari 2007, 12:06:34

Inlägg av net4all »

Det fungerar genom att jag(med discomike's hjälp) fick scanf() funktionen att ignorera LF-tecknet.

Eller menade du något annat?
Skriv svar