Unable to print string - c

How can we replace spaces in a string using pointers? I tried but unable to get it.
While replacing space with hyphen, the control is coming out of the loop without tracing further.
while (*str != '\0')
{
if (*str == ' ')
*str = '-';
str++;
}
print(str);

Pointers are special type of variables used to store address of other variables. when you changed value inside the str pointer with "str++", it then pointed to the next element and after the while loop str pointed to the last element of the string('\0'). So you must store the the address of the first character of the string to do something with it later.
int main() {
char *s = "abcde", *str =s; // s,str stores address of first character
while(*str!='\0'){
if(*str ==' ')
*str='-';
printf("%c", *str);
str= str+1; // str now points to the next character. But s remains unchanged
}
}

When you use pointers to do this and increment pointers then print(str) will show you end of str so \0.
You must store pointer to begin of str:
char* str = (char*) malloc(sizeof(char) * 255);
memcpy(str, "abc de", 255);
char* beginStr = str;
while(*str!='\0') {
if (*str == ' ') {
*str = '-';
}
str++;
}
printf("%s\n", beginStr);
free(beginStr);

Related

why this function returns null?

This code finds the next word in the string.
For example
given an input of " my cake" the function should return "my cake". as the expected output
If I use return then the output is (null), but I use printf then the code works
I would like to know how to get the expected output using return.
#include <stdio.h>
int main()
{
char* str[1000];
printf("enter:");
fgets(str,1000,stdin);
printf("%s",find_word_start(str));
}
char* find_word_start(char* str){
char* result[1000];
int c = 0, d = 0;
while(str[c] ==' ') {
c++;
}
while(str[c] != '\0'){
result[d++] = str[c++];
if(str[c]==' ') {
result[d++] = str[c++];
}
while(str[c]==' ') { //
c++;
}
}
result[d] = '\0';
//print or return char?
return result;
}
char* result[1000]; creates an array of 1000 pointers. That's wrong in a number of ways.
You want a block of 1000 chars, not pointers.
Actually, 1000 is not the number of characters you want. You usually want a smaller number, but you could also want a larger number.
You don't want to store the result in automatically allocated memory, because that will be freed as soon as you exit the function. Use malloc (or something that does a malloc such as strdup).
Fix:
// Returns a copy that needs to be freed.
char* find_word_start(const char* src) {
while (*src == ' ')
++src;
size_t len = 0;
while (str[len] != '\0')
++len;
++len; // Include NUL
result = malloc(len);
char* dst = result;
while (len--)
*(dst++) = *(src++);
return result;
}
Well, I was avoiding using string functions above like you did, but they greatly simplify the solution.
// Returns a copy that needs to be freed.
char* find_word_start(const char* src) {
while (*src == ' ')
++src;
return strdup(src);
}
That said, since you return the tail end of the string, you could simply return a pointer into the existing string.
// Returns a pointer into the provided string.
const char* find_word_start(const char* str) {
while (*str == ' ')
++str;
return str;
}
The following line allocates memory space in the stack but after the function ends everything is gone:
char result[1000];
You need to allocate memory in the heap like that:
char *result = malloc(sizeof(char) *1000);
Note: don't forget to free that memory space by free function.

Why string termination not happening at null character

Why it prints null character in second string?
Declaring character array should automatically add null character at end. Is this dependent on compiler?
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
bool ChckStrng(char *str);
void main()
{
char a[] = "hello";
char b[] = "abc";
printf("a:%d\n", ChckStrng(a));
printf("b:%d\n", ChckStrng(b));
}
bool ChckStrng(char *str)
{
int count[26];
while(str != NULL)
{
printf(":%d:\n", *str - 'a');
if(++count[*str - 'a'] > 1)
return false;
str = str + 1;
}
printf("end\n");
return true;
}
Output1:
:7:
:4:
:11:
:11:
a:0
:0:
:1:
:2:
:-97:
:-97:
b:0
You are comparing pointers here, in other words, if str is set to NULL:
while(str != NULL) /* str holds the address of a char */
You need to compare characters to the null-terminator, in other words, check whether the character str points to is the null-terminator:
while(*str != '\0')
str is a pointer which holds the address *str holds the value
bool ChckStrng(char *str)
{
int count[26];
while(*str != '\0')
{
printf(":%d:\n", *str - 'a');
if(++count[*str - 'a'] > 1)
return false;
str = str + 1;
}
printf("end\n");
return true;
}
You are comparing the value of the pointer itself instead of the value pointer points to.
while( *str != '\0' )
{
Not the difference: *str, and \0 which is a null character.
NULL is a null pointer not a null character.
Pointers are different than characters. In 'C' null termination of character array is signified by ascii value 0 or NUL

why is my 'reverse' string C function not working?

I'm trying to write a function to reverse the characters in a string in C, but it's not working.
This is what I have:
/* ... the */
char str[1000];
strcpy(&str[0], &text[0]); // get the values from existing 'char text[1000]'
if (DEBUG) printf("DEBUG: str value before reverse: %s\n", str);
// reverse the string
reverse(&str[0]);
if (DEBUG) printf("DEBUG: str value after reverse: %s\n", str);
/* ... */
After calling 'reverse', my output looks like this:
DEBUG: str value before reverse: this is a line of text
DEBUG: str value after reverse:
Here's my function:
void reverse(char * str)
{
char str2[1000];
int i = 0;
// find the null in str
while (str[i] != '\0') {
i++;
}
// now put the chars from str into str2 in the reverse order
int j = 0;
while (i >= 0) {
str2[j] = str[i];
i--;
j++;
}
str2[j] = '\0';
// now str2 contains the reverse of str, copy it to str
strcpy(&str[0], &str2[0]);
return;
}
What's wrong with it? And is there an easier way to reverse a string?
What's wrong with it?
After the first loop completes, str[i] is equal to 0. Therefore the first iteration of the second loop stores the null terminator at the first position of str2, making it effectively a string of length 0. Of course it then goes on and writes additional characters to the buffer, but those will be ignored by any function you use.
And is there an easier way to reverse a string?
Sure. For example, this implementation reverses a string in-place without allocating additional buffers:
char *strrev(char *str)
{
char *p1, *p2;
if (! str || ! *str)
return str;
for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2)
{
*p1 ^= *p2;
*p2 ^= *p1;
*p1 ^= *p2;
}
return str;
}
You start copying when str[i] is '\0', so your string will start with it and be empty.
I figured it out.
After the first while loop, i is the location of the '\0' and I'm making it the first character of str2, so str is always empty string.

