Hey guys,

I have a couple of quick questions, Iv searched the forums and the internet and found a not very much on removing an array element. If you could guide me to a website or a book with information on char arrays it would be helpful.

My second question is this, I have a char array shown in code below and I want to remove spaces from the array. For example I have and array

char arr[] = {'a', 'b', 'c', ' ', ' ', ' ', ' ', ' ', 'd', 'e', 'f', '\0'};

How can I make it so that all the space from arr[4] to arr[7] are removed?

Below is the code I have tried, Im running a loop to go through the array and then when it hits a space search the next element to see if that is a space as well. If it is I want to copy all the remaining elements into the next space and repeat the loop.

I understand that you can't give code so I don't expect any just a little heading so I can figure out what Im doing wrong or not doing at all.

for(int i = 0; i <= x; i++)
	{
		if(arr[i] == ' '){
			if(arr[i + 1] == ' '){
				for(int j = i; j <= x; j++){
				arr[i] = arr[i + 1];
			}
			}
			//causes all values to be removed from the back of array
			//x--;
		}
	}

Recommended Answers

All 13 Replies

Well, a simple way to achieve this would be to create another array, the same length as arr, go through each character, and if that character isn't a space then copy it to the second array. Like this.

#include <iostream>

int main() {
   char arr[] = "abc     def";

   // Create another array the same length as arr
   char temp[sizeof arr];

   // Index of where to insert character in new array
   int temp_index = 0;

   // Loop through each character until null-terminator is reached
   for (int i = 0; arr[i]; ++i) {
      if (arr[i] != ' ') {
         // Character isn't a space
         temp[temp_index++] = arr[i];
      }
   }

   // Add null-terminator
   temp[temp_index] = '\0';

   // Replace old array with new one
   strcpy_s(arr, sizeof(arr), temp);

   // Display the array
   std::cout << arr;

   // Pause
   std::cin.ignore();
   return 0;
}

But if you wanted to achieve this without the need of a second array, its going to require a more complex algorithm. Hope this helps, and I also hope I haven't given too much away :)

you can use memmove() to shift everything left one place to overwrite the second consecutive space.

char str[] = "Hello  World";
char* p = str;
while( !isspace(*p) )
   p++;
if( isspace(*p) && isspace(*(p+1)) )
   memmove(p+1, p+2, strlen(p+2) + 1); // + 1 to also move the NULL terminator

Here is a C++ solution to your problem using std::strings.

#include <string>
#include <iostream>
using namespace std;

int main()
{
    char arr[] = {'a', 'b', 'c', ' ', ' ', ' ',
                  ' ', ' ', 'd', 'e', 'f', '\0'};

    string s(arr);
    string tmp = "";

    for(int i = 0; i < s.length(); i++)
    {
        if( s.at(i) != ' ' )
	    tmp += s.at(i);
    }

    s = tmp;

    cout << s << endl;

    return 0;
}

At this point you could also iterate back over the array and write the new values from the string, and set the remaining elements to null. Alternatively, you could continue using std::string in favor of character arrays.

Furthermore, I believe that there is a very trivial way of removing whitespace from std::strings involving streams, but I'll leave that as an exercise to the reader.

Cheers.

(Sidenote: Is there an easy way to insert a tab into this response window without it simply tabbing to the next element on the web page? Also, can it be set to parse tabs as four spaces, not eight?)

you can use memmove() to shift everything left one place to overwrite the second consecutive space.

char str[] = "Hello  World";
char* p = str;
while( !isspace(*p) )
   p++;
if( isspace(*p) && isspace(*(p+1)) )
   memmove(p+1, p+2, strlen(p+2) + 1); // + 1 to also move the NULL terminator

You might need to revise this, as it will only remove one white-space. Not to mention the use of these tools for what should be simple strings is pretty dangerous!

How about this, based on the idea of the bubble sort?

void compact( char arr[], int size )
{
	int i, j;
	
	for( i = 1; i < size; i++ )
	{
		for( j = 1; j < size - i; j++ )
		{
			if( arr[j-1] == ' ' )
			{
				arr[j-1] = arr[j];
				arr[j] = ' ';
			}
				
		}
	}
}

(yeah, I know there will be those of you deriding bubble sort in any form, but, it works!)

You might need to revise this, as it will only remove one white-space.

That code must be put in a loop in order to remove other instances of multiple white spaces. I did not intend to post the entire solution, only a suggestion about how to go about solving it.

Not to mention the use of these tools for what should be simple strings is pretty dangerous!

memmove() is intended only for character arrays, not std::string. All C style string functions can be dangerous if the programmer uses them in a haphazard manner.

ninwa's solution uses the same technique as mine, but using std::string's instead. Though it might be a better idea, it may overall be slower. Just to check, I did I little test.

ninwa's version:

#include <iostream>
using namespace std;

typedef unsigned __int64 uint64;

inline __declspec(naked) uint64 GetCycleCount() {
    _asm rdtsc;
    _asm ret;
}

