【问题标题】:Kernighan and Ritchie - exercise 3.3 (expand function)Kernighan 和 Ritchie - 练习 3.3(扩展功能)
【发布时间】:2021-10-15 14:10:06
【问题描述】:

我已经解决了 K&R 书中的练习 3.3。我实施的解决方案似乎有效,但有点冗长,可能有更聪明的方法来编写这段代码。我想问一下我实现的解决方案是否存在问题,以及是否有更简单的方法来编写它:

编写一个扩展速记符号的函数 expand(s1,s2),例如 将字符串 s1 中的 a-z 放入等效的完整列表 abc...xyz 中 s2。允许使用大小写和数字的字母,并准备好 处理像 a-b-c 和 a-z0-9 和 -a-z 这样的情况。安排一个领先的或 尾随 - 字面意思

我的代码是这个:

#include <stdio.h>

void expand(char s1[],char s2[]){
  int j=0,i=0;
  while(s1[j] != '\0'){
    if (s1[j]>= 'a' &&  s1[j] <= 'z' && s1[j+1] == '-' && s1[j+1]!='\0' &&  s1[j+2] >= 'a' &&  s1[j+2] <= 'z' && s1[j+2] !='\0'){
      int z = s1[j+2]-s1[j];
      int c;
      for (c=0;c<=z;c++){
    s2[i]= c+s1[j];
    i++;
      }
      j=j+3;
            
    }
    else if (s1[j]>= 'A' &&  s1[j] <= 'Z' && s1[j+1] == '-' && s1[j+1]!='\0' &&  s1[j+2] >= 'A' &&  s1[j+2] <= 'Z' && s1[j+2] !='\0'){
      int z = s1[j+2]-s1[j];
      int c;
      for (c=0;c<=z;c++){
    s2[i]= c+s1[j];
    i++;
      }
      j=j+3;
            
    }
    else if (s1[j]>= '0' &&  s1[j] <= '9' && s1[j+1] == '-' && s1[j+1]!='\0' &&  s1[j+2] >= '0' &&  s1[j+2] <= '9' && s1[j+2] !='\0'){
      int z = s1[j+2]-s1[j];
      int c;
      for (c=0;c<=z;c++){
    s2[i]= c+s1[j];
    i++;
      }
      j=j+3;
            
    }
    else  if (j!= 0  && s1[j] == '-'  && (s1[j-1] < s1[j+1])){
      int z = s1[j+1]-(1+s1[j-1]);
      int c;
      for (c=0;c<=z;c++){
    s2[i]= c+(s1[j-1]+1);
    i++;
      }
      j=j+2;
      
    }      
    else if ( s1[j]>= 32 &&  s1[j] <= 127 && (s1[j+1] != '-' || s1[j+1]>= 32 &&  s1[j+1] <= 127 )){
      s2[i] = s1[j];
      
      j++;
      i++;      
     }
  }
  s2[i]='\n';
  i++;
  s2[i]='\0';
}


int main() {

  int c;
  char s2[100];
  expand("-a-c,a-c-g,A-Z0-9--", s2);
  
  printf("%s",s2);
 
 
}

代码是这样工作的:

首先它检查是否存在 x

条件 else if (j!= 0 &amp;&amp; s1[j] == '-' &amp;&amp; (s1[j-1] &lt; s1[j+1])) 用于检查“a-c-d1”等情况。我在这个例子中实现的代码将像这样工作: 由于我们从“a-c-d”中的第 0 个字符开始并且存在模式“x-y”,因此“abc”将被分配给数组。那我们就直接跳到第二个——在“a-c-f”。由于第二个 - 前面有一个字母“c”,后面是一个字母“f”,并且“c”

【问题讨论】:

  • 表达式s1[j+1] == '-' &amp;&amp; s1[j+1]!='\0' 是多余的。如果它等于-,那么它肯定不等于其他任何东西。 s1[j+2] 相同 - 如果它介于 'A''Z' 之间,则不能是 '\0'
  • 这个问题可能更适合CodeReview 网站。
  • 这个问题的代码很多,代码重复也很多。我个人会这样做:godbolt.org/z/WM45dGvs1
  • 结果有问题吗?
  • @PtitXav 我在其他测试中没有遇到问题,但想问问是否有更简单的方法来回答这个练习。

标签: c kernighan-and-ritchie


【解决方案1】:

其他方式:

  • 您只知道之前的最后一个字符 - 以及它是否与当前字符类型相同(小写或大写字母或数字)

  • 当你得到一个 - 并且前一个字符是一个字母或数字时,你知道你可能需要进行扩展

  • 如果您后面有一个字母或数字 - 并且它对应于之前的字母/数字 - 您知道您可以从之前的字符 / 扩展到当前字符。

  • 你确实需要向前看,但只保存之前的字符和字符 -

  • 您对每种不同的字符类型(字母/数字)进行相同类型的处理 你可以在下面找到一个例子:

    #include // 处理不同的字符类型 typedef 枚举 E_chartype { 小写字母, 大写字母, 数字09, 其他字符 } E_chartype;

    // 如果我们可能有一个可能的扩展,则保存 typedef 枚举 E_states { 什么都没有开始, 开始扩建 } E_states;

    // 查找字符的类型 E_chartype getCharType(char c) { if ((c >= 'a') && (c

    if (( c >= 'A') && (c <= 'Z'))
      return UpperCaseLetter;
    
    if ((c >= '0') && (c <= '9'))
      return Digit09;
    
    return OtherChar;
    

    }

    void expandopt(char *inS, char *outS) { // 初始化输出字符串为空字符串 输出[0] = 0; 字符 *endS = outS; E_states 自动 = NothingStarted; 字符已保存字符 = 0; 诠释当前索引; E_chartype prevCType=OtherChar,savedCType=OtherChar; char savedC = 0,prevC=0;

    // loop on input string
    for (currentIndex = 0; inS[currentIndex] != 0;currentIndex++) {
    
      // save current char in variable c for shorter writting
      char c = inS[currentIndex];
      printf("%c : ",c);
    

    // 保存当前字符的类型 E_chartype currentCType = getCharType(c);

    开关(自动){ // 一般情况尚未开始 案例NothingStarted: // 如果前一个 chsr 是字母或数字并且当前 char 是 - 则 possibkee 扩展 if ((prevCType != OtherChar) && (c == '-')) { printf("开始代表\n"); 自动 = StartedExpansion; // 保存前一个 char 及其类型,因为它会被引用 fircexpansion 保存的CType = prevCType; 已保存C = prevC; } 别的 { // 重置当前字符并将其转换为 iutput 自动 = NothingStarted; printf("什么都没有\n");

       *endS++ = c;
       }
       break;
    
     case StartedExpansion:
       // we make ecpansion only if still same char type and letter/digit is strictly after saved one
    

    if ((currentCType == savedCType) && (c > savedC)){ printf("展开"); 对于 (char newC = 已保存C+1;newC

         // save char in case thrre id a - after, which mean nee expansion
        savedC = c;
        } else {
           // save current chsrcsnd its type
          savedCType = currentCType;
      savedC = c;
      // copy previous char (= -) whch was not vopief in case of expansion
      *endS++ = prevC;
       *endS++ = c;
      }
    

    自动 = NothingStarted; 休息; }

    // save current chsr and type
    prevCType = currentCType;
    prevC = c;
    }
    

    // 在字符串末尾添加 0 *endS = 0; }

    int main() { expandopt("-a-c,a-c-g,A-Z0-9–",s2); printf("%s\n",s2); }

抱歉代码格式化,我在手机上没有找到好的代码编辑器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多