String works but prints random symbols - c

I want my program to display reversed string using pointers. It is working but it is also showing random symbols. Soo.. how can I make it show only the reversed string?
Example: input - hello , output - olleh.
#include <stdio.h>
int main(void)
{
char string[30];
printf("Enter string: ");
scanf("%s",&string);
int x =sizeof(string)/sizeof(string[0]);
char *p1 = string;
char *p2 = &string[x-1];
char temp;
while(p1<=p2)
{
temp = *p1;
*p1 = *p2;
*p2 =temp;
p1++;
p2--;
}
for(p1 =&string[0];p1<=&string[x - 1];p1++)
{
printf("%c",*p1);
}
return 0;
}

the problem is in calculating the string length
it does not matter the length of input this statement
int x =sizeof(string)/sizeof(string[0]);
will always return 30.
you can do two things to solve this problem
you can #include<string.h> and use strlen(string) to get the actual length.
you can write your own function that calculates the length and it will look like this
int string_length(char s[]) {
int c = 0;
while (s[c] != '\0')
c++;
return c;
}
Sample of working code using strlen
#include <stdio.h>
#include <string.h>
int main(void)
{
char string[30];
printf("Enter string: ");
scanf("%s",string);
int x =strlen(string);
printf("%d\n", x); // here the length of the input will be printed.
char *p1 = string;
char *p2 = &string[x-1];
char temp;
while(p1<=p2)
{
temp = *p1;
*p1 = *p2;
*p2 =temp;
p1++;
p2--;
}
for(p1 =&string[0];p1<=&string[x - 1];p1++){
printf("%c",*p1);
}
return 0;
}
for input "asd" the result will be "dsa".
Sample of working code using string_length function
#include <stdio.h>
int string_length(char s[]) {
int c = 0;
while (s[c] != '\0')
c++;
return c;
}
int main(void)
{
char string[30];
printf("Enter string: ");
scanf("%s",string);
int x =string_length(string);
printf("%d\n", x); // here the length of the input will be printed.
char *p1 = string;
char *p2 = &string[x-1];
char temp;
while(p1<=p2)
{
temp = *p1;
*p1 = *p2;
*p2 =temp;
p1++;
p2--;
}
for(p1 =&string[0];p1<=&string[x - 1];p1++){
printf("%c",*p1);
}
return 0;
}
for input "asd" the result will be "dsa".

This call of scanf
scanf("%s",&string);
is incorrect. The second argument has the type char( * )[30] instead of char *.
You should write
scanf("%29s",string);
The variable x keeps the size of the array itself instead of the stored string
int x =sizeof(string)/sizeof(string[0]);
Instead you should write
#include <string.h>
//...
size_t x = strlen( string );
The condition in the while loop should look like
while(p1 < p2)
instead of
while(p1<=p2)
because there is no great sense to swap a character with it itself.
The program can look the following way
#include <stdio.h>
#include <string.h>
int main(void)
{
char string[30];
printf("Enter string: ");
if ( scanf( "%29s", string ) == 1 )
{
char *p1 = string;
char *p2 = string + strlen( string );
if ( p1 != p2 )
{
for ( ; p1 < --p2; ++p1 )
{
char c = *p1;
*p1 = *p2;
*p2 = c;
}
}
for ( p1 = string; *p1 != '\0'; ++p1 )
{
printf( "%c", *p1 );
}
putchar( '\n' );
}
return 0;
}
You could write a separate function that reverse a string using pointers. Just move the code shown in the demonstration program in a function. For example
#include <stdio.h>
#include <string.h>
char * reverse_string( char *s )
{
char *p1 = s;
char *p2 = s + strlen( s );
if ( p1 != p2 )
{
for ( ; p1 < --p2; ++p1 )
{
char c = *p1;
*p1 = *p2;
*p2 = c;
}
}
return s;
}
int main(void)
{
char string[30];
printf("Enter string: ");
if ( scanf( "%29s", string ) == 1 )
{
puts( reverse_string( string ) );
}
return 0;
}

