Replace multiple spaces by single space in C - c

I want to repace multiple spaces in a string by single space, however my following code doesn't work. What's the logical mistake?
#include<stdio.h>
#include<string.h>
main()
{
char input[100];
int i,j,n,z=0;
scanf("%d",&n);
z=n;
for(i=0;i<n;i++)
scanf("%c",&input[i]);
for(i=0;i<n;i++)
{
if(input[i]==' ' && (input[i+1]==' ' || input[i-1]==' '))
{
--z;
for(j=i;j<n;j++)
input[j]=input[j+1];
}
}
for(i=0;i<z;i++)
printf("%c",input[i]);
printf("\n");
}

I would do something like this:
void replace_multi_space_with_single_space(char *str)
{
char *dest = str; /* Destination to copy to */
/* While we're not at the end of the string, loop... */
while (*str != '\0')
{
/* Loop while the current character is a space, AND the next
* character is a space
*/
while (*str == ' ' && *(str + 1) == ' ')
str++; /* Just skip to next character */
/* Copy from the "source" string to the "destination" string,
* while advancing to the next character in both
*/
*dest++ = *str++;
}
/* Make sure the string is properly terminated */
*dest = '\0';
}
Of course, the above function requires you to properly terminate the string, which you currently do not.
What the function above does, is basically copy the string over itself. The exception is when there is a space, when multiple spaces are simply discarded.
Since the function modifies the source string, it can not be used on string literals.

The scanf is giving you some problem: it reads the \n you give after inputting the length n. So, you will miss the last character since for loop exits. The already given answers are good enough. But if you want to follow your own logic, try this:
void main()
{
char input[100];
int i = 0,j,n = 0;
while ((input[n] = getchar()) != '\n') {
n++;
}
input[n] = '\0';
while (i < n)
{
if(input[i]==' ' && (input[i+1]==' ' || input[i-1]==' '))
{
for(j=i;j<n;j++)
input[j]=input[j+1];
n--;
}
else
{
i++;
}
}
printf("%s\n",input);
printf("\n");
}

if(input[i]==' ' && (input[i+1]==' ' || input[i-1]==' '))
case " 1 3" : when i == 0 accses input[i-1] Out-of-Bounds
scanf("%d",&n);
remain newline, (input[0] <-- '\n')
fix to
scanf("%d%*c",&n);
#include <stdio.h>
char* uniq_spc(char* str){
char *from, *to;
int spc=0;
to=from=str;
while(1){
if(spc && *from == ' ' && to[-1] == ' ')
++from;
else {
spc = (*from==' ')? 1 : 0;
*to++ = *from++;
if(!to[-1])break;
}
}
return str;
}
int main(){
char input[]= " abc de f ";
printf("\"%s\"\n", uniq_spc(input));//output:" abc de f "
return 0;
}

Why make it more complicated than it needs to be? You can use strtok to check for single whitespaces and just ignore those. Then you can use strcat to concatenate the string into a full sentence and then you're done.
This is how I did it:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main(void) {
char *pch;
char sentence[1000];
char without[1000];
printf("Sentence: ");
fgets(sentence,1000, stdin);
strtok(sentence, "\n"); // remove any newlines
pch = strtok(sentence, " ");
while(pch != NULL) {
strcat(without, pch);
strcat(without, " \0");
pch = strtok(NULL, " ");
}
without[strlen(without)-1] = '\0'; // remove extra whitespace at the end
printf("|%s|\n",without);
return 0;
}

#include <stdio.h>
#include <stdlib.h>
void remove_blanks(char* s);
int main()
{
char const s[] = {'1',' ',' ','2',' ',' ','3'};
remove_blanks(s);
printf("%s",s);
return 0;
}
void remove_blanks(char* s){
int i=0, delta=0, cnt=0;
for (i=0;s[i];++i){
if (s[i]==' ') cnt++;
if (cnt>1){
delta+=1;
cnt=0;
}
s[i-delta]=s[i];
if(delta>0) s[i]='\0';
}
}

You cant try this simple code:
#include <stdio.h>
#define IN 1
#define OUT 0
int main() {
int c, spaces, state;
spaces = 0;
state = OUT;
while ((c = getchar()) != EOF) {
if ( c == ' ') {
++spaces;
state = OUT;
}
else if (state == OUT) {
state = IN;
spaces = 0;
}
if (c == ' ' && spaces > 1 && state == OUT)
c = 0;
putchar(c);
}
return 0;
}

