Question

I apologize in advance for any orthographic or grammatical error due to the fact that English is not my mother tongue.

I'm new to HTML and I've made a C program to automate a repetitive encoding (creating button spoilers, asking for the hidden content and what's written on the button each time)

The thing is that I've been forced to convert all the text (array of char) I wanted to write in hexadecimal because it contained some of the reserved characters of C language...

The program runs smoothly and fits my needs for the moment but I'd like to know if there is another way than converting everything into hex.

Also, gcc gives me this warning twice :

format ‘%s’ expects argument of type ‘char ’, but argument 2 has type ‘char ()[50]’ [-Wformat]

after these kinds of lines :

scanf("%s", &hidden_text);

(hidden_text is an array of char initialized like :

char hidden_text[50];)

how do I fix that warning ? passing a %50s to scanf didn't work (the program ran but this warning bothers me and I'd be glad if anyone tell me a way out of it)

If anyone see a way of upgrading that program or have any hint, please help out the new programmer I am. (just for the record, I'm using linux, Emacs is my IDE and I'm using gcc to compile)

Here is the source code (hope I don't get reported for posting too much text):

#include<stdlib.h>
#include<stdio.h>
#include<string.h> /*strlen use this*/
int number_of_spoilers=10; /* the number of spoiler buttons you want to create (changed that value so you can test fast)*/
int a=0;
int spoiler=0; /*the spoiler Id I need to pass between each part*/
char part0[14]="\x3c\x68\x74\x6d\x6c\x3e\x0d\x0a\x3c\x62\x6f\x64\x79\x3e";
char part1[9]="\x3c\x64\x69\x76\x20\x69\x64\x3d\x22"; 
char part2[23]="\x22\x20\x73\x74\x79\x6c\x65\x3d\x22\x64\x69\x73\x70\x6c\x61\x79\x3a\x6e\x6f\x6e\x65\x22\x3e"; 
char hidden_text[50];
char part3[100]="\x3c\x2f\x64\x69\x76\x3e\x3c\x62\x75\x74\x74\x6f\x6e\x20\x74\x69\x74\x6c\x65\x3d\x22\x43\x6c\x69\x63\x6b\x20\x74\x6f\x20\x73\x68\x6f\x77\x2f\x68\x69\x64\x65\x20\x63\x6f\x6e\x74\x65\x6e\x74\x22\x20\x74\x79\x70\x65\x3d\x22\x62\x75\x74\x74\x6f\x6e\x22\x20\x6f\x6e\x63\x6c\x69\x63\x6b\x3d\x22\x69\x66\x28\x64\x6f\x63\x75\x6d\x65\x6e\x74\x2e\x67\x65\x74\x45\x6c\x65\x6d\x65\x6e\x74\x42\x79\x49\x64\x28\x27";
char part4[53]="\x27\x29\x20\x2e\x73\x74\x79\x6c\x65\x2e\x64\x69\x73\x70\x6c\x61\x79\x3d\x3d\x27\x6e\x6f\x6e\x65\x27\x29\x20\x7b\x64\x6f\x63\x75\x6d\x65\x6e\x74\x2e\x67\x65\x74\x45\x6c\x65\x6d\x65\x6e\x74\x42\x79\x49\x64\x28\x27";
char part5[51]="\x27\x29\x20\x2e\x73\x74\x79\x6c\x65\x2e\x64\x69\x73\x70\x6c\x61\x79\x3d\x27\x27\x7d\x65\x6c\x73\x65\x7b\x64\x6f\x63\x75\x6d\x65\x6e\x74\x2e\x67\x65\x74\x45\x6c\x65\x6d\x65\x6e\x74\x42\x79\x49\x64\x28\x27";
char part6[27]="\x27\x29\x20\x2e\x73\x74\x79\x6c\x65\x2e\x64\x69\x73\x70\x6c\x61\x79\x3d\x27\x6e\x6f\x6e\x65\x27\x7d\x22\x3e";
char button_text[50];
char part7[9]="\x3c\x2f\x62\x75\x74\x74\x6f\x6e\x3e";
char part_end[16]="\x3c\x2f\x68\x74\x6d\x6c\x3e\x0d\x0a\x3c\x2f\x62\x6f\x64\x79\x3e";
FILE *f=NULL;
main(FILE *f)
{
    f=fopen("/home/Spoilers.html","a");
    if(f==NULL)
        printf("Can't open file");
    else{
        fwrite(part0, sizeof(char), 14,f);
        while(a!=number_of_spoilers){
            printf("%s","button text ? :");
            scanf("%s", &button_text);

            printf("%s", "hidden text ? :");
            scanf("%s", &hidden_text);

            fwrite(part1, sizeof(char), 9,f); 
            char hex[5];
            sprintf(hex, "%x", spoiler); /*change the spoilerId value to hexa*/
            fwrite(&hex, sizeof(char), strlen(hex),f);

            fwrite(part2, sizeof(char), 23,f);
            fwrite(hidden_text, sizeof(char), strlen(hidden_text),f);

            fwrite(part3, sizeof(char), 100,f);
            fwrite(&hex, sizeof(char), strlen(hex),f);

            fwrite(part4, sizeof(char), 53,f);
            fwrite(&hex, sizeof(char), strlen(hex),f);

            fwrite(part5, sizeof(char), 51,f);
            fwrite(&hex, sizeof(char), strlen(hex),f);

            fwrite(part6, sizeof(char), 27,f);
            fwrite(button_text, sizeof(char), strlen(button_text),f);

            fwrite(part7, sizeof(char), 9, f);

            a=a+1; spoiler=spoiler+1;
        }
        fwrite(part_end, sizeof(char), 16,f); /*contain "</body></html>"*/
        fclose(f);
    }
}

Thanks by advance and have a good day (or night) !!

Was it helpful?

Solution

If you use scanf( "%s", ... ), the expcected argument is a char * because it just needs the address to copy the input into. If you declare char hidden_text[50]; then hidden_text already is the (constant) pointer to that array. So you have to call

scanf( "%s", hidden_text );

not

scanf( "%s", &hidden_text );

Even better is calling

scanf( "%49s", hidden_text );

to prevent your progam from crashing if the input is too long (note that the length within the format string doesn't include the terminating '\0').

OTHER TIPS

Please try

scanf("%s", &hidden_text[0]);

because you have to pass the address of the first character of the string.

Others have already pointed out the cause of the warning with scanf. Your program has other issues, most of them stylistic.

  • You are not using a legal form of ´main´ - This should also give a warning in gcc:

    main(FILE *f) ...
    

    The function main is special in that it can only have certain signatures. Passing in a file handle is not one of them. (You're also masking your global variable FILE *f, which doesn't hurt in your case, but that's probably not what you wanted.) In your case, where you don't use any command-line arguments, you should use:

    int main() ...
    
  • Your output is text, so you should use the output functions suited for null-terminated strings, fprintf, putc or fputs. The function fwrite writes raw data lof a certain length and can be used, but you'll always have to pass the correct string length. Speaking of which: Passing constant string lengths to hex-encoded strings like this:

    fwrite(part2, sizeof(char), 23,f);
    

    is recipe for disaster: What if your string changes? You'll have to update the call, too. You should at least use strlen(part2) instead of the constant 23.

  • You read your input with scanf. This is okay, but maybe not the best way: The strings scanned with scanf cannot contain spaces, they are, in effect, single words. You can use the %[...] syntax to specify which characers to read, but that's complicated in my opinion. I propose using fgets, which reads a whole line. (The resulting string does have a trailing newline, which you should remove before processing.)

  • The number of buttons is fixed in your program. That's okay for a simple program, but ultimately you want the number of buttons to be flexible. It would therefore be better to read until the end of input (Ctrl-D on Unix, Ctrl-Z on Windows). The input functions return special values to indicate the the end of input has been reached: scanf returns EOF and fgets returns NULL in that case.

  • The strings you write out as spoiler and button text should be "sanitised", i.e. characters that are special to HTML should be masked, such that the input <copy & paste> reads &lt;copy &amp; paste&gt; in the output file.

  • And a final note: You write out the (longish) code to show and hide buttons for every button. You could shorten that by writing a function for this once and then calling that function.

Putting all that together, your program might now look like this:

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

void print_html(FILE *f, const char *str)
{
    while (*str) {
        switch (*str) {
        case '<':   fprintf(f, "&lt;"); break;
        case '>':   fprintf(f, "&gt;"); break;
        case '&':   fprintf(f, "&amp;"); break;
        default:    putc(*str, f);
        }
        str++;
    }
}

int main()
{
    FILE *f = fopen("Spoilers.html", "w");
    int elid = 0;

    if (f == NULL) {
        fprintf(stderr, "Can't open file\n");
        exit(0);
    }

    fprintf(f, "<html>\n<head>\n");
    fprintf(f, "<script type=\"text/javascript\">\n");
    fprintf(f, "    function show_hide(elid) {\n");
    fprintf(f, "        var el = document.getElementById(elid);\n");
    fprintf(f, "        if (el) {\n");
    fprintf(f, "            if (el.style.display == 'none') {\n");
    fprintf(f, "                el.style.display = '';\n");
    fprintf(f, "            } else {\n");
    fprintf(f, "                el.style.display = 'none';\n");
    fprintf(f, "            }\n");
    fprintf(f, "        }\n");
    fprintf(f, "    }\n");
    fprintf(f, "</script>\n");
    fprintf(f, "</head>\n<body>\n");

    for (;;) {
        char button[50];
        char hidden[50];

        if (fgets(button, 50, stdin) == NULL) break;
        button[strlen(button) - 1] = '\0';

        if (fgets(hidden, 50, stdin) == NULL) break;
        hidden[strlen(hidden) - 1] = '\0';

        fprintf(f, "<div id=\"%04x\" style=\"display:none\">", elid);
        print_html(f, hidden);
        fprintf(f, "</div><button title=\"Click to show/hide content\" "
            "type=\"button\" onclick=\"show_hide('%04x')\">", elid);
        print_html(f, button);
        fprintf(f, "</button>\n");
        elid++;        
    }
    fprintf(f, "</body>\n</html>\n");
    fclose(f);

    return 0;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top