Weird pointer function

void r(char *str)
{
char *new = str;
while (*str != '\0') {
if (*str != ' ') *(new++) = *str;
str++;
}
*new = '\0';
}
I have this function but i don't understand the code after the if statement .I would be grateful if somebody could explain it to me.
This function is stripping spaces out of the passed in value str.
*(new++) = *str; means take the pointer to the string new and dereference it so that we can use it to store where in memeory it points. Then take the value that is pointed to by str and dereference it to the char it points at. Assign that char to where new is and then move the new pointer along to the next spot. Finally, always move the str pointer along with str++ if ithe value is a space or not.
May be it would be clearer to you if were wrote this way:
void r(char *str)
{
char *new = str;
int newStringIndex = 0;
for(int i=0; str[i] != '\0'; i++)
{
if (str[i] != ' ')
{
new[newStringIndex++] = str[i];
}
}
new[newStringIndex] = '\0';
}
Same code functionality, but using a for loop and array indexing instead of pointer math.
the function is removing spaces (in-place) - it copies everything but spaces to the same string as before.
so the if statement is saying: "if the character in str is not a space, then copy it to new" (which is in the same memory area as str, but will start to trail behind when str meets a space).
note how str is always incremented, but new is only incremented when a character is copied. so str scans the whole string, but the data are copied to earlier in the string because new doesn't update when there's a space.
then finally a terminating null is added at new so that the shortened version terminates correctly.
This version of the program (K&R style!) is shorter and does the same:
void r(char *str)
{
char *new;
for (new=str; *new = *str++; ) {
if (*new != ' ') new++;
}
}
while (*str != '\0') {
if (*str != ' ') *(new++) = *str;
str++;
}
is equivalent to:
while (*str != '\0') {
if (*str != ' ') {
*new = *str;
new++;
}
str++;
}

How to replace whitespaces and tabs with nothing in C?

I wrote this function:
void r_tabs_spaces(char *input) {
int i;
for (i = 0; i < strlen(input); i++)
{
if (input[i] == ' ' || input[i] == '\t')
input[i] = '';
}
}
However when I compile this and run it, the compiler complains that "error: empty character constant" at line where I try to input[i] = '';
How can I do this in C then?
In C, a string is an array of bytes. You can't assign an "empty byte", but you have to shift the remainder of the bytes forward.
Here's one way of how to do that:
char *write = str, *read = str;
do {
// Skip space and tab
if (*read != ' ' && *read != '\t')
*(write++) = *read;
} while (*(read++));
Remember that literal strings in C are usually in write-protected memory, so you have to copy to the heap before you can change them. For example, this usually segfaults:
char *str = "hello world!"; // Literal string
str[0] = 'H'; // Segfault
You can copy a string to the heap with strdup (among others):
char *str = strdup("hello world!"); // Copy string to heap
str[0] = 'H'; // Works
EDIT: Per your comment, you can skip only initial whitespace by remembering the fact that you've seen a non-whitespace character. For example:
char *write = str, *read = str;
do {
// Skip space and tab if we haven't copied anything yet
if (write != str || (*read != ' ' && *read != '\t')) {
*(write++) = *read;
}
} while (*(read++));
If you have a pointer to the string
" string with leading spaces"
^ pointer
just move it ...
" string with leading spaces"
^ pointer
for example:
#include <ctype.h>
/* ... */
char mystring[] = " string with leading spaces";
char *pointer = mystring;
while (*pointer && isspace((unsigned char)*pointer)) ++pointer;
/* pointer now points to a (possibly empty) string with no leading spaces */
The way to remove a character of a string is to move the rest of the string one character back.
Use
foo += strspn(foo, " \t");
to move the pointer foo to the first character which is not a space or tab.
To actually remove the characters from a dynamically allocated string, use
size_t offset = strspn(foo, " \t");
size_t size = strlen(foo + offset) + 1;
foo = realloc(memmove(foo, foo + offset, size), size);

Resources