Reputation: 55
so I'm trying to create a program which looks at a string defined in main, and deletes any non-alphabetical characters (excluding \0). So far this is my code:
/* Write code to which considers the string currently saved
* in the 'name' array, removes all spaces and non-alphabetical
* chars from the string, and makes all alphabetical characters
* lower case. */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define NAMELEN 30
int main (void) {
char name[NAMELEN];
strcpy(name, " William B. Gates");
int i, length, check;
length = strlen(name);
for ( i = 0; i < length; i++ ) {
check = isalpha(name[i]);
if ( check == 0 ) {
for ( ; i < length; i++ ) {
name[i] = name[i+1];
}
}
}
printf("The length is %lu.\n", strlen(name));
printf("Name after compression: %s\n", name);
return EXIT_SUCCESS;
}
So for the test data, " William B. Gates", the output should be "WilliamBGates", unfortunately the output I'm getting is:
The length is 16.
Name after compression: William B. Gates
I think the space before William has been deleted, but I'm unable to tell. Thanks for any help!
Upvotes: 2
Views: 603
Reputation: 16540
The posted code tries to hard.
The following code
notice the simplicity of the code, and all performed in only one pass through the name[] array.
#include <stdio.h>
#include <ctype.h>
int main( void )
{
char name[] = " William B. Gates";
printf( "\"%s\"\n", name );
size_t src = 0;
size_t dest = 0;
for( ; name[src]; src++) // will exit loop when string terminator '\0' encountered
{
if( isalpha(name[src]) )
{ // then current char is: a...zA...Z
name[dest] = tolower(name[src]); // force lower case
dest++; // update where to save next character
}
}
name[dest] = '\0'; // terminate the modified string
printf( "\"%s\"\n", name );
return 0;
} // end function: main
Upvotes: 1
Reputation: 66244
You don't need a complicated double-loop for this at all. The purpose of the exercise is to maintain independent source-reader and destination-writer, only copying and advancing the latter when the former is qualified by your criteria (i.e. it answers true to isalpha
).
in other words:
#include <stdio.h>
#include <ctype.h>
int main (void)
{
char name[] = " William B. Gates";
char *dst = name, *src;
for (src = name; *src; ++src)
{
if (isalpha((unsigned char)*src))
*dst++ = *src;
}
*dst = 0; // terminate the string
printf("result: %s\n", name);
}
Output
result: WilliamBGates
I leave translating to lower case during the copy-step as an exercise for you. (from your in-code comment: "makes all alphabetical characters lower case").
Upvotes: 7
Reputation: 311088
This inner loop is wrong
if ( check == 0 ) {
for ( ; i < length; i++ ) {
name[i] = name[i+1];
}
It copies the string in itself excluding the first character and after that your program does nothing because i is already equal to length.
So the program only removes one non-alpha character from the string.
When you are going to traverse a string sequantially then there is no need to calculate its length. The program can be written simpler or at least you may use the approach that is demonstrated below. For example
#include <stdio.h>
#include <ctype.h>
int main( void )
{
char name[] = " William B. Gates";
printf( "\"%s\"\n", name );
size_t j = 0;
for ( size_t i = 0; name[i] != '\0'; i++ )
{
if ( isalpha( ( unsigned char )name[i] ) )
{
if ( j != i ) name[j] = name[i];
++j;
}
}
name[j] = '\0';
printf( "\"%s\"\n", name );
}
The program output is
" William B. Gates"
"WilliamBGates"
Upvotes: 6