Deleting whitespace up to first valid character C - c

I basically have want to remove all the leading whitespace before the first valid character in an array.
For example if I have something like ' 1.6, 1.7', I want it to be '1.6, 1.7' or if it was just '1.7, 1.8', then it would be '1.7, 1.8'
This is my method for the whitespace, however it only shows where the whitespace are. I need help removing it.
char **storeArray
void Students::removeSpace()
{
int MAX_SIZE = 30;
for(int i=0; i<3; i++)
{
for(int j=0; j<MAX_SIZE; j++)
{
if(isspace(storeArray[i][j]) && !(isspace(storeArray[i][j++])
{
// I NEED HELP HERE. I'M TRYING TO REMOVE ALL THE LEADING WHITESPACE ONLY
}
}
}
}

To remove extra white-space, march through the string:
void Remove_Leading_ExtraMiddle_Trailing_Whitespace(char *s, int size) {
char *end = &s[size];
char *t = s;
// skip leading
while (isspace(*s))
s++;
// middle
for (;;) {
while (!isspace(*s) && *s != '\0') {
*t++ = *s++;
}
if (*s == '\0')
break;
*t = *s++;
while (isspace(*s))
s++;
if (*s == '\0') {
break;
}
t++;
}
// end
while (t < end) {
*t++ = '\0';
}
}
void removeSpace() {
int MAX_SIZE = 30;
char storeArray[4][MAX_SIZE];
for (int i = 0; i < 3; i++) {
Remove_Leading_ExtraMiddle_Trailing_Whitespace(storeArray[i], MAX_SIZE);
}
}

Try something like this:
#include <stdio.h>
int main()
{
char storeArray[20] = " Check it out.";
int whitespace = 0;
printf("%s\n", storeArray);
//Count leading whitespace
for(int i=0; i<20; i++)
{
if(storeArray[i] == ' ' || storeArray[i] == '\t')
whitespace++;
else
break;
}
//Shift everything left
for(int i=0; i<20; i++)
{
if (i+whitespace < 20)
storeArray[i] = storeArray[i+whitespace];
else
storeArray[i] = 0;
}
printf("%s\n", storeArray);
return 0;
}

If you're sure that the c-strings are not longer than MAX_SIZE and if they are null terminated strings:
for(int i=0; i<3; i++)
{
int j=0;
while (j<MAX_SIZE && isspace(storeArray[i][j])
j++;
if (j==MAX_SIZE) // oops ! Not null terminated and only whitespace ?
storeArray[i][0]='\0';
else if (j>0) // if no leading whiespace do nothing !
strcpy (storeArray[i], &storeArray[i][j]); // if you like c style
}
If you are working in C++ (as the Student::removeSpace() suggest), and if you really don't want to work with std::string, then you could consider replace all this with:
for(int i=0; i<3; i++)
copy(find_if(storeArray[i], storeArray[i] + MAX_SIZE, [](char c){ return c && !isspace(c); }), storeArray[i] + MAX_SIZE, storeArray[i]);
Edit: If you want to avoid moving your strings, and if you can afford to change the string pointers (i.e.you didn't dynamically allocate the strings), then you could do as well:
for(int i=0; i<3; i++)
for (int j=MAX_SIZE-1; j>=0 && isspace(*storeArray[i]); j--)
storeArray[i]++; // no move or copy, but original pointer lost forever

You can either keep strtrimws as a separate function or incorporate its contents within your Students::removeSpace function. The following function can be used with or without assigning the return. Examples: strtrimws (somestring); or char *newstring = strtrimws (somestring); Also note, while the original string 's' is modified by the function, the start address for 's' is unchanged making it safe for use with dynamically allocated strings. Shown below in context with your removeSpace function:
#include <ctype.h>
/** remove leading and trailing whitespace, original not preserved.
* this funciton can be used with or without assigning the return.
*/
char *strtrimws (char *s)
{
char *sp = s; /* start pointer to return */
char *p = s; /* pointer to parse string */
while (isspace (*s)) s++; /* skip leading whitespace */
while (*s) *p++ = *s++; /* reindex s to end */
while (isspace (*p)) *p-- = 0; /* null-terminate from end */
return sp;
}
char **storeArray;
void Students::removeSpace()
{
int i = 0;
for(int i=0; i<3; i++)
strtrimws (storeArray[i]);
}
NOTE: if you have initialized all pointers to zero/NULL in storeArray before assigning strings to (some or all) of the pointers-to-char you can simplify/improve removeSpace by eliminating the hardcoded number of iterations for i and replacing it with a simple:
void Students::removeSpace()
{
int i = 0;
while (storeArray[i])
strtrimws (storeArray[i++]);
}
Example of funciton in use:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
/** remove leading and trailing whitespace, original not preserved.
* this funciton can be used with or without assigning return.
*/
char *strtrimws (char *s)
{
char *sp = s; /* start pointer to return */
char *p = s; /* pointer to parse string */
while (isspace (*s)) s++; /* skip leading whitespace */
while (*s) *p++ = *s++; /* reindex s to end */
while (isspace (*p)) *p-- = 0; /* null-terminate from end */
return sp;
}
int main (int argc, char **argv)
{
if (argc < 2) {
fprintf (stderr, "\n error: insufficient input. Usage: %s char* char* ... (max 5)\n\n", argv[0]);
return 1;
}
char array[5][50] = {{0}};
int i = 0;
for (i = 1; i < argc; i++)
{
strncpy (array[i-1], argv[i], strlen (argv[i]));
printf ("\n array[%d] '%s'\n", i, strtrimws (array[i-1]));
}
return 0;
}
output:
$ ./bin/stripwsarray " string 1 ws " " string 2 ws " " string 3 ws "
array[0] 'string 1 ws'
array[1] 'string 2 ws'
array[2] 'string 3 ws'

Related

remove the "\n" from string

I'm learning C recently and I didn't learn about pointers so still not allowed to use it.
Note: i'm not allowed to use it or any function from string.h library.
I wrote a function that removes the "\n" from a string.
when I run my program appears to me:
main.c:20:14: warning: comparison between pointer and integer
main.c:80:39: warning: format not a string literal and no format arguments [-Wformat-security]
This is my function:
#include <stdio.h>
#define STRING_SIZE 100
void replace(char str[]){
int i=0;
while(str[i]!='\0'){
if(str[i]=="\n"){
str[i]='\0';
}
}
}
int my_strlen(char s[]) {
int i = 0;
while (s[i] != '\0') {
i++;
}
return i;
}
int remover(char s1[], char s2[], char s3[]) //removes the sustring s2 from string s1 and saved it to s3
{
int i = 0, j, t = 0, found;
while (s1[i])
{
found = 1;//Initilize found to true
for (j = 0; s2[j] != 0; j++) {
if (s1[i + j] != s2[j])
found = 0;//Set not found
}
if (found == 0) {
s3[t] = s1[i];// if not found add char to s3.
t++;
}
else {
i = i + my_strlen(s2) - 1;//if found skip
}
i++;
}
s3[t] = 0;
if (my_strlen(s1) > my_strlen(s3)) {
return 1;
}
return 0;
}
int main() {
char result_string[STRING_SIZE+1], MainString[STRING_SIZE+1], PatternString[STRING_SIZE+1];
printf("Please enter the main string..\n");
fgets(MainString, STRING_SIZE + 1, stdin);
replace(MainString);
printf("Please enter the pattern string to find..\n");
fgets(PatternString, STRING_SIZE + 1, stdin);
replace(PatternString);
int is_stripped = remover(MainString, PatternString, result_string);
printf("> ");
printf(is_stripped ? result_string : "Cannot find the pattern in the string!");
return 0;
}
what's the problem?
You have a lot of problems:
Your function returns a char, which is a single character.
A C-style string has to have a terminating zero byte. You don't put one on helper. So even if you could return it properly, the code that got it would have no way to know how long the string was.
You allocate helper on the stack in replace, so helper stops existing when you return. So where will the returned string be stored?
Just remove the '\n' from the string, in place, modifying the original string.
For instance:
void remove_newline(char str[])
{
int i;
for(i=0; str[i] != 0; ++i)
{
if (str[i] == '\n')
{
str[i] = 0;
break;
}
}
}

Remove all '\' from a string in C

I am trying to get rid of all \ characters in a string in C. For example, if a string is co\din\g it should convert the string to coding.
So far I have the code
for(i = 0; i < strlen(string); ++i){
if(string[i] == '\'){
}
}
That looks to see if there is a backslash. I don't know how I would do to remove the backslash, however. My only idea is to set the next character equal to the current character, however, I don't know how changing the length of the string would work with memory.
like this:
#include <stdio.h>
int main(){
char st[] = "co\\din\\g";
int k = 0;
for (int i = 0; st[i] != '\0'; ++i)
if (st[i] != '\\')
st[k++] = st[i];
st[k] = '\0';
fputs(st, stdout);
return 0;
}
This works. Since you're only deleting characters, you can write back into the same string. At the end, the termination '\0' will move to a lower index, and the rest of the array will simply be ignored by printf. Also, \ is the escape character, so to pass the \ itself you must write \\.
#include <stdio.h>
void nukechar(char s[], char c)
{
size_t j = 0;
for (size_t i = 0; s[i] != '\0'; ++i) {
if (s[i] != c) {
s[j] = s[i];
++j;
}
}
s[j] = '\0';
}
int main(void)
{
char s[200];
while (fgets(s, 200, stdin) != NULL) {
nukechar(s,'\\');
printf("%s", s);
}
return 0;
}
The simplest solution would be to use a second string for the result:
#include <stdio.h>
#include <string.h>
int main(void)
{
char result[100] = {'\0'}, string[] = "co\\din\\g";
for(int i = 0, j = 0; i < strlen(string); i++)
{
if(string[i] != '\\')
result[j++] = string[i];
}
printf("%s %s\n", result, string);
return 0;
}
Result
$ gcc main.c -o main.exe; ./main.exe;
coding co\din\g
Note
It is necessary to use double backslashes, \\, so the character following the backslash is not interpreted as an escape sequence.

C program copy string without using strcpy() with enough memory

I am trying to have this output:
Comparing results of concat and strcat ...
strcmp("Plain old stringTroy", "Plain old stringTroy") says: 0
The strcmp returns 0 if the two string arguments are identical. If the result is 0, then the concat behaves exactly like the library function strcat.
this is what I have for concat method.
#define MAXSIZE 32
void concat(char dest[], char src[])
{
int i=length(src);
int j=0;
for(j; j<src[j] !='\0'; j++) {
dest[i+j] = src[j];
}
dest[i+j] = '\0';
}
length method is:
int length(char str[])
{
// Add code here to return the length of the
// string str without using the strlen function
// Do not count the null character '\0'
// in computing the length of the string
int len=0;
int i;
for(i=0;i<str[i];i++) {
len++;
}
return len;
}
This is my main
int main()
{
// Variable declarations for all parts
char str2[] = "Troy";
char str4[] = "Plain old string";
char str6[MAXSIZE];
// Part 6
printf("\n----- Part 6 -----\n");
// Make a copy of the destination string first, to be reused later
strcpy(str6, str4);
concat(str4, str2);
strcat(str6, str2);
printf("Comparing results of concat and strcat ...\n");
printf("strcmp(\"%s\", \"%s\") says: %d\n",
str4, str6, strcmp(str4, str6)
);
return 0;
}
This is my output when I run it:
----- Part 6 -----
Comparing results of concat and strcat ...
strcmp("PlaiTroy", "Plain old stringTroy") says: -1
The first string is not the same as the second string which is why I am getting a -1. My problem is in my concat method but I can't seem to understand why it won't execute well. Is it because of the spaces? Is 0 and '\0' not executing well?
There are multiple problems in your code:
The loop test in the length function is incorrect: instead of i < str[i], it should be:
for (i = 0; str[i] != '\0'; i++)
the same problem in the concat function. Change the loop to:
for (j = 0; src[j] != '\0'; j++) {
also in the concat function, i should be the length of dst, not that of src. You might use len instead of i for this variable.
The array str4 in function main does not have any space available at the end for concat to append anything. Define it with a larger size this way:
char str4[MAXSIZE] = "Plain old string";
Here is the corrected version:
#include <stdio.h>
#include <string.h>
#define MAXSIZE 32
void concat(char dest[], char src[]) {
int len = length(dest);
int j;
for (j = 0; src[j] != '\0'; j++) {
dest[len + j] = src[j];
}
dest[len + j] = '\0';
}
int length(char str[]) {
int len = 0;
int i;
for (i = 0; i < str[i]; i++) {
len++;
}
return len;
}
int main(void) {
// Variable declarations for all parts
char str2[MAXSIZE] = "Troy";
char str4[MAXSIZE] = "Plain old string";
char str6[MAXSIZE];
// Part 6
printf("\n----- Part 6 -----\n");
// Make a copy of the destination string first, to be reused later
strcpy(str6, str4);
concat(str4, str2);
strcat(str6, str2);
printf("Comparing results of concat and strcat ...\n");
printf("strcmp(\"%s\", \"%s\") says: %d\n",
str4, str6, strcmp(str4, str6));
return 0;
}
You have several problems in both functions:
concat
for(j; j<src[j] !='\0'; j++) {
What is the for exit condition here?, src[j] != '\0' is enough.
dest[i+j] = src[j];
Here you add data with an offset of i, but I is the length of src, not dst.
So the corrected function could be:
void concat(char dest[], char src[])
{
/* descriptive variable name */
int len_dst = length(dst);
int j=0;
/* clear exit condition */
for(; src[j] != '\0'; j++) {
dest[len_dst+j] = src[j];
}
dest[len_dst+j] = '\0';
}
length
for(i=0;i<str[i];i++) {
Same remark, what is this exit condition? src[i] != '\0' is enough
So the corrected function could be:
int length(char str[])
{
int len=0;
int i;
/* clear exit condition */
for ( i=0; str[i] != '\0'; i++) {
len++;
}
return len;
}
main
And warning in main function:
char str4[] = "Plain old string";
concat(str4, str2); /* <- erases what is after str4 */
You do not have enough space to store result. Write something like:
char str2[] = "Troy";
char str4[MAXSIZE] = "Plain old string"; /* <-- reserve spaces after str4*/
/* ... */
concat(str4, str2);

Pushing characters in char array to index 0

I'm trying to build a string from f, being split at whitespace and read it into a struct.
f is the char array I'm iterating over.
I then copy the contents from tmp into ra1.callsign, and essentially empty the tmp char array.
What I want to do is have the the tmp variable start building from index 0 again, so that when I try to strcpy the second time round all the characters in tmp start from index 0.
The way I have it now, when it tries the line: strcpy(ra1.location, tmp) it doesn't copy anything, I think this is because at that point the first character in tmp doesn't appear until some time down the array.
char c;
char tmp[1000];
for (i = 0; i < len; ++i) {
c = f[i];
if (c != ' ') {
tmp[i] = c; //build string to be added
}
//add string to data structure
if (c == ' ') {
if (addTo == CALLSIGN) {
strncpy(ra1.callsign, tmp, strlen(tmp));
memset(tmp, '\0', strlen(tmp));
}
if (addTo == LOCATION) {
strcpy(ra1.location, tmp);
}
++addTo;
}
}
Hope this is clear enough, thanks.
You left out quite a few details in your code and I have made a number of assumptions.
So, using the assumptions that I have made (which you can see in the code below), I believe that this will do what you are trying to accomplish. There are much easier and cleaner ways to do this, but I am hoping that you can get a clear understanding of how it would work with your code.
I have basically added a terminating null character where it is required so the strlen() function will work correctly and utilized an extra variable called cur_size which can be used as an offset based on the current index i.
#include <string.h>
#include <stdio.h>
#define CALLSIGN 3U
#define LOCATION 5U
#define ARRAY_SIZE 50U
typedef struct
{
char callsign[ARRAY_SIZE];
char location[ARRAY_SIZE];
} MyStruct;
MyStruct ra1 = { .callsign = {0}, .location = {0} };
char f[] = "This is my character array. Let's see what happens.";
int main (void)
{
char c;
char tmp[ARRAY_SIZE];
unsigned char addTo = 0;
unsigned char i;
unsigned char cur_size = 0;
for(i = 0; i < sizeof(f); ++i)
{
c = f[i];
if(c != ' ')
{
tmp[i - cur_size] = c; //build string to be added
}
//add string to data structure
if(c == ' ')
{
tmp[i - cur_size] = '\0'; /* YOU NEED THIS FOR strlen(tmp) to work */
cur_size = i + 1;
if(addTo == CALLSIGN)
{
strncpy(ra1.callsign, tmp, strlen(tmp));
//memset(tmp, '\0', strlen(tmp));
}
else if (addTo == LOCATION)
{
strncpy(ra1.location, tmp, strlen(tmp));
}
++addTo;
}
}
for (i = 0; i < ARRAY_SIZE; i++)
{
printf("%c", ra1.callsign[i]);
}
printf("\r\n");
for (i = 0; i < ARRAY_SIZE; i++)
{
printf("%c", ra1.location[i]);
}
printf("\r\n");
return 0;
}

Replacing character in a string [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the function to replace string in C?
I am trying to replace a certain character in my string with multiple characters. Here is an example of what I am trying to do.
Say I have the string "aaabaa"
I want to replace all occurrences of the character "b" with 5 "c"s.
So when I am done, "aaabaa" becomes "aaacccccaa"
I have written the following code:
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[20] = "aaabaa";
int i, j;
for (i=0; s[i]!= '\0'; i++)
{
if (s[i] == 'b')
{
for (j=0; j<5; j++)
{
s[i+j] = 'c';
}
}
}
printf("%s\n", s);
}
My output from this function is "aaaccccc". It appears that it just overwrites the last two a's with the c's. Is there any way I would have it so that these last couple of a's dont get overwritten?
If you want to do this in general, without worrying about trying to size your buffers, you should malloc a new string just large enough to hold the result:
/* return a new string with every instance of ch replaced by repl */
char *replace(const char *s, char ch, const char *repl) {
int count = 0;
const char *t;
for(t=s; *t; t++)
count += (*t == ch);
size_t rlen = strlen(repl);
char *res = malloc(strlen(s) + (rlen-1)*count + 1);
char *ptr = res;
for(t=s; *t; t++) {
if(*t == ch) {
memcpy(ptr, repl, rlen);
ptr += rlen;
} else {
*ptr++ = *t;
}
}
*ptr = 0;
return res;
}
Usage:
int main() {
char *s = replace("aaabaa", 'b', "ccccc");
printf("%s\n", s);
free(s);
return 0;
}
Your problem is that you replace the "ccccc" into the original string thus overwriting the remaining characters after what you wish to replace... You should copy into a new string and keep track of two indices - one in each.
And be happy that you declared char s[20] larger than the size of your original string plus the replace values, as otherwise you'd have created a buffer overflow vulnerability in your critical login system :-)
Cheers,
It is necessary to declare a second char array. In below code it just copies content of array s to s1 when condition fails.
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[20] = "aaabaa";
char s1[1024];
int i, j, n;
for (i=0, n = 0; s[i]!= '\0'; i++)
{
if (s[i] == 'b')
{
for (j=0; j<5; j++)
{
s1[n] = 'c';
n++;
}
}
else
{
s1[n] = s[i];
n++;
}
}
s1[n] = '\0';
printf("%s\n", s1);
}
You can use a different variable
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[20] = "aaabaa";
char temp[20]="";
int i, j,k;
k=0;
for (i=0; s[i]!= '\0'; i++)
{
if (s[i] == 'b')
{
for (j=0; j<5; j++)
{
temp[k] = 'c';
k++;
}
}
else
{
temp[k]=s[i];
k++
}
}
printf("%s\n", temp);
}
#include <stdio.h>
#include <string.h>
int main(void)
{
char temp[20];
char s[20] = "aaabaa";
int i, j;
for (i=0; s[i]!= '\0'; i++)
{
if (s[i] == 'b')
{
strcpy(temp,s[i+1]); //copy rest of the string in this case 'aa'
for (j=0; j<5; j++)
{
s[i+j] = 'c';
}
s[i+j] = '\0'; // here we get s = "aaaccccc"
strcat(s,temp); // concat rest of the string (temp = "aa") after job is done.
// to this point s becomes s = "aaacccccaa"
}
}
printf("%s\n", s); //s = "aaacccccaa".
}
here we are using a buffer (temp) to store the rest of the string after our to be replaced character.
after the replacement is done we append it to the end.
so we get s = "aaacccccaa"
Well, if you're going to dynamically allocate the array, you will probably have to allocate a second array. This is necessary because your string s only has a fixed amount of memory allocated.
So, instead of tryig to overwrite the characters in your for loop, I would suggest incrementing a counter that told you how big your new array has to be. Your counter should start off as the size of your original string and increment by 4 each time an instance of 'b' is found. You should then be able to write a function that appropriately copies the modified string over to a new char buffer of size[counter], inserting 5 c's every time a 'b' is being found.
Use this function :
char *replace(char *st, char *orig, char *repl) {
static char buffer[4096];
char *ch;
if (!(ch = strstr(st, orig)))
return st;
strncpy(buffer, st, ch-st);
buffer[ch-st] = 0;
sprintf(buffer+(ch-st), "%s%s", repl, ch+strlen(orig));
return buffer;
}
for your case : printf("%s\n", replace(s,"b","ccccc"));

Resources