Note to self: write a whole chapter on the preprocessor for the C and C++ tutorials. An early chapter.
Yes, but the 'with' and 'use' statements in Ada actually work rather differently than C '#include' directives. Not only does it work in a diferent manner, to actual behavior is different.
The first thing you have to understand is the the '#include' statement in C is actually a preprocessor directive, not a part of the language as it is compiled. The C preprocessor reads the entire source code before the compiler does, and makes
textual changes to the code based on the directives and macros used. The 'textual' part is important; with the exception of #pragma directives, all of the effects of the preprocessor directives are on the source code itself. The #include directive, specifically, has the effect of 'replace this statement with the contents of the a named file'. It can, technically speaking, be any valid C source file; the usage of header files and separate declarations is a convention, albeit one borne out of long practice and many hard lessons.
The Ada 'with' and 'use' statements work differently. When an Ada program is compiled, a secondary file (or a special part of the object file, depending on the compiler) is generated, which contains all of the information about the publically accessible function and type declarations in the package (it is partly to make this process easier that Ada requires separate declaration and definition file sections). Unlike the C headers, this is not itself an Ada source file, but a data table of some sort, often in a binary format.
When a package makes a 'with' or statement, the compiler itself - not a preprocessor - checks the declaration data for the package in question, reading it from the compiled import file. While this is in some ways analogous to the #include directive, it works in a very different way. It also has the effect of a 'use namespace' directive in C++, in that it controls the visibility of a package's contents.
Ada's 'uses' directive has no exact equivalent in C, being (IIRC) a linker directive; it indicates that the functions in question should be linked to the file.
As for why you need several statements for even simple tasks, that's for two reasons. First, you need both a 'with' statement and a 'uses' statement for any package you intend to import (though if you are only using a few individual function calls from a package, it may be better to use the [tt]package.function[/tt] scoping syntax instead and not bother importing the whole package). I seem to recall that it is possible to use a 'with' statement alone, if you are importing a data structure or set of constants without any associated functions, but if so, it is rarely done. Second, the Ada libraries are designed to be much finer-grained than those in C; you need to use more import statements to get all the functions you need. Lastly, technically speaking, all of the basic data types ('character', 'integer', etc.) are defined in their own packages, not as part of the language per se; thus, just to use the basic data types requires one or more imports.
I could also add that the Java 'import' directive, the 'import/export' directives in Modula 2 and it's successors, and similar constructs in Eiffel, Sather, et. al., are generally closer to the Ada constructs than the C ones, though each has it's own quirks.
I advise you to take these assertions with a grain of salt, since they are based on recollections from the late 1980s, which may be incorrect. Also, I know that Ada has undergone a major revision (Ada 95) since I last studied it seriously. You may want to check the Ada references at
http://www.adapower.com/ to get the accurate explanations. C&CW.