【问题标题】:Storing a string in another variable in C将字符串存储在C中的另一个变量中
【发布时间】:2021-01-03 10:51:00
【问题描述】:

我正在编写一个程序来检查给定的字符串是否是回文。我写了一个函数来反转字符串,但无法将反转的字符串存储在不同的变量中。

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

char stringPalindrome(char s[100], int i, int n){
    char reversed = "";

    for(i=n;i>=0;i--){
        reversed += s[i];
    }

    return reversed;
}

int main(){
    char s[100];
    int i,n;

    gets(s);

    n = strlen(s)-1;

    printf("%s", stringPalindrome(s,i,n));

    return 0;
}

有没有办法在不使用pointersmalloccalloc 的情况下将字符串存储在另一个变量中,因为我是这种语言的新手,我还有很多东西要学

【问题讨论】:

  • 请检查 char reversed = ""; 的编译器警告 此外,在 C 语言中,您不能将字符串与 reversed += s[i]; 连接,您必须将缓冲区传递给您的 stringPalindrome,或为其分配内存。
  • 是的,我知道这个错误。除了将字符串与空字符串连接之外,我还能做什么?
  • 使用另一个char[100] 来计算反转的字符串,或者反转输入字符串本身
  • 将字符(按相反顺序)复制到另一个缓冲区(按顺序)并终止字符串。
  • 为什么 stringPalindrome 在参数中接收 i ?并且永远不要使用 gets,使用 fgets

标签: c string function palindrome


【解决方案1】:

这里的目标不是检查一个字符串是否是回文,而是反转一个字符串。

