#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2011
    Posts
    54
    Rep Power
    3

    New to C, need help please


    I am working on a project for school, and I think I am over thinking everything and complicating things more than they need. I just need a little guidance. In this part of the project, we will be getting a data stream via i/o redirect and then need to parse the data. There will be garbage up to the word HEADER, then everything will be formatted from there. So we need to get to HEADER, then need to get the data fields from inside the header until we get to ENDHEADER and then we get binary data representing an audio file. I have code written for it, which I will post, but I have not tried to compile yet as I feel like there is more work to be done before I can test it. Whatever assistance you guys can provide would be much appreciated!! Thank you!!

    Code:
    int parseToHeader();
    int parseHeader();
    int parseData();
    
    void main(int argc, char** argv) {
        char temp[80];
        scanf("%s", temp);
        struct datafile data;
        malloc((data.sample)*(data.bitres) + 15);
        int j;
        FILE *fp;
        if (argc == 1) {
            fp = stdin;
        } else if (argc == 2)
            fp = fopen(argv[*], "r")
    
    
            char compare[6];
        compare[5] = toupper(getchar());
        compare[4] = toupper(getchar());
        compare[3] = toupper(getchar());
        compare[2] = toupper(getchar());
        compare[1] = toupper(getchar());
        compare[0] = toupper(getchar());
    
        while (strncmp(compare, 'HEADER', 6) != 0) {
            compare[5] = compare[4];
            compare[4] = compare[3];
            compare[3] = compare[2];
            compare[2] = compare[1];
            compare[1] = compare[0];
            compare[0] = toupper(getchar());
        }
    
    
    
        scanf("%s", temp);
        while (strcasecmp(temp, 'ENDHEADER') != 0) {
            if ((strcasecmp(temp, 'FREQUENCY') == 0) && data.frequency == NULL) {
                scanf("%d", data.frequency);
                scanf("%s", temp);
            } else if ((strcasecmp(temp, 'SAMPLE') == 0) && data.sample == NULL) {
                scanf("%d", data.sample);
                scanf("%s", temp);
            } else if ((strcasecmp(temp, 'CHANNELS') == 0) && data.channels == NULL) {
                scanf("%s", data.channels);
                scanf("%s", temp);
            } else if ((strcasecmp(temp, 'BITRES') == 0) && data.bitres == NULL) {
                scanf("%d", data.bitres);
                scanf("%s", temp);
            } else
                printf("Improper format");
        }
    
    
    
    
        if (strcasecmp(data.channels, 'MONO') == 0) {
            for (j = 0; j <= data.sample; j++) {
                fread(data.data, (data.bitres / 8), 1, stdin);
            }
        } else if (strcasecmp(data.channels, 'STEREO') == 0) {
    
            for (j = 0; j <= data.sample; j++) {
                fread(data.data, (data.bitres / 8), 1, stdin);
                fread(*data.data, (data.bitres / 8), 1, stdin);
            }
        }
    
        printf("filename <%s>, Frequency <%i>, Stereo or mono <%s>, Bit Resolution <%i>, Samples <%i>", 'stdin', data.frequency, data.channels, data.bitres, data.sample);
    }
  2. #2
  3. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,091
    Rep Power
    2222
    You say you're new to C, but are you also new to computer science? If not, then are you familiar with finite state automata (fsa) or finite state machines (fsm)? If you are, then use an fsm implemented as a switch statement in which each case is a state in the fsm.

    You read in one character at a time and feed it to the switch statement at its current state (ie, you declare a state variable, eg iState, and switch on it). The current state will test the character and either ignore it or transition to another state based on that character (and do whatever other processing is needed, such as reading in a field's value and assigning it to a variable). Of course each state's conditions for transitioning will undoubtedly be different. And if you need to go off and do something else (eg, in parsing a file, you may need to go read the next block of data), when you return to the machine it remembers where you had left off because it remembers what state it was in (therefore, if iState is local, declare it as static).

    For example, in your initial state, you're looking for an 'H', so you don't transition until the input character is 'H'. In that next state, you expect the next character to be an 'E'; if it is, then you transition to the next state where you'll be looking for an 'A', but if it's not then you transition back to the initial state to look for that initial 'H', unless it's another 'H' in which case you stay put in case this is the 'H' you've been looking for. And so on.

    In constructing that machine, you will need to sketch it out in a standard nodes-and-edges diagram.

    If that made any sense to you, then know that such machines are common in parsing streams. If you have not yet learned about fsa's or fsm's and it didn't make any sense, then disregard it for now, but make a note for later when you will have learned those topics.
    Last edited by dwise1_aol; March 12th, 2012 at 02:48 PM.
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2011
    Posts
    54
    Rep Power
    3
    Originally Posted by dwise1_aol
    You say you're new to C, but are you also new to computer science? If not, then are you familiar with finite state automata (fsa) or finite state machines (fsm)? If you are, then use an fsm implemented as a switch statement in which each case is a state in the fsm.

    You read in one character at a time and feed it to the switch statement at its current state (ie, you declare a state variable, eg iState, and switch on it). The current state will test the character and either ignore it or transition to another state based on that character (and do whatever other processing is needed, such as reading in a field's value and assigning it to a variable). Of course each state's conditions for transitioning will undoubtedly be different. And if you need to go off and do something else (eg, in parsing a file, you may need to go read the next block of data), when you return to the machine it remembers where you had left off because it remembers what state it was in (therefore, if iState is local, declare it as static).

    For example, in your initial state, you're looking for an 'H', so you don't transition until the input character is 'H'. In that next state, you expect the next character to be an 'E'; if it is, then you transition to the next state where you'll be looking for an 'A', but if it's not then you transition back to the initial state to look for that initial 'H', unless it's another 'H' in which case you stay put in case this is the 'H' you've been looking for. And so on.

    In constructing that machine, you will need to sketch it out in a standard nodes-and-edges diagram.

    If that made any sense to you, then know that such machines are common in parsing streams. If you have not yet learned about fsa's or fsm's and it didn't make any sense, then disregard it for now, but make a note for later when you will have learned those topics.

    I've done finite state machines in digital logic but I have never implemented one is code. Here is my attempt at it. Thank you for your help!

    Code:
        c = toupper(getchar());
        switch (iState) {
            case H:
                c = toupper(getchar());
            case E:
                c = toupper(getchar());
            case A:
                c = toupper(getchar());
            case D:
                c = toupper(getchar());
            case E:
                c = toupper(getchar());
            case R:
                c = toupper(getchar());
            default:
                break;
        }
  6. #4
  7. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,091
    Rep Power
    2222
    Kind of. More like (with a little pseudo-code sneaked in):
    Code:
    void machine()
    {
        int iState = 0;
        char  ch;
    
        while((ch = getchar()) succeeds)
            switch (iState)
            {
                case 0:    // looking for 'H'
                    if (ch == 'H')
                        iState = 1;
                    break;
                case 1:    // looking for 'E'
                    if (ch == 'E')
                        iState = 2;
                    else if (ch != 'H')
                        iState = 0;    
                    break;
                case 2:    // looking for 'A'
                    if (ch == 'A')
                        iState = 3;
                    else if (ch == 'H')
                        iState = 1;    
                    else 
                        iState = 0;    
                    break;
                case 3:    // looking for 'D'
                    if (ch == 'D')
                        iState = 4;
                    else if (ch == 'H')
                        iState = 1;    
                    else 
                        iState = 0;    
                    break;
                case 4:    // looking for 'E'
                    if (ch == 'E')
                        iState = 5;
                    else if (ch == 'H')
                        iState = 1;    
                    else 
                        iState = 0;    
                    break;
                case 5:    // looking for 'R'
                    if (ch == 'ER)
                        iState = 6;
                    else if (ch == 'H')
                        iState = 1;    
                    else 
                        iState = 0;    
                    break;
                case 6:    // start parsing the data
                    break;
            }
    }
    I'm assuming that the keywords are case sensitive, so that "header" would not work. If that's not the case, then consider whether the data characters should also be subjected to toupper.

    Also, we normally name the states using #define's;eg:
    Code:
    #define STATE_INITIAL_H  0
    #define STATE_FIRST_E  1
    #define STATE_A           2
    If you don't name the states, then at least comment each one to identify what it's looking for or what it signifies.

    Here's an idea for using fewer states:
    Code:
    #define  STATE_INITIAL          0
    #define  STATE_GET_HEADER       1
    #define STATE_GET_FIRST_FIELD  2
    void machine()
    {
        int iState = 0;
        char  ch;
        char *keywords[] = {"HEADER", "ENDHEADER", "FREQUENCY"};
        int   pos = 0;
    
        while((ch = getchar()) succeeds)
            switch (iState)
            {
                case STATE_INITIAL:    // looking for "HEADER"
                    if (ch == keywords[0][pos])
                    {
                        pos++;
                        iState = STATE_GET_HEADER;
                    }
                    break;
                case STATE_GET_HEADER:    // verify "HEADER"
                    // is this next letter the one we expected?
                    if (ch == keywords[0][pos])
                    {
                        // is this the last letter?
                        //   if so, then move on to the header fields
                        //   else, stay here and move on to the next letter
                        if (pos == 5)  
                            iState = STATE_GET_FIRST_FIELD;
                        else
                            pos++;
                    }
                    // Not the letter we expected
                    // Is it the first letter? 
                    //    then assume we're starting over again and 
                    //          set up for the second letter
                    //    else go back to the beginning looking for 'H'
                    else if (ch == keywords[0][0])
                        pos = 1;    
                    else
                    {
                        pos = 0;
                        iState = STATE_INITIAL;
                    }
                    break;
                case STATE_GET_FIRST_FIELD:    // start processing the header fields
                   . . .
            }
    }
    Another example of that approach would be reading in an integer value. You initialize the int to zero and as long as you read in a digit character you use it to build that int value. Then when you reach a non-digit, you store that value in a variable and transition to the next state.

    Similarly, when you're reading in the name of the next field, you can use the first character of the field name to transition to the state that will process that field. And if there's more than one field that starts with that character, then you would transition to a state that will use the next character to transition to the appropriate state.

    And, of course, after you've read "ENDHEADER", you should need only one state to read in all the data.

    Another thought. If you number the states instead of naming them, which can be preferable if there are a large number of states, you don't need to be sequential. This is from the earlier versions BASIC where you needed to number each line. In the top-level design of your machine, number the entry point into each section by the 100's or 1000's; eg, initially looking for "HEADER" could be 0, but looking for "FREQUENCY" would start at 100, "SAMPLE" at 200, "CHANNELS" at 300, etc. And within each section, increment your states by 10. That way, if you need to insert some extra states here or there, you won't need to change any existing states' numbers.

    Just some thoughts. We use the state machine approach all the time for processing serial data or for keeping track of where we are in a process. I never learned this approach in school, but rather a fellow programmer had to show it to me once.

    Learn it and pay it forward.
  8. #5
  9. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2011
    Posts
    54
    Rep Power
    3
    Originally Posted by dwise1_aol
    Kind of. More like (with a little pseudo-code sneaked in):
    Code:
    void machine()
    {
        int iState = 0;
        char  ch;
    
        while((ch = getchar()) succeeds)
            switch (iState)
            {
                case 0:    // looking for 'H'
                    if (ch == 'H')
                        iState = 1;
                    break;
                case 1:    // looking for 'E'
                    if (ch == 'E')
                        iState = 2;
                    else if (ch != 'H')
                        iState = 0;    
                    break;
                case 2:    // looking for 'A'
                    if (ch == 'A')
                        iState = 3;
                    else if (ch == 'H')
                        iState = 1;    
                    else 
                        iState = 0;    
                    break;
                case 3:    // looking for 'D'
                    if (ch == 'D')
                        iState = 4;
                    else if (ch == 'H')
                        iState = 1;    
                    else 
                        iState = 0;    
                    break;
                case 4:    // looking for 'E'
                    if (ch == 'E')
                        iState = 5;
                    else if (ch == 'H')
                        iState = 1;    
                    else 
                        iState = 0;    
                    break;
                case 5:    // looking for 'R'
                    if (ch == 'ER)
                        iState = 6;
                    else if (ch == 'H')
                        iState = 1;    
                    else 
                        iState = 0;    
                    break;
                case 6:    // start parsing the data
                    break;
            }
    }
    I'm assuming that the keywords are case sensitive, so that "header" would not work. If that's not the case, then consider whether the data characters should also be subjected to toupper.

    Also, we normally name the states using #define's;eg:
    Code:
    #define STATE_INITIAL_H  0
    #define STATE_FIRST_E  1
    #define STATE_A           2
    If you don't name the states, then at least comment each one to identify what it's looking for or what it signifies.

    Here's an idea for using fewer states:
    Code:
    #define  STATE_INITIAL          0
    #define  STATE_GET_HEADER       1
    #define STATE_GET_FIRST_FIELD  2
    void machine()
    {
        int iState = 0;
        char  ch;
        char *keywords[] = {"HEADER", "ENDHEADER", "FREQUENCY"};
        int   pos = 0;
    
        while((ch = getchar()) succeeds)
            switch (iState)
            {
                case STATE_INITIAL:    // looking for "HEADER"
                    if (ch == keywords[0][pos])
                    {
                        pos++;
                        iState = STATE_GET_HEADER;
                    }
                    break;
                case STATE_GET_HEADER:    // verify "HEADER"
                    // is this next letter the one we expected?
                    if (ch == keywords[0][pos])
                    {
                        // is this the last letter?
                        //   if so, then move on to the header fields
                        //   else, stay here and move on to the next letter
                        if (pos == 5)  
                            iState = STATE_GET_FIRST_FIELD;
                        else
                            pos++;
                    }
                    // Not the letter we expected
                    // Is it the first letter? 
                    //    then assume we're starting over again and 
                    //          set up for the second letter
                    //    else go back to the beginning looking for 'H'
                    else if (ch == keywords[0][0])
                        pos = 1;    
                    else
                    {
                        pos = 0;
                        iState = STATE_INITIAL;
                    }
                    break;
                case STATE_GET_FIRST_FIELD:    // start processing the header fields
                   . . .
            }
    }
    Another example of that approach would be reading in an integer value. You initialize the int to zero and as long as you read in a digit character you use it to build that int value. Then when you reach a non-digit, you store that value in a variable and transition to the next state.

    Similarly, when you're reading in the name of the next field, you can use the first character of the field name to transition to the state that will process that field. And if there's more than one field that starts with that character, then you would transition to a state that will use the next character to transition to the appropriate state.

    And, of course, after you've read "ENDHEADER", you should need only one state to read in all the data.

    Another thought. If you number the states instead of naming them, which can be preferable if there are a large number of states, you don't need to be sequential. This is from the earlier versions BASIC where you needed to number each line. In the top-level design of your machine, number the entry point into each section by the 100's or 1000's; eg, initially looking for "HEADER" could be 0, but looking for "FREQUENCY" would start at 100, "SAMPLE" at 200, "CHANNELS" at 300, etc. And within each section, increment your states by 10. That way, if you need to insert some extra states here or there, you won't need to change any existing states' numbers.

    Just some thoughts. We use the state machine approach all the time for processing serial data or for keeping track of where we are in a process. I never learned this approach in school, but rather a fellow programmer had to show it to me once.

    Learn it and pay it forward.
    Thank you for helping me with this. It is starting to make sense to me. But I still don't think I have it down correct for the HEADER fields. This is what I came up with, but I don't think it will work correctly. Also, the fields are in the same format FREQUENCY 1000 but not the same order so I need to be able to read them in any order but they will always be between the HEADER and ENDHEADER fields.

    Code:
    case STATE_GET_FIRST_FIELD: // start processing the header fields
                            if (ch == keywords[2][0]) {
                                scanf("%d", data.frequency);
                            }
                        case STATE_GET_SECOND_FIELD:
                            if (ch == keywords[3][0]) {
                                scanf("%d", data.sample);
                            }
                        case STATE_GET_THIRD_FIELD:
                            if (ch == keywords[5][0]) {
                                scanf("%d", data.channels);
                            }
                        case STATE_GET_FOURTH_FIELD:
                            if (ch == keywords[5][0]) {
                                scanf("%d", data.bitres);
                            }
  10. #6
  11. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,709
    Rep Power
    480
    You don't use flex and bison to construct your fsms?
    [code]Code tags[/code] are essential for python code and Makefiles!
  12. #7
  13. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,091
    Rep Power
    2222
    We normally work character-by-character, but that's because all the protocols we work with contain binary. But when it's all text, it does look like it would make sense to use library I/O functions like scanf within a state in order to read in a field value.

    However, what you have would not work. You're using the first character to recognize which field it is, which is OK. But the rest of the field name is still in the input stream, so scanf will try to convert that to an integer value, which will fail. First, you need to consume the rest of the field name and only then can you attempt to read the field value. Something like:

    Code:
            case STATE_READ_THE_FIELDS:
                if (ch == keywords[2][0]) // eg, "FREQUENCY"
                    iState = STATE_CONSUME_FREQUENCY_NAME;
                else if (ch == keywords[3][0]) // eg, "SAMPLE"
                    iState = STATE_CONSUME_SAMPLE_NAME;
                else if (ch == keywords[4][0]) // eg, "COLUMNS"
                    iState = STATE_CONSUME_COLUMNS_NAME;
                else if (ch == keywords[4][0]) // eg, "ENDHEADER"
                    iState = STATE_CONSUME_ENDHEADER;
                break;
    
            case STATE_CONSUME_FREQUENCY_NAME:
                // get and discard the rest of the characters in "FREQUENCY"
                //  when you're done doing that, the next characters will be the value
                 scanf("%d", data.frequency);
                 // now go back to read the next field
                 iState = STATE_READ_THE_FIELDS;
                break;
    
            case STATE_CONSUME_SAMPLE_NAME:
                // get and discard the rest of the characters in "SAMPLE"
                //  when you're done doing that, the next characters will be the value
                 scanf("%d", data.sample);
                 // now go back to read the next field
                 iState = STATE_READ_THE_FIELDS;
                break;
    
            case STATE_CONSUME_COLUMNS_NAME:
                // get and discard the rest of the characters in "COLUMNS"
                //  when you're done doing that, the next characters will be the value
                 scanf("%d", data.channels);
                 // now go back to read the next field
                 iState = STATE_READ_THE_FIELDS;
                break;
    
            case STATE_CONSUME_ENDHEADER:
                // get and discard the rest of the characters in "ENDHEADER"
                //  when you're done doing that, the rest of what follows will
                //    be data, so go to the state that reads that in.
                iState = STATE_READ_THE_DATA;
                break;
    Try to always keep in mind exactly what's in that input stream and what the next character will be.
  14. #8
  15. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,091
    Rep Power
    2222
    Originally Posted by b49P23TIvg
    You don't use flex and bison to construct your fsms?
    Are you talkin' to me?

    That would be an unneccesary complication. The protocols we work with are already specified and all except one consist of binary data. Rather then try to concoct a BNF grammar for them, it's quicker and easier to simply sketch out the fsm by hand.
  16. #9
  17. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2011
    Posts
    54
    Rep Power
    3
    Originally Posted by dwise1_aol
    We normally work character-by-character, but that's because all the protocols we work with contain binary. But when it's all text, it does look like it would make sense to use library I/O functions like scanf within a state in order to read in a field value.

    However, what you have would not work. You're using the first character to recognize which field it is, which is OK. But the rest of the field name is still in the input stream, so scanf will try to convert that to an integer value, which will fail. First, you need to consume the rest of the field name and only then can you attempt to read the field value. Something like:

    Code:
            case STATE_READ_THE_FIELDS:
                if (ch == keywords[2][0]) // eg, "FREQUENCY"
                    iState = STATE_CONSUME_FREQUENCY_NAME;
                else if (ch == keywords[3][0]) // eg, "SAMPLE"
                    iState = STATE_CONSUME_SAMPLE_NAME;
                else if (ch == keywords[4][0]) // eg, "COLUMNS"
                    iState = STATE_CONSUME_COLUMNS_NAME;
                else if (ch == keywords[4][0]) // eg, "ENDHEADER"
                    iState = STATE_CONSUME_ENDHEADER;
                break;
    
            case STATE_CONSUME_FREQUENCY_NAME:
                // get and discard the rest of the characters in "FREQUENCY"
                //  when you're done doing that, the next characters will be the value
                 scanf("%d", data.frequency);
                 // now go back to read the next field
                 iState = STATE_READ_THE_FIELDS;
                break;
    
            case STATE_CONSUME_SAMPLE_NAME:
                // get and discard the rest of the characters in "SAMPLE"
                //  when you're done doing that, the next characters will be the value
                 scanf("%d", data.sample);
                 // now go back to read the next field
                 iState = STATE_READ_THE_FIELDS;
                break;
    
            case STATE_CONSUME_COLUMNS_NAME:
                // get and discard the rest of the characters in "COLUMNS"
                //  when you're done doing that, the next characters will be the value
                 scanf("%d", data.channels);
                 // now go back to read the next field
                 iState = STATE_READ_THE_FIELDS;
                break;
    
            case STATE_CONSUME_ENDHEADER:
                // get and discard the rest of the characters in "ENDHEADER"
                //  when you're done doing that, the rest of what follows will
                //    be data, so go to the state that reads that in.
                iState = STATE_READ_THE_DATA;
                break;
    Try to always keep in mind exactly what's in that input stream and what the next character will be.
    That is great! Thank you so much for your help!!

    My next question is this... When I am reading in the binary data, right now I am saving it to my struct but I don't think I need to save it. I am just using that program to check and retrieve the header data. Example is another part of project, I need to check the header info and then combine the two audio channels into a single channel. Which I know how to do once I am getting the data, but I need to call the finite state machine to get the header data and then process the binary data and I'm not sure how to do that? Any help would be great!
  18. #10
  19. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,091
    Rep Power
    2222
    I thought I had covered that with:
    iState = STATE_READ_THE_DATA;

    So you could add a state to process that binary data.

    Or better, you can finish with the fsm once you've detected and consumed the "ENDHEADER" -- it's done its job, after all -- exit the fsm function, and call another function in which you read in and process the binary data. All you really needed the fsm for was to parse the header.
  20. #11
  21. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2011
    Posts
    54
    Rep Power
    3
    Originally Posted by dwise1_aol
    I thought I had covered that with:
    iState = STATE_READ_THE_DATA;

    So you could add a state to process that binary data.

    Or better, you can finish with the fsm once you've detected and consumed the "ENDHEADER" -- it's done its job, after all -- exit the fsm function, and call another function in which you read in and process the binary data. All you really needed the fsm for was to parse the header.
    I think I am going to exit the fsm and then read the data. So I just need to do like an fread on the data and output to stdout? That data will then be IO redirected to the other function? Does that make any sense or am I just confusing myself even more.
  22. #12
  23. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,091
    Rep Power
    2222
    For an example of binary data going to stdout, use this command at the console command line:
    TYPE myprog.exe
    where "myprog.exe" is the name of your program's executable. What you will get is a bloody mess and, if you're lucky and there are some bytes in there set to 0x07, you will also hear beeps ('\7' is BEL).

    Is that what you want to output? stdin and stdout are really made for text, not for binary. For that matter, I suspect that your input will be likely to terminate prematurely in it happens to hit a byte of 0x1A, which should be Ctrl-Z, which marks end-of-file in MS-DOS; when using the MS-DOS "poor man's editor", COPY CON myfile.txt, you use Ctrl-Z to mark the end of your typing (my avatar alludes to using cat for the same purpose in UNIX).

    I'm assuming that you're to just use redirected input for getting the parsing of the header to work and not for processing the sound data and that in the next phase you will be reading the file using file I/O.

    So then actually the question is: What format is your output supposed to be in and where are you supposed to output it? I cannot see how dumping binary out to stdout would accomplish anything.
  24. #13
  25. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2011
    Posts
    54
    Rep Power
    3
    Originally Posted by dwise1_aol
    For an example of binary data going to stdout, use this command at the console command line:
    TYPE myprog.exe
    where "myprog.exe" is the name of your program's executable. What you will get is a bloody mess and, if you're lucky and there are some bytes in there set to 0x07, you will also hear beeps ('\7' is BEL).

    Is that what you want to output? stdin and stdout are really made for text, not for binary. For that matter, I suspect that your input will be likely to terminate prematurely in it happens to hit a byte of 0x1A, which should be Ctrl-Z, which marks end-of-file in MS-DOS; when using the MS-DOS "poor man's editor", COPY CON myfile.txt, you use Ctrl-Z to mark the end of your typing (my avatar alludes to using cat for the same purpose in UNIX).

    I'm assuming that you're to just use redirected input for getting the parsing of the header to work and not for processing the sound data and that in the next phase you will be reading the file using file I/O.

    So then actually the question is: What format is your output supposed to be in and where are you supposed to output it? I cannot see how dumping binary out to stdout would accomplish anything.
    Here is an example of part of the program we need to write.

    "Write two programs called “split” and “combine”. Split reads a mono stream in the format above from standard input and outputs the samples in stereo format to standard output by duplicating the mono channel into both stereo channels."
  26. #14
  27. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,091
    Rep Power
    2222
    OK, I just did a quick test case and found that Ctrl-Z has no effect when encountered while redirecting input, so that suspicion proved groundless.

    Still, outputting binary to stdout doesn't make any sense. Unless you're to always pipe it into another program (ie, piping is redirecting the output of one program to the input of another).

    At any rate, your specification is what it is.
  28. #15
  29. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2011
    Posts
    54
    Rep Power
    3
    Originally Posted by dwise1_aol
    OK, I just did a quick test case and found that Ctrl-Z has no effect when encountered while redirecting input, so that suspicion proved groundless.

    Still, outputting binary to stdout doesn't make any sense. Unless you're to always pipe it into another program (ie, piping is redirecting the output of one program to the input of another).

    At any rate, your specification is what it is.
    As far as this project goes, we will always be piping it into another program.

    Comments on this post

    • dwise1_aol agrees : OK. Now it makes sense.

IMN logo majestic logo threadwatch logo seochat tools logo