【问题标题】:C - Largest String From a Big OneC - 大字符串中的最大字符串
【发布时间】:2009-10-03 05:29:52
【问题描述】:

所以请告诉我,我将如何从 C 中的一串垃圾中获取最大的连续字母串?这是一个例子:

char *s = "(2034HEY!!11   th[]thisiswhatwewant44";

会返回...

thisiswhatwewant

前几天我在测验中遇到了这个问题......它让我发疯(仍然)试图弄清楚!

更新:

我的错伙计们,我忘了包括你被允许使用的唯一函数是 strlen 函数这一事实。从而变得更加困难......

【问题讨论】:

  • 什么样的白痴面试题除了strlen()之外什么功能都不能用? strlen() 甚至不是手动滚动的硬功能(如果必须的话),并且没有现实生活中的情况会施加这样的限制。这是一个愚蠢的问题。
  • 更不用说,如果唯一可用的函数是 strlen(),则无法打印结果。我想您可以使用 return(n); 将长度作为退出状态返回;来自 main(),但前提是它足够短以适合 8 位值。非常愚蠢的问题。

标签: c string pointers


【解决方案1】:

Uae strtok() 将您的字符串拆分为标记,使用所有非字母字符作为分隔符,并找到最长的标记。

要找到最长的令牌,您需要为令牌组织一些存储空间 - 我会使用链表。

就这么简单。

编辑

好的,如果 strlen() 是唯一允许的函数,您可以先找到源字符串的长度,然后循环遍历它并将所有非字母字符替换为 NULL - 基本上这就是 strtok() 所做的。

然后您需要再次检查修改后的源字符串,一次推进一个标记,并找到最长的一个,使用strlen()

