Thread: scanf and formating data

  1. #1
    essence of digital xddxogm3's Avatar
    Join Date
    Sep 2003
    Posts
    589

    scanf and formating data

    I'm trying to read in a bunch of strings from a dat file.

    bla,bla,bla

    I read that you can scan in data from a file using scanf()
    I have also read that you can read certain amount of characters by formating like follows.

    scanf(%3s,string)

    I also have a section that states you can eleminate certain characters in the string using [^(character to be eleminated)]

    so why does this not work?
    scanf(%3[^,]%3[^,]%3[^,],string1,string2,string3)

    which should store

    string1=bla
    string2=bla
    string3=bla
    "Hence to fight and conquer in all your battles is not supreme excellence;
    supreme excellence consists in breaking the enemy's resistance without fighting."
    Art of War Sun Tzu

  2. #2
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Code:
    #include <stdio.h>
    
    int main(void)
    {
       const char a[] = "abc,def,ghi";
       char b[4], c[4], d[4];
       if ( sscanf(a, "%3[^,]%*c%3[^,]%*c%3[^,]", b, c, d) == 3 )
       {
          puts(b);
          puts(c);
          puts(d);
       }
       return 0;
    }
    
    /* my output
    abc
    def
    ghi
    */
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  3. #3
    Ultraviolence Connoisseur
    Join Date
    Mar 2004
    Posts
    555
    um, if you have a string like so: blah,blah,blah
    just do scanf("%s,%s,%s",s,s1,s2);

  4. #4
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    I read that you can scan in data from a file using scanf()
    Not quite. scanf() is used with the stdin file. You are thinking of fscanf().

  5. #5
    essence of digital xddxogm3's Avatar
    Join Date
    Sep 2003
    Posts
    589
    thank you for the responses.
    I was actually looking to extract a strings from a file.
    I did mean fscanf().
    When I us
    Code:
    fscanf("%s,%s,%s",str1,str2,str3)
    printf("%s\n%s\n%s",str1,str2,str3)
    I get
    bla,bla
    bla
    "Hence to fight and conquer in all your battles is not supreme excellence;
    supreme excellence consists in breaking the enemy's resistance without fighting."
    Art of War Sun Tzu

  6. #6
    Registered User
    Join Date
    Dec 2003
    Posts
    92
    hi, dave.....i am also watching this topic, what is the job of '*' in your code inside the format ?
    blue_gene

  7. #7
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >what is the job of '*' in your code inside the format ?
    It's a modifier that says "read whatever the flag specifies and throw it away." In the case of Dave's code, it discards single characters separating the strings.
    My best code is written with the delete key.

  8. #8
    Registered User
    Join Date
    Dec 2003
    Posts
    92
    not clear..... In linux command these are called wildcards. whcih means for all

    but here it seems meaning is different. i removed * and found garbages. why?

    what i understand now>
    sscanf(a, "%3[^,]%*c%3[^,]%*c%3[^,]", b, c, d) == 3 )

    means.....

    1. start from the source a
    2. read 3 chars until you get ',' (as ^ means exclude)
    3.* means --> all, so keep on reading chars......

    nope ....i think my statements are not right.

    ohh....no ..no...i cant.....its very confusing.



    i dont understand how the things are processing here.

    can you tell me the processing in steps as i tried to clarify myself.

    is it a wildcard?
    blue_gene

  9. #9
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >not clear
    Read something and throw it away. What's so hard about that?

    >In linux command these are called wildcards
    C is not Shell. The sooner you realize that, the better off you'll be.

    >can you tell me the processing in steps as i tried to clarify myself
    >sscanf(a, "%3[^,]%*c%3[^,]%*c%3[^,]", b, c, d)
    The first flag is %3[^,]. It says to read at most 3 characters or until a comma is found and put everything (except the comma if found) in b. The next flag is %*c. It reads the comma that was left and discards it by not saving it anywhere. The next flag is %3[^,]. It does the same thing as the first one except it saves what is read to c. The next flag is %*c, it reads a comma and discards it by not saving it anywhere. The last flag is %3[^,]. It does the same thing as the previous flags that were exactly like it but writes to d.

    On a side note, any reference on C will tell you in detail what these flags and modifiers mean, along with examples usually.
    My best code is written with the delete key.

  10. #10
    Registered User
    Join Date
    Dec 2003
    Posts
    92
    i have understood your explanation. i would like to ask one more simple question.

    after % we write any conversion format .

    for example,

    %c
    %d
    %f
    %s


    but look in that code in the first flag after % there is no conversion format at all . it is simply "%3[^,]" the format is missing .....then another % has come.

    it seems the rule has been relaxed for the carrot [^] operator !!

    anyway, thanks for the clarification .
    blue_gene

  11. #11
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >it is simply "%3[^,]" the format is missing
    There are two odd format flags for scanf, [...] and [^...]. The first matches anything between the brackets, the second matches anything not between the brackets. So:
    Code:
    char buf[BUFSIZ];
    scanf ( "%[0123456789]", buf );
    Reads anything that is a digit, saves it to buf and stops at the first non-digit. On the other hand:
    Code:
    char buf[BUFSIZ];
    scanf ( "%[^0123456789]", buf );
    Reads anything that is not a digit, saves it to buf and stops reading at the first digit. The rules are still the same, you're just working with a scanset flag instead of a fixed format flag like %d or %c.
    My best code is written with the delete key.

  12. #12
    Registered User
    Join Date
    Dec 2003
    Posts
    92
    its ok..i have understood....fine.....i have no more question

    thanks
    blue_gene

  13. #13
    essence of digital xddxogm3's Avatar
    Join Date
    Sep 2003
    Posts
    589
    i have more questions though.
    I have formated my code as follows.
    Code:
    char label1[5];
    char label2[18];
    char label3[14];
    char label4[13];
    char label5[18];
    char label6[11];
    char label7[12];
    char label8[14];
    char label9[7];
    
    
             fscanf(infile,"%4[^,],%16[^,],%14[^,],%13[^,],",label1,label2,label3,label4)
             fscanf(infile,"%18[^,],%11[^,],%12[^,],%14[^,],",label5,label6,label7,label8)
             fscanf(infile,"%7[^,],",label9);
    
             printf("%s\n%s\n%s\n%s\n",label1,label2,label3,label4);
             printf("%s\n%s\n%s\n%s\n%s\n",label5,label6,label7,label8,label9);
    For some reason it reads everything into my arrays with out the comma, but it skips over the second label?

    here is my output
    Name
    <--here is where my label 2 should print.
    Perihelion AU
    Eccentricity
    Long. perihelion
    Long. node
    Inclination
    Semimajor axis
    Period
    you can see here that it reads the new line \n character, but not the array variable?
    Does anyone know why?
    Last edited by xviddivxoggmp3; 04-15-2004 at 12:09 PM.
    "Hence to fight and conquer in all your battles is not supreme excellence;
    supreme excellence consists in breaking the enemy's resistance without fighting."
    Art of War Sun Tzu

  14. #14
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by xviddivxoggmp3
    For some reason it reads everything into my arrays with out the comma, but it skips over the second label?

    you can see here that it reads the new line \n character, but not the array variable?
    Does anyone know why?
    A sample of the data file would be helpful, maybe two or three lines.

    If this code is in a loop and this occurs after the first line, then here is a guess: Since your format specifier doesn't read and discard the newline character, and since the [ specifier is not whitespace delimited, perhaps the newline character is the first character of the subsequent string. If so, add %*c after the last element to read and discard the newline.

    Also, it doesn't appear that you've done all of the width specifiers correctly for the strings. Each should be one less than the character array size. You may want to try something like this to have the compiler do the math.
    Code:
          char format[BUFSIZ];
          char label1[5],  label2[18], label3[14], label4[13], label5[18],
               label6[11], label7[12], label8[15], label9[7];
          sprintf(format, "%%%d[^,],%%%d[^,],%%%d[^,],%%%d[^,]"
                  ",%%%d[^,],%%%d[^,],%%%d[^,],%%%d[^,],%%%d[^,],%%*c",
                  (int)(sizeof label1 - 1), (int)(sizeof label2 - 1),
                  (int)(sizeof label3 - 1), (int)(sizeof label4 - 1),
                  (int)(sizeof label5 - 1), (int)(sizeof label6 - 1),
                  (int)(sizeof label7 - 1), (int)(sizeof label8 - 1),
                  (int)(sizeof label9 - 1));
          printf("format = \"%s\"\n\n", format);
    
          while ( fscanf(file, format, label1, label2, label3, label4,
                         label5, label6, label7, label8, label9) == 9 )
          {
             /* ... */
          }
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  15. #15
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >You may want to try something like this to have the compiler do the math.
    Yes, that certainly takes away the math and simplifies things.
    My best code is written with the delete key.

Popular pages Recent additions subscribe to a feed