How to reverse an array's values and input them into another array?

161 Views Asked by At

I am trying to create a code in which the person inputs a number N between 1 to 100, so they can input N amount of words-phrases up to 20 characters. The program then finds out if the said word or phrase is a palindrome or not and outputs the answer. I am new to coding in C so I don't know if the code is right or wrong, but everytime i try to input a word-phrase that's more than 8 characters long, or includes a blank space, the program seems to bug out. The first conversion from the array words to the other array sdrow seems to work just fine, but the other seems to be in another world of it's own

#include<stdio.h>
#include<string.h>

int main() {
    int N;
    int c;
    char words[21];
    char sdrow[21];
    char verify[21];
    printf("Please give me a number which constitutes to how many words you would like to type from 1 to 100: ");
    scanf("%d", &N);

    if(N<=0 || N>100) {
        printf("Come on my guy i asked for 1 to 100 not whatever you just typed");
        return 1;
    }
    while (getchar() != '\n');
    for(int i = 0; i < N; i++){
        printf("Please Type Word %d: " , i+1);
        fgets(words, sizeof(words), stdin);
        int k = (strlen(words)-2);
        c=0;
        for(int j=0;j<=k;j++){
                if(words[j]==' '){
                    j++;
                }
                sdrow[c]=words[j];
                c++;
        }
        printf("%s\n",sdrow);
        for(int j=k;j>=0;--j){
            verify[k-j]=sdrow[j];
        }
        printf("%s\n",verify);
        int result=strcmp(verify,sdrow);
        if(result==0){
            printf("Input is a palindrome\n");
        }
        else{
            printf("Input is not a palindrome\n");
        }
    }
    return 0;
}

Successfull Input

1
stats

Successfull Output

stats \\Printing the sdrow array
stats \\Printing the verify array
Input is a palindrome

Unsuccessfull Input

1
never odd or even

Unsuccessfull Output

neveroddoreven \\sdrow array got rid of blank spaces as intended
α              \\here's where the "flipped" version of sdrow is supposed to be
Input is not a palindrome

Sometimes the output spurts out garbage , while sometimes it doesn't output anything at all

The Problem seems to be on the reversal of sdrow to verify but i don't know how to fix it. is it just bad coding or is there something else going on? Would you mind taking a little time of your day to help me out?

I've tried using a "middle man" by using a char temp to firs input the values of the sdrow array and then put them to the verify array, but it still doesn't work

3

There are 3 best solutions below

2
greg spears On

Agree -- the problem does seem to be your string reverse method. Here is string reverse code for you, tested and runnable here.

NOTE: this code over-writes the original string, so be sure to save a copy of the original string if you still need it after this runs.

#include <stdio.h>

/* sreverse() 
*  reverse a string.  Modifies source string.
*/
char *sreverse(char *s)
{
    int i=0, k=-1;
    char ch;

    while(s[++k]);  //get strlen

    for(i = 0, k-=1; k>i; i++, k--)
    {
        ch = s[k];
        s[k] = s[i];
        s[i] = ch;
    }
    return s;
}

#define SAMPLES 5

int main()
{
    char s[SAMPLES][15] = { "yobwoc", "olleh", "ocat", "racecar", "yenom" };
    int runcount = 0;

    do{
        printf("Result: %s\n", sreverse(s[runcount++]));
    }while(runcount < SAMPLES);

    return 0;
}

Output:

    Result: cowboy
    Result: hello
    Result: taco
    Result: racecar
    Result: money

Putting it all together -- here is a suggested function for using sreverse() in your program -- is_palindrome() -- returns true (1) if reversed string matches original string -- tested, runnable code is here:

#include <stdio.h>
#include <string.h>

/* sreverse() 
*  reverses a string, original string is modified
*/
char *sreverse(char *s)
{
    int i=0, k=-1;
    char ch;

    while(s[++k]);  //get strlen

    for(i = 0, k-=1; k>i; i++, k--)
    {
        ch = s[k];
        s[k] = s[i];
        s[i] = ch;
    }
    return s;
}

/* is_palindrome()  Detects a palindrome word. 
* Returns 1 if palindrome, else 0 
*/
int is_palindrome(char * s)
{
    char temp[100];
        
    strcpy(temp, s); /* save a copy */
        
    return (int)(!strcmp(s, sreverse(temp)) );  /* do the compare */
}

#define SAMPLES 5

int main()
{
    char s[SAMPLES][15] = { "kayak", "hello", "taco", "racecar", "level" };
    int runcount = 0;

    do{
        printf("Result for %s: \t%d\n", s[runcount], is_palindrome(s[runcount]));
    }while(++runcount < SAMPLES);

    return 0;
}

Output:

    Result for kayak:   1
    Result for hello:   0
    Result for taco:    0
    Result for racecar: 1
    Result for level:   1

Here is yet another implementation of is_palindrome() inspired by what stackoverflow user einpoklum said -- you don't need to reverse the string.

Yes, it is true. So I put together one more for you...

Tested, runnable code is here

#include <stdio.h>

/* is_palindrome()  
* Detects a palendrome word. Returns 1 if palindrome detected, else 0.
 */
int is_palindrome(char * s)
{
    int i=0, k=-1;

    while(s[++k]);  //get strlen

    for(i = 0, k-=1; k>i; i++, k--)
    {
        if(s[k] != s[i])
            return 0;
    }
    return 1;
}

