I'm trying to make a simple string acquisition. What i need is to write a string from input (stdin), which can contain spaces, and save it without any spaces between words.
So far i've written this simple code which saves everything (also spaces), but i don't know how to make the scanf()
ignore the spaces.
int main(){
char str[10];
scanf("%[^\n]s, str);
printf("%s", str;
}
For example:
if my input is: I love C programming!
my output should be: IloveCprogramming!
I tried to use %*
, used to ignore characters, but without any success.
I also know that i could "rescan" the string once is saved and remove all the spaces, but i need to do this acquisition as efficient as possible, and rescan every string to remove the spaces will increase the computational time a lot (instead of just scanning and ignoring, which has complexity of O(n))
So far i've written this simple code which saves everything (also spaces), but i don't know how to make the
scanf()
ignore the spaces.
You're coming at this from the opposite direction of what most new C programmers do. The problem is not usually to make scanf
skip spaces, as it does that by default for most types of field, and in particular for %s
fields. Spaces are ordinarily recognized as field delimiters, so not only are leading spaces skipped, but also spaces are not read inside fields. I presume that it is because you know this that you are using a %[
field.
But you cannot have your cake and eat it too. The field directive %[^\n]
says that the data to be read consist of a run of non-newline characters. scanf
will faithfully read all such characters and transfer them to the array you designate. You do not have the option to instruct scanf
to avoid transferring some of the characters that you told it were part of the field.
If you want to continue to use scanf
then you have two options:
Another answer already describes how to do the former. Here's how you might do the latter:
int main(void) {
int field_count;
do {
char str[80];
char tail;
field_count = scanf("%79[^ \n]%c", str, &tail));
if (field_count == 0) {
// No string was scanned this iteration: the first available char
// was a space or newline. Consume it, then proceed appropriately.
field_count = scanf("%c", &tail);
if (field_count != 1 || tail == '\n') {
// newline, end-of-file, or error: break out of the loop
break;
} // else it's a space -- ignore it
} else if (field_count > 0) {
// A string was scanned; print it:
printf("%s", str);
if (field_count == 2) {
// A trailing character was scanned, too; take appropriate action:
if (tail == '\n') {
break;
} else if (tail != ' ') {
putchar(tail);
} // else it is a space; ignore it
}
} // else field_count == EOF
} while (field_count != EOF);
}
Things to note:
scanf
%79[^ \n]
directive. Without a field width, there is a serious risk of overrunning your array bound (which must be at least one character longer than the field to allow for a string terminator).[
is a field type, not a qualifier. s
is a separate field type that also handles strings, but has different behavior; no s
field is used here.scanf
's return value tells you how many fields were successfully scanned, which can be fewer than are described in the format string in the event that a mismatch occurs between input and format, or the end of the input is reached, or an I/O error occurs. These possibilities need to be taken into account.%c
, is in fact scanned, it allows you to determine whether the preceding string field ended because the field width was exhausted without reaching a space or newline, because a space was observed, or because a newline was observed. Each of these cases requires different handling.scanf
skips leading whitespace for most field types, %[
and %c
fields are two of the three exceptions.' '
) specifically; it does not skip other whitespace characters such as horizontal and vertical tabs, carriage returns, form feeds, etc.. This approach could be adapted to handle those, too, but what is presented is sufficient to demonstrate.