如何反转一个数组的值并将它们输入到另一个数组中?

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

提问人:IaMaPsYcHo 提问时间:11/7/2023 最后编辑:Vlad from MoscowIaMaPsYcHo 更新时间:11/10/2023 访问量:151

问:

我正在尝试创建一个代码,该代码使该人在其中输入一个介于 1 到 100 之间的数字 N,因此他们可以输入最多 20 个字符的 N 个单词短语。然后,程序找出所述单词或短语是否是回文并输出答案。我是 C 编码的新手,所以我不知道代码是对还是错,但每次我尝试输入一个超过 8 个字符的单词短语或包含空格时,程序似乎都会出错。从数组字到另一个数组 sdrow 的第一次转换似乎工作得很好,但另一个似乎在它自己的另一个世界中

#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;
}

成功输入

1
stats

成功输出

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

不连续输入

1
never odd or even

不连续输出

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

有时输出会喷出垃圾,而有时它根本不输出任何东西

问题似乎在sdrow的反转上进行验证,但我不知道如何解决。只是编码不好还是有其他事情发生? 你介意每天花一点时间来帮助我吗?

我尝试使用“中间人”,通过使用 char temp 来输入 sdrow 数组的值,然后将它们放入 verify 数组,但它仍然不起作用

for-loop 空白 C 弦回

评论

0赞 pmg 11/7/2023
当你这样做时,你正在计算空间......但后来你摆脱了上述空间......甚至更晚,您尝试复制您首先计算的字符数,包括现在更短的字符串中的空格。strlen()
1赞 Marco Bonelli 11/7/2023
顺便说一句,你真的不需要制作第二个副本来检查字符串是否是回文......如果你考虑一会儿,你可能会找到一个更简单的解决方案。
0赞 einpoklum 11/7/2023
这回答了你的问题吗?查找给定字符串是回文还是不是回文

答:

0赞 greg spears 11/7/2023 #1

同意 -- 问题似乎确实出在你的字符串反转方法上。这是给你的字符串反向代码,在这里经过测试和运行。

注意:此代码会覆盖原始字符串,因此,如果运行后仍需要原始字符串,请务必保存原始字符串的副本。

#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;
}

输出:

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

把它们放在一起 -- 这里是一个建议在你的程序中使用 sreverse() 的函数 -- is_palindrome() -- 如果反转字符串与原始字符串匹配,则返回 true (1) -- 经过测试的可运行代码在这里

#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;
}

输出:

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

这是 is_palindrome() 的另一个实现,灵感来自 stackoverflow 用户 einpoklum 所说的话——你不需要反转字符串。

是的,这是真的。所以我又给你整理了一个......

经过测试的可运行代码在这里

#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;
}

输出:

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

评论

1赞 Chris 11/7/2023
你可以更直接地返回一个动态分配的副本,或者取两个 char 数组,并将相反的数组写入目标数组。后一种方法无需担心释放动态分配的内存。reverse
0赞 greg spears 11/7/2023
@Chris -- 你是对的,谢谢你。
1赞 einpoklum 11/7/2023 #2

我正在尝试创建一个代码...这个人输入的......单词-短语,最多 20 个字符。然后,程序找出所述单词或短语是否是回文并输出答案。

在这种情况下,您不需要“反转一个数组的值并将它们输入到另一个数组中”。只需对当前单词/短语使用单个缓冲区,然后从两端(向前和向后)迭代它,以检查您是否获得相同的元素序列。

实际上,这是一个非常常见的 C 编程练习,我作为学生得到了它,并且不止一次地将其分发给我的学生:-)另请参阅:

等等等等。

评论

0赞 David C. Rankin 11/7/2023
所以,可以这么说,你和回文练习已经走完了一圈。这是一个很好的例行公事。有很多很多方法可以做到这一点,并且有很好的机会让学生看到在第一次尝试中改进的方法。
1赞 Vlad from Moscow 11/7/2023 #3

根据您对作业的描述

我正在尝试创建一个代码,该人在其中输入数字 N 介于 1 到 100 之间,因此他们可以输入最多 20 个单词短语 字符。然后,程序会找出所述单词或短语是否是 回文与否并输出答案

最好编写一个单独的函数来检查传递的字符串是否为回文。

本声明

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

容易出错。通常,在调用以下命令后,数组中可以缺少换行符:'\n'wordsfgets

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

例如,当用户在按下 键之前输入不少于符号时。或者,如果用户将输入一个空字符串,同时按下键(该字符串将仅包含换行符),则由于通常的算术转换,表达式将产生该类型的非常大的无符号值。20EnterEnter'\n'(strlen(words)-2)size_t

写起来更安全、更正确

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

下面 for 循环中的条件应该写成这样

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

此外,循环还包含一个错误。当遇到空格字符时,变量会在 if 语句和 for 循环语句本身中递增两次:j

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

如果数组包含相邻空格,则可能导致在数组中存储空格,或者如果数组在换行字符之前包含空格,则存储换行符。sdrowwords'\n'words

此外,您还应该考虑被视为空格字符的制表符以及字符。这就是循环的样子'\t'' '

#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];
    }
}

填充数组不包含字符串。因此,这个调用sdrowprintf

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

调用未定义的行为。

至少在 for 循环之后,在调用之前,你可以写printf

sdrow[c] = '\0';

填充数组包含符号。所以这个for循环sdrowc

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

至少应该看起来像

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

同样,数组不包含字符串。因此,以下对 和 函数的调用再次调用未定义的行为verifyprintfstrcmp

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

创建两个辅助数组来检查字符串是否为回文是低效且不安全的。正如我在答案开头所指出的,最好在不定义任何其他数组的情况下编写一个单独的函数。

这是一个演示程序。顺便说一句,根据 C 标准,没有参数的函数应声明如下main

int main( void )

而不是

int main()

例如,在 C23 标准中,甚至不允许声明任何没有原型的功能。

给你

#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 " );
}

程序输出为

"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.