你的代码有几个问题

  • char reversed = ""; 是错误的,反转char , not a char*nor aconst char *`
  • reversed += s[i]; 没有像您预期的那样附加 s[i]
  • stringPalindrome的参数i没有意义,i必须是局部变量,不是参数
  • 永远不要使用 gets,如果输入比接收数组长,则行为未定义
  • printf("%s", stringPalindrome(s,i,n)); 是未定义的行为,因为 stringPalindrome 返回 char 而不是字符串

stringPalindrome 函数不能将反向字符串存储在作为字符数组的局部变量中,然后返回具有未定义行为的数组。您可以让输入字符串保持不变:

  • stringPalindrome中使用静态局部变量,但每次调用该函数都会修改前一次调用生成的字符串
  • 使用 stringPalindrome 中的 malloc 动态分配堆中的反向字符串,在这种情况下,调用者有责任释放数组它停止使用它
  • 还接收存储到反转字符串的数组 in 参数,作为 out 参数,在这种情况下,调用者有责任提供足够长的数组来存储结果

在 C 中,函数 strcat 允许连接字符串,但在您的情况下,您希望添加 one 字符,因此直接分配该字符而不是使用对 strcat 的昂贵调用(还假设两个字符串都以 null 结尾)


使用全局变量,函数必须注意不要写出它的静态数组:

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

char * stringPalindrome(const char * s, size_t n)
{
  static char reversed[100];
  size_t i;
  
  if (n > sizeof(reversed) - 1)
    n = sizeof(reversed) - 1;
  
  for (i = 0; i < n; ++i)
    reversed[i] = s[n - i - 1];
  reversed[i] = 0;
  
  return reversed;
}

int main()
{
  char s[100];
  
  if (fgets(s, sizeof(s), stdin) != NULL)
    puts(stringPalindrome(s, strlen(s) - 1));
  
  return 0;
}

编译和执行:

pi@raspberrypi:/tmp $ ./a.out
azer ty

yt reza
pi@raspberrypi:/tmp $ 

使用动态分配:

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

char * stringPalindrome(const char * s, size_t n)
{
  char * reversed = malloc(n + 1);
  size_t i;
  
  for (i = 0; i < n; ++i)
    reversed[i] = s[n - i - 1];
  reversed[i] = 0;
  
  return reversed;
}

int main()
{
  char s[100];
  
  if (fgets(s, sizeof(s), stdin) != NULL) {
    char * r = stringPalindrome(s, strlen(s) - 1);
                         
    puts(r);
    free(r);
  }
  
  return 0;
}

编译和执行:

pi@raspberrypi:/tmp $ ./a.out
azer ty

yt reza
pi@raspberrypi:/tmp $ 

在输出参数中管理结果:

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

char * stringPalindrome(const char * s, char * reversed, size_t n)
{
  size_t i;
  
  for (i = 0; i < n; ++i)
    reversed[i] = s[n - i - 1];
  reversed[i] = 0;
  
  return reversed;
}

int main()
{
  char s[100];
  char r[100];
  
  if (fgets(s, sizeof(s), stdin) != NULL) {
    puts(stringPalindrome(s, r, strlen(s) - 1));
    puts(r);
  }
  
  return 0;
}

编译和执行:

pi@raspberrypi:/tmp $ gcc -Wall s.c
pi@raspberrypi:/tmp $ ./a.out
azer ty
yt reza
yt reza
pi@raspberrypi:/tmp $

【讨论】:

    【解决方案2】:

    嗯,不。

    C 中有 no 字符串类型。我们只有指向chars 的指针。按照惯例,字符串从给定位置一直运行到后面的第一个零字节。没有办法逃避。

    但是为了找出一个字符串是否是回文,你不必先反转。只需将第一个字符与最后一个字符进行比较,如果它们匹配,则继续第二个和倒数第二个,依此类推。直到一对不匹配。如果您用完了要比较的对(当它们在中间相遇时),则该字符串是回文。这样您就可以回避创建新字符串的问题。

    【讨论】:

      【解决方案3】:

      最简单的方法是遍历字符串并比较开始和结束字符。使用fgets() 可以设置字符串的最大长度,gets() 没有检查,所以应该避免。

        int palindrom()
        {
          char s[100];
          if (fgets(s,sizeof s,stdin) != NULL)
          {
            int len = strlen(s);
            if (s[len-1] == '\n') --len; // if string is 100 chars there is no \n
            for (char* p = s, *q = s + len - 1; p >= q; ++p,--q)
            {
              if (*p != *q) return 0; // look until difference
            }
            return 1; // palindrome
          }
          puts("no input");
          return 0;
        }
      

      【讨论】:

      • 警告,p &gt;= q 错误,必须替换为p &lt; q,否则函数始终返回 1,除非读取行为空(仅包含换行符,甚至没有换行符但通过 fgets 返回值)。 p &lt;= q 也是有效的,但是检查一个字符是否等于它自己是没有用的。除此之外,我认为最好在 EOF 的情况下返回例如 -1 以允许调用者具体区分这种情况,并删除 puts 而不会影响调用者,事实上不接收参数中的字符串似乎很奇怪,但这只是个人喜好。
      【解决方案4】:

      首先,您从编程开始就很棒。 您的代码中有三个小点:

      1. 您使用的是gets(),这对缓冲区溢出很危险,所以我在这里使用了fgets()。如果您不知道这意味着什么也没关系,因为那是高级的东西,但是如果您想了解更多,请告诉我。

      2. printf() 中,您想打印一个字符串 (%s),但您的函数 stringPalindrome 确实返回一个字符而不是字符数组。因此你得到了一个错误。我通过将函数声明为const char* 类型来解决此问题。 char reversed = ""; 还定义了一个空字符,因此在 for 循环中,您尝试将字符附加到空字符,这会给您带来内存错误。我通过使用第二个字符数组 (r) 来解决这个问题,例如 s,并将他添加到函数调用的参数中。

      3. 最后是 for 循环本身。这个问题是从第二个pa提出来的

         #include<stdio.h>
         #include<stdlib.h>
         #include<string.h>
        
         const char* stringPalindrome(char s[100], char r[100], int i, int p, int n){
        
             for(i=0;i<p;i++){
                 r[i] = s[n];
                 n--;
             }
             return r;
         }
        
         int main(){
             char s[100];
             char r[100];
             int i,n,p;
        
             fgets(s, 100, stdin);
        
             p = strlen(s);
             n = p-1;
        
             printf("%s", stringPalindrome(s,r,i,p,n));
        
             return 0;
         }
        

      【讨论】:

      • 谢谢!但我得到了错误的输出。我是其他一些价值。如果输入 = aba,则输出为 aba╕+
      猜你喜欢
      • 2017-02-23
      • 1970-01-01
      • 2014-02-12
      • 1970-01-01
      • 2022-01-15
      • 2018-12-01
      • 2022-10-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多