#define SAMPLES 5

int main()
{
    char s[SAMPLES][15] = { "kayak", "hello", "taco", "racecar", "level" };
    int runcount = 0;

    do{
        printf("Result for %s: \t%d\n", s[runcount], is_palindrome(s[runcount]));
    }while(++runcount < SAMPLES);

    return 0;
}

Output:

    Result for kayak:   1
    Result for hello:   0
    Result for taco:    0
    Result for racecar: 1
    Result for level:   1
1
einpoklum On

I am trying to create a code ... the which the person inputs ... words-phrases up to 20 characters. The program then finds out if the said word or phrase is a palindrome or not and outputs the answer.

In that case, you don't need to "reverse an array's values and input them into another array". Just use a single buffer for the current word/phrase, and iterate it from both sides (forwards and backwards) to check whether you get the same sequence of elements.

This is a very common C programming exercise actually, I got it as a student and I gave it out to my students more than once :-) See also:

etc. etc.

0
Vlad from Moscow On

According to your description of the assignment

I am trying to create a code in which the person inputs a number N between 1 to 100, so they can input N amount of words-phrases up to 20 characters. The program then finds out if the said word or phrase is a palindrome or not and outputs the answer

it is better to write a separate function that will check whether a passed string is a palindrome.

This statement

int k = (strlen(words)-2);

is error prone. The new line character '\n' in general can be absent in the array words after the call of fgets:

fgets(words, sizeof(words), stdin);

for example when the user will enter no less than 20 symbols before pressing the key Enter. Or if the user will enter an empty string pressing at once the key Enter (the string will contain only the new line character '\n') then the expression (strlen(words)-2) will yield a very big unsigned value of the type size_t due to the usual arithmetic conversions.

It is safer and more correctly to write

size_t k = strcspn( words, "\n" ); 
words[k] =  '\0';

and the condition in the following for loop should be written like

    for( size_t j = 0; j < k; j++ )
    //...

Also the loop contains a bug. When a space character is encountered then the variable j is incremented twice in the if statement and in the for loop statement itself:

for(int j=0;j<=k;j++){
        if(words[j]==' '){
            j++;
        }
        sdrow[c]=words[j];
        c++;
}

This can result in storing spaces in the array sdrow if the array words contains adjacent spaces or storing the new line character '\n' if before the new line character the array words contains a space.

Also you should take into account the tab character '\t' that is considered as a space character along with the character ' '. That is the loop can look like

#include <ctype.h>

//...

size_t c = 0;
for ( size_t j = 0; j < k; j++ )
{
    if ( !isblank( ( unsigned char )words[j] ) )
    {
        sdrow[c++] = words[j];
    }
}

The filled array sdrow does not contain a string. As a result this call of printf

printf("%s\n",sdrow);

invokes undefined behavior.

At least after the for loop before the call of printf yoiu could write

sdrow[c] = '\0';

The filled array sdrow contains c symbols. So this for loop

for(int j=k;j>=0;--j){
    verify[k-j]=sdrow[j];
}

should look at least like

for ( int j = c; j > 0; --j ){
      ^^^^^^^^^^    
    verify[c-j]=sdrow[j -1];
    ^^^^^^^^^^^^^^^^^^^^^^^^ 
}

Again the array verify does not contain a string. So the following calls of printf and the function strcmp again invoke undefined behavior

printf("%s\n",verify);
int result=strcmp(verify,sdrow);

Creating two auxiliary arrays to check whether a string is a palindrome is inefficient and unsafe. As I pointed in the beginning of the answer it is much better to write a separate function without defining any additional array.

Here is a demonstration program. By the way according to the C Standard the function main without parameters shall be declared like

int main( void )

instead of

int main()

For example in the C23 Standard declaring even any function without a prototype is not allowed.

Here you are

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>

bool is_palindrome( const char *s )
{
    const char *last = s + strlen( s );

    bool palindrome = true;

    do
    {
        while (isblank( ( unsigned char )*s )) ++s;

        if (s != last)
        {
            while (--last && isblank( ( unsigned char )*last ));
        }
    } while (s != last && ( palindrome = *s++ == *last ) );

    return palindrome;
}

int main( void )
{
    const char *s = "never odd or even";

    printf( "\"%s\" is %sa palindrome.\n", s, is_palindrome( s ) ? "" : "not " );

    s = " ";
    printf( "\"%s\" is %sa palindrome.\n", s, is_palindrome( s ) ? "" : "not " );

    s = " 1";
    printf( "\"%s\" is %sa palindrome.\n", s, is_palindrome( s ) ? "" : "not " );

    s = " 1 1 ";
    printf( "\"%s\" is %sa palindrome.\n", s, is_palindrome( s ) ? "" : "not " );

    s = " 1 2";
    printf( "\"%s\" is %sa palindrome.\n", s, is_palindrome( s ) ? "" : "not " );

    s = " 1 2\t1";
    printf( "\"%s\" is %sa palindrome.\n", s, is_palindrome( s ) ? "" : "not " );
}

The program output is

"never odd or even" is a palindrome.
" " is a palindrome.
" 1" is a palindrome.
" 1 1 " is a palindrome.
" 1 2" is not a palindrome.
" 1 2   1" is a palindrome.