【问题标题】:How to Copy the (ASCII) alphabetic characters contained in an existing string into a new one如何将现有字符串中包含的(ASCII)字母字符复制到新字符串中
【发布时间】:2014-11-12 05:39:34
【问题描述】:

新字符串应仅包含现有字符串中相同顺序的字母字符。不应复制非字母字符。如果 s 是空指针,则返回空指针。

示例输入: “准备瞄准开火!” 输出: Readyaimfire

我不知道为什么在我的第一个 for 循环中,代码从不进入 if 语句。我也不确定我是否为新字符串正确分配了内存。感谢您的帮助:)

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

char *alphabetic (const char *s);

char *alphabetic (const char *s)
{
    char *newChar;
    int i;
    char n = 0;
    long length = strlen(s);
    for(i=0; i<length; i++)
    {
        if( (s[i] >= 'A' && s[i] <= 'Z') ||  (s[i] >= 'a' && s[i] <= 'z') )
        {
                n++;
        }
    }
    newChar = (char*)malloc(sizeof(char)*n);
    for(i=0; i<length; i++)
    {
        if( (s[i] >= 'A' && s[i] <= 'Z') ||  (s[i] >= 'a' && s[i] <= 'z') )
        {
            newChar[i] = s[i];
        }
    }

    return newChar;
}

int main (void)
{
    char *a, *b, *c;
    a = alphabetic ("Ready... aim... fire!");
    b = alphabetic ("***");
    c = alphabetic ("*a*b*c*");

    printf ("%s\n", a);
    printf ("%s\n", b);
    printf ("%s\n", c);

    free(a);
    free(b);
    free(c);

    return 0;
}

【问题讨论】:

  • 您使用的是char n = 0;,它应该是int 类型。因为它没有分配内存。

标签: c string pointers char ascii


【解决方案1】:

第一个if 的条件和第二个if 的条件是这样的,如果一个是true,那么另一个是false。因此,您永远不会排队

n++;

你需要

if ( (s[i] <= 122 && s[i] >= 97) || (s[i] <= 90 && s[i] >= 65) )

为了使代码更具可读性,你可以让它:

if ( (s[i] >= 'A' && s[i] <= 'Z') ||  (s[i] >= 'a' && s[i] <= 'z') )

如果您可以选择使用标准库,则可以使用:

if ( isalpha(s[i]) )

顺便说一句,这条线

    s = s + i;

会把事情搞砸的。当您遍历循环时,您最终会跳过部分输入字符串。删除该行。

【讨论】:

    【解决方案2】:

    你可以使用一个循环

    int j = 0;               //take integer variable
    for(i=0; i<length; i++)
    {
        if( (s[i] >= 'A' && s[i] <= 'Z') ||  (s[i] >= 'a' && s[i] <= 'z') )
        {
             //n++;     //Remove this
             newChar[j] = s[i];
             j++;
        }
    }
    

    【讨论】:

      【解决方案3】:

      关于你的代码的事情:

      • n 应该是 n+1 以容纳 '\0' 字符

      • 第二个 for 循环:您需要有另一个变量说 j =0 并在每次匹配时递增。您不能像在原始数组 s 中那样将 i 用于 newChar 数组,因为 i 可能指向 newChar 数组中超出范围的地址。例如:ready...aim, newchar # elements 8 while s =11

        所以说newChar[8]=s[8]是错误的,应该是newChar[5]=s[8]。

      发布更正后的代码:

      char *alphabetic (const char *s)
      {
      char *newChar;
      int i,j=0;       //Change1: extra variable j to keep a track of elements for newChar
      char n = 0;
      long length = strlen(s);
      for(i=0; i<length; i++)
      {
          if( (s[i] >= 'A' && s[i] <= 'Z') ||  (s[i] >= 'a' && s[i] <= 'z') )
          {
                  n++;
          }
      }
      
      newChar = (char*)malloc(sizeof(char)*(n+1));       // Change2: n+1 instead of n
      
      
      for(i=0; i<length; i++)
      {
          if( (s[i] >= 'A' && s[i] <= 'Z') ||  (s[i] >= 'a' && s[i] <= 'z') )
          {
              newChar[j++] = s[i];       //Change3: j instead of i
          }
      }
      newChar[j]='\0';       //Termination of strings
      
      return newChar;
      }
      

      【讨论】:

        【解决方案4】:

        我无法告诉你为什么你的代码没有进入 if 语句,因为你没有提供算法没有进入 if 语句的测试用例(输入数据)。我可以告诉你的是,它不会做你想让它做的事情。让我们在这里分解一下 for 循环: 它说“使变量 i = 0,然后,当 i 小于 char 数组 s 的长度时,做一些事情然后增加 i”。这是解析 char 数组的一种非常方便的方法。这很好,很花哨,但是在 for 循环中,第一条指令是 s = s + i。这样做是在每次迭代时将指针 s 向前移动 i 个字符。请记住,我会随着时间的推移而增加。假设我们给该函数 char * “This is a sentence.”。函数 strlen(s) 将返回 19(将存储在长度中),因此 for 循环将迭代 19 次,其中 i 取值从 0 到 18 包括在内。让我们看看那里的 s 发生了什么。第一次,*s 的值是 T。当你使 s = s + i (i = 0) 时,*s 仍然是 T。T 的 ascii 代码是 84,if 检查 97 和 122(包括)之间的值。这就是第一次迭代。然后 i 变为 1。并且 s 进一步移动一个位置,因此 *s 将是 'h'。字母 h 的 ASCII 码是 104,所以它输入第一个 if(因为它在 122 和 97 之间)。然后,您询问 s[i] 是否在 90 和 65 之间。现在,因为您增加了 s,*s 是“h”,但此时 i == 1,因此 s[i] 实际上是“i”(其ASCII 码是 105,因此永远不会进入该循环)。因此,如果您想用给定的算法增加 n,我会说您需要一个输入测试用例,如下所示:“ThIsiSaSENTENCE”。你想要的是一个干净的字符串解析 for 循环和另一个干净的 if 检查当前字符是否是字母:

        for(i = 0; i < length; i++)
          {
            if((s[i]<='Z' && s[i] >= 'A') || (s[i]<='z' && s[i]>='a'))
              n++;
          }
        

        这将计算您的 char 数组 s 中有多少个字母。

        编辑: 如果您想删除那些不是字母的字符并返回新字符串,那么您可能想尝试这样的事情(不是最优的):

        char *copyStringByLetter(char *arg, int size)
        {
            int i = 0;
            int n = 0;
            for(i = 0; i < size; ++i){
                if((s[i]<='z' && s[i]>='a')||(s[i]<='Z' && s[i]>='A'))
                    n++;
            }
            char *result = malloc(n+1); //need #include <stdlib.h>
            if(!result){
              fprintf(stderr, "Error alocating memory!");
              exit(EXIT_FAILURE) //you need #include <stdlib.h> for this
              }
            int j = 0;
            for(i = 0; i < size; i++){
                if((s[i]<='z' && s[i]>='a')||(s[i]<='Z' && s[i]>='A')){
                    result[j] = s[i];
                    j++;
                }
            }
            result[j] = '\0' //terminate the array
            return result;
        }
        

        如果你想问我为什么要发送 char 数组的长度作为参数,那是为了防止 char 溢出(比你想象的更频繁地发生)

        【讨论】:

          猜你喜欢
          • 2011-01-27
          • 1970-01-01
          • 2013-05-27
          • 2015-11-04
          • 2014-11-06
          • 1970-01-01
          • 2015-04-15
          • 2017-01-08
          • 1970-01-01
          相关资源
          最近更新 更多