You have to fix the following for loop. the limit of your for loop should be z and not n
for(j=i;j<n;j++)
input[j]=input[j+1];
by
for(j=i;j<z;j++)
input[j]=input[j+1];
BTW: the fist charachter get by your scanf() (which read charachters) is newline (\n). this newline come from the first scanf() of decimal(%d)

#include<stdio.h>
#include<string.h>
int main(void)
{
char input[1000];
int i=0;
gets(input);
for(i=0;input[i]!='\0';i++)
{
if(input[i]!=' ' || input[i+1]!=' ')
printf("%c",input[i]);
}
return 0;
}

Related

Functions works only 1 time

I've encountered a problem with my code where the function I made rotate_left that's supposed to take the first word in a given string and puts it at the end of that string and that function works but when it tried to activate it twice it doesn't do anything other than printing the same result the first function printed anyone got any ideas about it?
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#define MAX 80
void rotate_left(char str[])
{
int j = 0;
int i = 0;
char Temp[MAX];
char Temp2[MAX];
while (str[i] != ' ')
{
i++;
}
Temp[i] = '\0';
strncpy(Temp, str, i);
strcat(str, " ");
while (str[i] != '\0')
{
Temp2[j] = str[i];
i++;
j++;
}
Temp2[j] = '\0';
strcat(Temp2, Temp);
printf("%s\n", Temp2);
}
int main()
{
char str[MAX];
char Temp2[MAX];
printf("Enter Your String To Swtich The : ");
gets(str);
rotate_left(str);
rotate_left(str);
rotate_left(str);
return 0;
}
You have two bugs in these codes :
First you must copy the rotated string in the passed one, printing the result is not sufficient. Next you must remove the space at the beginning of the extracted word otherwise the new string start with a space.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#define MAX 80
void rotate_left(char str[])
{
int j = 0;
int i = 0;
char Temp[MAX];
char Temp2[MAX];
// If the first space is not removed (see below), the next time
// the function is called, this loop stops immediately. It's why
// the second rotation didn't occur
while (str[i] != ' ')
{
i++;
}
Temp[i] = '\0';
strncpy(Temp, str, i);
strcat(str, " ");
i++; //<====== removes the space
while (str[i] != '\0')
{
Temp2[j] = str[i];
i++;
j++;
}
Temp2[j] = '\0';
strcat(Temp2, Temp);
strncpy(str, Temp2, strlen(Temp2) + 1); //<====== copies the string
printf("%s\n", str);
}
int main()
{
char str[MAX] = "Enter Your String To Switch The";
char Temp2[MAX];
for (int i=0; i<7; i++) rotate_left(str);
return 0;
}
Output :
Your String To Switch The Enter
String To Switch The Enter Your
To Switch The Enter Your String
Switch The Enter Your String To
The Enter Your String To Switch
Enter Your String To Switch The
Your String To Switch The Enter
I didn't handle special cases (if there is no space in the provided string for instance) and I removed the interactive dimension (gets) for the example.
Your code has issues:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#define MAX 80
void rotate_left(char str[])
{
int j = 0;
int i = 0;
char Temp[MAX];
char Temp2[MAX];
while (str[i] != ' ')
{
i++;
}
in the code below you are having a security leak and a potential problem because you have temp variables in the stack and you are touching these without boundary checks: Example of a buffer overflow leading to a security leak
you need to write code with boundary checks especially when the variable is in the stack:
while (i < MAX /*or i < sizeof(str)*/ && str[i] != ' ' && str[i] != '\0' /*Null check also?*/ )
{
i++;
}
If you call this method with a string without space in it then god knows what will it result,
There are other issues as well like "strncpy(str, Temp2, strlen(Temp2) + 1);" this is not how this method is intended to be called as it should be "strncpy(str, Temp2, sizeof(str));": https://linux.die.net/man/3/strncpy
Let me write you sample code it will be faster for you to track some of the missing checks:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 80
/* just your code with safety checks so you can track why it fails */
int rotate_left(char str[], const size_t inputSize)
{
int j = 0;
int i = 0;
char Temp[MAX];
char Temp2[MAX];
while (i < inputSize && str[i] != ' ' && str[i] != '\0')
{
i++;
}
if (i == inputSize || str[i] == '\0')
{
// string without any space in it so no need to rotate?
return 0;
}
if (i + 1/*+1 to include null*/ >= MAX) {
// We dont have enough memory to handle this request
return -1;
}
strncpy(Temp, str, i);
Temp[i] = '\0';
++i;
while (i < inputSize && j < MAX && str[i] != '\0')
{
Temp2[j] = str[i];
i++;
j++;
}
if (i == inputSize) {
// String is not null terminated?
return -1;
}
if (j + 2 /*Include space and null character*/ >= MAX) {
// We dont have enough memory to handle this request
return -1;
}
Temp2[j] = ' ';
Temp2[j + 1] = '\0';
strncat(Temp2, Temp, sizeof(Temp2));
strncpy(str, Temp2, inputSize); //<====== copies the string
printf("%s\n", str);
return 0;
}
/* bit more optimization */
errno_t rotate_left_optimized(char str[], const size_t inputSize)
{
errno_t lastCall;
char temp[MAX];
int i = 0;
while (i < inputSize && str[i] != ' ' && str[i] != '\0')
{
i++;
}
if (i == inputSize || str[i] == '\0')
{
// string without any space in it so no need to rotate?
return 0;
}
const size_t inputLen = strnlen(str, inputSize);
if (i + 1 /* Include lazy space character */>= sizeof(temp)) {
// We dont have enough memory to handle this request
return -1;
}
// hidden assert(str[i] == ' ');
temp[0] = ' ';
memcpy(temp + 1, str, i);
memmove(str, str + i + 1, inputLen);
lastCall = strncat_s(str, inputSize, temp, i + 1);
if (!lastCall)
{
return lastCall;
}
return 0;
}
int main()
{
char str[MAX] = "Enter Your String To Switch The";
for (int i = 0; i < 7; i++) {
if (rotate_left_optimized(str, MAX)) {
perror("failed to rotate");
exit(EXIT_FAILURE);
}
printf("%s\n", str);
}
return 0;
}

removing spaces from a string in C language

I can't figure out how to remove the spaces at the beginning of the sentence without using any libraries other than stdio.h and stdlib.h.
#include <stdio.h>
int main()
{
char text[1000], result[1000];
int c = 0, d = 0;
printf("Enter some text\n");
gets(text);
while (text[c] != '\0') { // till the end of the string
if (text[c] == ' ') {
int temp = c + 1;
if (text[temp] != '\0') {
while (text[temp] == ' ' && text[temp] != '\0') {
if (text[temp] == ' ') {
c++;
}
temp++;
}
}
}
result[d] = text[c];
c++;
d++;
}
result[d] = '\0';
printf("Text after removing blanks\n%s\n", result);
return 0;
}
This piece of code removes all the extra spaces of a sentence.
Example:
input: " this is my program."
output: " this is my program."
EXPECTED OUTPUT: "this is my program."
this code leaves only one space where there were more spaces, but I want to remove all spaces at the beginning as well like in the expected output.
#include <stdio.h>
int main()
{
char text[1000], result[1000];
int c = 0, d = 0;
printf("Enter some text\n");
gets(text);
// no space at beginning
while(text[c] ==' ') { c++; }
while(text[c] != '\0'){
result[d++] = text[c++]; //take non-space characters
if(text[c]==' ') { result[d++] = text[c++]; } // take one space between words
while(text[c]==' ') { c++; } // skip other spaces
}
result[d] = '\0';
printf("Text after removing blanks\n%s\n", result);
return 0;
}
I want to remove all spaces at the beginning as well.
After getting the input, begin processing up to the first non-white-space.
// do not use gets()
fgets(text, sizeof text, stdin);
text[strcspn(text, "\n")] = '\0'; //lop off potential \n
char *ptext = text;
while (isspace((unsigned char) *ptext)) {
ptext++;
}
// now use ptext instead of text for rest of code.
This function will process the input array as you need
void remove_white_space(char *source, char *result) {
int i=0,key=0,k=0;
while (source[i]!='\0') {
if(source[i]==' ') {
if (key== 0) {
if(i==0) {
key=1;
++i;
} else {
key=1;
result[k]=source[i];
++k;
++i;
}
} else
++i;
} else {
key=0;
result[k]=source[i];
++k;
++i;
}
}
result[k]='\0';
}

Convert the string into special string

Input:
Hello There
Output:
Olleh Ereht
Input:
How are you?
output:
Woh Era ?you
#include <stdio.h>
#include <string.h>
int main()
{
char s[100], r[100];
int n, c, d=0;
int p=0,t=0;
printf("Input a string\n");
gets(s);
//n = strlen(s);
while(s[p]!= '\0'){
while(s[p]!= ' ' || s[p]!= '\0'){
p++;
}
for (c = p-1; c >= t; c--, d++)
r[d] = s[c];
r[d++] = ' ';
// printf("%s\n", r);
t=p;
p++;
}
r[d]= '\0';
printf("%s\n", r);
return 0;
}
I am getting Time Limit Exceeded problem..Don't know where i am going wrong.Plz help me with the solution.
I think the inner while loop never terminates because the condition never gives false.
For the loop to terminate:
s[p] != ' ' and s[p] != '\0' both should be false.
That is to say
s[p]== ' ' and s[p]== '\0' both should be true, which is not possible.
That's why you are getting the time limit exceeded error.
Perhaps like this
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(void){
char s[100], r[100];
int p = 0, d = -1;
printf("Input a string\n");
scanf("%99[^\n]", s);//gets(s);<-- "gets" already was obsolete.
while(1){
if(s[p] != ' ' && s[p] != '\0'){
r[++d] = s[p];
} else {
if(d >= 0){
putchar(toupper(r[d--]));
while(d >= 0){
putchar(tolower(r[d--]));
}
}
if(s[p] == ' ')
putchar(' ');
else
break;
}
++p;
}
return 0;
}

C: counting number of words (need help fixing)

I am new to C programming and trying to write a code for counting the number of words in a string.Here is my code for counting the number of codes.
#include<stdio.h>
#include<string.h>
void main()
{
int count=0,i,len;
char str[100];
printf("enter the sentence");
gets(str);
len=strlen(str);
for(i=0;i<=len;i++)
{
if(str[i]==' ')
count++;
}
printf("the number of words are :\t%d",count+1);
}
When my input is:Here is four words it works fine. it gives output
the number of words are : 4
My question is how do I handle "two consecutive spaces" between the word, "space at the beginning" of the input and "space at the last" of the input.
Instead of counting spaces, count the first non-space character of each word.
#include<stdio.h>
int main()
{
int count=0;
char str[100];
printf("enter the sentence");
gets(str);
char *cur= str;
for (;;)
{
while (*cur == ' ')
{
cur++;
}
if (*cur == 0)
{
break;
}
count++;
while (*cur != 0 && *cur != ' ')
{
cur++;
}
}
printf("the number of words are :\t%d",count);
return 0;
}
You can use:
while(str[i]==' '&&str[i]!=EOF)
{
count++;
i++;
}
instead of your if part. You also need to add these code before the for loop to read the beginning spaces.
I think the loop in the current form may not work properly,
It should be as follows,
for(i=0;i<len;i++)
{
if(i!=0)
{
if(str[i]==' ')
count++;
}
}
To check the other criteria change the code as follows,
for(i=0;i<len;i++)
{
if(str[i]==' ')
{
if(i!=0)
{
if(str[i+1]!=' ')
{
count++;
}
}
}
Just ignore spaces at the beginning and spaces directly after other spaces, and +1 if there are no spaces at the last.
#include <stdio.h>
#include <string.h>
// #include <stdlib.h>
int main() // void main is a bad practice
{
int count = 0, i, len, ignoreSpace;
char str[100];
printf("enter the sentence\n");
gets(str);
len = strlen(str);
ignoreSpace = 1; // handle space at the beginning
for(i = 0; i < len; i++) // not i<=len
{
if(str[i] == ' '){
if(!ignoreSpace){
count++;
ignoreSpace = 1; // handle two or more consecutive spaces
}
}else{
ignoreSpace = 0;
}
}
if( !ignoreSpace ) // handle space at the last
count++;
printf("the number of words are :\t%d\n", count); // +1 is moved to previous line
// system("pause");
return 0;
}
use strtok and first call of strtok use strtok(string," ") and for rest of calls use strtok(NULL, " \n")
You should count the transitions from space to non-space characters + a possible non-space character in the beginning itself.
#include<stdio.h>
#include<string.h>
int main()
{
int count=0,i,len, cur_is_spc;
char str[100];
printf("enter the sentence");
gets(str);
len=strlen(str);
cur_is_spc = 0; // 0, if current character is not space. 1, if it is.
for(i=0; str[i]!='\0'; i++)
{
if(str[i] != ' ')
{
switch(cur_is_spc) // currently holding value for previous character
{
case 0: count++; break; //count the spc->non-spc transitions
case 1: break;
default: cout << "Erroneous value"; exit(1);
}
cur_is_spc = 1; //updated for current character.
}
else
{
cur_is_spc = 0; //updated for current character.
}
}
printf("the number of words are :\t%d",count+1);
return 0;
}
Here, I am checking with only spaces. But there can be characters like newline, tab etc. How would your code handle them? Hint: use isspace() function.
/moreover, the transition can be done from non-alphabet characters to alphabet characters if you decide that words are made up of alphabets only. This approach is inherently flexible to suit your needs.
One quick way to do this is use strtok and break everything according to a predicate. This function satisfy all your requirements.
#include<stdio.h>
#include<string.h>
int countSpace(char* str){
int counter = 0;
char * newString;
newString= strtok (str, " "); // now the newString has the str except first word
while (newString != NULL){
counter++; // Put counter here to ignore the newString == NULL
// Or just -1 from the counter on main()
newString= strtok (NULL, " "); //Break the str in to words seperated by spaces
}
return counter;
}
void main(){
int count=0,i,len;
char str[100];
printf("Enter the sentence:\n");
fgets (str , 100 , stdin);
count = countSpace(str);
printf("The number of words are :\t%d\n",count);
return 0;
}
Thank you
Why not use strtok and bypass it altogether:
int main()
{
int num_words = 0;
char str_one[] = "This string has a trailing space ";
char str_two[] = " This string has a preceeding space";
char str_three[] = "This string contains two spaces consecutively twice!";
char delim[] = " ";
char *ret;
/* fgets() for user input as desired... */
if (( ret = strtok(str_one, delim)) != NULL )
{
while ( ret )
{
num_words++;
ret = strtok(NULL, delim);
}
}
else
{
/* no spaces, but might contain a word if the string isn't empty */
if ( str_one[0] != '\0' )
num_words = 1;
}
printf("str_one contains %i words\n", num_words);
num_words = 0;
...
return 0;
}
And by the way: main should ALWAYS return!!!

Remove preceding spaces and tabs from a given string in C language

What C function, if any, removes all preceding spaces and tabs from a string?
In C a string is identified by a pointer, such as char *str, or possibly an array. Either way, we can declare our own pointer that will point to the start of the string:
char *c = str;
Then we can make our pointer move past any space-like characters:
while (isspace(*c))
++c;
That will move the pointer forwards until it is not pointing to a space, i.e. after any leading spaces or tabs. This leaves the original string unmodified - we've just changed the location our pointer c is pointing at.
You will need this include to get isspace:
#include <ctype.h>
Or if you are happy to define your own idea of what is a whitespace character, you can just write an expression:
while ((*c == ' ') || (*c == '\t'))
++c;
A simpler function to trim white spaces
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char * trim(char * buff);
int main()
{
char buff[] = " \r\n\t abcde \r\t\n ";
char* out = trim(buff);
printf(">>>>%s<<<<\n",out);
}
char * trim(char * buff)
{
//PRECEDING CHARACTERS
int x = 0;
while(1==1)
{
if((*buff == ' ') || (*buff == '\t') || (*buff == '\r') || (*buff == '\n'))
{
x++;
++buff;
}
else
break;
}
printf("PRECEDING spaces : %d\n",x);
//TRAILING CHARACTERS
int y = strlen(buff)-1;
while(1==1)
{
if(buff[y] == ' ' || (buff[y] == '\t') || (buff[y] == '\r') || (buff[y] == '\n'))
{
y--;
}
else
break;
}
y = strlen(buff)-y;
printf("TRAILING spaces : %d\n",y);
buff[strlen(buff)-y+1]='\0';
return buff;
}
void trim(const char* src, char* buff, const unsigned int sizeBuff)
{
if(sizeBuff < 1)
return;
const char* current = src;
unsigned int i = 0;
while(current != '\0' && i < sizeBuff-1)
{
if(*current != ' ' && *current != '\t')
buff[i++] = *current;
++current;
}
buff[i] = '\0';
}
You just need to give buff enough space.
You can setup a counter to count the corresponding number of spaces, and accordingly shift the characters by that many spaces. Complexity for this ends up at O(n).
void removeSpaces(char *str) {
// To keep track of non-space character count
int count = 0;
// Traverse the given string. If current character
// is not space, then place it at index count
for (int i = 0; str[i]; i++)
if (str[i] != ' ')
str[count++] = str[i]; // increment count
str[count] = '\0';
}

Resources