Devin Moore Devin Moore - 2 months ago 7
C Question

Creating loops to read an ascii (.txt) file by piping it into a program and then outputting it into another file

I am trying to essentially pipe a .txt ascii file into a program. My program needs to be able read the lines upon lines of ascii code and then output what it reads into a file. At which point i will compare the file I just filled with ascii to another file which has the correct output of the file already using the diff command. I am really new to C (it's my third week, with once a week lab instruction time with my prof), and I feel I'm quite close to figuring this out, but i feel the nesting of my loops is off.

The three files I'm dealing with:
encoded_picture.txt
decoded_picture.txt
ascii_cat.txt

eg (encoded_picture.txt) Using

less


29: 1. 1 4. 36: 1. 1 4. 3 2. 1: 1. 5 1. 1: 1. 8: -1?
30: 2. 39: 1. 1 3. 3 4. 7 1. 6: 2. 1: -1?
12: 1. 58: 6. 2 2. 9 1. 6: 2. 1: -1?
12: 2. 57: 1. 1 3. 1 3. 11 1. 8: -1?
12: 3 1. 55: 2. 2 1. 1 2. 12 1. 8: -1?
12: 1. 3 1. 53: 1. 1 1. 1 4. 13 1. 8: -1?
12: 1. 5 51: 8. 15 8: -1?
13: 1. 1 2. 2 1. 49: 7. 5 2. 9 8: -1?
14: 2 2. 2 1. 48: 6. 6 3. 2 1. 5 8: -1?
14: 1. 2 2. 3 1. 45: 6. 8 3. 1 2. 4 8: -1?
15: 1. 1 3. 3 1. 44: 5. 7 2. 1 6. 2 1. 8: -1?
16: 1 4. 4 1. 41: 5. 5 6. 1 5. 2 1. 8: -1?
16: 6. 5 1. 38: 6. 3 8. 1 5. 2 1. 8: -1?
17: 6. 5 2. 35: 6. 3 9. 1 5. 2 1. 8: -1?
17: 7. 6 2. 32: 6. 5 8. 1 5. 2 1. 8: -1?
18: 7. 7 1. 30: 6. 5 7. 1: 1. 1 3. 1 1. 2 1. 8: -1?

eg. (decoded_picture.txt)

::::::::::::::::::::::::::::::.. .....:::::::::::::::::::::::::::::::::::::.. ..... ...::.. ..::..:::::::::
:::::::::::::::::::::::::::::::...::::::::::::::::::::::::::::::::::::::::.. .... ..... ..:::::::...::
:::::::::::::..:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::....... ... ..:::::::...::
:::::::::::::...::::::::::::::::::::::::::::::::::::::::::::::::::::::::::.. .... .... ..:::::::::
::::::::::::: ..::::::::::::::::::::::::::::::::::::::::::::::::::::::::... .. ... ..:::::::::
:::::::::::::.. ..::::::::::::::::::::::::::::::::::::::::::::::::::::::.. .. ..... ..:::::::::
:::::::::::::.. ::::::::::::::::::::::::::::::::::::::::::::::::::::......... :::::::::
::::::::::::::.. ... ..::::::::::::::::::::::::::::::::::::::::::::::::::........ ... :::::::::
::::::::::::::: ... ..:::::::::::::::::::::::::::::::::::::::::::::::::....... .... .. :::::::::
:::::::::::::::.. ... ..::::::::::::::::::::::::::::::::::::::::::::::....... .... ... :::::::::
::::::::::::::::.. .... ..:::::::::::::::::::::::::::::::::::::::::::::...... ... ....... ..:::::::::
::::::::::::::::: ..... ..::::::::::::::::::::::::::::::::::::::::::...... ....... ...... ..:::::::::
:::::::::::::::::....... ..:::::::::::::::::::::::::::::::::::::::....... ......... ...... ..:::::::::
::::::::::::::::::....... ...::::::::::::::::::::::::::::::::::::....... .......... ...... ..:::::::::
::::::::::::::::::........ ...:::::::::::::::::::::::::::::::::....... ......... ...... ..:::::::::
:::::::::::::::::::........ ..:::::::::::::::::::::::::::::::....... ........::.. .... .. ..:::::::::
:::::::::::::::::::.......... ..::::::::::::oooo:::::::ooo:::ooo:::...... .........::: .. .. ..:::::::::
::::::::::::::::::::......... ...::::::oooooOO&&OOooooOOooOOOOOOOOoo::..... ..........::.. .. ..:::::::::
::::::::::::::::::::..::::..::..... ...::::ooOO&&OOO&&&&OOOO&&&&&&&OOOOOooo::.. ...........::.. ..::..::..::::::
:::::::::::::::::::::::::::..::.... ....::oooOO&&&&&&&&&&&&&&&&OOOOooo::oo:: ....:::........ ..:::::..:::::
:::::::::::::::::::::::::::::::... ::::oooOO&&&&OO&&&&&&&&&&&&OOOOOoo::... ...:::::::..... ..:::::::..:::
:::::::::::::::::::::::::::::::::....::oooOOOO&&&&OO&&&&&&OO&&&&&OO&&OOOOooo::::.. ........::::.... ..::::::::..::
::::::::::::::::::::::::::oooo::::::ooooOOOO&&&&OOOOO&&&&&OO&&&&OOO&&&OOOoooooo:::.. .... .......:::... ::..::::::..::..
:::::::::::::::::::::::ooo:::::::::oooOOOOOO&&&&OOOOO&&&&&OO&&&&OOOO&&OOOOOoooo:::..:::.. ....::... .. ..:::...:::::..::
:::::::::::::::::::::ooo::::::::ooooOOoooOOOO&&&&&OOOOO&&&&&&&OO&&OOooOOOOOOOOOooo::ooo..... ... ..::.....:::....
:::::::::::::::::::::ooo::::::oo::ooOOOOOOOO&&OO&&OOOOoooOO&&&&OO&&OOO&&OOooOOOOOOOOOooooo:::::........... .....::.......
:::::::::::::::::::::oo::..::...::ooOOOOO&&&OO&&OO&&OO&&OOOOOOO&&&&OOOOOOOoooOOOOOOOOOOOoo::ooo::::... ..... ..::...........
:::::::::::::::::::::::....::oooOO&&&&&&&&OO&&OOOOOOoooOOOOOooOOOOOOooooOOOOOOOOOOoooooo::..... .. ..::......:::....
::::::::::::::::::::::...:::ooOOOO&&&&&&OOOOOOOOOOoooOOOOOooooOOoooooooOOOOOOOOOOoooooo:::.... .. ....::..::::::::
::::::::::::::::::::::....::OOO&&&&&&&&OOOOOOOOOoooo&&OOOoooooooooooooooOOooooOOOOoooooo::.... .... ...::....::::::::
:::::::::::::::::::::... ..::oo&&&&&&&OOOOOooOOOoooooooOOOOooooooo:::oooooooooooOOOOooOOoooo:::::.. ..::::...::::::::
::::::::::::::::::::::....::ooOO&&&&OOOOOOOooOOooooooooooOOoo::oo:::oo:::ooooooooooooOOoooOOoooooooo.. ..::::::..:::::::
::::::::::::::::::::::....::OOO&&&OOOOOOooOOoooo::ooooo::ooOOoooo:::::::::oooo::ooooooOOOOOOooooooo.. ..:::::...:::::::
::::::::::::::::::::::.. ...ooOOOOOOOoooooo::::oooo::..ooOOoooo::..:::::::::::oooooooOOOOOOOoooo::.. :::::::..:::::::
:::::::::::::::::::::::...::OOOOooooooooo:::..::ooo:::..::OOooo:::..:::::...:::::oooooooooOOooooooo::.. ..:::::::::::::..
:::::::::::::::::::::::::ooOOOoooooo:::ooo::...::oo::::..ooOOooo::....:::....::::::::ooooooooooooo:::.. ..::::::::.....:::
::::::::::::::::::::::::oooooooooo:::::....:::::...ooooo.....::::....::::..:::oooooooooooooo::.. ..::::::::::::oo:::
::::::::::::::::::::::::oooo:::ooooo::::.....:::::..::ooooOO::........ ...::...:::ooooooooooooo::.. ..::::::::ooo::oo::::
:::::::::::::::::::::::oooo:::::::::::.. :::::..::OO:::OO::........ .....:::::oooooooooooo:: ..::::::::oo::::::oo
::::::::::::::::::::::oooo::::::::::::.. ....::...OOoo:::OOoo..::.... .....:::::::::oooooooo::.. :::::::::oo::::::oo
:::::::::::::::::::ooooooo:::..::::::..::..........::OOoo:::OOO::..... ......:::::::::::oooooo::.. :::..:::...::::::...::
:::::::::::oo::::::::oooooo::....::..::oo:: ..........ooOOooooOOO:: ... .....:::::::..::::ooooooo::.. ..::..:::...::::::.. ..
::::::::::oooo::::::oooOOOOoo....:::..::oo.. :::......::OOOoooOO&&OO:: ....:::::.....::oooooooo::.. ...:::...:::::.....
::::::::ooooo:::::::ooOOOOoo::....:::..ooo.. ::&&oo.....::OOOooOO&&&OO:: ........ ...:::ooooooo::.. ....::...::..::::::..
::::::ooooooo::::::ooOOOOOoo::....::...:::.. ::&&oo.....::OO&&OO&&&&OO.. .. ..oo:: ... ..::::oooooo::......::...:::ooo::::..
::::::ooooo:::::::OOOOOOOoo::::..::: ... ..oo&&:::....::OO&&&&&OOoo.. ... ..::: .... ..::::ooooo:::::...ooo::ooo:::.....
:::::ooooo:::::::ooOOOOOOOoo:::::::..... ::&&OO..::.. ..::OO&&&&OOoo::.. .... ..::...........:::ooooooo::oo:::ooo:::........
::::ooooo:::::::ooOOOOOOOOOoo:::..:::.. ....::oo.......OO&&&&&OOoo::.. ..::.. .............::::oooooooooo::...........
:::oooooooooo::oooOOOOOOOOOoo::........ ......::...::oo&&&&&&OOO::.. ....::: ... ...........:::ooooooooo::...... .....
:::oooOOooooo::::ooOOOOOOOOOOoo::......:::...:::...::...ooOO&&&&&&OOOoo::.. ....::::.. ... ...........:::::ooooooo:::...... ......
::oooooo::::...::OOOOOOOOOOOoo::......:::::........ooOO&&&&OOOOOoo::.. .....::..... ..........::::::oooooo:::..... .......
ESC

At this point in the command line i would compile and then:

./a.out < encoded_picture.txt > decoded_picture.txt


And then to compare to see if it work:

diff decoded_picture.txt ascii_cat.txt


At this point i know that if
diff
displays an output, I've done it wrong.

Any help would be appreciated (actual program part3_file.c).

int length;
int i;
// loop until the end of input sentinel is seen
while (1)
{
// get the first element in the line
scanf("%d%c", &length, &character);
if(length == -1)
{
break;
}
else
{
// is it the sentinel? if so, then break out of the loop
// reconstruct a line, as per part 2
while ( length != -1 )
{
for( i = 0; i<= length; i++)
{
printf("%c", character);
}
scanf("%d%c", &length, &character);
}
printf("\n");
}
}
return 0;

Answer

If I understand your question and you want to read encoded_picture.txt from stdin and then based on each encoded pair 'lc' (that's l as in length and c as in character) output l number of characters c to stdout until length is -1 where a '\n' is output, then you are on the right track. However your loop logic is a bit strange.

You can use your scanf format string "%d%c". However, you always, always want to check the return of scanf to validate the expected number of conversions took place. For example, to read each pair until end of file is encountered you can do something like the following:

    while (scanf ("%d%c", &l, &c) == 2) {

Your next task, to repeatedly output the specified number of characters, you can simply do:

        for (int i = 0; i < l; i++)
            printf ("%c", c);

(if l == -1 the loop will not execute anyway, also note: the loop is i < l for l characters, where i <= l would result in l+1 chars)

Your final task is to control the output of the newline in the event l == -1,

        if (l == -1)
            putchar ('\n');

Putting it together, you could do something like:

#include <stdio.h>

int main (void) {

    int l;
    char c;

    while (scanf ("%d%c", &l, &c) == 2) {
        for (int i = 0; i < l; i++)
            printf ("%c", c);
        if (l == -1)
            putchar ('\n');
    }

    return 0;
}

Example Use/Output

Based on the encoded_picture.txt text you provided, that would result in something like the following (that looks like the start of Ratchet's ears):

$ ./bin/decodpic <dat/encpic.txt
:::::::::::::::::::::::::::::. ....::::::::::::::::::::::::::::::::::::. ....   ..:.     .:.::::::::
::::::::::::::::::::::::::::::..:::::::::::::::::::::::::::::::::::::::. ...   ....       .::::::..:
::::::::::::.::::::::::::::::::::::::::::::::::::::::::::::::::::::::::......  ..         .::::::..:
::::::::::::..:::::::::::::::::::::::::::::::::::::::::::::::::::::::::. ... ...           .::::::::
::::::::::::   .:::::::::::::::::::::::::::::::::::::::::::::::::::::::..  . ..            .::::::::
::::::::::::.   .:::::::::::::::::::::::::::::::::::::::::::::::::::::. . ....             .::::::::
::::::::::::.     :::::::::::::::::::::::::::::::::::::::::::::::::::........               ::::::::
:::::::::::::. ..  .:::::::::::::::::::::::::::::::::::::::::::::::::.......     ..         ::::::::
::::::::::::::  ..  .::::::::::::::::::::::::::::::::::::::::::::::::......      ...  .     ::::::::
::::::::::::::.  ..   .:::::::::::::::::::::::::::::::::::::::::::::......        ... ..    ::::::::
:::::::::::::::. ...   .::::::::::::::::::::::::::::::::::::::::::::.....       .. ......  .::::::::
:::::::::::::::: ....    .:::::::::::::::::::::::::::::::::::::::::.....     ...... .....  .::::::::
::::::::::::::::......     .::::::::::::::::::::::::::::::::::::::......   ........ .....  .::::::::
:::::::::::::::::......     ..:::::::::::::::::::::::::::::::::::......   ......... .....  .::::::::
:::::::::::::::::.......      ..::::::::::::::::::::::::::::::::......     ........ .....  .::::::::
::::::::::::::::::.......       .::::::::::::::::::::::::::::::......     .......:. ... .  .::::::::

Look things over and let me know if I misunderstood or if you have questions.


Writing Output WITHOUT a final POSIX line-end

While this is improper, the decoded_picture.txt does not contain a POSIX line-end. If you run the first version of my code, and then use diff -uNb decoded_picture.txt the_output.txt you find the only difference is my code properly includes a POSIX line-end (e.g. '\n') after the final line written. You can dupe the code into not writing a POSIX line-end by setting a toggle to only write the newline if characters were previously written in that line. That effectively prevent a final newline. You can do that as follows:

#include <stdio.h>

int main (void) {

    int l, flag = 1;
    char c;

    while (scanf ("%d%c", &l, &c) == 2) {
        for (int i = 0; i < l; i++)
            printf ("%c", c);
        if (l == -1) {
            if (flag) {
                putchar ('\n');
                flag = 0;
            }
        }
        else
            flag = 1;
    }

    return 0;
}

Result

Then testing the code and output, you find the following:

$ gcc -Wall -Wextra -pedantic -std=gnu11 -Ofast -o bin/decodpic2 decodpic2.c
$ ./bin/decodpic2 <dat/encoded_picture.txt > dat/decode2.txt
$ diff -uNb dat/decoded_picture.txt dat/decode2.txt
(no output, the files match :)

While there is educational use in forcing a final write without a POSIX line-end -- do not do this is real life :)