The problem is that when I try to reverse a word, there are some words that prints out with unspecified and random characters. I tried to change the string size and the results change (some words make up random characters and some no)
#include <stdio.h>
#include <string.h>
#define LEN 20
void reverse( char w[LEN]);
int main() {
char word[LEN];
reverse(word);
return 0;
}
void reverse (char w[LEN]){
char rev[LEN];
int i,j;
fgets(w, LEN, stdin);
for (i = 0, j = strlen(w)-1; i < strlen(w); i++, j--){
rev[j] = w[i];
}
printf("%s\n", rev);
return;
}
An example of my problem is this:
Input: bathroom
Output: moorhtabp⬧⬧oz⬧
Every time I execute the program, with the same input the output changes.
You simply need to add a '\0' or 0 at the end of rev to terminate it.
for (i = 0, j = strlen(w)-1; i < strlen(w); i++, j--)
{
rev[j] = w[i];
}
rev[i] = 0;
There are a few errors:
fgets() add an newline \n at the end of the string.
You must add a string terminator (0 byte) after the last character.
(Lesser issue) Using strlen() in the loop condition will iterate over the string multiple times. It usually results in O(N^2) algorithms.
Fixes:
Variant A
Use scanf to parse a single word
scanf(" %19s", w)
The specifier %19s scans up to 19 characters and add NULL terminator to fix 20-char-long array
Variant B
Check if the last character of w is \n. If so, replace it with zero.
int L = strlen(w);
if (L > 0 && w[L - 1] == '\n') {
w[--L] = 0;
}
Just put
rev[i] = 0;
at the end.
Just iterate until j is negative, meaning it reached the "one before first" character and there is nothing more to do.
for (i = 0, j = L-1; j >= 0; i++, j--)
rev[j] = w[i];
For starters the call of the function
char word[LEN];
reverse(word);
does not make a sense because neither string is passed to the function. You passed an uninitialized character array.
The function should do only one thing: reverse the passed string.
So the call of fgets should be removed from the function and placed in main.
The function fgets can append the new line character '\n' to the entered string. You need to remove it.
Within the function reverse you forgot to append the terminating zero character '\0' to the reversed string. So this call
printf("%s\n", rev);
invokes undefined behavior.
Also the type of the returned value of the standard C function strlen is the unsigned integer type size_t. You should use this type instaed of the signed integer type int.
And this declaration of the function
void reverse( char w[LEN])
also does not make a great sense because the compiler will adjust it to the following declaration
void reverse( char *w)
and in general the user can pass to the function a string of any length that can be greater than the value LEN.
Below there is a demonstrative program that shows how the function can be written.
#include <stdio.h>
#include <string.h>
char * reverse( char *s )
{
for ( size_t i = 0, n = strlen( s ); i < n / 2; i++ )
{
char c = s[i];
s[i] = s[n - i - 1];
s[n - i - 1] = c;
}
return s;
}
int main(void)
{
enum { N = 20 };
char s[N];
fgets( s, N, stdin );
s[ strcspn( s, "\n" ) ] = '\0';
puts( s );
puts( reverse( s ) );
return 0;
}
If to enter string "Hello World!" then the program output will be
Hello World!
!dlroW olleH
Related
The task is for the user to insert a string and the program will output a secret message, that changes each occurrence of a character of that string with another character. The list of new characters that will be inserted are given by the permutation "qjczieaungsdfxmphybklortvw", which correspond to every letter of the alphabet. So for example, the string "abcxyz" will return "qjctvw". The program will ignore symbols and capital letters, so "Abc" will become "Ajc".
I tried to achieve this by comparing each position of the string with each letter of the alphabet. If it matches, then that position of the string will be replaced by the position of the secret permutation that is the same as the position of the traditional alphabet (since they correspond). The code technically works, but I'm not getting the right values. For instance, for every "a" I should get a "q", but I'm returned a "h". If anyone can fix my code, it will be greatly appreciated.
CODE BELOW: PLEASE COPY AND PASTE INTO YOUR PREFERRED CODE EDITOR TO SEE WHAT I MEAN BY RETURNING THE WRONG VALUES.
#include <string.h>
#define MAX_STR_LEN 256
int main(void)
{
char perm[] = "qjczieaungsdfxmphybklortvw";
char alphabet[] = "abcdefghijklmnopqrstuvwxyz";
int i, j;
char msg[MAX_STR_LEN+1];
/* read the message from the terminal using fgets. The variable msg will contain the message. */
fgets(msg, MAX_STR_LEN, stdin);
/*compares each value of the string to the alphabet*/
for (i = 0; i < (strlen(msg) - 1); i++) {
for (j = 0; j < (strlen(alphabet) - 1); j++) {
if (msg[i] == alphabet[j]) {msg[i] = perm[j];}
}
}
printf("%s", msg);
}
For starters after the call of fgets
fgets(msg, MAX_STR_LEN, stdin);
you need to remove the new line character '\n' that can be appended to the entered string by the function.
msg[ strcspn( msg, "\n" ) ] = '\0';
Also the for loops are incorrect.
At least instead of using the condition
j < (strlen(alphabet) - 1)
in the inner for loop
for (j = 0; j < (strlen(alphabet) - 1); j++) {
if (msg[i] == alphabet[j]) {msg[i] = perm[j];}
}
you need to use the condition
j < strlen(alphabet)
and when a character is found in the string alphabet you have to exit the loop. Otherwise the already changed character can be changed the second time.
You can use the function strchr instead of the manually written inner for loop. For example
/*compares each value of the string to the alphabet*/
for ( size_t i = 0; msg[i] != '\0'; i++ )
{
const char *p = strchr( alphabet, msg[i] );
if ( p != NULL )
{
msg[i] = perm[p - alphabet];
}
}
Here is your updated program.
#include <stdio.h>
#include <string.h>
#define MAX_STR_LEN 256
int main( void )
{
const char *perm= "qjczieaungsdfxmphybklortvw";
const char *alphabet= "abcdefghijklmnopqrstuvwxyz";
char msg[MAX_STR_LEN+1];
/* read the message from the terminal using fgets. The variable msg will contain the message. */
fgets( msg, MAX_STR_LEN, stdin );
msg[ strcspn( msg, "\n" ) ] = '\0';
/*compares each value of the string to the alphabet*/
for ( size_t i = 0; msg[i] != '\0'; i++ )
{
const char *p = strchr( alphabet, msg[i] );
if ( p != NULL )
{
msg[i] = perm[p - alphabet];
}
}
puts( msg );
}
If to enter the string
abcxyz
then the program output is
qjctvw
This task can be very easy once you get to the root of the problem and observe that:
Your alphabet replacements string is just a simple array having letter values mapped to indexes from 0 to 25.
Characters themselves have some integer values specified by the ASCII standard, and they happen to be conscutive ('b'=='a'+1).
Having this knowledge, we can invent a function that takes a character and converts it to the correct position in the perm string. We can do that in a extremely simple manner, by just subtracting 'a' from whatever character we have. 'a'-'a' will be equal to 0, and so on.
This can be implemented as a function like this: (or you can just inline it, since it's pretty trivial)
int get_char_index(char c){
return c - 'a';
}
And now, having access to this function, all we need to do is to iterate over a string character by character (for loop, while loop, doesn't matter), read the char from the string, feed it to the function, and then once you get the corresponding index of the perm, you just need to assign the value of char under that index back to the string.
int main() {
const char perm[] = "qjczieaungsdfxmphybklortvw";
char some_string_to_convert[] = "aabbccddeeffgghhiijjkkllmmnnoopprrssttqqvvwhatever";
for(int i=0; i<strlen(some_string_to_convert); i++){
char c = some_string_to_convert[i];
int perm_index = get_char_index(c);
some_string_to_convert[i] = perm[perm_index];
}
printf("%s", some_string_to_convert);
}
The following code outputs:
qqjjcczziieeaauunnggssddffxxmmppyybbkkhhooruqkioiy
I hope my answer helps you solve the problem.
I'm trying to do a function in C language that it's checking if a String is palindromic (read the same way from the begging to the end and backwards ) . So I use the puts() function to print the String backwards and after a number of elements (>7) it prints some unwanted characters.
My routine is :
void isPal ( char ptr[], int i){
char array[i];
int j=0,k=0;
int l = i-1;
for (j=0; j<i ; j++){
array[j] = ptr[l]; printf("%c\t", array[j] );
printf("Character :%c -> [%d]\n", array[j],l );
l--;
}
printf("\nThe upside string is : ");
puts(array);
for (k=0; k<i ; k++){
if ( array[k] != ptr[k]){
printf("\nNot palindromic!!!\n");
return;
}
}
printf("\nIS PALINDROMIC..\n");
}
The result is accurate but the printing isn't right . Why that ?
The created array does not contain a string because there is no the terminating zero in the array.
Also there is no need to define an auxiliary array to determine whether the passed string is a palindrome.
Creating a variable length array within the function is unsafe and can result in a stack overflow. Apart from this the user of the function can pass to the function the second argument less than or equal to 0. In this case the function will have undefined behavior.
The function should do only one thing i.e. to determine whether the passed string is a palindrome.
It is the caller of the function that will decide what message to output if any.
The function parameter that specifies the array should have the qualifier const because the passed string is not being changed in the function.
The function can be defined the following way
int isPal ( const char *s )
{
size_t n = strlen( s );
size_t i = 0;
while ( i < n / 2 && s[i] == s[n-i-1] ) ++i;
return i == n / 2;
}
Here is a demonstrative program.
#include <stdio.h>
#include <string.h>
int isPal ( const char *s )
{
size_t n = strlen( s );
size_t i = 0;
while ( i < n / 2 && s[i] == s[n-i-1] ) ++i;
return i == n / 2;
}
int main(void)
{
const char *s = "123454321";
printf( "The string \"%s\" is %sa palindrome.\n",
s, isPal( s ) ? "" : "not " );
return 0;
}
Its output is
The string "123454321" is a palindrome.
Just replace char array[i]; with following two lines:
char array[i+1];
array[i] = '\0';
puts() takes string as an argument. In c, string is basically a character array with '\0' at the end. So, when we add '\0' at the end of array[] it becomes a string and as a result puts() does not show any unpredictable behaviour.
I'm trying to write a program that reverses a string inputted by the user.
Enter a sentence: you can cage a swallow can't you
Reversal of sentence: you can't swallow a cage can you
So I thought about scanning for the string character by character. Then copying the string from the end to the beginning into a new string. At this point, I know that I've got a new word every time I see a space, so I have to invert the order of the letters that are between two spaces. Here's my code:
#include <stdio.h>
#include <string.h>
int main(){
char sentence[64], reversal[64], reversal_copy[64];
int i = 0, index = 0;
printf("Enter a sentence: ");
while(sentence[strlen(sentence)-1]!= '\n'){
scanf("%c", &sentence[i]);
i++;
}
printf("Reversal of sencente: ");
for(int h = strlen(sentence) - 2, k = 0; h >= 0; h++, k++){
reversal[k] = sentence[h];
strcpy(reversal_copy, reversal);
if(sentence[h] == ' '){
for(int m = h; m >= index && m <= h; m--, index++){
reversal[m] = reversal_copy[index];
}
}
}
printf("Reversal of sentence: %s\n\n", reversal);
return 0;
}
I get a segmentation fault error and I believe it happens around here:
for(int h = strlen(sentence) - 2, k = 0; h >= 0; h++, k++){
reversal[k] = sentence[h];
but I don't quite get why. Could you help me with this?
The condition for your first loop to continue is h >= 0, and as you are incrementing h each time this is going to keep getting bigger until it exceeds the size of sentence and throws the error.
If your intention for that loop is to work backwards through sentence then I think you should decrement h and k (h--, k--), but if the intention is to work forwards through sentence then your condition needs to be changed so that the loop finishes once h has reached the end of sentence
The word order can be reversed using a recursive function.
#include <stdio.h>
#include <string.h>
void reverse ( char *str, char *original) {
char temp[strlen ( str) + 1];
temp[0] = 0;
int offset = 0;
if ( 1 == sscanf ( str, "%s%n", temp, &offset)) {
reverse ( str + offset, original);//recursive call
}
else {//at the end of the original string
*original = 0;//set zero at first character
return;
}
//as recursion unwinds, concatenate the words
strcat ( original, temp);
if ( str != original) {//will be false when unwinds reaches first iteration
strcat ( original, " ");
}
return;
}
int main( void) {
char text[] = "you can cage a swallow can't you";
printf ( "%s\n", text);
reverse ( text, text);
printf ( "%s\n", text);
return 0;
}
For starters:
During the while-loop's 1st iteration strlen() is called on an un-initialised variable. This invokes undefined behaviour. Anything can happen.
In any case of updating a char-array character by character you completely ignore the fact that a 0-terminator is necessary to make a char-array a C-string. Only a C-string may be passed to (most of the) str*() functions.
Also scanf() might fail. Test for this.
I am blocked at solving a problem in the book.
The problem is:
read a word and output the string backwards, and output it backwards,
you should print the palindrome if it is the same as the original.
Also, do not use a library such as string.h, but include stdio.h
only.
So I created the code below.
#include <stdio.h>
int main()
{
char str[128];
char temp;
int leng = 0;
char a;
scanf("%s", str);
{
a = str;
}
while(str[leng] != '\0')
leng++;
for (int i = 0; i < leng/2; i++)
{
temp = str[i];
str[i] = str[leng - i - 1];
str[leng - i - 1] = temp;
}
printf("%s\n", str);
{
if (a == str)
printf("palindrome\n");
}
return 0;
}
The output in reverse order was easily solved, but I blocked in the process at printing palindrome. I tried to print the palindrome only when the input and output values are the same.
However, if (a == str) I used was a code to compare address values.
Also,I thought that it would be useful to implement strcmp as a loop, but I can not find a way to compare the input value with the output value using strcmp.
Is there a way to compare the input and output values in C? Or is there a way to make palindrome print only under certain circumstances (input = output)?
I am wondering if I can code the input value = output value in C exactly.
Note that my code prints the palindrome when the address values are the same. So I haven't seen yet :(
Here is a loosely written untested code that should resolve your issues.
char str[128];
if( fgets( str, 128, stdin ) )
{
/* I hate this but restriction on string.h
Calculate the size of this string */
size_t s_len = 0;
char *p = str;
for( ; *p && *p != '\n' ; p++ )
s_len++;
/* trim down nextLine characters */
if( p && *p == '\n' )
{
*p = '\0';
}
if( s_len == 0 )
{
/* Should never be the case here */
exit(0);
}
/* This should handle both cases of reversing and pallindrom */
int isPallindrom = 1; /* Lets Say Yes for now*/
for( size_t i = 0, j = s_len-1; i < j ; i ++, j -- )
{
if( str[i] != str[j] )
isPallindrom = 0; // Not a pallindrom
swap( str, i, j); // Write a swap function here
}
/* at this point you should have
1. a reversed string in a
2. based on isPallindrom value a confirmation if it really a pallindrom */
}
There are some fundamental errors in your code for instance
a = str;
if (a == str)
turn on warnings while compilation to catch these well before execution.
edit - swap for you.
void swap( char *s, size_t i, size_t j )
{
char t = s[i];
s[i] = s[j];
s[j] = t;
}
Use this function:
int compare(char *str1, char *str2)
{
while(*str1 && *str2){
if(*str1 == *str2){
str1++;
str2++;
}
else return (*str2 - *str1);
}
if(*str1)
return -1;
if(*str2)
return 1;
return 0;
}
Logic:
Until '\0' is encountered in one of the strings, check the character in either string. If the characters are equal, continue. Otherwise, return a negative number of the character in string1 > string2, or a positive number if the character in string1 < string2.
Once a '\0' is encountered, check if string1 has any more characters. If yes, it is the greater string, hence return a negative number.
If string1 doesn't have any more characters, check string2. If that too has no more characters, return 0. Otherwise return a positive number.
I am trying to make a program which takes in a input of "Hello" and outputs "olleH" from reversing the order of the characters. However I keep getting a segmentation fault and I don't understand why
#include <stdio.h>
#include<string.h>
int main()
{
int i;
int size;
char s[100],a[100];
printf("Enter the word you want to get reversed: ");
scanf("%s",s);
while(s[i]!='\0')
{
a[i]=s[i];
i++;
}
size=sizeof(s);
while(i<sizeof(s))
{
s[i]=a[size];
}
printf("The reversed string is : %s",s);
}
Another simple way to reverse string.
Try this:
while(s[++i]!='\0'); // find the size of string
while(i>=0)
a[j++] = s[--i]; // reverse the string
a[j]='\0';
printf("The reversed string is : %s",a);
This while loop
while(i<sizeof(s))
{
s[i]=a[size];
}
does not make sense because index i has a value that points to outside the entered string (provided that it was initially correctly initialized) and the loop is infinite because i is not changed (and was not initially initialized) in the loop and also the right hand expression of this statement
s[i]=a[size];
is always the same and again refers memory outside the array.
Take into account that neither function declared in <string.h> is used in the program. So the header may be removed.
The program can look the following way
#include <stdio.h>
#define N 100
int main()
{
char s[N], d[N];
printf( "Enter the word you want to get reversed: " );
fgets( s, N, stdin );
size_t n = 0;
while ( s[n] != '\0' && s[n] != '\n' ) n++;
for ( size_t i = 0; i != n; i++ ) d[i] = s[n-i-1];
d[n] = '\0';
printf( "The reversed string is : %s\n", d );
return 0;
}
You can reverse a string without using an auxiliary array. For example
#include <stdio.h>
#define N 100
int main()
{
char s[N];
printf( "Enter the word you want to get reversed: " );
fgets( s, N, stdin );
size_t n = 0;
while ( s[n] != '\0' && s[n] != '\n' ) n++;
s[n] = '\0';
for ( size_t i = 0; i < n / 2; i++ )
{
char c = s[i];
s[i] = s[n-i-1];
s[n-i-1] = c;
}
printf( "The reversed string is : %s\n", s );
return 0;
}
The problem is in this part:
size=sizeof(s);
while(i<sizeof(s))
{
s[i]=a[size];
}
sizeof(s) will be 100 whereas the string you read from input can be less than that -- which would be undefined if you access uninitialized parts of s. So, you want to use strlen() to get the actual size of the string and use it to reverse.
Notice that scanf() is unsafe as it's written (what if you input more than 100 chars?). Suggest using fgets() instead.