(This is pointed out in a comment by Zan Lynx, but I think it deserves an answer - given that the accepted answer doesn't mention it).
The essential difference between puts(mystr); and printf(mystr); is that in the latter the argument is interpreted as a formatting string. The result will be often the same (except for the added newline) if the string doesn't contain any control characters (%) but if you cannot rely on that (if mystr is a variable instead of a literal), you should  not use it.
So, it's generally dangerous - and conceptually wrong - to pass a dynamic string as single argument of printf:
char * myMessage;
// ... myMessage gets assigned at runtime, unpredictable content
printf(myMessage);  // <--- WRONG! (what if myMessage contains a '%' char?)
puts(myMessage);    // ok 
printf("%s\n",myMessage); // ok, equivalent to the previous, perhaps less efficient
The same applies to fputs vs fprintf (but fputs doesn't add the newline).