This is the problem that will never end. The task is to parse a request line in a web server -- of indeterminate length -- in C. I pulled the following off of the web as an example with which to work.
GET /path/script.cgi?field1=value1&field2=value2 HTTP/1.1
I must extract the absolute path: /path/script.cgi and the query: ?field1=value1&field2=value2. I'm told the following functions hold the key: strchr, strcpy, strncmp, strncpy, and/or strstr.
Here's what has happened so far: I've learned that using functions like strchr and strstr will absolutely allow me to truncate the request line at certain points, but will never allow me to get rid of portions of the request line I do not want, and it doesn't matter how I layer them.
For example, here's some code that get's me close to isolating the query, but I can't eliminate the http version.
bool parse(const char* line)
{
// request line w/o method
const char ch = '/';
char* lineptr = strchr(line, ch);
// request line w/ query and HTTP version
char ch_1 = '?';
char* lineptr_1 = strchr(lineptr, ch_1);
// request line w/o query
char ch_2 = ' ';
char* lineptr_2 = strchr(lineptr_1, ch_2);
printf("%s\n", lineptr_2);
if (lineptr_2 != NULL)
return true;
else
return false;
}
Needless to say, I have a similar issue trying to isolate the absolute path (I can ditch the method, but not the ? or anything thereafter), and I see no occasion on which I can use the functions that require me to know a priori how many chars I'd like to copy from one location (usually an array) to another because, when this is run in real time, I will have no clue what the request line will look like in advance. If someone sees something that I am missing and could point me in the right direction, I would be most grateful!
A more elegant solution.
#include <stdio.h>
#include <string.h>
int parse(const char* line)
{
/* Find out where everything is */
const char *start_of_path = strchr(line, ' ') + 1;
const char *start_of_query = strchr(start_of_path, '?');
const char *end_of_query = strchr(start_of_query, ' ');
/* Get the right amount of memory */
char path[start_of_query - start_of_path];
char query[end_of_query - start_of_query];
/* Copy the strings into our memory */
strncpy(path, start_of_path, start_of_query - start_of_path);
strncpy(query, start_of_query, end_of_query - start_of_query);
/* Null terminators (because strncpy does not provide them) */
path[sizeof(path)] = 0;
query[sizeof(query)] = 0;
/*Print */
printf("%s\n", query, sizeof(query));
printf("%s\n", path, sizeof(path));
}
int main(void)
{
parse("GET /path/script.cgi?field1=value1&field2=value2 HTTP/1.1");
return 0;
}
I wrote some functions in C a while back that manually parse c-strings up to a delimiter, similar to getline in C++.
// Trims all leading whitespace along with consecutive whitespace from provided cstring into destination char*. WARNING: ensure size <= sizeof(destination)
void Trim(char* destination, char* source, int size)
{
bool trim = true;
int index = 0;
int i;
for (i = 0; i < size; ++i)
{
if (source[i] == '\n' || source[i] == '\0')
{
destination[index++] = '\0';
break;
}
else if (source[i] != ' ' && source[i] != '\t')
{
destination[index++] = source[i];
trim = false;
}
else if (trim)
continue;
else
{
if (index > 0 && destination[index - 1] != ' ')
destination[index++] = ' ';
}
}
}
// Parses text up to the provided delimiter (or newline) into the destination char*. WARNING: ensure size <= sizeof(destination)
void ParseUpToSymbol(char* destination, char* source, int size, char delimiter)
{
int index = 0;
int i;
for (i = 0; i < size; ++i)
{
if (source[i] != delimiter && source[i] != '\n' && source[i] != '\0' && source[i] != ' '))
{
destination[index++] = source[i];
}
else
{
destination[i] = '\0';
break;
}
}
Trim(destination, destination, size);
}
Then you could parse your c-string with something along these lines:
char* buffer = (char*)malloc(64);
char* temp = (char*)malloc(256);
strcpy(temp, "GET /path/script.cgi?field1=value1&field2=value2 HTTP/1.1");
Trim(temp, temp, 256);
ParseUpToSymbol(buffer, cstr, 64, '?');
temp = temp + strlen(buffer) + 1;
Trim(temp, temp, 256);
The code above trims any leading and trailing whitespace from the target string, in this case "GET /path/script.cgi?field1=value1&field2=value2 HTTP/1.1", and then stores the parsed value into the variable buffer. Running this the first time should put the word "GET" inside of buffer. When you do the "temp = temp + strlen(buffer) + 1" you are readjusting the temp char-pointer so you can call ParseUpToSymbol again with the remaining part of the string. If you were to call it again, you should get the absolute path leading up to the first question mark. You could repeat this to get each individual query string or change the delimiter to a space and get the entire query string portion of the URL. I think you get the idea. This is just one of many solutions of course.
Related
What is the easiest and most efficient way to remove spaces from a string in C?
Easiest and most efficient don't usually go together…
Here's a possible solution for in-place removal:
void remove_spaces(char* s) {
char* d = s;
do {
while (*d == ' ') {
++d;
}
} while (*s++ = *d++);
}
Here's a very compact, but entirely correct version:
do while(isspace(*s)) s++; while(*d++ = *s++);
And here, just for my amusement, are code-golfed versions that aren't entirely correct, and get commenters upset.
If you can risk some undefined behavior, and never have empty strings, you can get rid of the body:
while(*(d+=!isspace(*s++)) = *s);
Heck, if by space you mean just space character:
while(*(d+=*s++!=' ')=*s);
Don't use that in production :)
As we can see from the answers posted, this is surprisingly not a trivial task. When faced with a task like this, it would seem that many programmers choose to throw common sense out the window, in order to produce the most obscure snippet they possibly can come up with.
Things to consider:
You will want to make a copy of the string, with spaces removed. Modifying the passed string is bad practice, it may be a string literal. Also, there are sometimes benefits of treating strings as immutable objects.
You cannot assume that the source string is not empty. It may contain nothing but a single null termination character.
The destination buffer can contain any uninitialized garbage when the function is called. Checking it for null termination doesn't make any sense.
Source code documentation should state that the destination buffer needs to be large enough to contain the trimmed string. Easiest way to do so is to make it as large as the untrimmed string.
The destination buffer needs to hold a null terminated string with no spaces when the function is done.
Consider if you wish to remove all white space characters or just spaces ' '.
C programming isn't a competition over who can squeeze in as many operators on a single line as possible. It is rather the opposite, a good C program contains readable code (always the single-most important quality) without sacrificing program efficiency (somewhat important).
For this reason, you get no bonus points for hiding the insertion of null termination of the destination string, by letting it be part of the copying code. Instead, make the null termination insertion explicit, to show that you haven't just managed to get it right by accident.
What I would do:
void remove_spaces (char* restrict str_trimmed, const char* restrict str_untrimmed)
{
while (*str_untrimmed != '\0')
{
if(!isspace(*str_untrimmed))
{
*str_trimmed = *str_untrimmed;
str_trimmed++;
}
str_untrimmed++;
}
*str_trimmed = '\0';
}
In this code, the source string "str_untrimmed" is left untouched, which is guaranteed by using proper const correctness. It does not crash if the source string contains nothing but a null termination. It always null terminates the destination string.
Memory allocation is left to the caller. The algorithm should only focus on doing its intended work. It removes all white spaces.
There are no subtle tricks in the code. It does not try to squeeze in as many operators as possible on a single line. It will make a very poor candidate for the IOCCC. Yet it will yield pretty much the same machine code as the more obscure one-liner versions.
When copying something, you can however optimize a bit by declaring both pointers as restrict, which is a contract between the programmer and the compiler, where the programmer guarantees that the destination and source are not the same address. This allows more efficient optimization, since the compiler can then copy straight from source to destination without temporary memory in between.
In C, you can replace some strings in-place, for example a string returned by strdup():
char *str = strdup(" a b c ");
char *write = str, *read = str;
do {
if (*read != ' ')
*write++ = *read;
} while (*read++);
printf("%s\n", str);
Other strings are read-only, for example those declared in-code. You'd have to copy those to a newly allocated area of memory and fill the copy by skipping the spaces:
char *oldstr = " a b c ";
char *newstr = malloc(strlen(oldstr)+1);
char *np = newstr, *op = oldstr;
do {
if (*op != ' ')
*np++ = *op;
} while (*op++);
printf("%s\n", newstr);
You can see why people invented other languages ;)
#include <ctype>
char * remove_spaces(char * source, char * target)
{
while(*source++ && *target)
{
if (!isspace(*source))
*target++ = *source;
}
return target;
}
Notes;
This doesn't handle Unicode.
if you are still interested, this function removes spaces from the beginning of the string, and I just had it working in my code:
void removeSpaces(char *str1)
{
char *str2;
str2=str1;
while (*str2==' ') str2++;
if (str2!=str1) memmove(str1,str2,strlen(str2)+1);
}
#include<stdio.h>
#include<string.h>
main()
{
int i=0,n;
int j=0;
char str[]=" Nar ayan singh ";
char *ptr,*ptr1;
printf("sizeof str:%ld\n",strlen(str));
while(str[i]==' ')
{
memcpy (str,str+1,strlen(str)+1);
}
printf("sizeof str:%ld\n",strlen(str));
n=strlen(str);
while(str[n]==' ' || str[n]=='\0')
n--;
str[n+1]='\0';
printf("str:%s ",str);
printf("sizeof str:%ld\n",strlen(str));
}
The easiest and most efficient way to remove spaces from a string is to simply remove the spaces from the string literal. For example, use your editor to 'find and replace' "hello world" with "helloworld", and presto!
Okay, I know that's not what you meant. Not all strings come from string literals, right? Supposing this string you want spaces removed from doesn't come from a string literal, we need to consider the source and destination of your string... We need to consider your entire algorithm, what actual problem you're trying to solve, in order to suggest the simplest and most optimal methods.
Perhaps your string comes from a file (e.g. stdin) and is bound to be written to another file (e.g. stdout). If that's the case, I would question why it ever needs to become a string in the first place. Just treat it as though it's a stream of characters, discarding the spaces as you come across them...
#include <stdio.h>
int main(void) {
for (;;) {
int c = getchar();
if (c == EOF) { break; }
if (c == ' ') { continue; }
putchar(c);
}
}
By eliminating the need for storage of a string, not only does the entire program become much, much shorter, but theoretically also much more efficient.
/* Function to remove all spaces from a given string.
https://www.geeksforgeeks.org/remove-spaces-from-a-given-string/
*/
void remove_spaces(char *str)
{
int count = 0;
for (int i = 0; str[i]; i++)
if (str[i] != ' ')
str[count++] = str[i];
str[count] = '\0';
}
Code taken from zString library
/* search for character 's' */
int zstring_search_chr(char *token,char s){
if (!token || s=='\0')
return 0;
for (;*token; token++)
if (*token == s)
return 1;
return 0;
}
char *zstring_remove_chr(char *str,const char *bad) {
char *src = str , *dst = str;
/* validate input */
if (!(str && bad))
return NULL;
while(*src)
if(zstring_search_chr(bad,*src))
src++;
else
*dst++ = *src++; /* assign first, then incement */
*dst='\0';
return str;
}
Code example
Exmaple Usage
char s[]="this is a trial string to test the function.";
char *d=" .";
printf("%s\n",zstring_remove_chr(s,d));
Example Output
thisisatrialstringtotestthefunction
Have a llok at the zString code, you may find it useful
https://github.com/fnoyanisi/zString
That's the easiest I could think of (TESTED) and it works!!
char message[50];
fgets(message, 50, stdin);
for( i = 0, j = 0; i < strlen(message); i++){
message[i-j] = message[i];
if(message[i] == ' ')
j++;
}
message[i] = '\0';
Here is the simplest thing i could think of. Note that this program uses second command line argument (argv[1]) as a line to delete whitespaces from.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
/*The function itself with debug printing to help you trace through it.*/
char* trim(const char* str)
{
char* res = malloc(sizeof(str) + 1);
char* copy = malloc(sizeof(str) + 1);
copy = strncpy(copy, str, strlen(str) + 1);
int index = 0;
for (int i = 0; i < strlen(copy) + 1; i++) {
if (copy[i] != ' ')
{
res[index] = copy[i];
index++;
}
printf("End of iteration %d\n", i);
printf("Here is the initial line: %s\n", copy);
printf("Here is the resulting line: %s\n", res);
printf("\n");
}
return res;
}
int main(int argc, char* argv[])
{
//trim function test
const char* line = argv[1];
printf("Here is the line: %s\n", line);
char* res = malloc(sizeof(line) + 1);
res = trim(line);
printf("\nAnd here is the formatted line: %s\n", res);
return 0;
}
This is implemented in micro controller and it works, it should avoid all problems and it is not a smart way of doing it, but it will work :)
void REMOVE_SYMBOL(char* string, uint8_t symbol)
{
uint32_t size = LENGHT(string); // simple string length function, made my own, since original does not work with string of size 1
uint32_t i = 0;
uint32_t k = 0;
uint32_t loop_protection = size*size; // never goes into loop that is unbrakable
while(i<size)
{
if(string[i]==symbol)
{
k = i;
while(k<size)
{
string[k]=string[k+1];
k++;
}
}
if(string[i]!=symbol)
{
i++;
}
loop_protection--;
if(loop_protection==0)
{
i = size;
break;
}
}
}
While this is not as concise as the other answers, it is very straightforward to understand for someone new to C, adapted from the Calculix source code.
char* remove_spaces(char * buff, int len)
{
int i=-1,k=0;
while(1){
i++;
if((buff[i]=='\0')||(buff[i]=='\n')||(buff[i]=='\r')||(i==len)) break;
if((buff[i]==' ')||(buff[i]=='\t')) continue;
buff[k]=buff[i];
k++;
}
buff[k]='\0';
return buff;
}
I assume the C string is in a fixed memory, so if you replace spaces you have to shift all characters.
The easiest seems to be to create new string and iterate over the original one and copy only non space characters.
I came across a variation to this question where you need to reduce multiply spaces into one space "represent" the spaces.
This is my solution:
char str[] = "Put Your string Here.....";
int copyFrom = 0, copyTo = 0;
printf("Start String %s\n", str);
while (str[copyTo] != 0) {
if (str[copyFrom] == ' ') {
str[copyTo] = str[copyFrom];
copyFrom++;
copyTo++;
while ((str[copyFrom] == ' ') && (str[copyFrom] !='\0')) {
copyFrom++;
}
}
str[copyTo] = str[copyFrom];
if (str[copyTo] != '\0') {
copyFrom++;
copyTo++;
}
}
printf("Final String %s\n", str);
Hope it helps :-)
This question already has answers here:
Reverse the ordering of words in a string
(48 answers)
Closed 8 years ago.
I need a program to reverse the words in a string.
Input: My car is fast
Output: fast is car My
int printRword(char * line) {
for(; *line; line++) {
if(*line == ' ') {
printRword(line + 1);
printf("%s", line);
return 0; // after you find the space set it to null
}
}
}
int main(void) {
char *line = "this is a long line that we are working with\n";
printf("%s", line);
printRword(line);
return 0;
}
I know I need to set space to null after I find it, and I've tried printRword(line + 1) = '\0';
and that doesn't work
any suggestions?
You could reverse the whole string, and then reverse each individual word, having the effect of reversing the order of the words but leaving the letters in each word in the correct order. Not the most efficient, perhaps, but conceptually clean -- and not language dependent!
Find the modified working code:
int printRword(char * line)
{
char tempbuf[100]; //Here length i have hardcoded to 100
char *ptr;
strcpy(tempbuf,line); //copied to tempbuf to keep the original string unmodified
//Replace the \n with the null character
ptr = strrchr(tempbuf,'\n');
if(ptr != NULL)
{
*ptr = '\0';
}
while(*tempbuf != '\0')
{
ptr = strrchr(tempbuf,' ');
if(NULL != ptr)
{
*ptr = '\0';
ptr++;
printf("%s ",ptr);
}
else
{
printf("%s\n",tempbuf);
*tempbuf ='\0';
}
}
}
test result:
atharv#atharv-Inspiron-5423:~/Programming$ ./a.out
this is a long line that we are working with
with working are we that line long a is this
atharv#atharv-Inspiron-5423:~/Programming$
You could go through the string character-by-character, replacing the spaces by ASCII NUL characters (C's string terminators), and recording the next position in each case (by pushing onto a stack), thus recording the beginning of each word. When you get to the end of the string, you can then go backwards through the list of “start-of-word” positions (perhaps by popping off the stack), printing out the word each time followed by a space.
This is the basic idea. If you have to handle multiple spaces between words or newlines, it gets a little bit more complicated, but not much.
I modified your code using the same recursive approach to get the desired output, just added a function that would print only till next space.. there must be a function for this already but i am not aware of it.
#include <stdio.h>
void printTillNextSpace(char *s){
while(*s != ' ' && *s != '\0' && *s != '\n')
printf("%c",*s++);
printf("%c",' ');
}
int printRword(char * line){
char* start = line;
for(;*line; line++){
if(*line == ' '){
printRword(line + 1);
printTillNextSpace(start);
start = line + 1;
return 0; // after you find the space set it to null
}
}
printTillNextSpace(start);
}
int main(){
char * line = "this is a long line that we are working with\n";
printf("%s", line);
printRword(line);
return 0;
}
I have a string representing an integer with spaces -- digits are grouped by three.
I was considering using strchr and strcat, as in:
char* remove_spaces (char* s)
{
char* space;
while (space = strchr(s, ' '))
{
*space = '\0';
strcat(s, space + 1);
}
return s;
}
But, first, I'm not sure it is safe to use strcat this way since the string to be appended overlaps the final string.
Next, I'm wondering whether this could be done better with something like sscanf.
char* trim (char* s)
{
char* space;
while (space = strchr(s, ' '))
{
memmove(space,space+1,strlen(space));
}
return s;
}
You could use strtok
//asuming line points to the beginning of your string
char *col_str = line, c;
short int *the_numbers;
int col, col_num, count = 0;
while((c = *col_str++) != '\0'){
if(c == ' '){
count++;
}
}
the_numbers = (*short int)malloc(sizeof(short int)*count+1);
for(col_num = 0,col_str = line; ; col_num++,col_str = NULL){
col = atoi(strtok(col_str, ' '));
the_numbers[col_num] = (short int)col;
}
EDIT:
If you have a constant number of items in each line you could just use malloc with that value instead of pre-counting the number of spaces in the string.
short int *the_numbers = (short int*)malloc(NUM_ITEMS * sizeof(short int));
You could probably do this with malloc and realloc as well but I'm not sure if that would be faster.
For this kind of simple problem it's usually easiest just to loop through character by character:
void trim(char* buffer)
{
char* r = buffer;
char* w = buffer;
for (;;)
{
char c = *r++;
if (c != ' ')
*w++ = c;
if (c == '\0')
break;
}
}
It's safe to use the same buffer for both reading and writing because we know the trimmed string will always be shorter than the original string. This is the fastest possible solution as each character is read once and written at most once.
You can't use strcpy() when the source and destination overlap --- the specification forbids it.
I'm don't know about scanf(); there's all kinds of obscure yet useful stuff buried deep within it, and it's worth going through the man page.
Edited: fixed the stupid typo that meant it didn't work.
An alternative method based on David Given's:
void removeSpaces( char* str )
{
char* input = str;
char* output = str;
for( ; *input != 0; ++input )
{
if( *input != ' ' )
*output++ = *input;
}
*output = 0;
}
I wouldn't worry about performance issues of using memmove unless your strings are really large. There isn't an easy way of using sscanf for this as it is hard to define where in the input string each call to sscanf should begin.
No, your use of strcat is not safe (§7.21.3.1/2: "If copying takes place between objects that overlap, the behavior is undefined.")
If you do a bit of looking, you can probably find a few dozen (or more) implementations of this on the web (one example).
You could use strtoul for the conversion, without having to manipulate the string at all. strtoul converts as much as it can, and tells you where it stopped. Handily it also skips over leading white space. So:
static unsigned long conv( const char* s)
{ unsigned long num, dig;
char* endp;
for(num=0;;s=endp)
{ dig = strtoul( s, &endp, 10);
if ( s == endp)
{ break;
}
num = num*1000 + dig;
}
return num;
}
This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
Painless way to trim leading/trailing whitespace in C?
Trim a string in C
I was writing the String trim method in c and this is the code I came up with. I think it does the job of eliminating leading and trailing whitespaces however, I wish the code could be cleaner. Can you suggest improvements?
void trim(char *String)
{
int i=0;j=0;
char c,lastc;
while(String[i])
{
c=String[i];
if(c!=' ')
{
String[j]=c;
j++;
}
else if(lastc!= ' ')
{
String[j]=c;
j++;
}
lastc = c;
i++;
}
Does this code look clean ??
It doesn't look clean. Assuming the first character is a space, you're using lastc with an undefined value. You're leaving one space at the end (if there's a space at the end, when it's hit c will be a space and lastc won't).
You're also not terminating the string. Assuming you fix the uninitialized lastc problem, you'll transform " abc" to "abcbc", since it's not being shortened at any point.
The code also collapses multiple spaces inside the string. This isn't what you described; is it desired behavior?
It often makes your code more readable if you make judicious use of the standard library functions - for example, isspace() and memmove() are particularly useful here:
#include <string.h>
#include <ctype.h>
void trim(char *str)
{
char *start, *end;
/* Find first non-whitespace */
for (start = str; *start; start++)
{
if (!isspace((unsigned char)start[0]))
break;
}
/* Find start of last all-whitespace */
for (end = start + strlen(start); end > start + 1; end--)
{
if (!isspace((unsigned char)end[-1]))
break;
}
*end = 0; /* Truncate last whitespace */
/* Shift from "start" to the beginning of the string */
if (start > str)
memmove(str, start, (end - start) + 1);
}
There's several problems with that code. It only checks for space. Not tabs or newlines. You are copying the entire non-whitespace part of the string. And you are using lastc before setting it.
Here's an alternate version (compiled but not tested):
char *trim(char *string)
{
char *start;
int len = strlen(string);
int i;
/* Find the first non whitespace char */
for (i = 0; i < len; i++) {
if (! isspace(string[i])) {
break;
}
}
if (i == len) {
/* string is all whitespace */
return NULL;
}
start = &string[i];
/* Remove trailing white space */
for (i = len; i > 0; i--) {
if (isspace(string[i])) {
string[i] = '\0';
} else {
break;
}
}
return start;
}
There are some problems: lastc could be used uninitialized. And you could make use of a for loop instead of a while loop, for example. Furthermore, trim/strip functions usually replace spaces, tabs and newlines.
Here's a solution using pointers that I wrote quite a while ago:
void trim(char *str)
{
char *ptr = str;
while(*ptr == ' ' || *ptr == '\t' || *ptr == '\r' || *ptr == '\n') ++ptr;
char *end = ptr;
while(*end) ++end;
if(end > ptr)
{
for(--end; end >= ptr && (*end == ' ' || *end == '\t' || *end == '\r' || *end == '\n'); --end);
}
memmove(str, ptr, end-ptr);
str[end-ptr] = 0;
}
Here is my solution.
Short, simple, clean, commented, and lightly tested.
It uses the "isspace" classification function, so you can easily change your definition of "white space" to be trimmed.
void trim(char* String)
{
int dest;
int src=0;
int len = strlen(String);
// Advance src to the first non-whitespace character.
while(isspace(String[src])) src++;
// Copy the string to the "front" of the buffer
for(dest=0; src<len; dest++, src++)
{
String[dest] = String[src];
}
// Working backwards, set all trailing spaces to NULL.
for(dest=len-1; isspace(String[dest]); --dest)
{
String[dest] = '\0';
}
}
Instead of comparing a character with the space character ' ', I'd use the "isspace" function, which I believe is defined in ctype.h.
I don't know about clean, but I find it hard to follow. If I needed to do this I'd initially think of it in two phases:
Figure out how many characters to drop from the beginning, then memmove the rest of the string (including the null terminator) to the start address. (You might not need the memmove if you are allowed to return a different start pointer, but if so you need to be very careful with memory hygiene.)
Figure out how many characters to drop from the (new) end and set a new null terminator there.
I might then look more closely at a one-pass solution like you seem to be trying to implement, but only if there was a speed problem.
By the way, you probably want to use isspace() rather than checking only for space.
What is the easiest and most efficient way to remove spaces from a string in C?
Easiest and most efficient don't usually go together…
Here's a possible solution for in-place removal:
void remove_spaces(char* s) {
char* d = s;
do {
while (*d == ' ') {
++d;
}
} while (*s++ = *d++);
}
Here's a very compact, but entirely correct version:
do while(isspace(*s)) s++; while(*d++ = *s++);
And here, just for my amusement, are code-golfed versions that aren't entirely correct, and get commenters upset.
If you can risk some undefined behavior, and never have empty strings, you can get rid of the body:
while(*(d+=!isspace(*s++)) = *s);
Heck, if by space you mean just space character:
while(*(d+=*s++!=' ')=*s);
Don't use that in production :)
As we can see from the answers posted, this is surprisingly not a trivial task. When faced with a task like this, it would seem that many programmers choose to throw common sense out the window, in order to produce the most obscure snippet they possibly can come up with.
Things to consider:
You will want to make a copy of the string, with spaces removed. Modifying the passed string is bad practice, it may be a string literal. Also, there are sometimes benefits of treating strings as immutable objects.
You cannot assume that the source string is not empty. It may contain nothing but a single null termination character.
The destination buffer can contain any uninitialized garbage when the function is called. Checking it for null termination doesn't make any sense.
Source code documentation should state that the destination buffer needs to be large enough to contain the trimmed string. Easiest way to do so is to make it as large as the untrimmed string.
The destination buffer needs to hold a null terminated string with no spaces when the function is done.
Consider if you wish to remove all white space characters or just spaces ' '.
C programming isn't a competition over who can squeeze in as many operators on a single line as possible. It is rather the opposite, a good C program contains readable code (always the single-most important quality) without sacrificing program efficiency (somewhat important).
For this reason, you get no bonus points for hiding the insertion of null termination of the destination string, by letting it be part of the copying code. Instead, make the null termination insertion explicit, to show that you haven't just managed to get it right by accident.
What I would do:
void remove_spaces (char* restrict str_trimmed, const char* restrict str_untrimmed)
{
while (*str_untrimmed != '\0')
{
if(!isspace(*str_untrimmed))
{
*str_trimmed = *str_untrimmed;
str_trimmed++;
}
str_untrimmed++;
}
*str_trimmed = '\0';
}
In this code, the source string "str_untrimmed" is left untouched, which is guaranteed by using proper const correctness. It does not crash if the source string contains nothing but a null termination. It always null terminates the destination string.
Memory allocation is left to the caller. The algorithm should only focus on doing its intended work. It removes all white spaces.
There are no subtle tricks in the code. It does not try to squeeze in as many operators as possible on a single line. It will make a very poor candidate for the IOCCC. Yet it will yield pretty much the same machine code as the more obscure one-liner versions.
When copying something, you can however optimize a bit by declaring both pointers as restrict, which is a contract between the programmer and the compiler, where the programmer guarantees that the destination and source are not the same address. This allows more efficient optimization, since the compiler can then copy straight from source to destination without temporary memory in between.
In C, you can replace some strings in-place, for example a string returned by strdup():
char *str = strdup(" a b c ");
char *write = str, *read = str;
do {
if (*read != ' ')
*write++ = *read;
} while (*read++);
printf("%s\n", str);
Other strings are read-only, for example those declared in-code. You'd have to copy those to a newly allocated area of memory and fill the copy by skipping the spaces:
char *oldstr = " a b c ";
char *newstr = malloc(strlen(oldstr)+1);
char *np = newstr, *op = oldstr;
do {
if (*op != ' ')
*np++ = *op;
} while (*op++);
printf("%s\n", newstr);
You can see why people invented other languages ;)
#include <ctype>
char * remove_spaces(char * source, char * target)
{
while(*source++ && *target)
{
if (!isspace(*source))
*target++ = *source;
}
return target;
}
Notes;
This doesn't handle Unicode.
if you are still interested, this function removes spaces from the beginning of the string, and I just had it working in my code:
void removeSpaces(char *str1)
{
char *str2;
str2=str1;
while (*str2==' ') str2++;
if (str2!=str1) memmove(str1,str2,strlen(str2)+1);
}
#include<stdio.h>
#include<string.h>
main()
{
int i=0,n;
int j=0;
char str[]=" Nar ayan singh ";
char *ptr,*ptr1;
printf("sizeof str:%ld\n",strlen(str));
while(str[i]==' ')
{
memcpy (str,str+1,strlen(str)+1);
}
printf("sizeof str:%ld\n",strlen(str));
n=strlen(str);
while(str[n]==' ' || str[n]=='\0')
n--;
str[n+1]='\0';
printf("str:%s ",str);
printf("sizeof str:%ld\n",strlen(str));
}
The easiest and most efficient way to remove spaces from a string is to simply remove the spaces from the string literal. For example, use your editor to 'find and replace' "hello world" with "helloworld", and presto!
Okay, I know that's not what you meant. Not all strings come from string literals, right? Supposing this string you want spaces removed from doesn't come from a string literal, we need to consider the source and destination of your string... We need to consider your entire algorithm, what actual problem you're trying to solve, in order to suggest the simplest and most optimal methods.
Perhaps your string comes from a file (e.g. stdin) and is bound to be written to another file (e.g. stdout). If that's the case, I would question why it ever needs to become a string in the first place. Just treat it as though it's a stream of characters, discarding the spaces as you come across them...
#include <stdio.h>
int main(void) {
for (;;) {
int c = getchar();
if (c == EOF) { break; }
if (c == ' ') { continue; }
putchar(c);
}
}
By eliminating the need for storage of a string, not only does the entire program become much, much shorter, but theoretically also much more efficient.
/* Function to remove all spaces from a given string.
https://www.geeksforgeeks.org/remove-spaces-from-a-given-string/
*/
void remove_spaces(char *str)
{
int count = 0;
for (int i = 0; str[i]; i++)
if (str[i] != ' ')
str[count++] = str[i];
str[count] = '\0';
}
Code taken from zString library
/* search for character 's' */
int zstring_search_chr(char *token,char s){
if (!token || s=='\0')
return 0;
for (;*token; token++)
if (*token == s)
return 1;
return 0;
}
char *zstring_remove_chr(char *str,const char *bad) {
char *src = str , *dst = str;
/* validate input */
if (!(str && bad))
return NULL;
while(*src)
if(zstring_search_chr(bad,*src))
src++;
else
*dst++ = *src++; /* assign first, then incement */
*dst='\0';
return str;
}
Code example
Exmaple Usage
char s[]="this is a trial string to test the function.";
char *d=" .";
printf("%s\n",zstring_remove_chr(s,d));
Example Output
thisisatrialstringtotestthefunction
Have a llok at the zString code, you may find it useful
https://github.com/fnoyanisi/zString
That's the easiest I could think of (TESTED) and it works!!
char message[50];
fgets(message, 50, stdin);
for( i = 0, j = 0; i < strlen(message); i++){
message[i-j] = message[i];
if(message[i] == ' ')
j++;
}
message[i] = '\0';
Here is the simplest thing i could think of. Note that this program uses second command line argument (argv[1]) as a line to delete whitespaces from.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
/*The function itself with debug printing to help you trace through it.*/
char* trim(const char* str)
{
char* res = malloc(sizeof(str) + 1);
char* copy = malloc(sizeof(str) + 1);
copy = strncpy(copy, str, strlen(str) + 1);
int index = 0;
for (int i = 0; i < strlen(copy) + 1; i++) {
if (copy[i] != ' ')
{
res[index] = copy[i];
index++;
}
printf("End of iteration %d\n", i);
printf("Here is the initial line: %s\n", copy);
printf("Here is the resulting line: %s\n", res);
printf("\n");
}
return res;
}
int main(int argc, char* argv[])
{
//trim function test
const char* line = argv[1];
printf("Here is the line: %s\n", line);
char* res = malloc(sizeof(line) + 1);
res = trim(line);
printf("\nAnd here is the formatted line: %s\n", res);
return 0;
}
This is implemented in micro controller and it works, it should avoid all problems and it is not a smart way of doing it, but it will work :)
void REMOVE_SYMBOL(char* string, uint8_t symbol)
{
uint32_t size = LENGHT(string); // simple string length function, made my own, since original does not work with string of size 1
uint32_t i = 0;
uint32_t k = 0;
uint32_t loop_protection = size*size; // never goes into loop that is unbrakable
while(i<size)
{
if(string[i]==symbol)
{
k = i;
while(k<size)
{
string[k]=string[k+1];
k++;
}
}
if(string[i]!=symbol)
{
i++;
}
loop_protection--;
if(loop_protection==0)
{
i = size;
break;
}
}
}
While this is not as concise as the other answers, it is very straightforward to understand for someone new to C, adapted from the Calculix source code.
char* remove_spaces(char * buff, int len)
{
int i=-1,k=0;
while(1){
i++;
if((buff[i]=='\0')||(buff[i]=='\n')||(buff[i]=='\r')||(i==len)) break;
if((buff[i]==' ')||(buff[i]=='\t')) continue;
buff[k]=buff[i];
k++;
}
buff[k]='\0';
return buff;
}
I assume the C string is in a fixed memory, so if you replace spaces you have to shift all characters.
The easiest seems to be to create new string and iterate over the original one and copy only non space characters.
I came across a variation to this question where you need to reduce multiply spaces into one space "represent" the spaces.
This is my solution:
char str[] = "Put Your string Here.....";
int copyFrom = 0, copyTo = 0;
printf("Start String %s\n", str);
while (str[copyTo] != 0) {
if (str[copyFrom] == ' ') {
str[copyTo] = str[copyFrom];
copyFrom++;
copyTo++;
while ((str[copyFrom] == ' ') && (str[copyFrom] !='\0')) {
copyFrom++;
}
}
str[copyTo] = str[copyFrom];
if (str[copyTo] != '\0') {
copyFrom++;
copyTo++;
}
}
printf("Final String %s\n", str);
Hope it helps :-)