Apart from abysmal formatting of the code, the "right end" of the "string" was set to the limit of the buffer size, not the actual end of the string entered by the user.
Here's a cleaned-up, annotated version for your consideration:
#include <stdio.h>
int main() {
char buf[100]; // name variable better
printf("Enter string: ");
fgets( buf, sizeof buf, stdin ); // use fgets(), not scanf()
char *pS = buf, *pE = buf; // two pointers, initialised
// find the end of the string with-or-without LF
while( *pE && *pE != '\n' ) pE++; // newline
if( *pE == '\n' ) *pE = '\0'; // clobber possible newline
pE--;
// swap characters, meeting in the middle
while( pS < pE ) {
char tmp = *pE;
*pE-- = *pS;
*pS++ = tmp;
}
printf( "%s\n", buf ); // output
return 0;
}
You can guess what the output is like.
.ekil si tuptuo eht tahw sseug nac uoY

Related

Why my returned value of strchr is ignored?

I have to make a function, that will code my sentence like this: I want to code all words with an o, so for example I love ice cream becomes I **** ice cream.
But my function ignores the result of strchr. And I don't know why.
This is my code:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#define LEN 1000
char *Shift(char *str, char *let) {
const char *limits = " ,-;+.";
char copy[LEN];
strcpy(copy, str);
char *p;
char *ptr;
ptr = strtok(copy, limits);
for (int j = 0; ptr != NULL; ptr = strtok(NULL, limits), ++j) {
int len = 0;
if (strchr(ptr, let) != NULL) {
p = strstr(str, ptr);
for (int i = 0; i < strlen(ptr); i++) {
p[i] = "*";
}
}
}
return str;
}
int main() {
char *s = Shift("I love my cocktail", "o");
puts(s);
}
Expected output is: I **** my ********
but I've got just printed the original string
For starters the function strchr is declared like
char *strchr(const char *s, int c);
that is its second parameter has the type int and the expected argument must represent a character. While you are calling the function passing an object of the type char * that results in undefined behavior
if (strchr(ptr, let) != NULL) {
It seems you mean
if (strchr(ptr, *let) != NULL) {
Also you may not change a string literal. Any attempt to change a string literal results in undefined behavior and this code snippet
p = strstr(str, ptr);
for (int i = 0; i < strlen(ptr); i++) {
p[i] = "*";
}
tries to change the string literal passed to the function
char *s = Shift("I love my cocktail", "o");
And moreover in this statement
p[i] = "*";
you are trying to assign a pointer of the type char * to a character. At least you should write
p[i] = '*';
If you want to change an original string you need to store it in an array and pass to the function the array instead of a string literal. For example
char s[] = "I love my cocktail";
puts( Shift( s, "o" ) );
Pay attention to that there is no great sense to declare the second parameter as having the type char *. Declare its type as char.
Also the function name Shift is confusing. You could name it for example like Hide or something else.
Here is a demonstration program.
#include <stdio.h>
#include <string.h>
char * Hide( char *s, char c )
{
const char *delim = " ,-;+.";
for ( char *p = s += strspn( s, delim ); *p; p += strspn( p, delim ) )
{
char *q = p;
p += strcspn( p, delim );
char *tmp = q;
while ( tmp != p && *tmp != c ) ++tmp;
if ( tmp != p )
{
for ( ; q != p; ++q ) *q = '*';
}
}
return s;
}
int main( void )
{
char s[] = "I love my cocktail";
puts(s);
puts( Hide( s, 'o' ) );
}
The program output is
I love my cocktail
I **** my ********
The for loop
for ( ; q != p; ++q ) *q = '*';
within the function can be rewritten as a call of memset
memset( q, '*', p - q );
There are multiple problems:
copying the string to a fixed length local array char copy[LEN] will cause undefined behavior if the string is longer than LEN-1. You should allocate memory from the heap instead.
you work on a copy of the string to use strtok to split the words, but you do not use the correct method to identify the parts of the original string to patch.
you should pass a character to strchr(), not a string.
patching the string with p[i] = "*" does not work: the address of the string literal "*" is converted to a char and stored into p[i]... this conversion is meaningless: you should use p[i] = '*' instead.
attempting to modify a string literal has undefined behavior anyway. You should define a modifiable array in main and pass the to Shift.
Here is a corrected version:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *Shift(char *str, char letter) {
const char *limits = " ,-;+.";
char *copy = strdup(str);
char *ptr = strtok(copy, limits);
while (ptr != NULL) {
if (strchr(ptr, letter)) {
while (*ptr != '\0') {
str[ptr - copy] = '*';
ptr++;
}
}
ptr = strtok(NULL, limits);
}
free(copy);
return str;
}
int main() {
char s[] = "I love my cocktail";
puts(Shift(s, 'o'));
return 0;
}
The above code still has undefined behavior if the memory cannot be allocated. Here is a modified version that operates in place to avoid this problem:
#include <ctype.h>
#include <stdio.h>
#include <string.h>
char *Shift(char *str, char letter) {
char *ptr = str;
while ((ptr = strchr(ptr, letter)) != NULL) {
char *p = ptr;
while (p > str && isalpha((unsigned char)p[-1]))
*--p = '*';
while (isalpha((unsigned char)*ptr)
*ptr++ = '*';
}
return str;
}
int main() {
char s[] = "I love my cocktail";
puts(Shift(s, 'o'));
return 0;
}
Note that you can also search for multiple characters at a time use strcspn():
#include <ctype.h>
#include <stdio.h>
#include <string.h>
char *Shift(char *str, const char *letters) {
char *ptr = str;
while (*(ptr += strcspn(ptr, letters)) != '\0') {
char *p = str;
while (p > str && isalpha((unsigned char)p[-1]))
*--p = '*';
while (isalpha((unsigned char)*ptr)
*ptr++ = '*';
}
return str;
}
int main() {
char s[] = "I love my Xtabentun cocktail";
puts(Shift(s, "oOxX"));
return 0;
}

C: print the longest common prefix

Beginner programmer here, trying to figure out how to find and print the longest common prefix in C.
I have a base here for the program.
#include <stdio.h>
void findprefix(char *str1, char *str2, char *found);
int main(void) {
char str1[100];
char str2[100];
char found[10] = { '\0' };
printf("\nGive string 1: ");
scanf("%99s", str1);
printf("\nGive string 2: ");
scanf("%99s", str2);
//Print prefix
findprefix(str1, str2, found);
printf("%s", found);
return 0;
}
//Function to find the longest common prefix
void findprefix(char *str1, char *str2, char *found) {
int i, j;
for () {
if () {
}
}
}
The initial idea is to use a for loop and an if statement in the function but I'm not sure how.
This declaration
char found[10] = { '\0' };
is redundant and does not make a sense.
Also the function findprefix should return the length of the common prefix.
The function should be declared and defined the following way
size_t findprefix( const char *str1, const char *str2 )
{
size_t n = 0;
for ( ; *str1 && *str1 == *str2; ++str1, ++str2 )
{
++n;
}
return n;
}
And in main you can write
size_t n = findprefix( str1, str2 );
if ( n != 0 ) printf( "%.*s\n", ( int )n, str1 );
Here is a demonstration progarn.
#include <stdio.h>
size_t findprefix( const char *str1, const char *str2 )
{
size_t n = 0;
for ( ; *str1 && *str1 == *str2; ++str1, ++str2 )
{
++n;
}
return n;
}
int main( void )
{
const char *str1 = "Hello Word!";
const char *str2 = "Hello Kallum Smith";
size_t n = findprefix( str1, str2 );
if ( n != 0 ) printf( "\"%.*s\"\n", ( int )n, str1 );
return 0;
}
The program output is
"Hello "
Using the return value of the function you also can dynamically allocate an array or declare a variable length array where you can copy the prefix if it is required.
You have a good base, except you should define prefix with a length of 100 for pathological cases.
In the function, you should iterate with an index i starting at 0, comparing the characters from str1 and str2 at offset i and stop when they differ or when either one is a null byte (a char with the value 0), otherwise copying the byte to the found array at the same offset i.
After the loop. you would store a null byte in found at the offset where you stopped the iteration.
Finally, you would return to the caller.
Here is an example:
#include <stdio.h>
//Function to extract the longest common prefix
int findprefix(const char *str1, const char *str2, char *found) {
int i;
for (i = 0; str1[i] == str2[i] && str1[i] != '\0'; i++) {
found[i] = str1[i];
}
found[i] = '\0';
return i;
}
int main(void) {
char str1[100];
char str2[100];
char prefix[100];
printf("\nGive string 1: ");
if (scanf("%99s", str1) != 1)
return 1;
printf("\nGive string 2: ");
if (scanf("%99s", str2) != 1)
return 1;
//Print prefix
findprefix(str1, str2, prefix);
printf("%s\n", prefix);
return 0;
}

How to scanf a string until specific word occurs

Input: I want to be something END. END is is that specific word. I need to store all my words.
do
{
scanf("%s", row[p]);
p++;
}while(strcmp(niz,'END')!=0);
Is this the right way ?
#include<stdio.h>
#include<string.h>
/*Description: How to scanf a string until a specific word occurs*/
int main(){
char row[6][10];
int p=0;
//I want to be something END. ( 6 words for input.)
printf("Please enter a word.\n");
/*
do
{
scanf("%s", row[p]);
p++;
}while(strcmp(row[p],"END")!=0);
//Above loop runs forever(or until row runs out of space), because p increments after info is read
*/
do
{
scanf("%s", row[p]);
p++;
}while(strcmp(row[p-1],"END")!=0);
//This loop ends once string just read in from keyboard/user equals "END"
return 0;
}
If I have understood your question correctly then you need something like the following.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
char * string_toupper( char *s )
{
for ( char *p = s; *p; ++p ) *p = toupper( ( unsigned char )*p );
return s;
}
int main( void )
{
enum { N = 50 };
char word[N];
char tmp[N];
const char *s = "one two three four end five";
for ( int offset = 0, pos = 0;
sscanf( s + offset, "%s%n", word, &pos ) == 1 && strcmp( string_toupper( strcpy( tmp, word ) ), "END" ) != 0;
offset += pos )
{
puts( word );
}
}
The program output is
one
two
three
four
Or something like the following
#include <stdio.h>
#include <ctype.h>
#include <string.h>
char * string_toupper( char *s )
{
for ( char *p = s; *p; ++p ) *p = toupper( ( unsigned char )*p );
return s;
}
int main( void )
{
enum { N = 50 };
char word[N];
for ( char tmp[N]; scanf( "%s", word ) == 1 && strcmp( string_toupper( strcpy( tmp, word ) ), "END" ) != 0; )
{
puts( word );
}
}
If to enter
one two three four end
then the output will be
one
two
three
four

Reverse String function in C without library functions

This is my task:
Realize function that reverses null terminated string. The prototype of the function is void Reverse(char *ptr);. Do not use standard library functions.
This is my code for now:
void Reverse(char *ptr) {
char *newString;
char ch = *ptr;
unsigned int size = 0;
for (int i = 1; ch != '\0'; i++) {
ch = *(ptr + i);
size++;
}
newString = (char*)malloc(size);
for (int left = 0, right = size - 1; left < size; left++, right--) {
*(newString + left) = *(ptr + right);
}
printf("%s", newString);
printf("\n");
}
It reverses the string and saves it in the newString
My first problem is that when I print the newString to see if the functions works the string is reversed, but after it there are some symbols.
For example:
If I have char *str = "hello"; and Reverse(str); in the main method
the result of printf("%s", newString) will be olleh****.
But if change the
newString = (char*)malloc(size); to
newString = (char*)malloc(1); it works fine.
My second problem is that I don't know how to save the newString into the given one. I am using a new String because the given one can't be changed.
For starters it is better to declare the function like
char * Reverse( char *ptr );
^^^^^^
because standard C string functions usually return pointers to destination strings.
The function should reverse the original string. It may not create a dynamic string because the caller of the function will be unable to free it provided that the function has return type void.
The function can look as it is shown in the following demonstrative program.
#include <stdio.h>
char * Reverse( char *ptr )
{
char *first = ptr, *last = ptr;
while ( *last ) ++last;
if ( first < last )
{
for ( ; first < --last; ++first )
{
char c = *first;
*first = *last;
*last = c;
}
}
return ptr;
}
int main( void )
{
char s[] = "Hello World!";
puts( s );
puts( Reverse( s ) );
return 0;
}
Its output is
Hello World!
!dlroW olleH
Take into account that you may not call the function like
puts( Reverse( "Hello World!" ) );
because string literals are immutable in C.
If you are going to declare the function like
void Reverse( char *ptr );
then just remove the return statement in the shown function. For example
#include <stdio.h>
void Reverse( char *ptr )
{
char *first = ptr, *last = ptr;
while ( *last ) ++last;
if ( first < last )
{
for ( ; first < --last; ++first )
{
char c = *first;
*first = *last;
*last = c;
}
}
}
int main( void )
{
char s[] = "Hello World!";
puts( s );
Reverse( s )
puts( s );
return 0;
}
If to use your approach with indices then the function can look like
#include <stdio.h>
void Reverse( char *ptr )
{
size_t size = 0;
while ( *( ptr + size ) ) ++size;
if ( size != 0 )
{
for ( size_t left = 0, right = size - 1; left < right; left++, right-- )
{
char c = ptr[left]; // or char c = *( ptr + left ); and so on
ptr[left] = ptr[right];
ptr[right] = c;
}
}
}
int main( void )
{
char s[] = "Hello World!";
puts( s );
Reverse( s );
puts( s );
return 0;
}
In your loop to get the size, you're not counting the null terminator. So your newString is missing the null terminator as well. make sure to do newString = malloc(size + 1);, and to place the null terminator onto the end of newString.
You have several problems in your code:
you do not allocate enough space for the resulting string, you must allocate size+1 bytes and set the \0 terminator at the end of the string.
you only copy half the characters from ptr to newString.
you are not even supposed to allocate memory, since you cannot call any library functions. You should instead reverse the string in place.
Your test fails because modifying a string literal invokes undefined behavior. You should pass an initialized array as shown below.
Here is an improved version:
#include <stdio.h>
void Reverse(char *ptr) {
unsigned int left, right;
for (right = 0; *(ptr + right) != '\0'; right++) {
continue;
}
for (left = 0; left < right; left++, right--) {
char ch = ptr[left];
ptr[left] = ptr[right - 1];
ptr[right - 1] = ch;
}
}
int main(void) {
char buf[] = "Hello world";
Reverse(buf);
printf("%s\n", buf);
return 0;
}
It should print dlrow olleH.
Simple string reverse function without string.h library functions :
#include <stdio.h>
void reverse(char *str, int n);
int main()
{
char str[100];
int n;
printf("Enter a string\n");
scanf("%s",&str);
for( n = 0; str[n] != '\0'; n++)
{
}
reverse(str,n);
puts(str);
return 0;
}
void reverse(char *str,int n)
{
printf("Length = %d\n",n);
printf("Reversed :\n");
int i;
char ch;
for(i = 0; i<n/2; i++)
{
ch = str[i];
str[i] = str[n-i-1];
str[n-i-1] = ch;
}
}

Restarting while loop in c without integers

I'm trying to get this code to work, but I have no idea how to restart the inner while loop. How would I do it?
/*
* Return a pointer to the first occurrence of any character in <stop>
* in the given <string> or NULL if the <string> contains no characters
* in <stop>.
*****
* YOU MAY *NOT* USE INTEGERS OR ARRAY INDEXING.
*****
*/
char *find_any_ptr(char *string, char* stop) {
char *newstring = (char*)0;
while(*stop != '\0'){
while(*string != '\0') {
if(*string == *stop){
if(newstring < string || newstring != (char*)0){
string++;
}else{
newstring = string;
string++;
}
}
}
stop++;
}
return newstring; // placeholder
}
Use a temporary variable for string pointer, and use this temp variable instead inside the inner loop.
while(*stop != '\0'){
char *p = string;
while (*p != '\0') {
... /* use 'p' in place of 'string' */
}
stop++;
}
This is relatively simple using nothing but a character pointer to the string and a pointer to stop. For each character in your string, you compare against each character in stop, returning the character in string on match, or NULL if no match is found:
#include <stdio.h>
char *find_any_index(char string[], char stop[]) {
char *p = string;
char *sp = NULL;
while (*p)
{
sp = stop;
while (*sp)
{
if (*sp == *p)
return p;
sp++;
}
p++;
}
return NULL;
}
int main (int argc, char **argv) {
if (argc < 3) {
printf ("usage: %s string stoplist\n", argv[0]);
}
printf ("\n string: %s\n stop : %s\n\n", argv[1], argv[2]);
printf (" first char in string matching a char in stop: %s\n\n", find_any_index (argv[1], argv[2]));
return 0;
}
Output
$ ./bin/find_substr_str thisIsAstring mase
string: thisIsAstring
stop : mase
first char in string matching a char in stop: sIsAstring
Here is a demonstrative program that shows how the function can be written
#include <stdio.h>
char * find_any_ptr( const char *string, const char* stop )
{
const char *p, *q;
_Bool found = 0;
p = string;
do
{
q = stop;
while ( *q && *q != *p ) ++q;
} while ( !( found = *q ) && *++p );
return ( char * )( found ? p : NULL );
}
int main(void)
{
const char *p = find_any_ptr( "abc9de", "1234567890" );
if ( p ) puts( p );
return 0;
}
The program output is
9de
Only I would name the function find_any_char instead of find_any_ptr:)
This is my implementation:
#include <stdio.h>
#include <stdlib.h>
char * findany(char *string, char *stop) {
char * app;
//To avoid segmentation fault!
if (stop==NULL || string==NULL || !*stop || !*string)
return NULL;
do {
app=string;
while(*app!=0 && *app!=*stop)
app++;
stop++;
} while(*app==0 && *stop!=0);
return (*app!=0)?app:NULL;
}
int main(void)
{
char string[100];
char stop[100];
char * found;
for(;;) {
printf("Insert a string without spaces[q<Enter> to exit]: ");
scanf("%s",string);
if (!strcmp(string,"q"))
break;
printf("Insert the chars to search without spaces: ");
scanf("%s",stop);
printf("Searching any occurence of a char in \"%s\""
" inside \"%s\"\n",stop,string);
found=findany(string,stop);
printf("%s\n",(found!=NULL)?found:"NULL");
}
return 0;
}
I think that is better to use also the following way to implement the function findany():
char * _findany(char *string, char *stop) {
char * app; // to start the first loop
//To avoid segmentation fault!
if (stop==NULL || string==NULL || !*stop || !*string)
return NULL;
do {
app=stop;
while(*app!=0 && *app!=*string)
app++;
string++;
} while(*app==0 && *string!=0);
return (*app!=0)?(string-1):NULL;
}
You may observe the difference between the two functions adding the function _findany in the code above and to call the new function adding the following code after (or before) the printf in the main above.
found=_findany(string,stop);
printf("%s\n",(found!=NULL)?found:"NULL");

Resources