Thanks, Glenn. I think using N is a good idea.
In the versions below, I also convert the output to a string. The form with the second argument always outputs n digit precision, regardless of the true precision of x.
I still think my solution less than elegant. Considering the need to interface with antiquated programming methods, it would be nice if WL offered built-in functions to emulate the behavior of Fortran formatted IO and also printf and scanf from C and its derivatives.
(* String reprsenting x in E format *)
fForm[x_] :=
ScientificForm[N[x],
NumberFormat -> (Row[{#1, "e", If[#3 == "", "0", #3]}] & )] //
ToString
(* The same, with n digits *)
fForm[x_, n_Integer] :=
ScientificForm[SetPrecision[N[x], n], n,
NumberFormat -> (Row[{#1, "e", If[#3 == "", "0", #3]}] & )] //
ToString