I have a string line with an array. Ex:- char array[]="I'm new to programing";
I want to rewrite code that variable remove spaces array[]="I'mnewtoprograming"
I already tried to build this
scanf("%[^\n]s",&line);
int len=strlen(line);
//remove space in lenth
for(int i=0;i<len;i++)
(line[i]==' ')?:newlen++;
if (line[i]==' ')
{
line[i]=line[i+1];
}
give me the reason that I mistake
You need to keep track of the current position in the string and the "tail" where next char is compared to the space.
char *removechar(char *str, int ch)
{
char *cpos = str, *tail = str;
while(*tail)
{
if(*tail != ch)
{
*cpos++ = *tail++;
}
else
{
tail++;
}
}
*cpos = 0;
return str;
}
Make For loop for array[] and count ' ' spaces .
line[i]=line[i+1]; this line is wrong .
(line[i]==' ')?:newlen++; this line is correct , i saw some comments that line was wrong .its same as if condition .
Related
I would like to print the remaining string by a deliminator.
The expected output should be:
String
in
C
int main()
{
/* loop over a string using subscript*/
char *s = "String in C";
char* ps;
ps = s;
while(*ps != ' ')
{
printf("%c",*ps);
ps++;
}
}
I can get the first String.
How can I get the rest of it?
This is not the best solution but it works.
#include <stdio.h>
int main()
{
char *s = "String in C";
char *ps;
ps = s;
while (*ps != '\0')
{
if (*ps == ' ')
{
printf("\n");
*ps++;
}
else
{
printf("%c", *ps);
ps++;
}
}
}
You need to examine the logic of your program.
What you are doing right now is you stop iterating right after the first word, when the first space is encountered; that is what while(*ps != ' ') does.
Instead, you can iterate through the whole string, taking advantage of the fact that a string in C ends with a \0, i.e. while (*ps != '\0').
Inside the while you can first test if the character is a blank, and if it is you can advance the pointer and skip to the next character using continue:
if (*ps == ' ') {
printf("\n");
ps++;
continue;
}
Note that the code also prints a newline for readability. This if should also be first thing in the loop and this way it will also skip trailing blanks.
The rest of the code is what you have now, though you may want to add another newline printf after the while loop.
I need to replace " (ASCII value 34) char by empty character "".
In output, instead of quote i get an "?" question mark character.
I tried to use things like:
mystring[itit] = "";
mystring[itit] = '';
mystring[itit] = "\O";
My code:
strcpy( mystring ,op->data.value.str );
for(itit=0;itit<10;itit++)
{
if(mystring[itit] == 34)
{
mystring[itit] = NULL;
}
}
printf( "%s\n",mystring);
Any ideas how to fix that?
For clarification: the strings in mystring are like:
"hello"
"place "
"school"
all with the quotation marks - I Actually need to remove them and get:
hello
place
school
int removeChar(char *str, char c) {
int i, j;
for(i = 0, j = 0 ; str[i] ; i++){
if( str[i] == c) continue; // skip c do not copy it
str[j] = str[i]; // shift characters left
j++;
}
str[j]=0; // terminate the string
return j; // return the actual size
}
What you need to do is remove the character, not replace it, since you're not replacing it with anything. To do this, when you find the character is question, you need to move the remaining characters down.
int i,j;
strcpy(mystring, "aa\"bb\"cc");
for(i=0,j=0;i<10;i++)
{
if(mystring[i] != '"')
{
mystring[j] = mystring[i];
j++;
}
}
mystring[j] = '\0';
printf("mystring=%s\n",mystring);
Result:
mystring=aabbcc
To remove a character from a string, you can do this:
void remove(char* str, char rm)
{
char *src, *dst;
for (src = dst = str; *src != '\0'; ++src) {
*dst = *src;
if (*dst != rm) ++dst;
}
*dst = '\0'; /*insert terminator at the new place*/
}
and call with rm equal to 34.
This algorithm is well-known; I've adopted it from Kernighan & Ritchie. Do study it carefully with your debugger.
In C, strings are simply arrays of characters with a NUL (0) at the end. (They cannot contain NULs.) As with any array, you can't simply "remove" an element. You need to shift all the following elements one position, with the result that there will be an unneeded element at the end. With strings this extra element isn't a huge problem becauyse the NUL still identifies where the string ends.
In this case, you are copying the string first, so you might as well copy it without the characters you want to delete. Unless you know how many such characters there are, you will need to have allocated enough space in the new string for the entire string you want to copy:
/* Before this, you must ensure that mystring has enough space */
{
char* out = mystring;
const char* in = op->data.value.str;
do {
if (*in != '"') *out++ = *in;
} while (*in++);
}
Note: I use the fact that strings are NUL-terminated to terminate the loop, which saves me from having to know in advance how long op->data.value.str is. For this reason, I use character pointers rather than indexes.
There is no "empty character". A string can be empty by having no characters, but a character is an atomic element and can't be empty, like a box of apples can be empty, but one can't have an "empty apple".
Instead, you need to remove the quotes and close the space they took up. Better yet, if you do the copying yourself, just don't copy them:
char *psrc = op->data.value.str;
char *pdest = mystring;
while (*psrc != '\0')
{
if (*psrc != '\"')
{
*pdest = *psrc;
++pdest;
}
++psrc;
}
*pdest = '\0';
You can use this to strip all '\"'-characters:
void stripquotes(char *ptr) {
char *ptr2 = ptr;
do {
*ptr2 = *ptr++;
if (*ptr2 != '\"')
ptr2++;
} while (*ptr);
}
Suppose I have a string that may look something like this:
"value" "some other value" "other value" "some value"
My goal is to remove the blanks selectively, like so:
"value""some other value""other value""some value"
such that the blanks remain only inside strings contained in quotes:
"some other value"
I have the following function:
void rmChar(char *str, char c)
{
char *src, *dest;
src = dest = str;
while(*src != '\0')
{
if (*src != c)
{
*dest = *src;
dest++;
}
src++;
}
*dest = '\0';
}
which removes all occurrences of char c in str and I though I should use some more conditional expressions to do the removal only when certain things happen.
Got any clues?
I just thought of doing this. Below is my program.
Note: This may not be an efficient program (bad time or space complexity), however it does what you are trying to do (if I understood your question right).
Note Also I have used malloc() in this code. You would not use it if you were changing the contents of the original string without using any other string. But as I understood from your question you were making a NEW string which contained the value of original string after removing the spaces.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void rmChar(char *,char, int );
int main()
{
char string[200] = "\"This is a value\" \"and another value\" \"value2 this\"";
char c;
c = '"';
printf("%s\n",string);
int len = strlen(string);
/*Pass the address of the stringi, char c, and the length of the string*/
/*Length of the string will be required for malloc() inside function rmChar()*/
rmChar(string, c, len);
return 0;
}
void rmChar(char *str,char c, int len)
{
char *dest1, *dest2;
char *src = str;
int removeFlag = 0; /* You will remove all the spaces ' ' that come after removeFlag is odd*/
dest1 = malloc(len);
dest2 = dest1;
while(*str != '\0')
{
if(*str == c)
{
removeFlag++;
if (removeFlag %2 == 0)
{
/* This is required because every 2nd time you get a " removeFlag is increased so next if is NOT true*/
*dest2 = *str;
dest2++;
}
}
if ((removeFlag % 2) == 1)
{
*dest2 = *str;
dest2++;
}
str++;
}
*dest2 = '\0';
printf("%s\n", dest1);
/* If you want to copy the string without spaces to the original string uncomment below line*/
//strcpy(src, dest1);
free(dest1);
}
You needed one more variable to use as some kind of flag which indicated after which " you need to remove spaces. Then you would use that flag in a if() statement in some way. Here int removeFlag is the flag I have used.
The loop that iterates over the string has to keep track if it is currently looking at a character inside a quoted string or not, and then use that information to only delete when appropriate.
To keep track of that information you could use an additional variable that gets updated every time there is a ".
int quoted = 0;
while (...) {
if (*src == '"') {
// set `quoted` to 1 or 0, as appropriate
...
}
// delete only if !quoted
...
}
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 was practicing some programming problems and tried to code the popular "reverse words in a string" problem.
I tried to come up with my own code in C. I am able to partially get it right. That is, "hello world" becomes "world olleh". I am wondering what the bug is here. I think somewhere I am creating an off by 1 bug.
As much as possible, I wanted to do it without using library functions. I searched here for this problem & found many solutions, but I'd like to know why my solution doesn't work.
Here is the code:
#include <stdio.h>
#include <string.h>
void reverse(char*, int);
int main(int argc, char **argv)
{
char st[]= "hello world";
int len = strlen(st);
int i=0,j=0;
reverse(st,len-1); // Reverse the entire string. hello world => dlrow olleh
while(st[j]){ //Loop till end of the string
if ( *(st+j) == ' ' || *(st+j) == '\0' ) { //if you hit a blank space or the end of the string
reverse(st+i,j-1); // reverse the string starting at position i till position before the blank space i.e j-1
i=++j; //new i & j are 1 position to the right of old j
}
else {
j++; //if a chacacter is found, move to next position
}
}
printf("%s",st);
return 0;
}
void reverse(char *s, int n)
{
char *end = s+n; //end is a pointer to an address which is n addresses from the starting address
char tmp;
while (end>s) //perform swap
{
tmp = *end;
*end = *s;
*s = tmp;
end--;
s++;
}
}
Thank you!
UPDATE: Based on #Daniel Fischer's answer, here is the correct implementation : http://ideone.com/TYw1k
The problem is that
while(st[j]){ //Loop till end of the string
if ( *(st+j) == ' ' || *(st+j) == '\0' )
the while condition prevents the loop being entered at the end of the string, so the last word doesn't get reversed again.
You can either make it an infinite loop, and add an
if (st[j] == '\0') break;
after the reversing, or reverse the last word after the while loop was left.
You have an off by one error indeed: the call
reverse(st+i,j-1);
should be
reverse(st+i,j-i-1);
Your code passes j-1 which is the length from the beginning of the string to the position of the last space; it should be the length of the last word, so you need to subtract the index of the first character (i.e. i).
You are also not reversing the last word (see the other answer for the details on that).
I think that you want to reverse words in a string, not reverse the whole string and then rereverse single words. So, delete first reverse and then apply suggested changes above.
#include <stdio.h>
#include <string.h>
void reverse(char*, int);
int main(int argc, char **argv)
{
char st[]= "hello world";
int i=0, j=0;
while(st[j]){ //Loop till end of the string
if ( st[j] == ' ') { //if you hit a blank space or the end of the string
reverse(&st[i], j - i - 1); // reverse the string starting at position i till position before the blank space i.e j-1
i = ++j; //new i & j are 1 position to the right of old j
}
else {
j++; //if a chacacter is found, move to next position
}
}
reverse(&st[i], j - i - 1);
printf("%s\n",st);
return 0;
}
void reverse(char *s, int n)
{
char *end = s + n; //end is a pointer to an address which is n addresses from the starting address
char tmp;
while (end > s) //perform swap
{
tmp = *end;
*end = *s;
*s = tmp;
end--;
s++;
}
}
Take care when input string would be '\0' or something like ' Hello world'. Above code doesn't managed this kind of situations. Think about it!
#RBK: You first take a string, reverse it, then based on specific words you again reverse them.
I followed a slightly different approach of doing this. I take the string then reverse if required otherwise i copy the same word as it is.
int main(int argc, char*argv[])
{
char *p,st[]= "hello world";
char buf[12]={0};
char fstr[12]={0};
int i=0,j=0,k=0,l=0;
for(p=st;*p!='\0';p++){
//Get the Word
buf[i++] = *p;
//Parse the Word
if(*p == ' ' || *(p+1) == '\0'){
buf[i]='\0';
j=i-1;
i=0; //reset counter
if(k){ //reverse word and copy
while(j>=i){
fstr[l++]=buf[j--];
}
k=0;
}
else{ //copy same word
while(i<=j){
fstr[l++]=buf[i++];
}
i=0; //reset counter
k=1;
}
}
}
fstr[l]='\0';
printf("%s\n",fstr);
return 0;
}