【讨论】:

    【解决方案2】:

    这听起来类似于标准的 UNIX 'strings' 实用程序。

    跟踪由 NULL 终止的最长可打印字符。 遍历字节,直到找到可打印的字符。开始数。如果您遇到不可打印的字符,请停止计数并丢弃起点。如果命中 NULL,请检查当前运行的长度是否大于前一个记录保持者。如果是,记录下来,然后开始寻找下一个字符串。

    【讨论】:

      【解决方案3】:

      与许多其他子字符串相比,“好”子字符串的定义是什么——仅是小写字母? (即,没有空格、数字、标点符号、大写字母等)?

      无论使用哪个谓词 P 来检查一个字符是否“好”,对每个字符应用 P 的单次遍历 P 可以让您轻松识别每个“好字符运行”的开始和结束,并记住并选择最长的。在伪代码中:

      longest_run_length = 0
      longest_run_start = longest_run_end = null
      status = bad
      for i in (all indices over s):
        if P(s[i]):  # current char is good
          if status == bad:  # previous one was bad
            current_run_start = current_run_end = i
            status = good
          else: # previous one was also good
            current_run_end = i
        else:  # current char is bad
          if status == good:  # previous one was good -> end of run
            current_run_length = current_run_end - current_run_start + 1
            if current_run_length > longest_run_length:
              longest_run_start = current_run_start
              longest_run_end = current_run_end
              longest_run_length = current_run_length
            status = bad
      
      # if a good run ends with end-of-string:
      if status == good:  # previous one was good -> end of run
        current_run_length = current_run_end - current_run_start + 1
        if current_run_length > longest_run_length:
          longest_run_start = current_run_start
          longest_run_end = current_run_end
          longest_run_length = current_run_length
      

      【讨论】:

      • @Chris,因为 Python (差不多)“可执行伪代码”——所以它让你(只需将一些通用性,例如 all indices over s 转录成 Python, range(len(s)) 在这种情况下,并在您需要在伪代码中分配和测试时使用诸如我的数据持有者类之类的小技巧)通过运行一些测试用例来验证您的伪代码的逻辑(在将其转录为您可能需要的任何其他语言之前 - - 在这种情况下是 C ——当然,如果您确实需要其他特定语言)。那么为什么要使用任何不同的伪代码...?
      【解决方案4】:

      为什么要使用strlen()? 这是我的版本,它不使用任何功能。

      #ifdef UNIT_TEST #include #include #include #万一 /* // 最大字母序列() // 返回一个指向最大字母开头的指针 // 序列(包括不是字母的尾随字符) // 如果在 s 中没有找到字母,则为 NULL // 在 `s` 中传递 NULL 会导致未定义的行为 // 如果字符串有两个或多个字母数相同的序列 // 返回值是指向第一个序列的指针。 // 参数`len`,如果不为NULL,将有字母序列的大小 // // 这个函数假定一个类似 ASCII 的字符集 // ('z' > 'a'; 'z' - 'a' == 25; ('a' maxlen){ maxlen = 卷曲; p = p; } } 别的 { 卷曲 = 0; p = 空; } s++; } if (len != NULL) *len = maxlen; 返回页码; } #ifdef UNIT_TEST 无效 fxtest(const char *s) { 字符*测试; 常量字符 *p; 尺寸_t len; p = 最大字母序列(s, &len); if (len && (len %s\n", s, test); 免费(测试); } 别的 { 如果(len == 0){ printf("在\"%s\"\n"中没有找到字母, s); } 别的 { fprintf(stderr, "错误: 字符串太大\n"); } } } 诠释主要(无效){ fxtest("(2034HEY!!11 th[]thisiswhatwewant44"); fxtest("123456789"); fxtest(""); fxtest("aaa%ggg"); 返回0; } #万一

      【讨论】:

        【解决方案5】:

        在等待您将其作为问题发布时,我编写了一些代码。

        此代码遍历传递给“最长”函数的字符串,当它找到一系列字母中的第一个时,它会设置一个指向它的指针并开始计算它的长度。如果它是最长的字母序列,它会将另一个指针('maxStringStart'指针)设置到该序列的开头,直到找到更长的字母。

        最后,它为新字符串分配足够的空间并返回一个指向它的指针。

        #include<stdio.h>
        #include<stdlib.h>
        #include<string.h>
        
        int isLetter(char c){
        
            return ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') );
        
        }
        
        char *longest(char *s) {
        
            char *newString = 0;
            int maxLength = 0;
            char *maxStringStart = 0;
            int curLength = 0;
            char *curStringStart = 0;
        
            do {
        
                //reset the current string length and skip this
                //iteration if it's not a letter
                if( ! isLetter(*s)) {
                    curLength = 0;
                    continue;
                }
        
                //increase the current sequence length. If the length before
                //incrementing is zero, then it's the first letter of the sequence:
                //set the pointer to the beginning of the sequence of letters
                if(curLength++ == 0) curStringStart = s;
        
                //if this is the longest sequence so far, set the
                //maxStringStart pointer to the beginning of it
                //and start increasing the max length.
                if(curLength > maxLength) {
                    maxStringStart = curStringStart;
                    maxLength++;
                }
        
            } while(*s++);
        
            //return null pointer if there were no letters in the string,
            //or if we can't allocate any memory.
            if(maxLength == 0) return NULL;
            if( ! (newString = malloc(maxLength + 1)) ) return NULL;
        
            //copy the longest string into our newly allocated block of
            //memory (see my update for the strlen() only requirement)
            //and null-terminate the string by putting 0 at the end of it.
            memcpy(newString, maxStringStart, maxLength);
            newString[maxLength + 1] = 0;
        
            return newString;
        
        }
        
        int main(int argc, char *argv[]) {
        
            int i;
        
            for(i = 1; i < argc; i++) {
                printf("longest all-letter string in argument %d:\n", i);
                printf("   argument: \"%s\"\n", argv[i]);
                printf("    longest: \"%s\"\n\n", longest(argv[i]));
            }
        
            return 0;
        
        }
        

        这是我的简单 C 语言解决方案,没有任何数据结构。

        我可以像这样在终端中运行它:

        ~/c/t $ ./longest "hello there, My name is Carson Myers." "abc123defg4567hijklmnop890"
        longest all-letter string in argument 1:
           argument: "hello there, My name is Carson Myers."
            longest: "Carson"
        
        longest all-letter string in argument 2:
           argument: "abc123defg4567hijklmnop890"
            longest: "hijklmnop"
        
        ~/c/t $
        

        可以在isLetter() 函数中轻松更改构成字母的标准。例如:

        return ( 
            (c >= 'a' && c <= 'z') ||
            (c >= 'A' && c <= 'Z') ||
            (c == '.') || 
            (c == ' ') || 
            (c == ',') );
        

        将句点、逗号和空格也算作“字母”。


        根据您的更新:

        memcpy(newString, maxStringStart, maxLength); 替换为:

        int i;
        for(i = 0; i < maxLength; i++)
            newString[i] = maxStringStart[i];
        

        但是,使用 C 标准库会更容易解决这个问题:

        char *longest(char *s) {
        
            int longest = 0;
            int curLength = 0;
            char *curString = 0;
            char *longestString = 0;
            char *tokens = " ,.!?'\"()@$%\r\n;:+-*/\\";
        
            curString = strtok(s, tokens);
            do {
        
                curLength = strlen(curString);
                if( curLength > longest ) {
                    longest = curLength;
                    longestString = curString;
                }
        
            } while( curString = strtok(NULL, tokens) );
        
            char *newString = 0;
        
            if( longest == 0 ) return NULL;
            if( ! (newString = malloc(longest + 1)) ) return NULL;
        
            strcpy(newString, longestString);
        
            return newString;
        
        }
        

        【讨论】:

        • 没什么,我只是没想到——只是现在他说他只能使用strlen。在他的最后一个问题中,他使用了malloc,所以我想那个还可以。
        • 我认为这是一个愚蠢的要求 - 特别是因为 C 标准不保证您的替换函数可以正常工作(不幸的是,字母字符不需要是连续的,只有数字字符)。我认为你应该制作一个使用所有标准函数的第二个版本,如果只是为了向后来的读者展示使用标准库有多容易。
        【解决方案6】:

        首先,定义“字符串”并定义“垃圾”。您认为什么是有效的非垃圾字符串?写下你可以编程的具体定义——这就是编程规范的编写方式。它是一个字母数字字符序列吗?它应该以字母而不是数字开头吗?

        一旦你弄清楚了,编程就非常简单了。从一种天真的方法开始,循环遍历“垃圾”来寻找你需要的东西。完成后,查找有用的 C 库函数(如 strtok)以使代码更精简。

        【讨论】:

          【解决方案7】:

          另一个变种。

          #include <stdio.h>
          #include <string.h>
          
          int main(void)
          {
                  char s[] = "(2034HEY!!11   th[]thisiswhatwewant44";
                  int len = strlen(s);
                  int i = 0;
                  int biggest = 0;
                  char* p = s;
          
                  while (p[0])
                  {
                          if (!((p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z')))
                          {
                                  p[0] = '\0';
                          }
          
                          p++;
                  }
          
                  for (; i < len; i++)
                  {
                          if (s[i] && strlen(&s[i]) > biggest)
                          {
                                  biggest = strlen(&s[i]);
                                  p = &s[i];
                          }
                  }
          
                  printf("%s\n", p);
                  return 0;
          }
          

          【讨论】:

          • 嘿 - 不打印结果 - 你只能使用 strlen()! :D 这只是为了强调这个问题是多么毫无意义。
          • 为什么不用*p 而不是p[0]
          猜你喜欢
          • 2016-06-19
          • 2016-03-05
          • 2012-01-20
          • 1970-01-01
          • 2017-01-14
          • 2022-12-17
          • 1970-01-01
          • 2017-03-16
          • 1970-01-01
          相关资源
          最近更新 更多