int main() {
   uint64 cycle_timer_beg;
   uint64 cycle_timer_end;

   cycle_timer_beg = GetCycleCount();

   for (int j = 0; j < 10000; ++j) {

         char arr[] = {'a', 'b', 'c', ' ', ' ', ' ',
                       ' ', ' ', 'd', 'e', 'f', '\0'};
         string s(arr);
         string tmp = "";
         for (int i = 0; i < s.length(); i++) {
            if (s.at(i) != ' ') {
               tmp += s.at(i);
            }
         }
         s = tmp;

   }

   cycle_timer_end = GetCycleCount();

   cout << "Average cycle count: " << ((cycle_timer_end - cycle_timer_beg) / 10000);
   cin.ignore();
   return 0;
}

My version:

#include <iostream>
using namespace std;

typedef unsigned __int64 uint64;

inline __declspec(naked) uint64 GetCycleCount() {
    _asm rdtsc;
    _asm ret;
}

int main() {
   uint64 cycle_timer_beg;
   uint64 cycle_timer_end;

   cycle_timer_beg = GetCycleCount();

   for (int j = 0; j < 10000; ++j) {

      char arr[] = "abc     def";
      char temp[sizeof arr];
      int temp_index = 0;
      for (int i = 0; arr[i]; ++i) {
         if (arr[i] != ' ') {
            temp[temp_index++] = arr[i];
         }
      }
      temp[temp_index] = '\0';
      strcpy_s(arr, sizeof(arr), temp);

   }

   cycle_timer_end = GetCycleCount();

   cout << "Average cycle count: " << ((cycle_timer_end - cycle_timer_beg) / 10000);
   cin.ignore();
   return 0;
}

Hopefully this isn't going over the top with comparison, but I got the following output:

ninwa's version. "Average cycle count: 917"
My version.      "Average cycle count: 106"

Thats over 8 times faster :) But ninwa's version I would say is more readable, even though it uses the same amount of code. Personally I prefer speed to readability, so I would stick with mine :icon_cheesygrin:

Is that inline assembly code I see in both your programs? I guess you don't code for portability so that the code can be compiled by other people using other operating systems and/or compilers. And I'm sure a programming teacher would deduct points for that, unless its required as part of the assignment.

>>Personally I prefer speed to readability
Depends. Maintainability (and readability) are pretty important in the real-world.

Portability isn't too important when it comes to making a quick speed test, as I woulden't be keeping it that way. Either way, if the code didn't compile for you, I posted my output :)

>Depends. Maintainability (and readability) are pretty important in the real-world.
Thats true

Thanks for all the suggestions. I was going to do a bubble sort as vmanes suggested, but I think williamhemsworth way of removing spaces using a temporary array maybe a better option as I can use it to remove and \t or \n by making them spaces.

I'll post my code as soon as I finish testing it.

If you want to remove mutliple characters from the array, you can simply change it like this.

#include <iostream>

// Returns true if text contains ch
inline bool contains(char *text, char ch) {
   while (*text) {
      if (*text++ == ch) {
         return true;
      }
   }
   return false;
}

int main() {
   char arr[] = "abc  \n   \t\ndef";
   char spaces[] = " \t\n";

   // Create another array the same length as arr
   char temp[sizeof arr];

   // Index of where to insert character in new array
   int temp_index = 0;

   // Loop through each character until null-terminator is reached
   for (int i = 0; arr[i]; ++i) {
      if (!contains(spaces, arr[i])) {
         // Character isn't in the spaces array
         temp[temp_index++] = arr[i];
      }
   }

   // Add null-terminator
   temp[temp_index] = '\0';

   // Replace old array with new one
   strcpy_s(arr, sizeof(arr), temp);

   // Display the array
   std::cout << arr; // Outputs "abcdef"

   // Pause
   std::cin.ignore();
   return 0;
}

Now this will check to see if any of the char's in arr contain any of the char's in spaces, if it does, then it will remove them from the arr array.

You people are making a mountain out of a molehill.

int main()
{
char arr[] = {'a', 'b', 'c', ' ', ' ', ' ', ' ', ' ', 'd', 'e', 'f', '\0'};
char *p1, *p2;

p1 = strchr(arr,' '); // find 1st space
p2 = strrchr(arr,' '); // find last space
if(p1 && p2)
   memmove(p1,p2+1,strlen(p2)+1); // remove all spaces
cout << arr << "\n";

}

I have just managed to finish my program, I was on the right track just needed help so thanks for everything. I should have been clear from the start that I wanted to separate the letters to make words but I figured it out it finally.

Predicting output to be: abc def ghi

The code I used was:

for(int i = 0; arr[i]; ++i){
		if(arr[i] != ' '){
			temp[temp_index++] = arr[i];
		}
			else if(arr[i] == ' ' && arr[i + 1] != ' '){
				temp[temp_index++] = arr[i];
			}
		else{
			;
		}
   }

Still needs a little ironing out but its mostly done :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.