THE MESSAGE:
/usr/local/webide/runners/c_runner.sh: line 54: 20533 Segmentation fault
nice -n 10 valgrind --leak-check=full --log-file="$valgrindout" "$exefile"
I can't understand why I can't use pointer arithmetic when my function type is not void. Take a look at this example:
Let's say I have to write a function that would 'erase' all whitespaces before the first word in a string.
For example, if we had a char array:
" Hi everyone"
it should produce "Hi everyone" after the function's modification.
Here is my code which works fine when instead of
char* EraseWSbeforethefirstword() I have
void EraseWSbeforethefirstword.
When the function returns an object char* it can't even be compiled.
char* EraseWSbeforethefirstword(char *s) {
char *p = s, *q = s;
if (*p == ' ') { /*first let's see if I have a string that begins with a space */
while (*p == ' ') {
p++;
} /*moving forward to the first non-space character*/
while (*p!= '\0') {
*q = *p;
p++;
q++;
} /*copying the text*/
*q = '\0'; /*If I had n spaces at the beginning the new string has n characters less */
}
return s;
}
Here is a function implementation that has the return type char * as you want.
#include <stdio.h>
char * EraseWSbeforethefirstword( char *s )
{
if ( *s == ' ' || *s == '\t' )
{
char *p = s, *q = s;
while ( *p == ' ' || *p == '\t' ) ++p;
while ( ( *q++ = *p++ ) );
}
return s;
}
int main(void)
{
char s[] = "\t Hello World";
printf( "\"%s\"\n", s );
printf( "\"%s\"\n", EraseWSbeforethefirstword( s ) );
return 0;
}
The program output is
" Hello World"
"Hello World"
Take into account that you may not modify string literals. So the program will have undefined behavior if instead of the array
char s[] = "\t Hello World";
there will be declared a pointer to a string literal
char *s = "\t Hello World";
If you want that the function could deal with string literals then the function has to allocate a new array dynamically and to return a pointer to its first element.
If you may not use standard C string functions then the function can look the following way
#include <stdio.h>
#include <stdlib.h>
char * EraseWSbeforethefirstword( const char *s )
{
size_t blanks = 0;
while ( s[blanks] == ' ' || s[blanks] == '\t' ) ++blanks;
size_t length = 0;
while ( s[length + blanks] != '\0' ) ++length;
char *p = malloc( length + 1 );
if ( p != NULL )
{
size_t i = 0;
while ( ( p[i] = s[i + blanks] ) != '\0' ) ++i;
}
return p;
}
int main(void)
{
char *s= "\t Hello World";
printf( "\"%s\"\n", s );
char *p = EraseWSbeforethefirstword( s );
if ( p ) printf( "\"%s\"\n", p );
free( p );
return 0;
}
Related
I'm writing this function to return a char pointer of reversed string.
void * PreverseStr (char str[])
{
int size = strlen (str);
char *returnstr = (char *)malloc (size * sizeof(char));
for (int i = size - 1; i >= 0 ; i--)
{
*returnstr = str[i];
returnstr ++;
}
returnstr = 0;
returnstr -= size;
return returnstr ;
}
To test this function I wrote a main function like this
int main()
{
char str[] = "abcdefghijklmnopqrstuvwxyz";
char *newstr = PreverseStr(str);
printf("Reversed string using pointer: %s\n", newstr);
free(newstr);
return 0;
}
But it crashes before it could print out anything. I wonder what's wrong with my code. It would be much helpful if you can explain a fix to this.
For starters the return type void * makes no sense. The return type should be char *. As the function creates a new string without changing the source string then the function parameter should have the qualifier const.
This memory allocation
char *returnstr = (char *)malloc (size * sizeof(char));
allocates not enough space tp store the terminating zero character '\0' of the source string.
You need to write at least
char *returnstr = (char *)malloc ( ( size + 1 ) * sizeof(char));
After the for loop the pointer returnstr points to beyond the allocated memory because it is increased within the loop
returnstr ++;
Moreover after this assignment
returnstr = 0;
it becomes a null pointer.
The function can be declared and defined the following way
char * reverse_copy( const char s[] )
{
size_t n = strlen( s );
char *p = malloc( n + 1 );
if ( p != NULL )
{
p += n;
*p = '\0';
while ( n-- )
{
*--p = *s++;
}
}
return p;
}
Here is a demonstration program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *reverse_copy( const char s[] )
{
size_t n = strlen( s );
char *p = malloc( n + 1 );
if (p != NULL)
{
p += n;
*p = '\0';
while (n--)
{
*--p = *s++;
}
}
return p;
}
int main( void )
{
const char *s = "Hello, World!";
puts( s );
char *p = reverse_copy( s );
if (p) puts( p );
free( p );
}
Its output is
Hello, World!
!dlroW ,olleH
I', learning C and I'm getting no output for some reason, probably I don't return as I should but how I should? (described the problem in the comments below :D)
Any help is appreciated!
#include <stdio.h>
#include <ctype.h>
#include <string.h>
char *makeUpperCase (char *string);
int main()
{
printf(makeUpperCase("hello")); //Here there is no output, and when I'm trying with the format %s it returns null
return 0;
}
char *makeUpperCase(char *string)
{
char str_out[strlen(string) + 1];
for (int i = 0; i < strlen(string); ++i)
str_out[i] = toupper(string[i]);
printf(str_out); //Here I get the output.
return str_out;
}
You declared within the function a local variable length array that will not be alive after exiting the function
char str_out[strlen(string) + 1];
So your program has undefined behavior.
If the function parameter declared without the qualifier const then it means that the function changes the passed string in place. Such a function can be defined the following way
char * makeUpperCase( char *string )
{
for ( char *p = string; *p != '\0'; ++p )
{
*p = toupper( ( unsigned char )*p );
}
return string;
}
Otherwise you need to allocate dynamically a new string. For example
char * makeUpperCase( const char *string )
{
char *str_out = malloc( strlen( string ) + 1 );
if ( str_out != NULL )
{
char *p = str_out;
for ( ; *string != '\0'; ++string )
{
*p++ = toupper( ( unsigned char )*string );
}
*p = '\0';
}
return str_out;
}
Here is a demonstration program.
#include <stdop.h>
#include <stdlib.h>
#include <string.h>
char *makeUpperCase( const char *string )
{
char *str_out = malloc( strlen( string ) + 1 );
if (str_out != NULL)
{
char *p = str_out;
for (; *string != '\0'; ++string)
{
*p++ = toupper( ( unsigned char )*string );
}
*p = '\0';
}
return str_out;
}
int main( void )
{
char *p = makeUpperCase( "hello" );
puts( p );
free( p );
}
The program output is
HELLO
The problem is that printf() is buffering output based on a bit complex mechanism. When you are outputting to a terminal, printf() just buffers everything until the buffer fills (which is not going to happen with just the string "hello", or until it receives a '\n' character (which you have not used in your statement)
So, to force a buffer flush, just add the following statement
fflush(stdout);
after your printf() call.
I want to know how to count how many words are in a string.
I use strstr to compare and it works but only works for one time
like this
char buff = "This is a real-life, or this is just fantasy";
char op = "is";
if (strstr(buff,op)){
count++;
}
printf("%d",count);
and the output is 1 but there are two "is" in the sentence, please tell me.
For starters you have to write the declarations at least like
char buff[] = "This is a real-life, or this is just fantasy";
const char *op = "is";
Also if you need to count words you have to check whether words are separated by white spaces.
You can do the task the following way
#include <string.h>
#include <stdio.h>
#include <ctype.h>
//...
size_t n = strlen( op );
for ( const char *p = buff; ( p = strstr( p, op ) ) != NULL; p += n )
{
if ( p == buff || isblank( ( unsigned char )p[-1] ) )
{
if ( p[n] == '\0' || isblank( ( unsigned char )p[n] ) )
{
count++;
}
}
}
printf("%d",count);
Here is a demonstration program.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(void)
{
char buff[] = "This is a real-life, or this is just fantasy";
const char *op = "is";
size_t n = strlen( op );
size_t count = 0;
for ( const char *p = buff; ( p = strstr( p, op ) ) != NULL; p += n )
{
if ( p == buff || isblank( ( unsigned char )p[-1] ) )
{
if ( p[n] == '\0' || isblank( ( unsigned char )p[n] ) )
{
count++;
}
}
}
printf( "The word \"%s\" is encountered %zu time(s).\n", op, count );
return 0;
}
The program output is
The word "is" is encountered 2 time(s).
Parse the string, in a loop.
As OP has "but there are two "is" in the sentence", it is not enough just to look for "is" as that occurs 4x, twice in "This". Code needs to parse the string for the idea of a "word".
Case sensitively is also a concern.
char buff = "This is a real-life, or this is just fantasy";
char op = "is";
char *p = buff;
char *candidate;
while ((candidate = strstr(p, op)) {
// Add code to test if candidate is a stand-alone word
// Test if candidate is beginning of buff or prior character is a white-space.
// Test if candidate is end of buff or next character is a white-space/punctuation.
p += strlen(op); // advance
}
For me, I would not use strstr(), but look for "words" with isalpha().
// Concept code
size_t n = strlen(op);
while (*p) {
if (isalpha(*p)) { // Start of word
// some limited case insensitive compare
if (strnicmp(p, op, n) == 0 && !isalpha(p[n]) {
count++;
}
while (isalpha(*p)) p++; // Find end of word
} else {
p++;
}
}
Hello and sorry if this questions is already answered (in the way I want to :-) ) but I think I have a memory problem.
Assuming the following C function (yes, this one is very dirty and not optimized):
char *strreplace(char **str, char *dst, char *replace) {
int replacestart = stringcompare(*str, dst), replaceend = strlen(dst), replacelen = strlen(replace);
char *tmp1 = (char *)malloc(sizeof(char) * (replacestart + 1)), *tmp2 = (char *)malloc(sizeof(char) * ((strlen(*str) - replaceend) + 1));
memset(tmp1, 0, sizeof(char) * (replacestart + 1));
memset(tmp2, 0, sizeof(char) * ((strlen(*str) - replaceend) + 1));
strncpy(tmp1, *str, replacestart);
strncpy(tmp2, *str + replacestart + replaceend, (strlen(*str) - (replaceend + replacestart)));
*str = realloc(*str, strlen(tmp1) + replacelen + strlen(tmp2));
memset(*str, 0, strlen(tmp1) + replacelen + strlen(tmp2));
strncpy(*str, tmp1, strlen(tmp1));
strncpy(*str + strlen(tmp1), replace, replacelen);
strncpy(*str + strlen(tmp1) + replacelen, tmp2, strlen(tmp2));
return *str;
}
As seen, it should replace *dst with *replace whithin **str.
This works basically as expected. Here's the problem:
The output (*str) is not cleard out with zeros after memsetting it and has still the wrong length, even after reallocating.
Means, if the string is longer after replacing, the last chars are cutted of *str.
In turn, if the string is shorter, old chars are at the end of the char string are found.
What did I wrong. Mentioned that I don't want to use sprintf and no C++-STL, just want to do this with pointers in C.
Other words, what would be the right way to replace a string in an c char string with pointers.
Thanks alot.
EDIT after reqeuest for more information
I use this function as following:
...open a textfile via FILE type, determining file lengts (fseek)...
char *filecontent = (char *)malloc(sizeof(char) * filesize);
if(filesize != fread(filecontent, sizeof(char), filesize, fd)) {
free(filecontent);
return -1;
}
streplace(&filecontent, "[#TOBEREPLACED#]", "replaced");
...doing other stuff with filecontent...
EDIT 2, adding stringcompare()
int stringcompare(const char *string, const char *substr) {
int i, j, firstOcc;
i = 0, j = 0;
while(string[i] != '\0') {
while(string[i] != substr[0] && string[i] != '\0') {
i++;
}
if(string[i] == '\0') {
return -1;
}
firstOcc = i;
while(string[i] == substr[j] && string[i] != '\0' && substr[j] != '\0') {
i++;
j++;
}
if(substr[j] == '\0') {
return firstOcc;
}
if(string[i] == '\0') {
return -1;
}
i = firstOcc + 1;
j = 0;
}
}
The logic of the function is not simple as it seems at the first glance.
You should decide what action to execute 1) if the source string is empty and 2) if the destination string is empty.
For example if the destination string is empty then the standard function strstr will return the address of the first character of the source string. However logically if dst is an empty string then the source string should not be changed except the case when it is in turn an empty string. In this case the function should just create a new string equal to the string replace.
Take into account that as the strings dst and replace are not changed within the function they should be declared with the qualifier const.
char * strreplace( char **str, const char *dst, const char *replace );
Also the function should report whether a new memory allocation was successful within the function by returning a null pointer in case when the allocation failed.
Taking all this into account the function can look the following way as it is shown in the demonstrative program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * strreplace( char **str, const char *dst, const char *replace )
{
char *result = *str;
if ( *str[0] == '\0' )
{
if ( dst[0] == '\0' && replace[0] != '\0' )
{
char *result = malloc( strlen( replace ) + 1 );
if ( result )
{
strcpy( result, replace );
free( *str );
*str = result;
}
}
}
else if ( dst[0] != '\0' )
{
char *pos = strstr( *str, dst );
if ( pos != NULL )
{
size_t dst_n = strlen( dst );
size_t replace_n = strlen( replace );
result = ( char * )malloc( strlen( *str ) - dst_n + replace_n + 1 );
if ( result )
{
size_t n = pos - *str;
strncpy( result, *str, n );
strcpy( result + n, replace );
strcpy( result + n + replace_n, *str + n + dst_n );
}
free( *str );
*str = result;
}
}
return result;
}
int main(void)
{
const char *hello = "Hello everybody here";
char *str = malloc( sizeof( char ) );
str[0] = '\0';
if ( strreplace( &str, "", hello ) )
{
puts( str );
}
if ( strreplace( &str, "everybody", "Eurobertics" ) )
{
puts( str );
}
if ( strreplace( &str, "Hello", "Bye" ) )
{
puts( str );
}
if ( strreplace( &str, " here", "" ) )
{
puts( str );
}
if ( strreplace( &str, "Bye ", "" ) )
{
puts( str );
}
free( str );
return 0;
}
The program output is
Hello everybody here
Hello Eurobertics here
Bye Eurobertics here
Bye Eurobertics
Eurobertics
Your function looks overly complex. Here is a simple, working version:
char *strreplace(char **str, char *dst, char *replace) char *strreplace(char **str, char *dst, char *replace)
{
char *start, *tmp;
int n;
if ((start=strstr(*str,dst))==0) return(0);
n= (start-*str) + strlen(start+strlen(dst)) + strlen(replace) + 1;
tmp=malloc(n);
strncpy(tmp,*str,start-*str);
strcpy(tmp+(start-*str),replace);
strcat(tmp,start+strlen(dst));
free(*str);
*str= tmp;
return(tmp);
}
With test function:
void reptest(void)
{
char *src;
char rep[]= "brave new world";
src=malloc(strlen("Hello world of wonders")+1);
strcpy(src,"Hello world of wonders");
strreplace(&src,"world",rep);
printf("%s\n", src);
free(src);
}
Edit: my previous version forgot to copy the remainder. Fixed.
i want to replace "\ " for every space when copying a string in C.
This is needed for call function system(), it identifies spaces as "\ ".
So every space should be replace by that.
#include <stdio.h>
char *my_strcopy(char *destination,char *source){
char *p;
p=destination;
while(*source != '\0'){
if(*source == ' '){
*p='\\';
*p++='\\';
*p++='\\';
*p++=' ';
}
else{
*p=*source;
}
*p++;
*source++;
}
*p='\0';
return destination;
}
The output of this come as "hello\ �world\ �hi"
how to get the it correctly. need help
I think you are adding too many \ for each space when your requirement is to only have one. You were also incrementing the destination pointer more often than necessary. Finally, it is not necessary to deference the pointers at the bottom of the loop while incrementing them, although it does not hurt.
The following correction seems to produce the output you want.
#include <stdio.h>
char *my_strcopy(char *destination,char *source){
char *p;
p=destination;
while(*source != '\0'){
if(*source == ' '){
*p++='\\';
*p=' ';
}
else{
*p=*source;
}
p++;
source++;
}
*p='\0';
return destination;
}
int main(){
char* src = "foobar bar bar";
char dst[2048];
my_strcopy(dst, src);
printf("%s\n", dst);
}
Output:
foobar\ bar\ bar
If I have understood correctly then the function can look like
char * my_strcopy( char *destination, const char *source )
{
char *p = destination;
do
{
if ( *source == ' ' ) *p++ = '\\';
*p++ = *source;
} while ( *source++ );
return destination;
}
Here is a demonstrative program
#include <stdio.h>
char * my_strcopy( char *destination, const char *source )
{
char *p = destination;
do
{
if ( *source == ' ' ) *p++ = '\\';
*p++ = *source;
} while ( *source++ );
return destination;
}
int main()
{
char s[] = "Hello world hi";
char d[sizeof( s ) + 2];
puts( s );
puts( my_strcopy( d, s ) );
return 0;
}
The program outputs is
Hello world hi
Hello\ world\ hi
I hope the function does not contain any redundant code.:) The body of the function loop contains only two statements.:)