Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 您将如何改进此算法?(c字符串反转)_C++_Algorithm_Cstring - Fatal编程技术网

C++ 您将如何改进此算法?(c字符串反转)

C++ 您将如何改进此算法?(c字符串反转),c++,algorithm,cstring,C++,Algorithm,Cstring,通过在线发现的一些编程面试挑战,我不得不编写一个算法来反转常量字符*并返回指向新字符*的指针。我想我有它,但是为了让它正常工作,我不得不做一些不可靠的事情——基本上我必须自己解释这个空终止字符。不知何故,我觉得这是错误的,但我被难住了,我想知道是否有人能帮助我: char * reverse(const char * str) { int length = strlen(str); char * reversed_string = new char[length+1]; for(i

通过在线发现的一些编程面试挑战,我不得不编写一个算法来反转常量字符*并返回指向新字符*的指针。我想我有它,但是为了让它正常工作,我不得不做一些不可靠的事情——基本上我必须自己解释这个空终止字符。不知何故,我觉得这是错误的,但我被难住了,我想知道是否有人能帮助我:

char * reverse(const char * str)
{
  int length = strlen(str);
  char * reversed_string = new char[length+1];

  for(int i = 0; i < length; ++i)
  {
    reversed_string[i] = str[(length-1) - i];
  }
  //need to null terminate the string
  reversed_string[length] = '\0';

  return reversed_string;

}

int main(int argc, char * argv[])
{

  char * rev_str = reverse("Testing");

  cout << "Your string reversed is this: " << rev_str << endl;

  delete rev_str;
  rev_str = 0;

  return 0;
}
char*反向(const char*str)
{
int长度=strlen(str);
字符*反向_字符串=新字符[长度+1];
对于(int i=0;i我曾经问过一个问题。这是我想到的第一个答案,但接下来的问题是,“现在就做,不要分配任何内存。”

但一般来说,现代编译器可以优化原始交换的局部变量。有关详细信息,请参见:

#include <algorithm>
#include <iostream>
#include <cstring>

void reverse_string(char *str) {    
    char *end = str + strlen(str) - 1;
    while (str < end) {
        std::iter_swap(str++, end--);
    }
}

int main() {
    char s[] = "this is a test";
    reverse_string(s);
    std::cout << "[" << s << "]" << std::endl;
}
#包括
#包括
#包括
无效反向_字符串(char*str){
char*end=str+strlen(str)-1;
while(strif(字符串[0])
{
char*end=string+strlen(string)-1;
while(开始<结束)
{
char temp=*字符串;
*字符串+=*结束;
*结束--=温度;
}
}
中的适用于字符串和
字符
数组:

string str = "Hello";
char chx[] = "Hello";

reverse(str.begin(), str.end());
reverse(chx, chx + strlen(chx));

cout << str << endl;
cout << chx << endl;

我会像这样解决它(我的c有点生锈,请原谅)


事实上,考虑到原始字符串不能被修改的限制,我认为问题中给出的原始方法是最好的。所有这些扭转人们发布位置的奇特方法都很好,但一旦考虑到复制给定字符串的因素,它们都不如简单地向后复制字符串有效。

我们以前用过这个问题——结果令人惊讶地发现很多人做不到(即使有丰富的C/C++经验!)。我更喜欢就地变量,因为它节省了一些开销,并且增加了只需要在strlen(s)/2个字符上迭代的扭曲

你在面试中的解决方案会很好。使用指针而不是数组语法的(正确的!)解决方案会得到更高的评价,因为它显示了在C/C++编程中非常关键的指针的更高舒适度


次要的批评是,strlen返回的是大小而不是整数,您应该在rev_str上使用delete[.

它不会更有效,但您可以通过将每个字母推到堆栈上,然后将它们弹出到新分配的缓冲区中来展示数据结构的知识

这将需要两个过程和一个临时堆栈,但我可能更相信自己能在第一次正确完成这项任务,而不是像上面所述的一个错误

char* stringReverse(const char* sInput)
{
    std::size_t nLen = strlen(sInput);
    std::stack<char> charStack;
    for(std::size_t i = 0; i < nLen; ++i)
    {
        charStack.push(sInput[i]);
    }
    char * result = new char[nLen + 1];
    std::size_t counter = 0;
    while (!charStack.empty())
    {
        result[counter++] = charStack.top();
        charStack.pop();
    }
    result[counter] = '\0';
    return result;
}
char*stringReverse(const char*sInput)
{
标准:尺寸=标准长度(sInput);
std::stack charStack;
对于(标准:尺寸i=0;i
嗯?没人用指针做过吗

char *reverse(const char *s) {
    size_t n = strlen(s);
    char *dest = new char[n + 1];
    char *d = (dest + n - 1);

    dest[n] = 0;
    while (*s) {
        *d-- = *s++
    }

    return dest;
}
希望多年的Java没有毁掉我的C;-)


编辑:用一个额外的变量替换了所有的strlen调用。strlen这些天返回了什么?(谢谢)。

您的代码是直截了当的,毫不奇怪。有几件事:

  • 对循环索引使用size\u t而不是int
  • 虽然您的编译器很可能足够聪明,可以看出(length-1)是不变的,但它可能不够聪明,无法看出(length-1)-i最好由不同的循环变量替换,该变量在每个过程中递减
  • 我会使用指针而不是数组语法——在循环中使用*dst-->=*src++;,看起来会更干净
  • 换言之:

    char *dst = reversed_string + length;
    *dst-- = '\0';
    while (*src) {
       *dst-- = *src++;
    }
    

    作为一名面试官,当我问这个问题时,我希望找到一个干净、易懂的解决方案,并且可能会问如何使最初的解决方案更有效。我对“聪明”的解决方案不感兴趣

    我在想这样的事情:应征者是否在他们的循环中用一个错误来替换旧的,他们是否预先分配了足够的内存,他们是否检查了错误的输入,他们是否使用了足够有效的类型

    不幸的是,正如已经指出的,太多的人甚至不能做到这一点。

    @Konrad Rudolph:(对不起,我没有“经验”发表评论)

    我想指出的是,STL提供了一种算法,类似于。您不必像以前那样引入临时字符,只需分配一个大小合适的新字符即可。

    WRT:“现在不使用临时保持变量就可以了”…可能类似于这样(暂时保留数组索引):

    int length=strlen(字符串);
    对于(int i=0;i
    我知道这是非常不可移植的,但x86汇编指令bswap允许您仅通过一条指令交换四个字节,这可能是提高代码质量的好方法

    这是一个如何让它与GCC一起工作的示例

    /* 
     * reverse.c
     *
     * $20081020 23:33 fernando DOT miguelez AT gmail DOT com$
     */
    
    #include <stdint.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    #define MAX_CHARS 10 * 1024 * 1024
    
    /*
     * Borrowed from http://coding.derkeiler.com/Archive/Assembler/comp.lang.asm.x86/2007-03/msg00004.html
     * GNU Compiler syntax
     */
    inline uint32_t bswap(uint32_t val)
    {
        __asm__("bswap %0" : "=r" (val) : "0" (val));
        return val;
    }
    
    char * reverseAsm(const char * str)
    {
        int i;
        int length = strlen(str);
        int dwordLength = length/4;
    
        if(length % 4 != 0)
        {
            printf("Error: Input string length must be multiple of 4: %d\n", length);       
            return NULL;
        }
    
        char * reversed_string = (char *) malloc(length+1);
        for(i = 0; i < dwordLength; i++)
        {
            *(((uint32_t *) reversed_string) + dwordLength - i - 1) = bswap(*(((uint32_t *) str) + i));
        }
    
        reversed_string[length] = '\0';
    
        return reversed_string;
    }
    
    char * reverse(const char * str)
    {
        int i;
        int length = strlen(str);
        char * reversed_string = (char *) malloc(length+1);
    
        for(i = 0; i < length; ++i)
        {
            reversed_string[i] = str[(length-1) - i];
        }
    
            //need to null terminate the string
    
        reversed_string[length] = '\0';
    
        return reversed_string;
    }
    
    int main(void)
    {
        int i;
        char *reversed_str, *reversed_str2;
        clock_t start, total;
        char *str = (char *) malloc(MAX_CHARS+1);
    
        str[MAX_CHARS] = '\0';
    
        srand(time(0));
    
        for(i = 0; i < MAX_CHARS; i++)
        {
            str[i] = 'A' + rand() % 26;     
        }
    
        start = clock();
        reversed_str = reverse(str);
        total = clock() - start;
        if(reversed_str != NULL)
        {
            printf("Total clock ticks to reverse %d chars with pure C method: %d\n", MAX_CHARS, total); 
            free(reversed_str);
        }
        start = clock();
        reversed_str2 = reverseAsm(str);
        total = clock() - start;
        if(reversed_str2 != NULL)
        {
            printf("Total clock ticks to reverse %d chars with ASM+C method: %d\n", MAX_CHARS, total); 
            free(reversed_str2);
        }
    
        free(str);
    
        return 0;
    }
    

    字符串在适当位置反转,没有临时变量

    static inline void
    byteswap (char *a, char *b)
    {
      *a = *a^*b;
      *b = *a^*b;
      *a = *a^*b;
    }
    
    void
    reverse (char *string)
    {
      char *end = string + strlen(string) - 1;
    
      while (string < end) {
        byteswap(string++, end--);
      }
    }
    
    静态内联void
    byteswap(字符*a,字符*b)
    {
    *a=*a^*b;
    *b=*a^*b;
    *a=*a^*b;
    }
    无效的
    反向(字符*字符串)
    {
    char*end=string+strlen(string)-1;
    while(字符串<结束){
    byteswap(字符串++,结束--);
    }
    }
    
    不需要临时变量的方法

    int length = strlen(string);
    for(int i = 0; i < length/2; i++) {
      string[i] ^= string[length - i] ^= string[i] ^= string[length - i];
    }
    
    int length=st
    
    char *reverse(const char *s) {
        size_t n = strlen(s);
        char *dest = new char[n + 1];
        char *d = (dest + n - 1);
    
        dest[n] = 0;
        while (*s) {
            *d-- = *s++
        }
    
        return dest;
    }
    
    char *dst = reversed_string + length;
    *dst-- = '\0';
    while (*src) {
       *dst-- = *src++;
    }
    
    int length = strlen(string);
    for(int i = 0; i < length/2; i++) {
      string[i] ^= string[length - i];
      string[length - i] ^= string[i];
      string[i] ^= string[length - i];
    }
    
    /* 
     * reverse.c
     *
     * $20081020 23:33 fernando DOT miguelez AT gmail DOT com$
     */
    
    #include <stdint.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    #define MAX_CHARS 10 * 1024 * 1024
    
    /*
     * Borrowed from http://coding.derkeiler.com/Archive/Assembler/comp.lang.asm.x86/2007-03/msg00004.html
     * GNU Compiler syntax
     */
    inline uint32_t bswap(uint32_t val)
    {
        __asm__("bswap %0" : "=r" (val) : "0" (val));
        return val;
    }
    
    char * reverseAsm(const char * str)
    {
        int i;
        int length = strlen(str);
        int dwordLength = length/4;
    
        if(length % 4 != 0)
        {
            printf("Error: Input string length must be multiple of 4: %d\n", length);       
            return NULL;
        }
    
        char * reversed_string = (char *) malloc(length+1);
        for(i = 0; i < dwordLength; i++)
        {
            *(((uint32_t *) reversed_string) + dwordLength - i - 1) = bswap(*(((uint32_t *) str) + i));
        }
    
        reversed_string[length] = '\0';
    
        return reversed_string;
    }
    
    char * reverse(const char * str)
    {
        int i;
        int length = strlen(str);
        char * reversed_string = (char *) malloc(length+1);
    
        for(i = 0; i < length; ++i)
        {
            reversed_string[i] = str[(length-1) - i];
        }
    
            //need to null terminate the string
    
        reversed_string[length] = '\0';
    
        return reversed_string;
    }
    
    int main(void)
    {
        int i;
        char *reversed_str, *reversed_str2;
        clock_t start, total;
        char *str = (char *) malloc(MAX_CHARS+1);
    
        str[MAX_CHARS] = '\0';
    
        srand(time(0));
    
        for(i = 0; i < MAX_CHARS; i++)
        {
            str[i] = 'A' + rand() % 26;     
        }
    
        start = clock();
        reversed_str = reverse(str);
        total = clock() - start;
        if(reversed_str != NULL)
        {
            printf("Total clock ticks to reverse %d chars with pure C method: %d\n", MAX_CHARS, total); 
            free(reversed_str);
        }
        start = clock();
        reversed_str2 = reverseAsm(str);
        total = clock() - start;
        if(reversed_str2 != NULL)
        {
            printf("Total clock ticks to reverse %d chars with ASM+C method: %d\n", MAX_CHARS, total); 
            free(reversed_str2);
        }
    
        free(str);
    
        return 0;
    }
    
    fer@fernando /cygdrive/c/tmp$ ./reverse.exe
    Total clock ticks to reverse 10485760 chars with pure C method: 221
    Total clock ticks to reverse 10485760 chars with ASM+C method: 140
    
    static inline void
    byteswap (char *a, char *b)
    {
      *a = *a^*b;
      *b = *a^*b;
      *a = *a^*b;
    }
    
    void
    reverse (char *string)
    {
      char *end = string + strlen(string) - 1;
    
      while (string < end) {
        byteswap(string++, end--);
      }
    }
    
    int length = strlen(string);
    for(int i = 0; i < length/2; i++) {
      string[i] ^= string[length - i] ^= string[i] ^= string[length - i];
    }
    
    char * reverse(const char * str)
    {
      if (!str)
        return NULL;
    
      int length = strlen(str);
      char * reversed_string = new char[length+1];
    
      for(int i = 0; i < length/2; ++i)
      {
        reversed_string[i] = str[(length-1) - i];
        reversed_string[(length-1) - i] = str[i];
      }
      //need to null terminate the string
      reversed_string[length] = '\0';
    
      return reversed_string;
    
    }
    
    string[i] ^= string[length - i] ^= string[i] ^= string[length - i];